159 lines
4.8 KiB
PHP
159 lines
4.8 KiB
PHP
|
<?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;
|
||
|
}
|
||
|
}
|