|
1
|
|
|
<?php |
|
2
|
|
|
namespace PhpQuery; |
|
3
|
|
|
|
|
4
|
|
|
use PhpQuery\Dom\DOMEvent; |
|
5
|
|
|
|
|
6
|
|
|
/** |
|
7
|
|
|
* Event handling class. |
|
8
|
|
|
* |
|
9
|
|
|
* @author Tobiasz Cudnik |
|
10
|
|
|
* @package PhpQuery |
|
11
|
|
|
* @static |
|
12
|
|
|
*/ |
|
13
|
|
|
abstract class PhpQueryEvents |
|
14
|
|
|
{ |
|
15
|
|
|
/** |
|
16
|
|
|
* Trigger a type of event on every matched element. |
|
17
|
|
|
* |
|
18
|
|
|
* |
|
19
|
|
|
* @TODO exclusive events (with !) |
|
20
|
|
|
* @TODO global events (test) |
|
21
|
|
|
* @TODO support more than event in $type (space-separated) |
|
22
|
|
|
* @param $document |
|
23
|
|
|
* @param $type |
|
24
|
|
|
* @param array $data |
|
25
|
|
|
* @param null $node |
|
26
|
|
|
*/ |
|
27
|
|
|
public static function trigger($document, $type, $data = array(), $node = null) |
|
28
|
|
|
{ |
|
29
|
|
|
// trigger: function(type, data, elem, donative, extra) { |
|
|
|
|
|
|
30
|
|
|
$documentID = PhpQuery::getDocumentID($document); |
|
31
|
|
|
$namespace = null; |
|
32
|
|
|
if (strpos($type, '.') !== false) { |
|
33
|
|
|
list($name, $namespace) = explode('.', $type); |
|
34
|
|
|
} else { |
|
35
|
|
|
$name = $type; |
|
36
|
|
|
} |
|
37
|
|
|
if (!$node) { |
|
38
|
|
|
if (self::issetGlobal($documentID, $type)) { |
|
39
|
|
|
$pq = PhpQuery::getDocument($documentID); |
|
|
|
|
|
|
40
|
|
|
// TODO check add($pq->document) |
|
|
|
|
|
|
41
|
|
|
$pq->find('*')->add($pq->document)->trigger($type, $data); |
|
42
|
|
|
} |
|
43
|
|
|
} else { |
|
44
|
|
|
if (isset($data[0]) && $data[0] instanceof DOMEvent) { |
|
45
|
|
|
$event = $data[0]; |
|
46
|
|
|
$event->relatedTarget = $event->target; |
|
47
|
|
|
$event->target = $node; |
|
48
|
|
|
$data = array_slice($data, 1); |
|
49
|
|
|
} else { |
|
50
|
|
|
$event = new DOMEvent(array( |
|
51
|
|
|
'type' => $type, |
|
52
|
|
|
'target' => $node, |
|
53
|
|
|
'timeStamp' => time(), |
|
54
|
|
|
)); |
|
55
|
|
|
} |
|
56
|
|
|
$i = 0; |
|
57
|
|
|
while ($node) { |
|
58
|
|
|
// TODO whois |
|
59
|
|
|
PhpQuery::debug( |
|
60
|
|
|
"Triggering " . ($i ? "bubbled " : '') |
|
61
|
|
|
. "event '{$type}' on " . "node \n" |
|
62
|
|
|
); |
|
63
|
|
|
//.PhpQueryObject::whois($node)."\n"); |
|
|
|
|
|
|
64
|
|
|
$event->currentTarget = $node; |
|
65
|
|
|
$eventNode = self::getNode($documentID, $node); |
|
66
|
|
|
if (isset($eventNode->eventHandlers)) { |
|
67
|
|
|
foreach ($eventNode->eventHandlers as $eventType => $handlers) { |
|
68
|
|
|
$eventNamespace = null; |
|
69
|
|
|
if (strpos($type, '.') !== false) { |
|
70
|
|
|
list($eventName, $eventNamespace) = explode('.', $eventType); |
|
71
|
|
|
} else { |
|
72
|
|
|
$eventName = $eventType; |
|
73
|
|
|
} |
|
74
|
|
|
if ($name != $eventName) { |
|
75
|
|
|
continue; |
|
76
|
|
|
} |
|
77
|
|
|
if ($namespace && $eventNamespace && $namespace != $eventNamespace) { |
|
78
|
|
|
continue; |
|
79
|
|
|
} |
|
80
|
|
|
foreach ($handlers as $handler) { |
|
81
|
|
|
PhpQuery::debug("Calling event handler\n"); |
|
82
|
|
|
$event->data = $handler['data'] ? $handler['data'] : null; |
|
83
|
|
|
$params = array_merge( |
|
84
|
|
|
array( |
|
85
|
|
|
$event |
|
86
|
|
|
), |
|
87
|
|
|
$data |
|
88
|
|
|
); |
|
89
|
|
|
$return = PhpQuery::callbackRun($handler['callback'], $params); |
|
90
|
|
|
if ($return === false) { |
|
91
|
|
|
$event->bubbles = false; |
|
92
|
|
|
} |
|
93
|
|
|
} |
|
94
|
|
|
} |
|
95
|
|
|
} |
|
96
|
|
|
// to bubble or not to bubble... |
|
97
|
|
|
if (!$event->bubbles) { |
|
98
|
|
|
break; |
|
99
|
|
|
} |
|
100
|
|
|
$node = $node->parentNode; |
|
101
|
|
|
$i++; |
|
102
|
|
|
} |
|
103
|
|
|
} |
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
|
|
/** |
|
107
|
|
|
* Binds a handler to one or more events (like click) for each matched element. |
|
108
|
|
|
* Can also bind custom events. |
|
109
|
|
|
* |
|
110
|
|
|
* @param \DOMNode|PhpQueryObject|string $document |
|
111
|
|
|
* @param $node |
|
112
|
|
|
* @param string $type |
|
113
|
|
|
* @param string $data Optional |
|
114
|
|
|
* @param $callback |
|
115
|
|
|
* |
|
116
|
|
|
* @TODO support '!' (exclusive) events |
|
117
|
|
|
* @TODO support more than event in $type (space-separated) |
|
118
|
|
|
* @TODO support binding to global events |
|
119
|
|
|
*/ |
|
120
|
|
|
public static function add($document, $node, $type, $data, $callback = null) |
|
121
|
|
|
{ |
|
122
|
|
|
PhpQuery::debug("Binding '$type' event"); |
|
123
|
|
|
$documentID = PhpQuery::getDocumentID($document); |
|
124
|
|
|
// if (is_null($callback) && is_callable($data)) { |
|
|
|
|
|
|
125
|
|
|
// $callback = $data; |
|
|
|
|
|
|
126
|
|
|
// $data = null; |
|
|
|
|
|
|
127
|
|
|
// } |
|
128
|
|
|
$eventNode = self::getNode($documentID, $node); |
|
129
|
|
|
if (!$eventNode) { |
|
130
|
|
|
$eventNode = self::setNode($documentID, $node); |
|
131
|
|
|
} |
|
132
|
|
|
if (!isset($eventNode->eventHandlers[$type])) { |
|
133
|
|
|
$eventNode->eventHandlers[$type] = array(); |
|
134
|
|
|
} |
|
135
|
|
|
$eventNode->eventHandlers[$type][] = array( |
|
136
|
|
|
'callback' => $callback, |
|
137
|
|
|
'data' => $data, |
|
138
|
|
|
); |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
|
|
/** |
|
142
|
|
|
* Enter description here... |
|
143
|
|
|
* |
|
144
|
|
|
* @param \DOMNode|PhpQueryObject|string $document |
|
145
|
|
|
* @param $node |
|
146
|
|
|
* @param string $type |
|
147
|
|
|
* @param $callback |
|
148
|
|
|
* |
|
149
|
|
|
* @TODO namespace events |
|
150
|
|
|
* @TODO support more than event in $type (space-separated) |
|
151
|
|
|
*/ |
|
152
|
|
|
public static function remove($document, $node, $type = null, $callback = null) |
|
153
|
|
|
{ |
|
154
|
|
|
$documentID = PhpQuery::getDocumentID($document); |
|
155
|
|
|
$eventNode = self::getNode($documentID, $node); |
|
156
|
|
|
if (is_object($eventNode) && isset($eventNode->eventHandlers[$type])) { |
|
157
|
|
|
if ($callback) { |
|
158
|
|
|
foreach ($eventNode->eventHandlers[$type] as $k => $handler) { |
|
159
|
|
|
if ($handler['callback'] == $callback) { |
|
160
|
|
|
unset($eventNode->eventHandlers[$type][$k]); |
|
161
|
|
|
} |
|
162
|
|
|
} |
|
163
|
|
|
} else { |
|
164
|
|
|
unset($eventNode->eventHandlers[$type]); |
|
165
|
|
|
} |
|
166
|
|
|
} |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
protected static function getNode($documentID, $node) |
|
170
|
|
|
{ |
|
171
|
|
|
foreach (PhpQuery::$documents[$documentID]->eventsNodes as $eventNode) { |
|
172
|
|
|
if ($node->isSameNode($eventNode)) { |
|
173
|
|
|
return $eventNode; |
|
174
|
|
|
} |
|
175
|
|
|
} |
|
176
|
|
|
} |
|
177
|
|
|
|
|
178
|
|
|
protected static function setNode($documentID, $node) |
|
179
|
|
|
{ |
|
180
|
|
|
PhpQuery::$documents[$documentID]->eventsNodes[] = $node; |
|
181
|
|
|
return PhpQuery::$documents[$documentID]->eventsNodes[count(PhpQuery::$documents[$documentID]->eventsNodes) |
|
182
|
|
|
- 1]; |
|
183
|
|
|
} |
|
184
|
|
|
|
|
185
|
|
|
protected static function issetGlobal($documentID, $type) |
|
186
|
|
|
{ |
|
187
|
|
|
return isset(PhpQuery::$documents[$documentID]) ? in_array( |
|
188
|
|
|
$type, |
|
189
|
|
|
PhpQuery::$documents[$documentID]->eventsGlobal |
|
190
|
|
|
) |
|
191
|
|
|
: false; |
|
192
|
|
|
} |
|
193
|
|
|
} |
|
194
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.