<?php
/**
* Event handling class.
*
* @author Tobiasz Cudnik
* @package phpQuery
* @static
*/
abstract class phpQueryEvents {
/**
* Trigger a type of event on every matched element.
*
* @param DOMNode|phpQueryObject|string $document
* @param unknown_type $type
* @param unknown_type $data
*
* @TODO exclusive events (with !)
* @TODO global events (test)
* @TODO support more than event in $type (space-separated)
*/
public static function trigger($document, $type, $data = array(), $node = null) {
// trigger: function(type, data, elem, donative, extra) {
$documentID = phpQuery::getDocumentID($document);
$namespace = null;
if (strpos($type, '.') !== false)
list($name, $namespace) = explode('.', $type);
else
$name = $type;
if (! $node) {
if (self::issetGlobal($documentID, $type)) {
$pq = phpQuery::getDocument($documentID);
// TODO check add($pq->document)
$pq->find('*')->add($pq->document)
->trigger($type, $data);
}
} else {
if (isset($data[0]) && $data[0] instanceof DOMEvent) {
$event = $data[0];
$event->relatedTarget = $event->target;
$event->target = $node;
$data = array_slice($data, 1);
} else {
$event = new DOMEvent(array(
'type' => $type,
'target' => $node,
'timeStamp' => time(),
));
}
$i = 0;
while($node) {
// TODO whois
phpQuery::debug("Triggering ".($i?"bubbled ":'')."event '{$type}' on "
."node \n");//.phpQueryObject::whois($node)."\n");
$event->currentTarget = $node;
$eventNode = self::getNode($documentID, $node);
if (isset($eventNode->eventHandlers)) {
foreach($eventNode->eventHandlers as $eventType => $handlers) {
$eventNamespace = null;
if (strpos($type, '.') !== false)
list($eventName, $eventNamespace) = explode('.', $eventType);
else
$eventName = $eventType;
if ($name != $eventName)
continue;
if ($namespace && $eventNamespace && $namespace != $eventNamespace)
continue;
foreach($handlers as $handler) {
phpQuery::debug("Calling event handler\n");
$event->data = $handler['data']
? $handler['data']
: null;
$params = array_merge(array($event), $data);
$return = phpQuery::callbackRun($handler['callback'], $params);
if ($return === false) {
$event->bubbles = false;
}
}
}
}
// to bubble or not to bubble...
if (! $event->bubbles)
break;
$node = $node->parentNode;
$i++;
}
}
}
/**
* Binds a handler to one or more events (like click) for each matched element.
* Can also bind custom events.
*
* @param DOMNode|phpQueryObject|string $document
* @param unknown_type $type
* @param unknown_type $data Optional
* @param unknown_type $callback
*
* @TODO support '!' (exclusive) events
* @TODO support more than event in $type (space-separated)
* @TODO support binding to global events
*/
public static function add($document, $node, $type, $data, $callback = null) {
phpQuery::debug("Binding '$type' event");
$documentID = phpQuery::getDocumentID($document);
// if (is_null($callback) && is_callable($data)) {
// $callback = $data;
// $data = null;
// }
$eventNode = self::getNode($documentID, $node);
if (! $eventNode)
$eventNode = self::setNode($documentID, $node);
if (!isset($eventNode->eventHandlers[$type]))
$eventNode->eventHandlers[$type] = array();
$eventNode->eventHandlers[$type][] = array(
'callback' => $callback,
'data' => $data,
);
}
/**
* Enter description here...
*
* @param DOMNode|phpQueryObject|string $document
* @param unknown_type $type
* @param unknown_type $callback
*
* @TODO namespace events
* @TODO support more than event in $type (space-separated)
*/
public static function remove($document, $node, $type = null, $callback = null) {
$documentID = phpQuery::getDocumentID($document);
$eventNode = self::getNode($documentID, $node);
if (is_object($eventNode) && isset($eventNode->eventHandlers[$type])) {
if ($callback) {
foreach($eventNode->eventHandlers[$type] as $k => $handler)
if ($handler['callback'] == $callback)
unset($eventNode->eventHandlers[$type][$k]);
} else {
unset($eventNode->eventHandlers[$type]);
}
}
}
protected static function getNode($documentID, $node) {
foreach(phpQuery::$documents[$documentID]->eventsNodes as $eventNode) {
if ($node->isSameNode($eventNode))
return $eventNode;
}
}
protected static function setNode($documentID, $node) {
phpQuery::$documents[$documentID]->eventsNodes[] = $node;
return phpQuery::$documents[$documentID]->eventsNodes[
count(phpQuery::$documents[$documentID]->eventsNodes)-1
];
}
protected static function issetGlobal($documentID, $type) {
return isset(phpQuery::$documents[$documentID])
? in_array($type, phpQuery::$documents[$documentID]->eventsGlobal)
: false;
}
}