phpQueryEvents.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <?php
  2. /**
  3. * Event handling class.
  4. *
  5. * @author Tobiasz Cudnik
  6. * @package phpQuery
  7. * @static
  8. */
  9. abstract class phpQueryEvents {
  10. /**
  11. * Trigger a type of event on every matched element.
  12. *
  13. * @param DOMNode|phpQueryObject|string $document
  14. * @param unknown_type $type
  15. * @param unknown_type $data
  16. *
  17. * @TODO exclusive events (with !)
  18. * @TODO global events (test)
  19. * @TODO support more than event in $type (space-separated)
  20. */
  21. public static function trigger($document, $type, $data = array(), $node = null) {
  22. // trigger: function(type, data, elem, donative, extra) {
  23. $documentID = phpQuery::getDocumentID($document);
  24. $namespace = null;
  25. if (strpos($type, '.') !== false)
  26. list($name, $namespace) = explode('.', $type);
  27. else
  28. $name = $type;
  29. if (! $node) {
  30. if (self::issetGlobal($documentID, $type)) {
  31. $pq = phpQuery::getDocument($documentID);
  32. // TODO check add($pq->document)
  33. $pq->find('*')->add($pq->document)
  34. ->trigger($type, $data);
  35. }
  36. } else {
  37. if (isset($data[0]) && $data[0] instanceof DOMEvent) {
  38. $event = $data[0];
  39. $event->relatedTarget = $event->target;
  40. $event->target = $node;
  41. $data = array_slice($data, 1);
  42. } else {
  43. $event = new DOMEvent(array(
  44. 'type' => $type,
  45. 'target' => $node,
  46. 'timeStamp' => time(),
  47. ));
  48. }
  49. $i = 0;
  50. while($node) {
  51. // TODO whois
  52. phpQuery::debug("Triggering ".($i?"bubbled ":'')."event '{$type}' on "
  53. ."node \n");//.phpQueryObject::whois($node)."\n");
  54. $event->currentTarget = $node;
  55. $eventNode = self::getNode($documentID, $node);
  56. if (isset($eventNode->eventHandlers)) {
  57. foreach($eventNode->eventHandlers as $eventType => $handlers) {
  58. $eventNamespace = null;
  59. if (strpos($type, '.') !== false)
  60. list($eventName, $eventNamespace) = explode('.', $eventType);
  61. else
  62. $eventName = $eventType;
  63. if ($name != $eventName)
  64. continue;
  65. if ($namespace && $eventNamespace && $namespace != $eventNamespace)
  66. continue;
  67. foreach($handlers as $handler) {
  68. phpQuery::debug("Calling event handler\n");
  69. $event->data = $handler['data']
  70. ? $handler['data']
  71. : null;
  72. $params = array_merge(array($event), $data);
  73. $return = phpQuery::callbackRun($handler['callback'], $params);
  74. if ($return === false) {
  75. $event->bubbles = false;
  76. }
  77. }
  78. }
  79. }
  80. // to bubble or not to bubble...
  81. if (! $event->bubbles)
  82. break;
  83. $node = $node->parentNode;
  84. $i++;
  85. }
  86. }
  87. }
  88. /**
  89. * Binds a handler to one or more events (like click) for each matched element.
  90. * Can also bind custom events.
  91. *
  92. * @param DOMNode|phpQueryObject|string $document
  93. * @param unknown_type $type
  94. * @param unknown_type $data Optional
  95. * @param unknown_type $callback
  96. *
  97. * @TODO support '!' (exclusive) events
  98. * @TODO support more than event in $type (space-separated)
  99. * @TODO support binding to global events
  100. */
  101. public static function add($document, $node, $type, $data, $callback = null) {
  102. phpQuery::debug("Binding '$type' event");
  103. $documentID = phpQuery::getDocumentID($document);
  104. // if (is_null($callback) && is_callable($data)) {
  105. // $callback = $data;
  106. // $data = null;
  107. // }
  108. $eventNode = self::getNode($documentID, $node);
  109. if (! $eventNode)
  110. $eventNode = self::setNode($documentID, $node);
  111. if (!isset($eventNode->eventHandlers[$type]))
  112. $eventNode->eventHandlers[$type] = array();
  113. $eventNode->eventHandlers[$type][] = array(
  114. 'callback' => $callback,
  115. 'data' => $data,
  116. );
  117. }
  118. /**
  119. * Enter description here...
  120. *
  121. * @param DOMNode|phpQueryObject|string $document
  122. * @param unknown_type $type
  123. * @param unknown_type $callback
  124. *
  125. * @TODO namespace events
  126. * @TODO support more than event in $type (space-separated)
  127. */
  128. public static function remove($document, $node, $type = null, $callback = null) {
  129. $documentID = phpQuery::getDocumentID($document);
  130. $eventNode = self::getNode($documentID, $node);
  131. if (is_object($eventNode) && isset($eventNode->eventHandlers[$type])) {
  132. if ($callback) {
  133. foreach($eventNode->eventHandlers[$type] as $k => $handler)
  134. if ($handler['callback'] == $callback)
  135. unset($eventNode->eventHandlers[$type][$k]);
  136. } else {
  137. unset($eventNode->eventHandlers[$type]);
  138. }
  139. }
  140. }
  141. protected static function getNode($documentID, $node) {
  142. foreach(phpQuery::$documents[$documentID]->eventsNodes as $eventNode) {
  143. if ($node->isSameNode($eventNode))
  144. return $eventNode;
  145. }
  146. }
  147. protected static function setNode($documentID, $node) {
  148. phpQuery::$documents[$documentID]->eventsNodes[] = $node;
  149. return phpQuery::$documents[$documentID]->eventsNodes[
  150. count(phpQuery::$documents[$documentID]->eventsNodes)-1
  151. ];
  152. }
  153. protected static function issetGlobal($documentID, $type) {
  154. return isset(phpQuery::$documents[$documentID])
  155. ? in_array($type, phpQuery::$documents[$documentID]->eventsGlobal)
  156. : false;
  157. }
  158. }