1f8369d7dSTobias Sarnowski<?php 2f8369d7dSTobias Sarnowski/** 3f8369d7dSTobias Sarnowski * phpQuery is a server-side, chainable, CSS3 selector driven 4f8369d7dSTobias Sarnowski * Document Object Model (DOM) API based on jQuery JavaScript Library. 5f8369d7dSTobias Sarnowski * 6f8369d7dSTobias Sarnowski * @version 0.9.5 7f8369d7dSTobias Sarnowski * @link http://code.google.com/p/phpquery/ 8f8369d7dSTobias Sarnowski * @link http://phpquery-library.blogspot.com/ 9f8369d7dSTobias Sarnowski * @link http://jquery.com/ 10f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 11f8369d7dSTobias Sarnowski * @license http://www.opensource.org/licenses/mit-license.php MIT License 12f8369d7dSTobias Sarnowski * @package phpQuery 13acdf738aSAndreas Gohr * @deprecated 2022-10-19 14f8369d7dSTobias Sarnowski */ 15f8369d7dSTobias Sarnowski 16f8369d7dSTobias Sarnowski// class names for instanceof 17f8369d7dSTobias Sarnowski// TODO move them as class constants into phpQuery 18f8369d7dSTobias Sarnowskidefine('DOMDOCUMENT', 'DOMDocument'); 19f8369d7dSTobias Sarnowskidefine('DOMELEMENT', 'DOMElement'); 20f8369d7dSTobias Sarnowskidefine('DOMNODELIST', 'DOMNodeList'); 21f8369d7dSTobias Sarnowskidefine('DOMNODE', 'DOMNode'); 22f8369d7dSTobias Sarnowski 23f8369d7dSTobias Sarnowski/** 24f8369d7dSTobias Sarnowski * DOMEvent class. 25f8369d7dSTobias Sarnowski * 26f8369d7dSTobias Sarnowski * Based on 27f8369d7dSTobias Sarnowski * @link http://developer.mozilla.org/En/DOM:event 28f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 29f8369d7dSTobias Sarnowski * @package phpQuery 30f8369d7dSTobias Sarnowski * @todo implement ArrayAccess ? 31f8369d7dSTobias Sarnowski */ 32f8369d7dSTobias Sarnowskiclass DOMEvent { 33f8369d7dSTobias Sarnowski /** 34f8369d7dSTobias Sarnowski * Returns a boolean indicating whether the event bubbles up through the DOM or not. 35f8369d7dSTobias Sarnowski * 36f8369d7dSTobias Sarnowski * @var unknown_type 37f8369d7dSTobias Sarnowski */ 38f8369d7dSTobias Sarnowski public $bubbles = true; 39f8369d7dSTobias Sarnowski /** 40f8369d7dSTobias Sarnowski * Returns a boolean indicating whether the event is cancelable. 41f8369d7dSTobias Sarnowski * 42f8369d7dSTobias Sarnowski * @var unknown_type 43f8369d7dSTobias Sarnowski */ 44f8369d7dSTobias Sarnowski public $cancelable = true; 45f8369d7dSTobias Sarnowski /** 46f8369d7dSTobias Sarnowski * Returns a reference to the currently registered target for the event. 47f8369d7dSTobias Sarnowski * 48f8369d7dSTobias Sarnowski * @var unknown_type 49f8369d7dSTobias Sarnowski */ 50f8369d7dSTobias Sarnowski public $currentTarget; 51f8369d7dSTobias Sarnowski /** 52f8369d7dSTobias Sarnowski * Returns detail about the event, depending on the type of event. 53f8369d7dSTobias Sarnowski * 54f8369d7dSTobias Sarnowski * @var unknown_type 55f8369d7dSTobias Sarnowski * @link http://developer.mozilla.org/en/DOM/event.detail 56f8369d7dSTobias Sarnowski */ 57f8369d7dSTobias Sarnowski public $detail; // ??? 58f8369d7dSTobias Sarnowski /** 59f8369d7dSTobias Sarnowski * Used to indicate which phase of the event flow is currently being evaluated. 60f8369d7dSTobias Sarnowski * 61f8369d7dSTobias Sarnowski * NOT IMPLEMENTED 62f8369d7dSTobias Sarnowski * 63f8369d7dSTobias Sarnowski * @var unknown_type 64f8369d7dSTobias Sarnowski * @link http://developer.mozilla.org/en/DOM/event.eventPhase 65f8369d7dSTobias Sarnowski */ 66f8369d7dSTobias Sarnowski public $eventPhase; // ??? 67f8369d7dSTobias Sarnowski /** 68f8369d7dSTobias Sarnowski * The explicit original target of the event (Mozilla-specific). 69f8369d7dSTobias Sarnowski * 70f8369d7dSTobias Sarnowski * NOT IMPLEMENTED 71f8369d7dSTobias Sarnowski * 72f8369d7dSTobias Sarnowski * @var unknown_type 73f8369d7dSTobias Sarnowski */ 74f8369d7dSTobias Sarnowski public $explicitOriginalTarget; // moz only 75f8369d7dSTobias Sarnowski /** 76f8369d7dSTobias Sarnowski * The original target of the event, before any retargetings (Mozilla-specific). 77f8369d7dSTobias Sarnowski * 78f8369d7dSTobias Sarnowski * NOT IMPLEMENTED 79f8369d7dSTobias Sarnowski * 80f8369d7dSTobias Sarnowski * @var unknown_type 81f8369d7dSTobias Sarnowski */ 82f8369d7dSTobias Sarnowski public $originalTarget; // moz only 83f8369d7dSTobias Sarnowski /** 84f8369d7dSTobias Sarnowski * Identifies a secondary target for the event. 85f8369d7dSTobias Sarnowski * 86f8369d7dSTobias Sarnowski * @var unknown_type 87f8369d7dSTobias Sarnowski */ 88f8369d7dSTobias Sarnowski public $relatedTarget; 89f8369d7dSTobias Sarnowski /** 90f8369d7dSTobias Sarnowski * Returns a reference to the target to which the event was originally dispatched. 91f8369d7dSTobias Sarnowski * 92f8369d7dSTobias Sarnowski * @var unknown_type 93f8369d7dSTobias Sarnowski */ 94f8369d7dSTobias Sarnowski public $target; 95f8369d7dSTobias Sarnowski /** 96f8369d7dSTobias Sarnowski * Returns the time that the event was created. 97f8369d7dSTobias Sarnowski * 98f8369d7dSTobias Sarnowski * @var unknown_type 99f8369d7dSTobias Sarnowski */ 100f8369d7dSTobias Sarnowski public $timeStamp; 101f8369d7dSTobias Sarnowski /** 102f8369d7dSTobias Sarnowski * Returns the name of the event (case-insensitive). 103f8369d7dSTobias Sarnowski */ 104f8369d7dSTobias Sarnowski public $type; 105f8369d7dSTobias Sarnowski public $runDefault = true; 106f8369d7dSTobias Sarnowski public $data = null; 107f8369d7dSTobias Sarnowski public function __construct($data) { 108f8369d7dSTobias Sarnowski foreach($data as $k => $v) { 109f8369d7dSTobias Sarnowski $this->$k = $v; 110f8369d7dSTobias Sarnowski } 111f8369d7dSTobias Sarnowski if (! $this->timeStamp) 112f8369d7dSTobias Sarnowski $this->timeStamp = time(); 113f8369d7dSTobias Sarnowski } 114f8369d7dSTobias Sarnowski /** 115f8369d7dSTobias Sarnowski * Cancels the event (if it is cancelable). 116f8369d7dSTobias Sarnowski * 117f8369d7dSTobias Sarnowski */ 118f8369d7dSTobias Sarnowski public function preventDefault() { 119f8369d7dSTobias Sarnowski $this->runDefault = false; 120f8369d7dSTobias Sarnowski } 121f8369d7dSTobias Sarnowski /** 122f8369d7dSTobias Sarnowski * Stops the propagation of events further along in the DOM. 123f8369d7dSTobias Sarnowski * 124f8369d7dSTobias Sarnowski */ 125f8369d7dSTobias Sarnowski public function stopPropagation() { 126f8369d7dSTobias Sarnowski $this->bubbles = false; 127f8369d7dSTobias Sarnowski } 128f8369d7dSTobias Sarnowski} 129f8369d7dSTobias Sarnowski 130f8369d7dSTobias Sarnowski 131f8369d7dSTobias Sarnowski/** 132f8369d7dSTobias Sarnowski * DOMDocumentWrapper class simplifies work with DOMDocument. 133f8369d7dSTobias Sarnowski * 134f8369d7dSTobias Sarnowski * Know bug: 135f8369d7dSTobias Sarnowski * - in XHTML fragments, <br /> changes to <br clear="none" /> 136f8369d7dSTobias Sarnowski * 137f8369d7dSTobias Sarnowski * @todo check XML catalogs compatibility 138f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 139f8369d7dSTobias Sarnowski * @package phpQuery 140f8369d7dSTobias Sarnowski */ 141f8369d7dSTobias Sarnowskiclass DOMDocumentWrapper { 142f8369d7dSTobias Sarnowski /** 143f8369d7dSTobias Sarnowski * @var DOMDocument 144f8369d7dSTobias Sarnowski */ 145f8369d7dSTobias Sarnowski public $document; 146f8369d7dSTobias Sarnowski public $id; 147f8369d7dSTobias Sarnowski /** 148f8369d7dSTobias Sarnowski * @todo Rewrite as method and quess if null. 149f8369d7dSTobias Sarnowski * @var unknown_type 150f8369d7dSTobias Sarnowski */ 151f8369d7dSTobias Sarnowski public $contentType = ''; 152f8369d7dSTobias Sarnowski public $xpath; 153f8369d7dSTobias Sarnowski public $uuid = 0; 154f8369d7dSTobias Sarnowski public $data = array(); 155f8369d7dSTobias Sarnowski public $dataNodes = array(); 156f8369d7dSTobias Sarnowski public $events = array(); 157f8369d7dSTobias Sarnowski public $eventsNodes = array(); 158f8369d7dSTobias Sarnowski public $eventsGlobal = array(); 159f8369d7dSTobias Sarnowski /** 160f8369d7dSTobias Sarnowski * @TODO iframes support http://code.google.com/p/phpquery/issues/detail?id=28 161f8369d7dSTobias Sarnowski * @var unknown_type 162f8369d7dSTobias Sarnowski */ 163f8369d7dSTobias Sarnowski public $frames = array(); 164f8369d7dSTobias Sarnowski /** 165f8369d7dSTobias Sarnowski * Document root, by default equals to document itself. 166f8369d7dSTobias Sarnowski * Used by documentFragments. 167f8369d7dSTobias Sarnowski * 168f8369d7dSTobias Sarnowski * @var DOMNode 169f8369d7dSTobias Sarnowski */ 170f8369d7dSTobias Sarnowski public $root; 171f8369d7dSTobias Sarnowski public $isDocumentFragment; 172f8369d7dSTobias Sarnowski public $isXML = false; 173f8369d7dSTobias Sarnowski public $isXHTML = false; 174f8369d7dSTobias Sarnowski public $isHTML = false; 175f8369d7dSTobias Sarnowski public $charset; 176f8369d7dSTobias Sarnowski public function __construct($markup = null, $contentType = null, $newDocumentID = null) { 177f8369d7dSTobias Sarnowski if (isset($markup)) 178f8369d7dSTobias Sarnowski $this->load($markup, $contentType, $newDocumentID); 179f8369d7dSTobias Sarnowski $this->id = $newDocumentID 180f8369d7dSTobias Sarnowski ? $newDocumentID 181f8369d7dSTobias Sarnowski : md5(microtime()); 182f8369d7dSTobias Sarnowski } 183f8369d7dSTobias Sarnowski public function load($markup, $contentType = null, $newDocumentID = null) { 184f8369d7dSTobias Sarnowski// phpQuery::$documents[$id] = $this; 185f8369d7dSTobias Sarnowski $this->contentType = strtolower($contentType); 186f8369d7dSTobias Sarnowski if ($markup instanceof DOMDOCUMENT) { 187f8369d7dSTobias Sarnowski $this->document = $markup; 188f8369d7dSTobias Sarnowski $this->root = $this->document; 189f8369d7dSTobias Sarnowski $this->charset = $this->document->encoding; 190f8369d7dSTobias Sarnowski // TODO isDocumentFragment 191f8369d7dSTobias Sarnowski } else { 192f8369d7dSTobias Sarnowski $loaded = $this->loadMarkup($markup); 193f8369d7dSTobias Sarnowski } 194f8369d7dSTobias Sarnowski if ($loaded) { 195f8369d7dSTobias Sarnowski// $this->document->formatOutput = true; 196f8369d7dSTobias Sarnowski $this->document->preserveWhiteSpace = true; 197f8369d7dSTobias Sarnowski $this->xpath = new DOMXPath($this->document); 198f8369d7dSTobias Sarnowski $this->afterMarkupLoad(); 199f8369d7dSTobias Sarnowski return true; 200f8369d7dSTobias Sarnowski // remember last loaded document 201f8369d7dSTobias Sarnowski// return phpQuery::selectDocument($id); 202f8369d7dSTobias Sarnowski } 203f8369d7dSTobias Sarnowski return false; 204f8369d7dSTobias Sarnowski } 205f8369d7dSTobias Sarnowski protected function afterMarkupLoad() { 206f8369d7dSTobias Sarnowski if ($this->isXHTML) { 207f8369d7dSTobias Sarnowski $this->xpath->registerNamespace("html", "http://www.w3.org/1999/xhtml"); 208f8369d7dSTobias Sarnowski } 209f8369d7dSTobias Sarnowski } 210f8369d7dSTobias Sarnowski protected function loadMarkup($markup) { 211f8369d7dSTobias Sarnowski $loaded = false; 212f8369d7dSTobias Sarnowski if ($this->contentType) { 213f8369d7dSTobias Sarnowski self::debug("Load markup for content type {$this->contentType}"); 214f8369d7dSTobias Sarnowski // content determined by contentType 215f8369d7dSTobias Sarnowski list($contentType, $charset) = $this->contentTypeToArray($this->contentType); 216f8369d7dSTobias Sarnowski switch($contentType) { 217f8369d7dSTobias Sarnowski case 'text/html': 218f8369d7dSTobias Sarnowski phpQuery::debug("Loading HTML, content type '{$this->contentType}'"); 219f8369d7dSTobias Sarnowski $loaded = $this->loadMarkupHTML($markup, $charset); 220f8369d7dSTobias Sarnowski break; 221f8369d7dSTobias Sarnowski case 'text/xml': 222f8369d7dSTobias Sarnowski case 'application/xhtml+xml': 223f8369d7dSTobias Sarnowski phpQuery::debug("Loading XML, content type '{$this->contentType}'"); 224f8369d7dSTobias Sarnowski $loaded = $this->loadMarkupXML($markup, $charset); 225f8369d7dSTobias Sarnowski break; 226f8369d7dSTobias Sarnowski default: 227f8369d7dSTobias Sarnowski // for feeds or anything that sometimes doesn't use text/xml 228f8369d7dSTobias Sarnowski if (strpos('xml', $this->contentType) !== false) { 229f8369d7dSTobias Sarnowski phpQuery::debug("Loading XML, content type '{$this->contentType}'"); 230f8369d7dSTobias Sarnowski $loaded = $this->loadMarkupXML($markup, $charset); 231f8369d7dSTobias Sarnowski } else 232f8369d7dSTobias Sarnowski phpQuery::debug("Could not determine document type from content type '{$this->contentType}'"); 233f8369d7dSTobias Sarnowski } 234f8369d7dSTobias Sarnowski } else { 235f8369d7dSTobias Sarnowski // content type autodetection 236f8369d7dSTobias Sarnowski if ($this->isXML($markup)) { 237f8369d7dSTobias Sarnowski phpQuery::debug("Loading XML, isXML() == true"); 238f8369d7dSTobias Sarnowski $loaded = $this->loadMarkupXML($markup); 239f8369d7dSTobias Sarnowski if (! $loaded && $this->isXHTML) { 240f8369d7dSTobias Sarnowski phpQuery::debug('Loading as XML failed, trying to load as HTML, isXHTML == true'); 241f8369d7dSTobias Sarnowski $loaded = $this->loadMarkupHTML($markup); 242f8369d7dSTobias Sarnowski } 243f8369d7dSTobias Sarnowski } else { 244f8369d7dSTobias Sarnowski phpQuery::debug("Loading HTML, isXML() == false"); 245f8369d7dSTobias Sarnowski $loaded = $this->loadMarkupHTML($markup); 246f8369d7dSTobias Sarnowski } 247f8369d7dSTobias Sarnowski } 248f8369d7dSTobias Sarnowski return $loaded; 249f8369d7dSTobias Sarnowski } 250f8369d7dSTobias Sarnowski protected function loadMarkupReset() { 251f8369d7dSTobias Sarnowski $this->isXML = $this->isXHTML = $this->isHTML = false; 252f8369d7dSTobias Sarnowski } 253f8369d7dSTobias Sarnowski protected function documentCreate($charset, $version = '1.0') { 254f8369d7dSTobias Sarnowski if (! $version) 255f8369d7dSTobias Sarnowski $version = '1.0'; 256f8369d7dSTobias Sarnowski $this->document = new DOMDocument($version, $charset); 257f8369d7dSTobias Sarnowski $this->charset = $this->document->encoding; 258f8369d7dSTobias Sarnowski// $this->document->encoding = $charset; 259f8369d7dSTobias Sarnowski $this->document->formatOutput = true; 260f8369d7dSTobias Sarnowski $this->document->preserveWhiteSpace = true; 261f8369d7dSTobias Sarnowski } 262f8369d7dSTobias Sarnowski protected function loadMarkupHTML($markup, $requestedCharset = null) { 263f8369d7dSTobias Sarnowski if (phpQuery::$debug) 264f8369d7dSTobias Sarnowski phpQuery::debug('Full markup load (HTML): '.substr($markup, 0, 250)); 265f8369d7dSTobias Sarnowski $this->loadMarkupReset(); 266f8369d7dSTobias Sarnowski $this->isHTML = true; 267f8369d7dSTobias Sarnowski if (!isset($this->isDocumentFragment)) 268f8369d7dSTobias Sarnowski $this->isDocumentFragment = self::isDocumentFragmentHTML($markup); 269f8369d7dSTobias Sarnowski $charset = null; 270f8369d7dSTobias Sarnowski $documentCharset = $this->charsetFromHTML($markup); 271f8369d7dSTobias Sarnowski $addDocumentCharset = false; 272f8369d7dSTobias Sarnowski if ($documentCharset) { 273f8369d7dSTobias Sarnowski $charset = $documentCharset; 274f8369d7dSTobias Sarnowski $markup = $this->charsetFixHTML($markup); 275f8369d7dSTobias Sarnowski } else if ($requestedCharset) { 276f8369d7dSTobias Sarnowski $charset = $requestedCharset; 277f8369d7dSTobias Sarnowski } 278f8369d7dSTobias Sarnowski if (! $charset) 279f8369d7dSTobias Sarnowski $charset = phpQuery::$defaultCharset; 280f8369d7dSTobias Sarnowski // HTTP 1.1 says that the default charset is ISO-8859-1 281f8369d7dSTobias Sarnowski // @see http://www.w3.org/International/O-HTTP-charset 282f8369d7dSTobias Sarnowski if (! $documentCharset) { 283f8369d7dSTobias Sarnowski $documentCharset = 'ISO-8859-1'; 284f8369d7dSTobias Sarnowski $addDocumentCharset = true; 285f8369d7dSTobias Sarnowski } 286f8369d7dSTobias Sarnowski // Should be careful here, still need 'magic encoding detection' since lots of pages have other 'default encoding' 287f8369d7dSTobias Sarnowski // Worse, some pages can have mixed encodings... we'll try not to worry about that 288f8369d7dSTobias Sarnowski $requestedCharset = strtoupper($requestedCharset); 289f8369d7dSTobias Sarnowski $documentCharset = strtoupper($documentCharset); 290f8369d7dSTobias Sarnowski phpQuery::debug("DOC: $documentCharset REQ: $requestedCharset"); 291f8369d7dSTobias Sarnowski if ($requestedCharset && $documentCharset && $requestedCharset !== $documentCharset) { 292f8369d7dSTobias Sarnowski phpQuery::debug("CHARSET CONVERT"); 293f8369d7dSTobias Sarnowski // Document Encoding Conversion 294f8369d7dSTobias Sarnowski // http://code.google.com/p/phpquery/issues/detail?id=86 295f8369d7dSTobias Sarnowski if (function_exists('mb_detect_encoding')) { 296f8369d7dSTobias Sarnowski $possibleCharsets = array($documentCharset, $requestedCharset, 'AUTO'); 297f8369d7dSTobias Sarnowski $docEncoding = mb_detect_encoding($markup, implode(', ', $possibleCharsets)); 298f8369d7dSTobias Sarnowski if (! $docEncoding) 299f8369d7dSTobias Sarnowski $docEncoding = $documentCharset; // ok trust the document 300f8369d7dSTobias Sarnowski phpQuery::debug("DETECTED '$docEncoding'"); 301f8369d7dSTobias Sarnowski // Detected does not match what document says... 302f8369d7dSTobias Sarnowski if ($docEncoding !== $documentCharset) { 303f8369d7dSTobias Sarnowski // Tricky.. 304f8369d7dSTobias Sarnowski } 305f8369d7dSTobias Sarnowski if ($docEncoding !== $requestedCharset) { 306f8369d7dSTobias Sarnowski phpQuery::debug("CONVERT $docEncoding => $requestedCharset"); 307f8369d7dSTobias Sarnowski $markup = mb_convert_encoding($markup, $requestedCharset, $docEncoding); 308f8369d7dSTobias Sarnowski $markup = $this->charsetAppendToHTML($markup, $requestedCharset); 309f8369d7dSTobias Sarnowski $charset = $requestedCharset; 310f8369d7dSTobias Sarnowski } 311f8369d7dSTobias Sarnowski } else { 312f8369d7dSTobias Sarnowski phpQuery::debug("TODO: charset conversion without mbstring..."); 313f8369d7dSTobias Sarnowski } 314f8369d7dSTobias Sarnowski } 315f8369d7dSTobias Sarnowski $return = false; 316f8369d7dSTobias Sarnowski if ($this->isDocumentFragment) { 317f8369d7dSTobias Sarnowski phpQuery::debug("Full markup load (HTML), DocumentFragment detected, using charset '$charset'"); 318f8369d7dSTobias Sarnowski $return = $this->documentFragmentLoadMarkup($this, $charset, $markup); 319f8369d7dSTobias Sarnowski } else { 320f8369d7dSTobias Sarnowski if ($addDocumentCharset) { 321f8369d7dSTobias Sarnowski phpQuery::debug("Full markup load (HTML), appending charset: '$charset'"); 322f8369d7dSTobias Sarnowski $markup = $this->charsetAppendToHTML($markup, $charset); 323f8369d7dSTobias Sarnowski } 324f8369d7dSTobias Sarnowski phpQuery::debug("Full markup load (HTML), documentCreate('$charset')"); 325f8369d7dSTobias Sarnowski $this->documentCreate($charset); 326f8369d7dSTobias Sarnowski $return = phpQuery::$debug === 2 327f8369d7dSTobias Sarnowski ? $this->document->loadHTML($markup) 328f8369d7dSTobias Sarnowski : @$this->document->loadHTML($markup); 329f8369d7dSTobias Sarnowski if ($return) 330f8369d7dSTobias Sarnowski $this->root = $this->document; 331f8369d7dSTobias Sarnowski } 332f8369d7dSTobias Sarnowski if ($return && ! $this->contentType) 333f8369d7dSTobias Sarnowski $this->contentType = 'text/html'; 334f8369d7dSTobias Sarnowski return $return; 335f8369d7dSTobias Sarnowski } 336f8369d7dSTobias Sarnowski protected function loadMarkupXML($markup, $requestedCharset = null) { 337f8369d7dSTobias Sarnowski if (phpQuery::$debug) 338f8369d7dSTobias Sarnowski phpQuery::debug('Full markup load (XML): '.substr($markup, 0, 250)); 339f8369d7dSTobias Sarnowski $this->loadMarkupReset(); 340f8369d7dSTobias Sarnowski $this->isXML = true; 341f8369d7dSTobias Sarnowski // check agains XHTML in contentType or markup 342f8369d7dSTobias Sarnowski $isContentTypeXHTML = $this->isXHTML(); 343f8369d7dSTobias Sarnowski $isMarkupXHTML = $this->isXHTML($markup); 344f8369d7dSTobias Sarnowski if ($isContentTypeXHTML || $isMarkupXHTML) { 345f8369d7dSTobias Sarnowski self::debug('Full markup load (XML), XHTML detected'); 346f8369d7dSTobias Sarnowski $this->isXHTML = true; 347f8369d7dSTobias Sarnowski } 348f8369d7dSTobias Sarnowski // determine document fragment 349f8369d7dSTobias Sarnowski if (! isset($this->isDocumentFragment)) 350f8369d7dSTobias Sarnowski $this->isDocumentFragment = $this->isXHTML 351f8369d7dSTobias Sarnowski ? self::isDocumentFragmentXHTML($markup) 352f8369d7dSTobias Sarnowski : self::isDocumentFragmentXML($markup); 353f8369d7dSTobias Sarnowski // this charset will be used 354f8369d7dSTobias Sarnowski $charset = null; 355f8369d7dSTobias Sarnowski // charset from XML declaration @var string 356f8369d7dSTobias Sarnowski $documentCharset = $this->charsetFromXML($markup); 357f8369d7dSTobias Sarnowski if (! $documentCharset) { 358f8369d7dSTobias Sarnowski if ($this->isXHTML) { 359f8369d7dSTobias Sarnowski // this is XHTML, try to get charset from content-type meta header 360f8369d7dSTobias Sarnowski $documentCharset = $this->charsetFromHTML($markup); 361f8369d7dSTobias Sarnowski if ($documentCharset) { 362f8369d7dSTobias Sarnowski phpQuery::debug("Full markup load (XML), appending XHTML charset '$documentCharset'"); 363f8369d7dSTobias Sarnowski $this->charsetAppendToXML($markup, $documentCharset); 364f8369d7dSTobias Sarnowski $charset = $documentCharset; 365f8369d7dSTobias Sarnowski } 366f8369d7dSTobias Sarnowski } 367f8369d7dSTobias Sarnowski if (! $documentCharset) { 368f8369d7dSTobias Sarnowski // if still no document charset... 369f8369d7dSTobias Sarnowski $charset = $requestedCharset; 370f8369d7dSTobias Sarnowski } 371f8369d7dSTobias Sarnowski } else if ($requestedCharset) { 372f8369d7dSTobias Sarnowski $charset = $requestedCharset; 373f8369d7dSTobias Sarnowski } 374f8369d7dSTobias Sarnowski if (! $charset) { 375f8369d7dSTobias Sarnowski $charset = phpQuery::$defaultCharset; 376f8369d7dSTobias Sarnowski } 377f8369d7dSTobias Sarnowski if ($requestedCharset && $documentCharset && $requestedCharset != $documentCharset) { 378f8369d7dSTobias Sarnowski // TODO place for charset conversion 379f8369d7dSTobias Sarnowski// $charset = $requestedCharset; 380f8369d7dSTobias Sarnowski } 381f8369d7dSTobias Sarnowski $return = false; 382f8369d7dSTobias Sarnowski if ($this->isDocumentFragment) { 383f8369d7dSTobias Sarnowski phpQuery::debug("Full markup load (XML), DocumentFragment detected, using charset '$charset'"); 384f8369d7dSTobias Sarnowski $return = $this->documentFragmentLoadMarkup($this, $charset, $markup); 385f8369d7dSTobias Sarnowski } else { 386f8369d7dSTobias Sarnowski // FIXME ??? 387f8369d7dSTobias Sarnowski if ($isContentTypeXHTML && ! $isMarkupXHTML) 388f8369d7dSTobias Sarnowski if (! $documentCharset) { 389f8369d7dSTobias Sarnowski phpQuery::debug("Full markup load (XML), appending charset '$charset'"); 390f8369d7dSTobias Sarnowski $markup = $this->charsetAppendToXML($markup, $charset); 391f8369d7dSTobias Sarnowski } 39259752844SAnders Sandblad // see http://php.net/manual/en/book.dom.php#78929 393f8369d7dSTobias Sarnowski // LIBXML_DTDLOAD (>= PHP 5.1) 394f8369d7dSTobias Sarnowski // does XML ctalogues works with LIBXML_NONET 395f8369d7dSTobias Sarnowski // $this->document->resolveExternals = true; 396f8369d7dSTobias Sarnowski // TODO test LIBXML_COMPACT for performance improvement 397f8369d7dSTobias Sarnowski // create document 398f8369d7dSTobias Sarnowski $this->documentCreate($charset); 399f8369d7dSTobias Sarnowski if (phpversion() < 5.1) { 400f8369d7dSTobias Sarnowski $this->document->resolveExternals = true; 401f8369d7dSTobias Sarnowski $return = phpQuery::$debug === 2 402f8369d7dSTobias Sarnowski ? $this->document->loadXML($markup) 403f8369d7dSTobias Sarnowski : @$this->document->loadXML($markup); 404f8369d7dSTobias Sarnowski } else { 40559752844SAnders Sandblad /** @link http://php.net/manual/en/libxml.constants.php */ 406f8369d7dSTobias Sarnowski $libxmlStatic = phpQuery::$debug === 2 407f8369d7dSTobias Sarnowski ? LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET 408f8369d7dSTobias Sarnowski : LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET|LIBXML_NOWARNING|LIBXML_NOERROR; 409f8369d7dSTobias Sarnowski $return = $this->document->loadXML($markup, $libxmlStatic); 410f8369d7dSTobias Sarnowski// if (! $return) 411f8369d7dSTobias Sarnowski// $return = $this->document->loadHTML($markup); 412f8369d7dSTobias Sarnowski } 413f8369d7dSTobias Sarnowski if ($return) 414f8369d7dSTobias Sarnowski $this->root = $this->document; 415f8369d7dSTobias Sarnowski } 416f8369d7dSTobias Sarnowski if ($return) { 417f8369d7dSTobias Sarnowski if (! $this->contentType) { 418f8369d7dSTobias Sarnowski if ($this->isXHTML) 419f8369d7dSTobias Sarnowski $this->contentType = 'application/xhtml+xml'; 420f8369d7dSTobias Sarnowski else 421f8369d7dSTobias Sarnowski $this->contentType = 'text/xml'; 422f8369d7dSTobias Sarnowski } 423f8369d7dSTobias Sarnowski return $return; 424f8369d7dSTobias Sarnowski } else { 425f8369d7dSTobias Sarnowski throw new Exception("Error loading XML markup"); 426f8369d7dSTobias Sarnowski } 427f8369d7dSTobias Sarnowski } 428f8369d7dSTobias Sarnowski protected function isXHTML($markup = null) { 429f8369d7dSTobias Sarnowski if (! isset($markup)) { 430f8369d7dSTobias Sarnowski return strpos($this->contentType, 'xhtml') !== false; 431f8369d7dSTobias Sarnowski } 432f8369d7dSTobias Sarnowski // XXX ok ? 433f8369d7dSTobias Sarnowski return strpos($markup, "<!DOCTYPE html") !== false; 434f8369d7dSTobias Sarnowski// return stripos($doctype, 'xhtml') !== false; 435f8369d7dSTobias Sarnowski// $doctype = isset($dom->doctype) && is_object($dom->doctype) 436f8369d7dSTobias Sarnowski// ? $dom->doctype->publicId 437f8369d7dSTobias Sarnowski// : self::$defaultDoctype; 438f8369d7dSTobias Sarnowski } 439f8369d7dSTobias Sarnowski protected function isXML($markup) { 440f8369d7dSTobias Sarnowski// return strpos($markup, '<?xml') !== false && stripos($markup, 'xhtml') === false; 441f8369d7dSTobias Sarnowski return strpos(substr($markup, 0, 100), '<'.'?xml') !== false; 442f8369d7dSTobias Sarnowski } 443f8369d7dSTobias Sarnowski protected function contentTypeToArray($contentType) { 444f8369d7dSTobias Sarnowski $matches = explode(';', trim(strtolower($contentType))); 445f8369d7dSTobias Sarnowski if (isset($matches[1])) { 446f8369d7dSTobias Sarnowski $matches[1] = explode('=', $matches[1]); 447f8369d7dSTobias Sarnowski // strip 'charset=' 448f8369d7dSTobias Sarnowski $matches[1] = isset($matches[1][1]) && trim($matches[1][1]) 449f8369d7dSTobias Sarnowski ? $matches[1][1] 450f8369d7dSTobias Sarnowski : $matches[1][0]; 451f8369d7dSTobias Sarnowski } else 452f8369d7dSTobias Sarnowski $matches[1] = null; 453f8369d7dSTobias Sarnowski return $matches; 454f8369d7dSTobias Sarnowski } 455f8369d7dSTobias Sarnowski /** 456f8369d7dSTobias Sarnowski * 457f8369d7dSTobias Sarnowski * @param $markup 458f8369d7dSTobias Sarnowski * @return array contentType, charset 459f8369d7dSTobias Sarnowski */ 460f8369d7dSTobias Sarnowski protected function contentTypeFromHTML($markup) { 461f8369d7dSTobias Sarnowski $matches = array(); 462f8369d7dSTobias Sarnowski // find meta tag 463f8369d7dSTobias Sarnowski preg_match('@<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i', 464f8369d7dSTobias Sarnowski $markup, $matches 465f8369d7dSTobias Sarnowski ); 466f8369d7dSTobias Sarnowski if (! isset($matches[0])) 467f8369d7dSTobias Sarnowski return array(null, null); 468f8369d7dSTobias Sarnowski // get attr 'content' 469f8369d7dSTobias Sarnowski preg_match('@content\\s*=\\s*(["|\'])(.+?)\\1@', $matches[0], $matches); 470f8369d7dSTobias Sarnowski if (! isset($matches[0])) 471f8369d7dSTobias Sarnowski return array(null, null); 472f8369d7dSTobias Sarnowski return $this->contentTypeToArray($matches[2]); 473f8369d7dSTobias Sarnowski } 474f8369d7dSTobias Sarnowski protected function charsetFromHTML($markup) { 475f8369d7dSTobias Sarnowski $contentType = $this->contentTypeFromHTML($markup); 476f8369d7dSTobias Sarnowski return $contentType[1]; 477f8369d7dSTobias Sarnowski } 478f8369d7dSTobias Sarnowski protected function charsetFromXML($markup) { 479f8369d7dSTobias Sarnowski $matches; 480f8369d7dSTobias Sarnowski // find declaration 481f8369d7dSTobias Sarnowski preg_match('@<'.'?xml[^>]+encoding\\s*=\\s*(["|\'])(.*?)\\1@i', 482f8369d7dSTobias Sarnowski $markup, $matches 483f8369d7dSTobias Sarnowski ); 484f8369d7dSTobias Sarnowski return isset($matches[2]) 485f8369d7dSTobias Sarnowski ? strtolower($matches[2]) 486f8369d7dSTobias Sarnowski : null; 487f8369d7dSTobias Sarnowski } 488f8369d7dSTobias Sarnowski /** 489f8369d7dSTobias Sarnowski * Repositions meta[type=charset] at the start of head. Bypasses DOMDocument bug. 490f8369d7dSTobias Sarnowski * 491f8369d7dSTobias Sarnowski * @link http://code.google.com/p/phpquery/issues/detail?id=80 492f8369d7dSTobias Sarnowski * @param $html 493f8369d7dSTobias Sarnowski */ 494f8369d7dSTobias Sarnowski protected function charsetFixHTML($markup) { 495f8369d7dSTobias Sarnowski $matches = array(); 496f8369d7dSTobias Sarnowski // find meta tag 497f8369d7dSTobias Sarnowski preg_match('@\s*<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i', 498f8369d7dSTobias Sarnowski $markup, $matches, PREG_OFFSET_CAPTURE 499f8369d7dSTobias Sarnowski ); 500f8369d7dSTobias Sarnowski if (! isset($matches[0])) 501f8369d7dSTobias Sarnowski return; 502f8369d7dSTobias Sarnowski $metaContentType = $matches[0][0]; 503f8369d7dSTobias Sarnowski $markup = substr($markup, 0, $matches[0][1]) 504f8369d7dSTobias Sarnowski .substr($markup, $matches[0][1]+strlen($metaContentType)); 505f8369d7dSTobias Sarnowski $headStart = stripos($markup, '<head>'); 506f8369d7dSTobias Sarnowski $markup = substr($markup, 0, $headStart+6).$metaContentType 507f8369d7dSTobias Sarnowski .substr($markup, $headStart+6); 508f8369d7dSTobias Sarnowski return $markup; 509f8369d7dSTobias Sarnowski } 510f8369d7dSTobias Sarnowski protected function charsetAppendToHTML($html, $charset, $xhtml = false) { 511f8369d7dSTobias Sarnowski // remove existing meta[type=content-type] 512f8369d7dSTobias Sarnowski $html = preg_replace('@\s*<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i', '', $html); 513f8369d7dSTobias Sarnowski $meta = '<meta http-equiv="Content-Type" content="text/html;charset=' 514f8369d7dSTobias Sarnowski .$charset.'" ' 515f8369d7dSTobias Sarnowski .($xhtml ? '/' : '') 516f8369d7dSTobias Sarnowski .'>'; 517f8369d7dSTobias Sarnowski if (strpos($html, '<head') === false) { 518f8369d7dSTobias Sarnowski if (strpos($hltml, '<html') === false) { 519f8369d7dSTobias Sarnowski return $meta.$html; 520f8369d7dSTobias Sarnowski } else { 521f8369d7dSTobias Sarnowski return preg_replace( 522f8369d7dSTobias Sarnowski '@<html(.*?)(?(?<!\?)>)@s', 523f8369d7dSTobias Sarnowski "<html\\1><head>{$meta}</head>", 524f8369d7dSTobias Sarnowski $html 525f8369d7dSTobias Sarnowski ); 526f8369d7dSTobias Sarnowski } 527f8369d7dSTobias Sarnowski } else { 528f8369d7dSTobias Sarnowski return preg_replace( 529f8369d7dSTobias Sarnowski '@<head(.*?)(?(?<!\?)>)@s', 530f8369d7dSTobias Sarnowski '<head\\1>'.$meta, 531f8369d7dSTobias Sarnowski $html 532f8369d7dSTobias Sarnowski ); 533f8369d7dSTobias Sarnowski } 534f8369d7dSTobias Sarnowski } 535f8369d7dSTobias Sarnowski protected function charsetAppendToXML($markup, $charset) { 536f8369d7dSTobias Sarnowski $declaration = '<'.'?xml version="1.0" encoding="'.$charset.'"?'.'>'; 537f8369d7dSTobias Sarnowski return $declaration.$markup; 538f8369d7dSTobias Sarnowski } 539f8369d7dSTobias Sarnowski public static function isDocumentFragmentHTML($markup) { 540f8369d7dSTobias Sarnowski return stripos($markup, '<html') === false && stripos($markup, '<!doctype') === false; 541f8369d7dSTobias Sarnowski } 542f8369d7dSTobias Sarnowski public static function isDocumentFragmentXML($markup) { 543f8369d7dSTobias Sarnowski return stripos($markup, '<'.'?xml') === false; 544f8369d7dSTobias Sarnowski } 545f8369d7dSTobias Sarnowski public static function isDocumentFragmentXHTML($markup) { 546f8369d7dSTobias Sarnowski return self::isDocumentFragmentHTML($markup); 547f8369d7dSTobias Sarnowski } 548f8369d7dSTobias Sarnowski public function importAttr($value) { 549f8369d7dSTobias Sarnowski // TODO 550f8369d7dSTobias Sarnowski } 551f8369d7dSTobias Sarnowski /** 552f8369d7dSTobias Sarnowski * 553f8369d7dSTobias Sarnowski * @param $source 554f8369d7dSTobias Sarnowski * @param $target 555f8369d7dSTobias Sarnowski * @param $sourceCharset 556f8369d7dSTobias Sarnowski * @return array Array of imported nodes. 557f8369d7dSTobias Sarnowski */ 558f8369d7dSTobias Sarnowski public function import($source, $sourceCharset = null) { 559f8369d7dSTobias Sarnowski // TODO charset conversions 560f8369d7dSTobias Sarnowski $return = array(); 561f8369d7dSTobias Sarnowski if ($source instanceof DOMNODE && !($source instanceof DOMNODELIST)) 562f8369d7dSTobias Sarnowski $source = array($source); 563f8369d7dSTobias Sarnowski// if (is_array($source)) { 564f8369d7dSTobias Sarnowski// foreach($source as $node) { 565f8369d7dSTobias Sarnowski// if (is_string($node)) { 566f8369d7dSTobias Sarnowski// // string markup 567f8369d7dSTobias Sarnowski// $fake = $this->documentFragmentCreate($node, $sourceCharset); 568f8369d7dSTobias Sarnowski// if ($fake === false) 569f8369d7dSTobias Sarnowski// throw new Exception("Error loading documentFragment markup"); 570f8369d7dSTobias Sarnowski// else 571f8369d7dSTobias Sarnowski// $return = array_merge($return, 572f8369d7dSTobias Sarnowski// $this->import($fake->root->childNodes) 573f8369d7dSTobias Sarnowski// ); 574f8369d7dSTobias Sarnowski// } else { 575f8369d7dSTobias Sarnowski// $return[] = $this->document->importNode($node, true); 576f8369d7dSTobias Sarnowski// } 577f8369d7dSTobias Sarnowski// } 578f8369d7dSTobias Sarnowski// return $return; 579f8369d7dSTobias Sarnowski// } else { 580f8369d7dSTobias Sarnowski// // string markup 581f8369d7dSTobias Sarnowski// $fake = $this->documentFragmentCreate($source, $sourceCharset); 582f8369d7dSTobias Sarnowski// if ($fake === false) 583f8369d7dSTobias Sarnowski// throw new Exception("Error loading documentFragment markup"); 584f8369d7dSTobias Sarnowski// else 585f8369d7dSTobias Sarnowski// return $this->import($fake->root->childNodes); 586f8369d7dSTobias Sarnowski// } 587f8369d7dSTobias Sarnowski if (is_array($source) || $source instanceof DOMNODELIST) { 588f8369d7dSTobias Sarnowski // dom nodes 589f8369d7dSTobias Sarnowski self::debug('Importing nodes to document'); 590f8369d7dSTobias Sarnowski foreach($source as $node) 591f8369d7dSTobias Sarnowski $return[] = $this->document->importNode($node, true); 592f8369d7dSTobias Sarnowski } else { 593f8369d7dSTobias Sarnowski // string markup 594f8369d7dSTobias Sarnowski $fake = $this->documentFragmentCreate($source, $sourceCharset); 595f8369d7dSTobias Sarnowski if ($fake === false) 596f8369d7dSTobias Sarnowski throw new Exception("Error loading documentFragment markup"); 597f8369d7dSTobias Sarnowski else 598f8369d7dSTobias Sarnowski return $this->import($fake->root->childNodes); 599f8369d7dSTobias Sarnowski } 600f8369d7dSTobias Sarnowski return $return; 601f8369d7dSTobias Sarnowski } 602f8369d7dSTobias Sarnowski /** 603f8369d7dSTobias Sarnowski * Creates new document fragment. 604f8369d7dSTobias Sarnowski * 605f8369d7dSTobias Sarnowski * @param $source 606f8369d7dSTobias Sarnowski * @return DOMDocumentWrapper 607f8369d7dSTobias Sarnowski */ 608f8369d7dSTobias Sarnowski protected function documentFragmentCreate($source, $charset = null) { 609f8369d7dSTobias Sarnowski $fake = new DOMDocumentWrapper(); 610f8369d7dSTobias Sarnowski $fake->contentType = $this->contentType; 611f8369d7dSTobias Sarnowski $fake->isXML = $this->isXML; 612f8369d7dSTobias Sarnowski $fake->isHTML = $this->isHTML; 613f8369d7dSTobias Sarnowski $fake->isXHTML = $this->isXHTML; 614f8369d7dSTobias Sarnowski $fake->root = $fake->document; 615f8369d7dSTobias Sarnowski if (! $charset) 616f8369d7dSTobias Sarnowski $charset = $this->charset; 617f8369d7dSTobias Sarnowski// $fake->documentCreate($this->charset); 618f8369d7dSTobias Sarnowski if ($source instanceof DOMNODE && !($source instanceof DOMNODELIST)) 619f8369d7dSTobias Sarnowski $source = array($source); 620f8369d7dSTobias Sarnowski if (is_array($source) || $source instanceof DOMNODELIST) { 621f8369d7dSTobias Sarnowski // dom nodes 622f8369d7dSTobias Sarnowski // load fake document 623f8369d7dSTobias Sarnowski if (! $this->documentFragmentLoadMarkup($fake, $charset)) 624f8369d7dSTobias Sarnowski return false; 625f8369d7dSTobias Sarnowski $nodes = $fake->import($source); 626f8369d7dSTobias Sarnowski foreach($nodes as $node) 627f8369d7dSTobias Sarnowski $fake->root->appendChild($node); 628f8369d7dSTobias Sarnowski } else { 629f8369d7dSTobias Sarnowski // string markup 630f8369d7dSTobias Sarnowski $this->documentFragmentLoadMarkup($fake, $charset, $source); 631f8369d7dSTobias Sarnowski } 632f8369d7dSTobias Sarnowski return $fake; 633f8369d7dSTobias Sarnowski } 634f8369d7dSTobias Sarnowski /** 635f8369d7dSTobias Sarnowski * 636f8369d7dSTobias Sarnowski * @param $document DOMDocumentWrapper 637f8369d7dSTobias Sarnowski * @param $markup 638f8369d7dSTobias Sarnowski * @return $document 639f8369d7dSTobias Sarnowski */ 640f8369d7dSTobias Sarnowski private function documentFragmentLoadMarkup($fragment, $charset, $markup = null) { 641f8369d7dSTobias Sarnowski // TODO error handling 642f8369d7dSTobias Sarnowski // TODO copy doctype 643f8369d7dSTobias Sarnowski // tempolary turn off 644f8369d7dSTobias Sarnowski $fragment->isDocumentFragment = false; 645f8369d7dSTobias Sarnowski if ($fragment->isXML) { 646f8369d7dSTobias Sarnowski if ($fragment->isXHTML) { 647f8369d7dSTobias Sarnowski // add FAKE element to set default namespace 648f8369d7dSTobias Sarnowski $fragment->loadMarkupXML('<?xml version="1.0" encoding="'.$charset.'"?>' 649f8369d7dSTobias Sarnowski .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ' 650f8369d7dSTobias Sarnowski .'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' 651f8369d7dSTobias Sarnowski .'<fake xmlns="http://www.w3.org/1999/xhtml">'.$markup.'</fake>'); 652f8369d7dSTobias Sarnowski $fragment->root = $fragment->document->firstChild->nextSibling; 653f8369d7dSTobias Sarnowski } else { 654f8369d7dSTobias Sarnowski $fragment->loadMarkupXML('<?xml version="1.0" encoding="'.$charset.'"?><fake>'.$markup.'</fake>'); 655f8369d7dSTobias Sarnowski $fragment->root = $fragment->document->firstChild; 656f8369d7dSTobias Sarnowski } 657f8369d7dSTobias Sarnowski } else { 658f8369d7dSTobias Sarnowski $markup2 = phpQuery::$defaultDoctype.'<html><head><meta http-equiv="Content-Type" content="text/html;charset=' 659f8369d7dSTobias Sarnowski .$charset.'"></head>'; 660f8369d7dSTobias Sarnowski $noBody = strpos($markup, '<body') === false; 661f8369d7dSTobias Sarnowski if ($noBody) 662f8369d7dSTobias Sarnowski $markup2 .= '<body>'; 663f8369d7dSTobias Sarnowski $markup2 .= $markup; 664f8369d7dSTobias Sarnowski if ($noBody) 665f8369d7dSTobias Sarnowski $markup2 .= '</body>'; 666f8369d7dSTobias Sarnowski $markup2 .= '</html>'; 667f8369d7dSTobias Sarnowski $fragment->loadMarkupHTML($markup2); 668f8369d7dSTobias Sarnowski // TODO resolv body tag merging issue 669f8369d7dSTobias Sarnowski $fragment->root = $noBody 670f8369d7dSTobias Sarnowski ? $fragment->document->firstChild->nextSibling->firstChild->nextSibling 671f8369d7dSTobias Sarnowski : $fragment->document->firstChild->nextSibling->firstChild->nextSibling; 672f8369d7dSTobias Sarnowski } 673f8369d7dSTobias Sarnowski if (! $fragment->root) 674f8369d7dSTobias Sarnowski return false; 675f8369d7dSTobias Sarnowski $fragment->isDocumentFragment = true; 676f8369d7dSTobias Sarnowski return true; 677f8369d7dSTobias Sarnowski } 678f8369d7dSTobias Sarnowski protected function documentFragmentToMarkup($fragment) { 679f8369d7dSTobias Sarnowski phpQuery::debug('documentFragmentToMarkup'); 680f8369d7dSTobias Sarnowski $tmp = $fragment->isDocumentFragment; 681f8369d7dSTobias Sarnowski $fragment->isDocumentFragment = false; 682f8369d7dSTobias Sarnowski $markup = $fragment->markup(); 683f8369d7dSTobias Sarnowski if ($fragment->isXML) { 684f8369d7dSTobias Sarnowski $markup = substr($markup, 0, strrpos($markup, '</fake>')); 685f8369d7dSTobias Sarnowski if ($fragment->isXHTML) { 686f8369d7dSTobias Sarnowski $markup = substr($markup, strpos($markup, '<fake')+43); 687f8369d7dSTobias Sarnowski } else { 688f8369d7dSTobias Sarnowski $markup = substr($markup, strpos($markup, '<fake>')+6); 689f8369d7dSTobias Sarnowski } 690f8369d7dSTobias Sarnowski } else { 691f8369d7dSTobias Sarnowski $markup = substr($markup, strpos($markup, '<body>')+6); 692f8369d7dSTobias Sarnowski $markup = substr($markup, 0, strrpos($markup, '</body>')); 693f8369d7dSTobias Sarnowski } 694f8369d7dSTobias Sarnowski $fragment->isDocumentFragment = $tmp; 695f8369d7dSTobias Sarnowski if (phpQuery::$debug) 696f8369d7dSTobias Sarnowski phpQuery::debug('documentFragmentToMarkup: '.substr($markup, 0, 150)); 697f8369d7dSTobias Sarnowski return $markup; 698f8369d7dSTobias Sarnowski } 699f8369d7dSTobias Sarnowski /** 700f8369d7dSTobias Sarnowski * Return document markup, starting with optional $nodes as root. 701f8369d7dSTobias Sarnowski * 702f8369d7dSTobias Sarnowski * @param $nodes DOMNode|DOMNodeList 703f8369d7dSTobias Sarnowski * @return string 704f8369d7dSTobias Sarnowski */ 705f8369d7dSTobias Sarnowski public function markup($nodes = null, $innerMarkup = false) { 706f8369d7dSTobias Sarnowski if (isset($nodes) && count($nodes) == 1 && $nodes[0] instanceof DOMDOCUMENT) 707f8369d7dSTobias Sarnowski $nodes = null; 708f8369d7dSTobias Sarnowski if (isset($nodes)) { 709f8369d7dSTobias Sarnowski $markup = ''; 710f8369d7dSTobias Sarnowski if (!is_array($nodes) && !($nodes instanceof DOMNODELIST) ) 711f8369d7dSTobias Sarnowski $nodes = array($nodes); 712f8369d7dSTobias Sarnowski if ($this->isDocumentFragment && ! $innerMarkup) 713f8369d7dSTobias Sarnowski foreach($nodes as $i => $node) 714f8369d7dSTobias Sarnowski if ($node->isSameNode($this->root)) { 715f8369d7dSTobias Sarnowski // var_dump($node); 716f8369d7dSTobias Sarnowski $nodes = array_slice($nodes, 0, $i) 717f8369d7dSTobias Sarnowski + phpQuery::DOMNodeListToArray($node->childNodes) 718f8369d7dSTobias Sarnowski + array_slice($nodes, $i+1); 719f8369d7dSTobias Sarnowski } 720f8369d7dSTobias Sarnowski if ($this->isXML && ! $innerMarkup) { 721f8369d7dSTobias Sarnowski self::debug("Getting outerXML with charset '{$this->charset}'"); 722f8369d7dSTobias Sarnowski // we need outerXML, so we can benefit from 723f8369d7dSTobias Sarnowski // $node param support in saveXML() 724f8369d7dSTobias Sarnowski foreach($nodes as $node) 725f8369d7dSTobias Sarnowski $markup .= $this->document->saveXML($node); 726f8369d7dSTobias Sarnowski } else { 727f8369d7dSTobias Sarnowski $loop = array(); 728f8369d7dSTobias Sarnowski if ($innerMarkup) 729f8369d7dSTobias Sarnowski foreach($nodes as $node) { 730f8369d7dSTobias Sarnowski if ($node->childNodes) 731f8369d7dSTobias Sarnowski foreach($node->childNodes as $child) 732f8369d7dSTobias Sarnowski $loop[] = $child; 733f8369d7dSTobias Sarnowski else 734f8369d7dSTobias Sarnowski $loop[] = $node; 735f8369d7dSTobias Sarnowski } 736f8369d7dSTobias Sarnowski else 737f8369d7dSTobias Sarnowski $loop = $nodes; 738f8369d7dSTobias Sarnowski self::debug("Getting markup, moving selected nodes (".count($loop).") to new DocumentFragment"); 739f8369d7dSTobias Sarnowski $fake = $this->documentFragmentCreate($loop); 740f8369d7dSTobias Sarnowski $markup = $this->documentFragmentToMarkup($fake); 741f8369d7dSTobias Sarnowski } 742f8369d7dSTobias Sarnowski if ($this->isXHTML) { 743f8369d7dSTobias Sarnowski self::debug("Fixing XHTML"); 744f8369d7dSTobias Sarnowski $markup = self::markupFixXHTML($markup); 745f8369d7dSTobias Sarnowski } 746f8369d7dSTobias Sarnowski self::debug("Markup: ".substr($markup, 0, 250)); 747f8369d7dSTobias Sarnowski return $markup; 748f8369d7dSTobias Sarnowski } else { 749f8369d7dSTobias Sarnowski if ($this->isDocumentFragment) { 750f8369d7dSTobias Sarnowski // documentFragment, html only... 751f8369d7dSTobias Sarnowski self::debug("Getting markup, DocumentFragment detected"); 752f8369d7dSTobias Sarnowski// return $this->markup( 753f8369d7dSTobias Sarnowski//// $this->document->getElementsByTagName('body')->item(0) 754f8369d7dSTobias Sarnowski// $this->document->root, true 755f8369d7dSTobias Sarnowski// ); 756f8369d7dSTobias Sarnowski $markup = $this->documentFragmentToMarkup($this); 757f8369d7dSTobias Sarnowski // no need for markupFixXHTML, as it's done thought markup($nodes) method 758f8369d7dSTobias Sarnowski return $markup; 759f8369d7dSTobias Sarnowski } else { 760f8369d7dSTobias Sarnowski self::debug("Getting markup (".($this->isXML?'XML':'HTML')."), final with charset '{$this->charset}'"); 761f8369d7dSTobias Sarnowski $markup = $this->isXML 762f8369d7dSTobias Sarnowski ? $this->document->saveXML() 763f8369d7dSTobias Sarnowski : $this->document->saveHTML(); 764f8369d7dSTobias Sarnowski if ($this->isXHTML) { 765f8369d7dSTobias Sarnowski self::debug("Fixing XHTML"); 766f8369d7dSTobias Sarnowski $markup = self::markupFixXHTML($markup); 767f8369d7dSTobias Sarnowski } 768f8369d7dSTobias Sarnowski self::debug("Markup: ".substr($markup, 0, 250)); 769f8369d7dSTobias Sarnowski return $markup; 770f8369d7dSTobias Sarnowski } 771f8369d7dSTobias Sarnowski } 772f8369d7dSTobias Sarnowski } 773f8369d7dSTobias Sarnowski protected static function markupFixXHTML($markup) { 774f8369d7dSTobias Sarnowski $markup = self::expandEmptyTag('script', $markup); 775f8369d7dSTobias Sarnowski $markup = self::expandEmptyTag('select', $markup); 776f8369d7dSTobias Sarnowski $markup = self::expandEmptyTag('textarea', $markup); 777f8369d7dSTobias Sarnowski return $markup; 778f8369d7dSTobias Sarnowski } 779f8369d7dSTobias Sarnowski public static function debug($text) { 780f8369d7dSTobias Sarnowski phpQuery::debug($text); 781f8369d7dSTobias Sarnowski } 782f8369d7dSTobias Sarnowski /** 783f8369d7dSTobias Sarnowski * expandEmptyTag 784f8369d7dSTobias Sarnowski * 785f8369d7dSTobias Sarnowski * @param $tag 786f8369d7dSTobias Sarnowski * @param $xml 787f8369d7dSTobias Sarnowski * @return unknown_type 788f8369d7dSTobias Sarnowski * @author mjaque at ilkebenson dot com 789f8369d7dSTobias Sarnowski * @link http://php.net/manual/en/domdocument.savehtml.php#81256 790f8369d7dSTobias Sarnowski */ 791f8369d7dSTobias Sarnowski public static function expandEmptyTag($tag, $xml){ 792f8369d7dSTobias Sarnowski $indice = 0; 793f8369d7dSTobias Sarnowski while ($indice< strlen($xml)){ 794f8369d7dSTobias Sarnowski $pos = strpos($xml, "<$tag ", $indice); 795f8369d7dSTobias Sarnowski if ($pos){ 796f8369d7dSTobias Sarnowski $posCierre = strpos($xml, ">", $pos); 797f8369d7dSTobias Sarnowski if ($xml[$posCierre-1] == "/"){ 798f8369d7dSTobias Sarnowski $xml = substr_replace($xml, "></$tag>", $posCierre-1, 2); 799f8369d7dSTobias Sarnowski } 800f8369d7dSTobias Sarnowski $indice = $posCierre; 801f8369d7dSTobias Sarnowski } 802f8369d7dSTobias Sarnowski else break; 803f8369d7dSTobias Sarnowski } 804f8369d7dSTobias Sarnowski return $xml; 805f8369d7dSTobias Sarnowski } 806f8369d7dSTobias Sarnowski} 807f8369d7dSTobias Sarnowski 808f8369d7dSTobias Sarnowski/** 809f8369d7dSTobias Sarnowski * Event handling class. 810f8369d7dSTobias Sarnowski * 811f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik 812f8369d7dSTobias Sarnowski * @package phpQuery 813f8369d7dSTobias Sarnowski * @static 814f8369d7dSTobias Sarnowski */ 815f8369d7dSTobias Sarnowskiabstract class phpQueryEvents { 816f8369d7dSTobias Sarnowski /** 817f8369d7dSTobias Sarnowski * Trigger a type of event on every matched element. 818f8369d7dSTobias Sarnowski * 819f8369d7dSTobias Sarnowski * @param DOMNode|phpQueryObject|string $document 820f8369d7dSTobias Sarnowski * @param unknown_type $type 821f8369d7dSTobias Sarnowski * @param unknown_type $data 822f8369d7dSTobias Sarnowski * 823f8369d7dSTobias Sarnowski * @TODO exclusive events (with !) 824f8369d7dSTobias Sarnowski * @TODO global events (test) 825f8369d7dSTobias Sarnowski * @TODO support more than event in $type (space-separated) 826f8369d7dSTobias Sarnowski */ 827f8369d7dSTobias Sarnowski public static function trigger($document, $type, $data = array(), $node = null) { 828f8369d7dSTobias Sarnowski // trigger: function(type, data, elem, donative, extra) { 829f8369d7dSTobias Sarnowski $documentID = phpQuery::getDocumentID($document); 830f8369d7dSTobias Sarnowski $namespace = null; 831f8369d7dSTobias Sarnowski if (strpos($type, '.') !== false) 832f8369d7dSTobias Sarnowski list($name, $namespace) = explode('.', $type); 833f8369d7dSTobias Sarnowski else 834f8369d7dSTobias Sarnowski $name = $type; 835f8369d7dSTobias Sarnowski if (! $node) { 836f8369d7dSTobias Sarnowski if (self::issetGlobal($documentID, $type)) { 837f8369d7dSTobias Sarnowski $pq = phpQuery::getDocument($documentID); 838f8369d7dSTobias Sarnowski // TODO check add($pq->document) 839f8369d7dSTobias Sarnowski $pq->find('*')->add($pq->document) 840f8369d7dSTobias Sarnowski ->trigger($type, $data); 841f8369d7dSTobias Sarnowski } 842f8369d7dSTobias Sarnowski } else { 843f8369d7dSTobias Sarnowski if (isset($data[0]) && $data[0] instanceof DOMEvent) { 844f8369d7dSTobias Sarnowski $event = $data[0]; 845f8369d7dSTobias Sarnowski $event->relatedTarget = $event->target; 846f8369d7dSTobias Sarnowski $event->target = $node; 847f8369d7dSTobias Sarnowski $data = array_slice($data, 1); 848f8369d7dSTobias Sarnowski } else { 849f8369d7dSTobias Sarnowski $event = new DOMEvent(array( 850f8369d7dSTobias Sarnowski 'type' => $type, 851f8369d7dSTobias Sarnowski 'target' => $node, 852f8369d7dSTobias Sarnowski 'timeStamp' => time(), 853f8369d7dSTobias Sarnowski )); 854f8369d7dSTobias Sarnowski } 855f8369d7dSTobias Sarnowski $i = 0; 856f8369d7dSTobias Sarnowski while($node) { 857f8369d7dSTobias Sarnowski // TODO whois 858f8369d7dSTobias Sarnowski phpQuery::debug("Triggering ".($i?"bubbled ":'')."event '{$type}' on " 859f8369d7dSTobias Sarnowski ."node \n");//.phpQueryObject::whois($node)."\n"); 860f8369d7dSTobias Sarnowski $event->currentTarget = $node; 861f8369d7dSTobias Sarnowski $eventNode = self::getNode($documentID, $node); 862f8369d7dSTobias Sarnowski if (isset($eventNode->eventHandlers)) { 863f8369d7dSTobias Sarnowski foreach($eventNode->eventHandlers as $eventType => $handlers) { 864f8369d7dSTobias Sarnowski $eventNamespace = null; 865f8369d7dSTobias Sarnowski if (strpos($type, '.') !== false) 866f8369d7dSTobias Sarnowski list($eventName, $eventNamespace) = explode('.', $eventType); 867f8369d7dSTobias Sarnowski else 868f8369d7dSTobias Sarnowski $eventName = $eventType; 869f8369d7dSTobias Sarnowski if ($name != $eventName) 870f8369d7dSTobias Sarnowski continue; 871f8369d7dSTobias Sarnowski if ($namespace && $eventNamespace && $namespace != $eventNamespace) 872f8369d7dSTobias Sarnowski continue; 873f8369d7dSTobias Sarnowski foreach($handlers as $handler) { 874f8369d7dSTobias Sarnowski phpQuery::debug("Calling event handler\n"); 875f8369d7dSTobias Sarnowski $event->data = $handler['data'] 876f8369d7dSTobias Sarnowski ? $handler['data'] 877f8369d7dSTobias Sarnowski : null; 878f8369d7dSTobias Sarnowski $params = array_merge(array($event), $data); 879f8369d7dSTobias Sarnowski $return = phpQuery::callbackRun($handler['callback'], $params); 880f8369d7dSTobias Sarnowski if ($return === false) { 881f8369d7dSTobias Sarnowski $event->bubbles = false; 882f8369d7dSTobias Sarnowski } 883f8369d7dSTobias Sarnowski } 884f8369d7dSTobias Sarnowski } 885f8369d7dSTobias Sarnowski } 886f8369d7dSTobias Sarnowski // to bubble or not to bubble... 887f8369d7dSTobias Sarnowski if (! $event->bubbles) 888f8369d7dSTobias Sarnowski break; 889f8369d7dSTobias Sarnowski $node = $node->parentNode; 890f8369d7dSTobias Sarnowski $i++; 891f8369d7dSTobias Sarnowski } 892f8369d7dSTobias Sarnowski } 893f8369d7dSTobias Sarnowski } 894f8369d7dSTobias Sarnowski /** 895f8369d7dSTobias Sarnowski * Binds a handler to one or more events (like click) for each matched element. 896f8369d7dSTobias Sarnowski * Can also bind custom events. 897f8369d7dSTobias Sarnowski * 898f8369d7dSTobias Sarnowski * @param DOMNode|phpQueryObject|string $document 899f8369d7dSTobias Sarnowski * @param unknown_type $type 900f8369d7dSTobias Sarnowski * @param unknown_type $data Optional 901f8369d7dSTobias Sarnowski * @param unknown_type $callback 902f8369d7dSTobias Sarnowski * 903f8369d7dSTobias Sarnowski * @TODO support '!' (exclusive) events 904f8369d7dSTobias Sarnowski * @TODO support more than event in $type (space-separated) 905f8369d7dSTobias Sarnowski * @TODO support binding to global events 906f8369d7dSTobias Sarnowski */ 907f8369d7dSTobias Sarnowski public static function add($document, $node, $type, $data, $callback = null) { 908f8369d7dSTobias Sarnowski phpQuery::debug("Binding '$type' event"); 909f8369d7dSTobias Sarnowski $documentID = phpQuery::getDocumentID($document); 910f8369d7dSTobias Sarnowski// if (is_null($callback) && is_callable($data)) { 911f8369d7dSTobias Sarnowski// $callback = $data; 912f8369d7dSTobias Sarnowski// $data = null; 913f8369d7dSTobias Sarnowski// } 914f8369d7dSTobias Sarnowski $eventNode = self::getNode($documentID, $node); 915f8369d7dSTobias Sarnowski if (! $eventNode) 916f8369d7dSTobias Sarnowski $eventNode = self::setNode($documentID, $node); 917f8369d7dSTobias Sarnowski if (!isset($eventNode->eventHandlers[$type])) 918f8369d7dSTobias Sarnowski $eventNode->eventHandlers[$type] = array(); 919f8369d7dSTobias Sarnowski $eventNode->eventHandlers[$type][] = array( 920f8369d7dSTobias Sarnowski 'callback' => $callback, 921f8369d7dSTobias Sarnowski 'data' => $data, 922f8369d7dSTobias Sarnowski ); 923f8369d7dSTobias Sarnowski } 924f8369d7dSTobias Sarnowski /** 925f8369d7dSTobias Sarnowski * Enter description here... 926f8369d7dSTobias Sarnowski * 927f8369d7dSTobias Sarnowski * @param DOMNode|phpQueryObject|string $document 928f8369d7dSTobias Sarnowski * @param unknown_type $type 929f8369d7dSTobias Sarnowski * @param unknown_type $callback 930f8369d7dSTobias Sarnowski * 931f8369d7dSTobias Sarnowski * @TODO namespace events 932f8369d7dSTobias Sarnowski * @TODO support more than event in $type (space-separated) 933f8369d7dSTobias Sarnowski */ 934f8369d7dSTobias Sarnowski public static function remove($document, $node, $type = null, $callback = null) { 935f8369d7dSTobias Sarnowski $documentID = phpQuery::getDocumentID($document); 936f8369d7dSTobias Sarnowski $eventNode = self::getNode($documentID, $node); 937f8369d7dSTobias Sarnowski if (is_object($eventNode) && isset($eventNode->eventHandlers[$type])) { 938f8369d7dSTobias Sarnowski if ($callback) { 939f8369d7dSTobias Sarnowski foreach($eventNode->eventHandlers[$type] as $k => $handler) 940f8369d7dSTobias Sarnowski if ($handler['callback'] == $callback) 941f8369d7dSTobias Sarnowski unset($eventNode->eventHandlers[$type][$k]); 942f8369d7dSTobias Sarnowski } else { 943f8369d7dSTobias Sarnowski unset($eventNode->eventHandlers[$type]); 944f8369d7dSTobias Sarnowski } 945f8369d7dSTobias Sarnowski } 946f8369d7dSTobias Sarnowski } 947f8369d7dSTobias Sarnowski protected static function getNode($documentID, $node) { 948f8369d7dSTobias Sarnowski foreach(phpQuery::$documents[$documentID]->eventsNodes as $eventNode) { 949f8369d7dSTobias Sarnowski if ($node->isSameNode($eventNode)) 950f8369d7dSTobias Sarnowski return $eventNode; 951f8369d7dSTobias Sarnowski } 952f8369d7dSTobias Sarnowski } 953f8369d7dSTobias Sarnowski protected static function setNode($documentID, $node) { 954f8369d7dSTobias Sarnowski phpQuery::$documents[$documentID]->eventsNodes[] = $node; 955f8369d7dSTobias Sarnowski return phpQuery::$documents[$documentID]->eventsNodes[ 956f8369d7dSTobias Sarnowski count(phpQuery::$documents[$documentID]->eventsNodes)-1 957f8369d7dSTobias Sarnowski ]; 958f8369d7dSTobias Sarnowski } 959f8369d7dSTobias Sarnowski protected static function issetGlobal($documentID, $type) { 960f8369d7dSTobias Sarnowski return isset(phpQuery::$documents[$documentID]) 961f8369d7dSTobias Sarnowski ? in_array($type, phpQuery::$documents[$documentID]->eventsGlobal) 962f8369d7dSTobias Sarnowski : false; 963f8369d7dSTobias Sarnowski } 964f8369d7dSTobias Sarnowski} 965f8369d7dSTobias Sarnowski 966f8369d7dSTobias Sarnowski 967f8369d7dSTobias Sarnowskiinterface ICallbackNamed { 968f8369d7dSTobias Sarnowski function hasName(); 969f8369d7dSTobias Sarnowski function getName(); 970f8369d7dSTobias Sarnowski} 971f8369d7dSTobias Sarnowski/** 972f8369d7dSTobias Sarnowski * Callback class introduces currying-like pattern. 973f8369d7dSTobias Sarnowski * 974f8369d7dSTobias Sarnowski * Example: 975f8369d7dSTobias Sarnowski * function foo($param1, $param2, $param3) { 976f8369d7dSTobias Sarnowski * var_dump($param1, $param2, $param3); 977f8369d7dSTobias Sarnowski * } 978f8369d7dSTobias Sarnowski * $fooCurried = new Callback('foo', 979f8369d7dSTobias Sarnowski * 'param1 is now statically set', 980f8369d7dSTobias Sarnowski * new CallbackParam, new CallbackParam 981f8369d7dSTobias Sarnowski * ); 982f8369d7dSTobias Sarnowski * phpQuery::callbackRun($fooCurried, 983f8369d7dSTobias Sarnowski * array('param2 value', 'param3 value' 984f8369d7dSTobias Sarnowski * ); 985f8369d7dSTobias Sarnowski * 986f8369d7dSTobias Sarnowski * Callback class is supported in all phpQuery methods which accepts callbacks. 987f8369d7dSTobias Sarnowski * 988f8369d7dSTobias Sarnowski * @link http://code.google.com/p/phpquery/wiki/Callbacks#Param_Structures 989f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 990f8369d7dSTobias Sarnowski * 991f8369d7dSTobias Sarnowski * @TODO??? return fake forwarding function created via create_function 992f8369d7dSTobias Sarnowski * @TODO honor paramStructure 993f8369d7dSTobias Sarnowski */ 994f8369d7dSTobias Sarnowskiclass Callback 995f8369d7dSTobias Sarnowski implements ICallbackNamed { 996f8369d7dSTobias Sarnowski public $callback = null; 997f8369d7dSTobias Sarnowski public $params = null; 998f8369d7dSTobias Sarnowski protected $name; 999f8369d7dSTobias Sarnowski public function __construct($callback, $param1 = null, $param2 = null, 1000f8369d7dSTobias Sarnowski $param3 = null) { 1001f8369d7dSTobias Sarnowski $params = func_get_args(); 1002f8369d7dSTobias Sarnowski $params = array_slice($params, 1); 1003f8369d7dSTobias Sarnowski if ($callback instanceof Callback) { 1004f8369d7dSTobias Sarnowski // TODO implement recurention 1005f8369d7dSTobias Sarnowski } else { 1006f8369d7dSTobias Sarnowski $this->callback = $callback; 1007f8369d7dSTobias Sarnowski $this->params = $params; 1008f8369d7dSTobias Sarnowski } 1009f8369d7dSTobias Sarnowski } 1010f8369d7dSTobias Sarnowski public function getName() { 1011f8369d7dSTobias Sarnowski return 'Callback: '.$this->name; 1012f8369d7dSTobias Sarnowski } 1013f8369d7dSTobias Sarnowski public function hasName() { 1014f8369d7dSTobias Sarnowski return isset($this->name) && $this->name; 1015f8369d7dSTobias Sarnowski } 1016f8369d7dSTobias Sarnowski public function setName($name) { 1017f8369d7dSTobias Sarnowski $this->name = $name; 1018f8369d7dSTobias Sarnowski return $this; 1019f8369d7dSTobias Sarnowski } 1020f8369d7dSTobias Sarnowski // TODO test me 1021f8369d7dSTobias Sarnowski// public function addParams() { 1022f8369d7dSTobias Sarnowski// $params = func_get_args(); 1023f8369d7dSTobias Sarnowski// return new Callback($this->callback, $this->params+$params); 1024f8369d7dSTobias Sarnowski// } 1025f8369d7dSTobias Sarnowski} 1026a3095052SOscar Merida 1027f8369d7dSTobias Sarnowski/** 1028f8369d7dSTobias Sarnowski * Callback type which on execution returns reference passed during creation. 1029f8369d7dSTobias Sarnowski * 1030f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 1031f8369d7dSTobias Sarnowski */ 1032f8369d7dSTobias Sarnowskiclass CallbackReturnReference extends Callback 1033f8369d7dSTobias Sarnowski implements ICallbackNamed { 1034f8369d7dSTobias Sarnowski protected $reference; 1035f8369d7dSTobias Sarnowski public function __construct(&$reference, $name = null){ 1036f8369d7dSTobias Sarnowski $this->reference =& $reference; 1037f8369d7dSTobias Sarnowski $this->callback = array($this, 'callback'); 1038f8369d7dSTobias Sarnowski } 1039f8369d7dSTobias Sarnowski public function callback() { 1040f8369d7dSTobias Sarnowski return $this->reference; 1041f8369d7dSTobias Sarnowski } 1042f8369d7dSTobias Sarnowski public function getName() { 1043f8369d7dSTobias Sarnowski return 'Callback: '.$this->name; 1044f8369d7dSTobias Sarnowski } 1045f8369d7dSTobias Sarnowski public function hasName() { 1046f8369d7dSTobias Sarnowski return isset($this->name) && $this->name; 1047f8369d7dSTobias Sarnowski } 1048f8369d7dSTobias Sarnowski} 1049f8369d7dSTobias Sarnowski/** 1050f8369d7dSTobias Sarnowski * Callback type which on execution returns value passed during creation. 1051f8369d7dSTobias Sarnowski * 1052f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 1053f8369d7dSTobias Sarnowski */ 1054f8369d7dSTobias Sarnowskiclass CallbackReturnValue extends Callback 1055f8369d7dSTobias Sarnowski implements ICallbackNamed { 1056f8369d7dSTobias Sarnowski protected $value; 1057f8369d7dSTobias Sarnowski protected $name; 1058f8369d7dSTobias Sarnowski public function __construct($value, $name = null){ 1059f8369d7dSTobias Sarnowski $this->value =& $value; 1060f8369d7dSTobias Sarnowski $this->name = $name; 1061f8369d7dSTobias Sarnowski $this->callback = array($this, 'callback'); 1062f8369d7dSTobias Sarnowski } 1063f8369d7dSTobias Sarnowski public function callback() { 1064f8369d7dSTobias Sarnowski return $this->value; 1065f8369d7dSTobias Sarnowski } 1066f8369d7dSTobias Sarnowski public function __toString() { 1067f8369d7dSTobias Sarnowski return $this->getName(); 1068f8369d7dSTobias Sarnowski } 1069f8369d7dSTobias Sarnowski public function getName() { 1070f8369d7dSTobias Sarnowski return 'Callback: '.$this->name; 1071f8369d7dSTobias Sarnowski } 1072f8369d7dSTobias Sarnowski public function hasName() { 1073f8369d7dSTobias Sarnowski return isset($this->name) && $this->name; 1074f8369d7dSTobias Sarnowski } 1075f8369d7dSTobias Sarnowski} 1076f8369d7dSTobias Sarnowski/** 1077f8369d7dSTobias Sarnowski * CallbackParameterToReference can be used when we don't really want a callback, 1078f8369d7dSTobias Sarnowski * only parameter passed to it. CallbackParameterToReference takes first 1079f8369d7dSTobias Sarnowski * parameter's value and passes it to reference. 1080f8369d7dSTobias Sarnowski * 1081f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 1082f8369d7dSTobias Sarnowski */ 1083f8369d7dSTobias Sarnowskiclass CallbackParameterToReference extends Callback { 1084f8369d7dSTobias Sarnowski /** 1085f8369d7dSTobias Sarnowski * @param $reference 1086f8369d7dSTobias Sarnowski * @TODO implement $paramIndex; 1087f8369d7dSTobias Sarnowski * param index choose which callback param will be passed to reference 1088f8369d7dSTobias Sarnowski */ 1089f8369d7dSTobias Sarnowski public function __construct(&$reference){ 1090f8369d7dSTobias Sarnowski $this->callback =& $reference; 1091f8369d7dSTobias Sarnowski } 1092f8369d7dSTobias Sarnowski} 1093f8369d7dSTobias Sarnowski//class CallbackReference extends Callback { 1094f8369d7dSTobias Sarnowski// /** 1095f8369d7dSTobias Sarnowski// * 1096f8369d7dSTobias Sarnowski// * @param $reference 1097f8369d7dSTobias Sarnowski// * @param $paramIndex 1098f8369d7dSTobias Sarnowski// * @todo implement $paramIndex; param index choose which callback param will be passed to reference 1099f8369d7dSTobias Sarnowski// */ 1100f8369d7dSTobias Sarnowski// public function __construct(&$reference, $name = null){ 1101f8369d7dSTobias Sarnowski// $this->callback =& $reference; 1102f8369d7dSTobias Sarnowski// } 1103f8369d7dSTobias Sarnowski//} 1104f8369d7dSTobias Sarnowskiclass CallbackParam {} 1105f8369d7dSTobias Sarnowski 1106f8369d7dSTobias Sarnowski/** 1107f8369d7dSTobias Sarnowski * Class representing phpQuery objects. 1108f8369d7dSTobias Sarnowski * 1109f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 1110f8369d7dSTobias Sarnowski * @package phpQuery 1111f8369d7dSTobias Sarnowski * @method phpQueryObject clone() clone() 1112f8369d7dSTobias Sarnowski * @method phpQueryObject empty() empty() 1113f8369d7dSTobias Sarnowski * @method phpQueryObject next() next($selector = null) 1114f8369d7dSTobias Sarnowski * @method phpQueryObject prev() prev($selector = null) 1115f8369d7dSTobias Sarnowski * @property Int $length 1116f8369d7dSTobias Sarnowski */ 1117f8369d7dSTobias Sarnowskiclass phpQueryObject 1118f8369d7dSTobias Sarnowski implements Iterator, Countable, ArrayAccess { 1119f8369d7dSTobias Sarnowski public $documentID = null; 1120f8369d7dSTobias Sarnowski /** 1121f8369d7dSTobias Sarnowski * DOMDocument class. 1122f8369d7dSTobias Sarnowski * 1123f8369d7dSTobias Sarnowski * @var DOMDocument 1124f8369d7dSTobias Sarnowski */ 1125f8369d7dSTobias Sarnowski public $document = null; 1126f8369d7dSTobias Sarnowski public $charset = null; 1127f8369d7dSTobias Sarnowski /** 1128f8369d7dSTobias Sarnowski * 1129f8369d7dSTobias Sarnowski * @var DOMDocumentWrapper 1130f8369d7dSTobias Sarnowski */ 1131f8369d7dSTobias Sarnowski public $documentWrapper = null; 1132f8369d7dSTobias Sarnowski /** 1133f8369d7dSTobias Sarnowski * XPath interface. 1134f8369d7dSTobias Sarnowski * 1135f8369d7dSTobias Sarnowski * @var DOMXPath 1136f8369d7dSTobias Sarnowski */ 1137f8369d7dSTobias Sarnowski public $xpath = null; 1138f8369d7dSTobias Sarnowski /** 1139f8369d7dSTobias Sarnowski * Stack of selected elements. 1140f8369d7dSTobias Sarnowski * @TODO refactor to ->nodes 1141f8369d7dSTobias Sarnowski * @var array 1142f8369d7dSTobias Sarnowski */ 1143f8369d7dSTobias Sarnowski public $elements = array(); 1144f8369d7dSTobias Sarnowski /** 1145f8369d7dSTobias Sarnowski * @access private 1146f8369d7dSTobias Sarnowski */ 1147f8369d7dSTobias Sarnowski protected $elementsBackup = array(); 1148f8369d7dSTobias Sarnowski /** 1149f8369d7dSTobias Sarnowski * @access private 1150f8369d7dSTobias Sarnowski */ 1151f8369d7dSTobias Sarnowski protected $previous = null; 1152f8369d7dSTobias Sarnowski /** 1153f8369d7dSTobias Sarnowski * @access private 1154f8369d7dSTobias Sarnowski * @TODO deprecate 1155f8369d7dSTobias Sarnowski */ 1156f8369d7dSTobias Sarnowski protected $root = array(); 1157f8369d7dSTobias Sarnowski /** 1158f8369d7dSTobias Sarnowski * Indicated if doument is just a fragment (no <html> tag). 1159f8369d7dSTobias Sarnowski * 1160f8369d7dSTobias Sarnowski * Every document is realy a full document, so even documentFragments can 1161f8369d7dSTobias Sarnowski * be queried against <html>, but getDocument(id)->htmlOuter() will return 1162f8369d7dSTobias Sarnowski * only contents of <body>. 1163f8369d7dSTobias Sarnowski * 1164f8369d7dSTobias Sarnowski * @var bool 1165f8369d7dSTobias Sarnowski */ 1166f8369d7dSTobias Sarnowski public $documentFragment = true; 1167f8369d7dSTobias Sarnowski /** 1168f8369d7dSTobias Sarnowski * Iterator interface helper 1169f8369d7dSTobias Sarnowski * @access private 1170f8369d7dSTobias Sarnowski */ 1171f8369d7dSTobias Sarnowski protected $elementsInterator = array(); 1172f8369d7dSTobias Sarnowski /** 1173f8369d7dSTobias Sarnowski * Iterator interface helper 1174f8369d7dSTobias Sarnowski * @access private 1175f8369d7dSTobias Sarnowski */ 1176f8369d7dSTobias Sarnowski protected $valid = false; 1177f8369d7dSTobias Sarnowski /** 1178f8369d7dSTobias Sarnowski * Iterator interface helper 1179f8369d7dSTobias Sarnowski * @access private 1180f8369d7dSTobias Sarnowski */ 1181f8369d7dSTobias Sarnowski protected $current = null; 1182f8369d7dSTobias Sarnowski /** 1183f8369d7dSTobias Sarnowski * Enter description here... 1184f8369d7dSTobias Sarnowski * 1185f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 1186f8369d7dSTobias Sarnowski */ 1187f8369d7dSTobias Sarnowski public function __construct($documentID) { 1188acdf738aSAndreas Gohr dbg_deprecated(\DOMWrap\Document::class); 1189acdf738aSAndreas Gohr 1190f8369d7dSTobias Sarnowski// if ($documentID instanceof self) 1191f8369d7dSTobias Sarnowski// var_dump($documentID->getDocumentID()); 1192f8369d7dSTobias Sarnowski $id = $documentID instanceof self 1193f8369d7dSTobias Sarnowski ? $documentID->getDocumentID() 1194f8369d7dSTobias Sarnowski : $documentID; 1195f8369d7dSTobias Sarnowski// var_dump($id); 1196f8369d7dSTobias Sarnowski if (! isset(phpQuery::$documents[$id] )) { 1197f8369d7dSTobias Sarnowski// var_dump(phpQuery::$documents); 1198f8369d7dSTobias Sarnowski throw new Exception("Document with ID '{$id}' isn't loaded. Use phpQuery::newDocument(\$html) or phpQuery::newDocumentFile(\$file) first."); 1199f8369d7dSTobias Sarnowski } 1200f8369d7dSTobias Sarnowski $this->documentID = $id; 1201f8369d7dSTobias Sarnowski $this->documentWrapper =& phpQuery::$documents[$id]; 1202f8369d7dSTobias Sarnowski $this->document =& $this->documentWrapper->document; 1203f8369d7dSTobias Sarnowski $this->xpath =& $this->documentWrapper->xpath; 1204f8369d7dSTobias Sarnowski $this->charset =& $this->documentWrapper->charset; 1205f8369d7dSTobias Sarnowski $this->documentFragment =& $this->documentWrapper->isDocumentFragment; 1206f8369d7dSTobias Sarnowski // TODO check $this->DOM->documentElement; 1207f8369d7dSTobias Sarnowski// $this->root = $this->document->documentElement; 1208f8369d7dSTobias Sarnowski $this->root =& $this->documentWrapper->root; 1209f8369d7dSTobias Sarnowski// $this->toRoot(); 1210f8369d7dSTobias Sarnowski $this->elements = array($this->root); 1211f8369d7dSTobias Sarnowski } 1212f8369d7dSTobias Sarnowski /** 1213f8369d7dSTobias Sarnowski * 1214f8369d7dSTobias Sarnowski * @access private 1215f8369d7dSTobias Sarnowski * @param $attr 1216f8369d7dSTobias Sarnowski * @return unknown_type 1217f8369d7dSTobias Sarnowski */ 1218f8369d7dSTobias Sarnowski public function __get($attr) { 1219f8369d7dSTobias Sarnowski switch($attr) { 1220f8369d7dSTobias Sarnowski // FIXME doesnt work at all ? 1221f8369d7dSTobias Sarnowski case 'length': 1222f8369d7dSTobias Sarnowski return $this->size(); 1223f8369d7dSTobias Sarnowski break; 1224f8369d7dSTobias Sarnowski default: 1225f8369d7dSTobias Sarnowski return $this->$attr; 1226f8369d7dSTobias Sarnowski } 1227f8369d7dSTobias Sarnowski } 1228f8369d7dSTobias Sarnowski /** 1229f8369d7dSTobias Sarnowski * Saves actual object to $var by reference. 1230f8369d7dSTobias Sarnowski * Useful when need to break chain. 1231f8369d7dSTobias Sarnowski * @param phpQueryObject $var 1232f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 1233f8369d7dSTobias Sarnowski */ 1234f8369d7dSTobias Sarnowski public function toReference(&$var) { 1235f8369d7dSTobias Sarnowski return $var = $this; 1236f8369d7dSTobias Sarnowski } 1237f8369d7dSTobias Sarnowski public function documentFragment($state = null) { 1238f8369d7dSTobias Sarnowski if ($state) { 1239f8369d7dSTobias Sarnowski phpQuery::$documents[$this->getDocumentID()]['documentFragment'] = $state; 1240f8369d7dSTobias Sarnowski return $this; 1241f8369d7dSTobias Sarnowski } 1242f8369d7dSTobias Sarnowski return $this->documentFragment; 1243f8369d7dSTobias Sarnowski } 1244f8369d7dSTobias Sarnowski /** 1245f8369d7dSTobias Sarnowski * @access private 1246f8369d7dSTobias Sarnowski * @TODO documentWrapper 1247f8369d7dSTobias Sarnowski */ 1248f8369d7dSTobias Sarnowski protected function isRoot( $node) { 1249f8369d7dSTobias Sarnowski// return $node instanceof DOMDOCUMENT || $node->tagName == 'html'; 1250f8369d7dSTobias Sarnowski return $node instanceof DOMDOCUMENT 1251f8369d7dSTobias Sarnowski || ($node instanceof DOMELEMENT && $node->tagName == 'html') 1252f8369d7dSTobias Sarnowski || $this->root->isSameNode($node); 1253f8369d7dSTobias Sarnowski } 1254f8369d7dSTobias Sarnowski /** 1255f8369d7dSTobias Sarnowski * @access private 1256f8369d7dSTobias Sarnowski */ 1257f8369d7dSTobias Sarnowski protected function stackIsRoot() { 1258f8369d7dSTobias Sarnowski return $this->size() == 1 && $this->isRoot($this->elements[0]); 1259f8369d7dSTobias Sarnowski } 1260f8369d7dSTobias Sarnowski /** 1261f8369d7dSTobias Sarnowski * Enter description here... 1262f8369d7dSTobias Sarnowski * NON JQUERY METHOD 1263f8369d7dSTobias Sarnowski * 1264f8369d7dSTobias Sarnowski * Watch out, it doesn't creates new instance, can be reverted with end(). 1265f8369d7dSTobias Sarnowski * 1266f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 1267f8369d7dSTobias Sarnowski */ 1268f8369d7dSTobias Sarnowski public function toRoot() { 1269f8369d7dSTobias Sarnowski $this->elements = array($this->root); 1270f8369d7dSTobias Sarnowski return $this; 1271f8369d7dSTobias Sarnowski// return $this->newInstance(array($this->root)); 1272f8369d7dSTobias Sarnowski } 1273f8369d7dSTobias Sarnowski /** 1274f8369d7dSTobias Sarnowski * Saves object's DocumentID to $var by reference. 1275f8369d7dSTobias Sarnowski * <code> 1276f8369d7dSTobias Sarnowski * $myDocumentId; 1277f8369d7dSTobias Sarnowski * phpQuery::newDocument('<div/>') 1278f8369d7dSTobias Sarnowski * ->getDocumentIDRef($myDocumentId) 1279f8369d7dSTobias Sarnowski * ->find('div')->... 1280f8369d7dSTobias Sarnowski * </code> 1281f8369d7dSTobias Sarnowski * 1282f8369d7dSTobias Sarnowski * @param unknown_type $domId 1283f8369d7dSTobias Sarnowski * @see phpQuery::newDocument 1284f8369d7dSTobias Sarnowski * @see phpQuery::newDocumentFile 1285f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 1286f8369d7dSTobias Sarnowski */ 1287f8369d7dSTobias Sarnowski public function getDocumentIDRef(&$documentID) { 1288f8369d7dSTobias Sarnowski $documentID = $this->getDocumentID(); 1289f8369d7dSTobias Sarnowski return $this; 1290f8369d7dSTobias Sarnowski } 1291f8369d7dSTobias Sarnowski /** 1292f8369d7dSTobias Sarnowski * Returns object with stack set to document root. 1293f8369d7dSTobias Sarnowski * 1294f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 1295f8369d7dSTobias Sarnowski */ 1296f8369d7dSTobias Sarnowski public function getDocument() { 1297f8369d7dSTobias Sarnowski return phpQuery::getDocument($this->getDocumentID()); 1298f8369d7dSTobias Sarnowski } 1299f8369d7dSTobias Sarnowski /** 1300f8369d7dSTobias Sarnowski * 1301f8369d7dSTobias Sarnowski * @return DOMDocument 1302f8369d7dSTobias Sarnowski */ 1303f8369d7dSTobias Sarnowski public function getDOMDocument() { 1304f8369d7dSTobias Sarnowski return $this->document; 1305f8369d7dSTobias Sarnowski } 1306f8369d7dSTobias Sarnowski /** 1307f8369d7dSTobias Sarnowski * Get object's Document ID. 1308f8369d7dSTobias Sarnowski * 1309f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 1310f8369d7dSTobias Sarnowski */ 1311f8369d7dSTobias Sarnowski public function getDocumentID() { 1312f8369d7dSTobias Sarnowski return $this->documentID; 1313f8369d7dSTobias Sarnowski } 1314f8369d7dSTobias Sarnowski /** 1315f8369d7dSTobias Sarnowski * Unloads whole document from memory. 1316f8369d7dSTobias Sarnowski * CAUTION! None further operations will be possible on this document. 1317f8369d7dSTobias Sarnowski * All objects refering to it will be useless. 1318f8369d7dSTobias Sarnowski * 1319f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 1320f8369d7dSTobias Sarnowski */ 1321f8369d7dSTobias Sarnowski public function unloadDocument() { 1322f8369d7dSTobias Sarnowski phpQuery::unloadDocuments($this->getDocumentID()); 1323f8369d7dSTobias Sarnowski } 1324f8369d7dSTobias Sarnowski public function isHTML() { 1325f8369d7dSTobias Sarnowski return $this->documentWrapper->isHTML; 1326f8369d7dSTobias Sarnowski } 1327f8369d7dSTobias Sarnowski public function isXHTML() { 1328f8369d7dSTobias Sarnowski return $this->documentWrapper->isXHTML; 1329f8369d7dSTobias Sarnowski } 1330f8369d7dSTobias Sarnowski public function isXML() { 1331f8369d7dSTobias Sarnowski return $this->documentWrapper->isXML; 1332f8369d7dSTobias Sarnowski } 1333f8369d7dSTobias Sarnowski /** 1334f8369d7dSTobias Sarnowski * Enter description here... 1335f8369d7dSTobias Sarnowski * 1336f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Ajax/serialize 1337f8369d7dSTobias Sarnowski * @return string 1338f8369d7dSTobias Sarnowski */ 1339f8369d7dSTobias Sarnowski public function serialize() { 1340f8369d7dSTobias Sarnowski return phpQuery::param($this->serializeArray()); 1341f8369d7dSTobias Sarnowski } 1342f8369d7dSTobias Sarnowski /** 1343f8369d7dSTobias Sarnowski * Enter description here... 1344f8369d7dSTobias Sarnowski * 1345f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Ajax/serializeArray 1346f8369d7dSTobias Sarnowski * @return array 1347f8369d7dSTobias Sarnowski */ 1348f8369d7dSTobias Sarnowski public function serializeArray($submit = null) { 1349f8369d7dSTobias Sarnowski $source = $this->filter('form, input, select, textarea') 1350f8369d7dSTobias Sarnowski ->find('input, select, textarea') 1351f8369d7dSTobias Sarnowski ->andSelf() 1352f8369d7dSTobias Sarnowski ->not('form'); 1353f8369d7dSTobias Sarnowski $return = array(); 1354f8369d7dSTobias Sarnowski// $source->dumpDie(); 1355f8369d7dSTobias Sarnowski foreach($source as $input) { 1356f8369d7dSTobias Sarnowski $input = phpQuery::pq($input); 1357f8369d7dSTobias Sarnowski if ($input->is('[disabled]')) 1358f8369d7dSTobias Sarnowski continue; 1359f8369d7dSTobias Sarnowski if (!$input->is('[name]')) 1360f8369d7dSTobias Sarnowski continue; 1361f8369d7dSTobias Sarnowski if ($input->is('[type=checkbox]') && !$input->is('[checked]')) 1362f8369d7dSTobias Sarnowski continue; 1363f8369d7dSTobias Sarnowski // jquery diff 1364f8369d7dSTobias Sarnowski if ($submit && $input->is('[type=submit]')) { 1365f8369d7dSTobias Sarnowski if ($submit instanceof DOMELEMENT && ! $input->elements[0]->isSameNode($submit)) 1366f8369d7dSTobias Sarnowski continue; 1367f8369d7dSTobias Sarnowski else if (is_string($submit) && $input->attr('name') != $submit) 1368f8369d7dSTobias Sarnowski continue; 1369f8369d7dSTobias Sarnowski } 1370f8369d7dSTobias Sarnowski $return[] = array( 1371f8369d7dSTobias Sarnowski 'name' => $input->attr('name'), 1372f8369d7dSTobias Sarnowski 'value' => $input->val(), 1373f8369d7dSTobias Sarnowski ); 1374f8369d7dSTobias Sarnowski } 1375f8369d7dSTobias Sarnowski return $return; 1376f8369d7dSTobias Sarnowski } 1377f8369d7dSTobias Sarnowski /** 1378f8369d7dSTobias Sarnowski * @access private 1379f8369d7dSTobias Sarnowski */ 1380f8369d7dSTobias Sarnowski protected function debug($in) { 1381f8369d7dSTobias Sarnowski if (! phpQuery::$debug ) 1382f8369d7dSTobias Sarnowski return; 1383f8369d7dSTobias Sarnowski print('<pre>'); 1384f8369d7dSTobias Sarnowski print_r($in); 1385f8369d7dSTobias Sarnowski // file debug 1386f8369d7dSTobias Sarnowski// file_put_contents(dirname(__FILE__).'/phpQuery.log', print_r($in, true)."\n", FILE_APPEND); 1387f8369d7dSTobias Sarnowski // quite handy debug trace 1388f8369d7dSTobias Sarnowski// if ( is_array($in)) 1389f8369d7dSTobias Sarnowski// print_r(array_slice(debug_backtrace(), 3)); 1390f8369d7dSTobias Sarnowski print("</pre>\n"); 1391f8369d7dSTobias Sarnowski } 1392f8369d7dSTobias Sarnowski /** 1393f8369d7dSTobias Sarnowski * @access private 1394f8369d7dSTobias Sarnowski */ 1395f8369d7dSTobias Sarnowski protected function isRegexp($pattern) { 1396f8369d7dSTobias Sarnowski return in_array( 1397f8369d7dSTobias Sarnowski $pattern[ mb_strlen($pattern)-1 ], 1398f8369d7dSTobias Sarnowski array('^','*','$') 1399f8369d7dSTobias Sarnowski ); 1400f8369d7dSTobias Sarnowski } 1401f8369d7dSTobias Sarnowski /** 1402f8369d7dSTobias Sarnowski * Determines if $char is really a char. 1403f8369d7dSTobias Sarnowski * 1404f8369d7dSTobias Sarnowski * @param string $char 1405f8369d7dSTobias Sarnowski * @return bool 1406f8369d7dSTobias Sarnowski * @todo rewrite me to charcode range ! ;) 1407f8369d7dSTobias Sarnowski * @access private 1408f8369d7dSTobias Sarnowski */ 1409f8369d7dSTobias Sarnowski protected function isChar($char) { 1410f8369d7dSTobias Sarnowski return extension_loaded('mbstring') && phpQuery::$mbstringSupport 1411f8369d7dSTobias Sarnowski ? mb_eregi('\w', $char) 1412f8369d7dSTobias Sarnowski : preg_match('@\w@', $char); 1413f8369d7dSTobias Sarnowski } 1414f8369d7dSTobias Sarnowski /** 1415f8369d7dSTobias Sarnowski * @access private 1416f8369d7dSTobias Sarnowski */ 1417f8369d7dSTobias Sarnowski protected function parseSelector($query) { 1418f8369d7dSTobias Sarnowski // clean spaces 1419f8369d7dSTobias Sarnowski // TODO include this inside parsing ? 1420f8369d7dSTobias Sarnowski $query = trim( 1421f8369d7dSTobias Sarnowski preg_replace('@\s+@', ' ', 1422f8369d7dSTobias Sarnowski preg_replace('@\s*(>|\\+|~)\s*@', '\\1', $query) 1423f8369d7dSTobias Sarnowski ) 1424f8369d7dSTobias Sarnowski ); 1425f8369d7dSTobias Sarnowski $queries = array(array()); 1426f8369d7dSTobias Sarnowski if (! $query) 1427f8369d7dSTobias Sarnowski return $queries; 1428f8369d7dSTobias Sarnowski $return =& $queries[0]; 1429f8369d7dSTobias Sarnowski $specialChars = array('>',' '); 1430f8369d7dSTobias Sarnowski// $specialCharsMapping = array('/' => '>'); 1431f8369d7dSTobias Sarnowski $specialCharsMapping = array(); 1432f8369d7dSTobias Sarnowski $strlen = mb_strlen($query); 1433f8369d7dSTobias Sarnowski $classChars = array('.', '-'); 1434f8369d7dSTobias Sarnowski $pseudoChars = array('-'); 1435f8369d7dSTobias Sarnowski $tagChars = array('*', '|', '-'); 1436f8369d7dSTobias Sarnowski // split multibyte string 1437f8369d7dSTobias Sarnowski // http://code.google.com/p/phpquery/issues/detail?id=76 1438f8369d7dSTobias Sarnowski $_query = array(); 1439f8369d7dSTobias Sarnowski for ($i=0; $i<$strlen; $i++) 1440f8369d7dSTobias Sarnowski $_query[] = mb_substr($query, $i, 1); 1441f8369d7dSTobias Sarnowski $query = $_query; 1442f8369d7dSTobias Sarnowski // it works, but i dont like it... 1443f8369d7dSTobias Sarnowski $i = 0; 1444f8369d7dSTobias Sarnowski while( $i < $strlen) { 1445f8369d7dSTobias Sarnowski $c = $query[$i]; 1446f8369d7dSTobias Sarnowski $tmp = ''; 1447f8369d7dSTobias Sarnowski // TAG 1448f8369d7dSTobias Sarnowski if ($this->isChar($c) || in_array($c, $tagChars)) { 1449f8369d7dSTobias Sarnowski while(isset($query[$i]) 1450f8369d7dSTobias Sarnowski && ($this->isChar($query[$i]) || in_array($query[$i], $tagChars))) { 1451f8369d7dSTobias Sarnowski $tmp .= $query[$i]; 1452f8369d7dSTobias Sarnowski $i++; 1453f8369d7dSTobias Sarnowski } 1454f8369d7dSTobias Sarnowski $return[] = $tmp; 1455f8369d7dSTobias Sarnowski // IDs 1456f8369d7dSTobias Sarnowski } else if ( $c == '#') { 1457f8369d7dSTobias Sarnowski $i++; 1458f8369d7dSTobias Sarnowski while( isset($query[$i]) && ($this->isChar($query[$i]) || $query[$i] == '-')) { 1459f8369d7dSTobias Sarnowski $tmp .= $query[$i]; 1460f8369d7dSTobias Sarnowski $i++; 1461f8369d7dSTobias Sarnowski } 1462f8369d7dSTobias Sarnowski $return[] = '#'.$tmp; 1463f8369d7dSTobias Sarnowski // SPECIAL CHARS 1464f8369d7dSTobias Sarnowski } else if (in_array($c, $specialChars)) { 1465f8369d7dSTobias Sarnowski $return[] = $c; 1466f8369d7dSTobias Sarnowski $i++; 1467f8369d7dSTobias Sarnowski // MAPPED SPECIAL MULTICHARS 1468f8369d7dSTobias Sarnowski// } else if ( $c.$query[$i+1] == '//') { 1469f8369d7dSTobias Sarnowski// $return[] = ' '; 1470f8369d7dSTobias Sarnowski// $i = $i+2; 1471f8369d7dSTobias Sarnowski // MAPPED SPECIAL CHARS 1472f8369d7dSTobias Sarnowski } else if ( isset($specialCharsMapping[$c])) { 1473f8369d7dSTobias Sarnowski $return[] = $specialCharsMapping[$c]; 1474f8369d7dSTobias Sarnowski $i++; 1475f8369d7dSTobias Sarnowski // COMMA 1476f8369d7dSTobias Sarnowski } else if ( $c == ',') { 1477f8369d7dSTobias Sarnowski $queries[] = array(); 1478f8369d7dSTobias Sarnowski $return =& $queries[ count($queries)-1 ]; 1479f8369d7dSTobias Sarnowski $i++; 1480f8369d7dSTobias Sarnowski while( isset($query[$i]) && $query[$i] == ' ') 1481f8369d7dSTobias Sarnowski $i++; 1482f8369d7dSTobias Sarnowski // CLASSES 1483f8369d7dSTobias Sarnowski } else if ($c == '.') { 1484f8369d7dSTobias Sarnowski while( isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $classChars))) { 1485f8369d7dSTobias Sarnowski $tmp .= $query[$i]; 1486f8369d7dSTobias Sarnowski $i++; 1487f8369d7dSTobias Sarnowski } 1488f8369d7dSTobias Sarnowski $return[] = $tmp; 1489f8369d7dSTobias Sarnowski // ~ General Sibling Selector 1490f8369d7dSTobias Sarnowski } else if ($c == '~') { 1491f8369d7dSTobias Sarnowski $spaceAllowed = true; 1492f8369d7dSTobias Sarnowski $tmp .= $query[$i++]; 1493f8369d7dSTobias Sarnowski while( isset($query[$i]) 1494f8369d7dSTobias Sarnowski && ($this->isChar($query[$i]) 1495f8369d7dSTobias Sarnowski || in_array($query[$i], $classChars) 1496f8369d7dSTobias Sarnowski || $query[$i] == '*' 1497f8369d7dSTobias Sarnowski || ($query[$i] == ' ' && $spaceAllowed) 1498f8369d7dSTobias Sarnowski )) { 1499f8369d7dSTobias Sarnowski if ($query[$i] != ' ') 1500f8369d7dSTobias Sarnowski $spaceAllowed = false; 1501f8369d7dSTobias Sarnowski $tmp .= $query[$i]; 1502f8369d7dSTobias Sarnowski $i++; 1503f8369d7dSTobias Sarnowski } 1504f8369d7dSTobias Sarnowski $return[] = $tmp; 1505f8369d7dSTobias Sarnowski // + Adjacent sibling selectors 1506f8369d7dSTobias Sarnowski } else if ($c == '+') { 1507f8369d7dSTobias Sarnowski $spaceAllowed = true; 1508f8369d7dSTobias Sarnowski $tmp .= $query[$i++]; 1509f8369d7dSTobias Sarnowski while( isset($query[$i]) 1510f8369d7dSTobias Sarnowski && ($this->isChar($query[$i]) 1511f8369d7dSTobias Sarnowski || in_array($query[$i], $classChars) 1512f8369d7dSTobias Sarnowski || $query[$i] == '*' 1513f8369d7dSTobias Sarnowski || ($spaceAllowed && $query[$i] == ' ') 1514f8369d7dSTobias Sarnowski )) { 1515f8369d7dSTobias Sarnowski if ($query[$i] != ' ') 1516f8369d7dSTobias Sarnowski $spaceAllowed = false; 1517f8369d7dSTobias Sarnowski $tmp .= $query[$i]; 1518f8369d7dSTobias Sarnowski $i++; 1519f8369d7dSTobias Sarnowski } 1520f8369d7dSTobias Sarnowski $return[] = $tmp; 1521f8369d7dSTobias Sarnowski // ATTRS 1522f8369d7dSTobias Sarnowski } else if ($c == '[') { 1523f8369d7dSTobias Sarnowski $stack = 1; 1524f8369d7dSTobias Sarnowski $tmp .= $c; 1525f8369d7dSTobias Sarnowski while( isset($query[++$i])) { 1526f8369d7dSTobias Sarnowski $tmp .= $query[$i]; 1527f8369d7dSTobias Sarnowski if ( $query[$i] == '[') { 1528f8369d7dSTobias Sarnowski $stack++; 1529f8369d7dSTobias Sarnowski } else if ( $query[$i] == ']') { 1530f8369d7dSTobias Sarnowski $stack--; 1531f8369d7dSTobias Sarnowski if (! $stack ) 1532f8369d7dSTobias Sarnowski break; 1533f8369d7dSTobias Sarnowski } 1534f8369d7dSTobias Sarnowski } 1535f8369d7dSTobias Sarnowski $return[] = $tmp; 1536f8369d7dSTobias Sarnowski $i++; 1537f8369d7dSTobias Sarnowski // PSEUDO CLASSES 1538f8369d7dSTobias Sarnowski } else if ($c == ':') { 1539f8369d7dSTobias Sarnowski $stack = 1; 1540f8369d7dSTobias Sarnowski $tmp .= $query[$i++]; 1541f8369d7dSTobias Sarnowski while( isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $pseudoChars))) { 1542f8369d7dSTobias Sarnowski $tmp .= $query[$i]; 1543f8369d7dSTobias Sarnowski $i++; 1544f8369d7dSTobias Sarnowski } 1545f8369d7dSTobias Sarnowski // with arguments ? 1546f8369d7dSTobias Sarnowski if ( isset($query[$i]) && $query[$i] == '(') { 1547f8369d7dSTobias Sarnowski $tmp .= $query[$i]; 1548f8369d7dSTobias Sarnowski $stack = 1; 1549f8369d7dSTobias Sarnowski while( isset($query[++$i])) { 1550f8369d7dSTobias Sarnowski $tmp .= $query[$i]; 1551f8369d7dSTobias Sarnowski if ( $query[$i] == '(') { 1552f8369d7dSTobias Sarnowski $stack++; 1553f8369d7dSTobias Sarnowski } else if ( $query[$i] == ')') { 1554f8369d7dSTobias Sarnowski $stack--; 1555f8369d7dSTobias Sarnowski if (! $stack ) 1556f8369d7dSTobias Sarnowski break; 1557f8369d7dSTobias Sarnowski } 1558f8369d7dSTobias Sarnowski } 1559f8369d7dSTobias Sarnowski $return[] = $tmp; 1560f8369d7dSTobias Sarnowski $i++; 1561f8369d7dSTobias Sarnowski } else { 1562f8369d7dSTobias Sarnowski $return[] = $tmp; 1563f8369d7dSTobias Sarnowski } 1564f8369d7dSTobias Sarnowski } else { 1565f8369d7dSTobias Sarnowski $i++; 1566f8369d7dSTobias Sarnowski } 1567f8369d7dSTobias Sarnowski } 1568f8369d7dSTobias Sarnowski foreach($queries as $k => $q) { 1569f8369d7dSTobias Sarnowski if (isset($q[0])) { 1570f8369d7dSTobias Sarnowski if (isset($q[0][0]) && $q[0][0] == ':') 1571f8369d7dSTobias Sarnowski array_unshift($queries[$k], '*'); 1572f8369d7dSTobias Sarnowski if ($q[0] != '>') 1573f8369d7dSTobias Sarnowski array_unshift($queries[$k], ' '); 1574f8369d7dSTobias Sarnowski } 1575f8369d7dSTobias Sarnowski } 1576f8369d7dSTobias Sarnowski return $queries; 1577f8369d7dSTobias Sarnowski } 1578f8369d7dSTobias Sarnowski /** 1579f8369d7dSTobias Sarnowski * Return matched DOM nodes. 1580f8369d7dSTobias Sarnowski * 1581f8369d7dSTobias Sarnowski * @param int $index 1582f8369d7dSTobias Sarnowski * @return array|DOMElement Single DOMElement or array of DOMElement. 1583f8369d7dSTobias Sarnowski */ 1584f8369d7dSTobias Sarnowski public function get($index = null, $callback1 = null, $callback2 = null, $callback3 = null) { 1585f8369d7dSTobias Sarnowski $return = isset($index) 1586f8369d7dSTobias Sarnowski ? (isset($this->elements[$index]) ? $this->elements[$index] : null) 1587f8369d7dSTobias Sarnowski : $this->elements; 1588f8369d7dSTobias Sarnowski // pass thou callbacks 1589f8369d7dSTobias Sarnowski $args = func_get_args(); 1590f8369d7dSTobias Sarnowski $args = array_slice($args, 1); 1591f8369d7dSTobias Sarnowski foreach($args as $callback) { 1592f8369d7dSTobias Sarnowski if (is_array($return)) 1593f8369d7dSTobias Sarnowski foreach($return as $k => $v) 1594f8369d7dSTobias Sarnowski $return[$k] = phpQuery::callbackRun($callback, array($v)); 1595f8369d7dSTobias Sarnowski else 1596f8369d7dSTobias Sarnowski $return = phpQuery::callbackRun($callback, array($return)); 1597f8369d7dSTobias Sarnowski } 1598f8369d7dSTobias Sarnowski return $return; 1599f8369d7dSTobias Sarnowski } 1600f8369d7dSTobias Sarnowski /** 1601f8369d7dSTobias Sarnowski * Return matched DOM nodes. 1602f8369d7dSTobias Sarnowski * jQuery difference. 1603f8369d7dSTobias Sarnowski * 1604f8369d7dSTobias Sarnowski * @param int $index 1605f8369d7dSTobias Sarnowski * @return array|string Returns string if $index != null 1606f8369d7dSTobias Sarnowski * @todo implement callbacks 1607f8369d7dSTobias Sarnowski * @todo return only arrays ? 1608f8369d7dSTobias Sarnowski * @todo maybe other name... 1609f8369d7dSTobias Sarnowski */ 1610f8369d7dSTobias Sarnowski public function getString($index = null, $callback1 = null, $callback2 = null, $callback3 = null) { 1611f8369d7dSTobias Sarnowski if ($index) 1612f8369d7dSTobias Sarnowski $return = $this->eq($index)->text(); 1613f8369d7dSTobias Sarnowski else { 1614f8369d7dSTobias Sarnowski $return = array(); 1615f8369d7dSTobias Sarnowski for($i = 0; $i < $this->size(); $i++) { 1616f8369d7dSTobias Sarnowski $return[] = $this->eq($i)->text(); 1617f8369d7dSTobias Sarnowski } 1618f8369d7dSTobias Sarnowski } 1619f8369d7dSTobias Sarnowski // pass thou callbacks 1620f8369d7dSTobias Sarnowski $args = func_get_args(); 1621f8369d7dSTobias Sarnowski $args = array_slice($args, 1); 1622f8369d7dSTobias Sarnowski foreach($args as $callback) { 1623f8369d7dSTobias Sarnowski $return = phpQuery::callbackRun($callback, array($return)); 1624f8369d7dSTobias Sarnowski } 1625f8369d7dSTobias Sarnowski return $return; 1626f8369d7dSTobias Sarnowski } 1627f8369d7dSTobias Sarnowski /** 1628f8369d7dSTobias Sarnowski * Return matched DOM nodes. 1629f8369d7dSTobias Sarnowski * jQuery difference. 1630f8369d7dSTobias Sarnowski * 1631f8369d7dSTobias Sarnowski * @param int $index 1632f8369d7dSTobias Sarnowski * @return array|string Returns string if $index != null 1633f8369d7dSTobias Sarnowski * @todo implement callbacks 1634f8369d7dSTobias Sarnowski * @todo return only arrays ? 1635f8369d7dSTobias Sarnowski * @todo maybe other name... 1636f8369d7dSTobias Sarnowski */ 1637f8369d7dSTobias Sarnowski public function getStrings($index = null, $callback1 = null, $callback2 = null, $callback3 = null) { 1638f8369d7dSTobias Sarnowski if ($index) 1639f8369d7dSTobias Sarnowski $return = $this->eq($index)->text(); 1640f8369d7dSTobias Sarnowski else { 1641f8369d7dSTobias Sarnowski $return = array(); 1642f8369d7dSTobias Sarnowski for($i = 0; $i < $this->size(); $i++) { 1643f8369d7dSTobias Sarnowski $return[] = $this->eq($i)->text(); 1644f8369d7dSTobias Sarnowski } 1645f8369d7dSTobias Sarnowski // pass thou callbacks 1646f8369d7dSTobias Sarnowski $args = func_get_args(); 1647f8369d7dSTobias Sarnowski $args = array_slice($args, 1); 1648f8369d7dSTobias Sarnowski } 1649f8369d7dSTobias Sarnowski foreach($args as $callback) { 1650f8369d7dSTobias Sarnowski if (is_array($return)) 1651f8369d7dSTobias Sarnowski foreach($return as $k => $v) 1652f8369d7dSTobias Sarnowski $return[$k] = phpQuery::callbackRun($callback, array($v)); 1653f8369d7dSTobias Sarnowski else 1654f8369d7dSTobias Sarnowski $return = phpQuery::callbackRun($callback, array($return)); 1655f8369d7dSTobias Sarnowski } 1656f8369d7dSTobias Sarnowski return $return; 1657f8369d7dSTobias Sarnowski } 1658f8369d7dSTobias Sarnowski /** 1659f8369d7dSTobias Sarnowski * Returns new instance of actual class. 1660f8369d7dSTobias Sarnowski * 1661f8369d7dSTobias Sarnowski * @param array $newStack Optional. Will replace old stack with new and move old one to history.c 1662f8369d7dSTobias Sarnowski */ 1663f8369d7dSTobias Sarnowski public function newInstance($newStack = null) { 1664f8369d7dSTobias Sarnowski $class = get_class($this); 1665f8369d7dSTobias Sarnowski // support inheritance by passing old object to overloaded constructor 1666f8369d7dSTobias Sarnowski $new = $class != 'phpQuery' 1667f8369d7dSTobias Sarnowski ? new $class($this, $this->getDocumentID()) 1668f8369d7dSTobias Sarnowski : new phpQueryObject($this->getDocumentID()); 1669f8369d7dSTobias Sarnowski $new->previous = $this; 1670f8369d7dSTobias Sarnowski if (is_null($newStack)) { 1671f8369d7dSTobias Sarnowski $new->elements = $this->elements; 1672f8369d7dSTobias Sarnowski if ($this->elementsBackup) 1673f8369d7dSTobias Sarnowski $this->elements = $this->elementsBackup; 1674f8369d7dSTobias Sarnowski } else if (is_string($newStack)) { 1675f8369d7dSTobias Sarnowski $new->elements = phpQuery::pq($newStack, $this->getDocumentID())->stack(); 1676f8369d7dSTobias Sarnowski } else { 1677f8369d7dSTobias Sarnowski $new->elements = $newStack; 1678f8369d7dSTobias Sarnowski } 1679f8369d7dSTobias Sarnowski return $new; 1680f8369d7dSTobias Sarnowski } 1681f8369d7dSTobias Sarnowski /** 1682f8369d7dSTobias Sarnowski * Enter description here... 1683f8369d7dSTobias Sarnowski * 1684f8369d7dSTobias Sarnowski * In the future, when PHP will support XLS 2.0, then we would do that this way: 1685f8369d7dSTobias Sarnowski * contains(tokenize(@class, '\s'), "something") 1686f8369d7dSTobias Sarnowski * @param unknown_type $class 1687f8369d7dSTobias Sarnowski * @param unknown_type $node 1688f8369d7dSTobias Sarnowski * @return boolean 1689f8369d7dSTobias Sarnowski * @access private 1690f8369d7dSTobias Sarnowski */ 1691f8369d7dSTobias Sarnowski protected function matchClasses($class, $node) { 1692f8369d7dSTobias Sarnowski // multi-class 1693f8369d7dSTobias Sarnowski if ( mb_strpos($class, '.', 1)) { 1694f8369d7dSTobias Sarnowski $classes = explode('.', substr($class, 1)); 1695f8369d7dSTobias Sarnowski $classesCount = count( $classes ); 1696f8369d7dSTobias Sarnowski $nodeClasses = explode(' ', $node->getAttribute('class') ); 1697f8369d7dSTobias Sarnowski $nodeClassesCount = count( $nodeClasses ); 1698f8369d7dSTobias Sarnowski if ( $classesCount > $nodeClassesCount ) 1699f8369d7dSTobias Sarnowski return false; 1700f8369d7dSTobias Sarnowski $diff = count( 1701f8369d7dSTobias Sarnowski array_diff( 1702f8369d7dSTobias Sarnowski $classes, 1703f8369d7dSTobias Sarnowski $nodeClasses 1704f8369d7dSTobias Sarnowski ) 1705f8369d7dSTobias Sarnowski ); 1706f8369d7dSTobias Sarnowski if (! $diff ) 1707f8369d7dSTobias Sarnowski return true; 1708f8369d7dSTobias Sarnowski // single-class 1709f8369d7dSTobias Sarnowski } else { 1710f8369d7dSTobias Sarnowski return in_array( 1711f8369d7dSTobias Sarnowski // strip leading dot from class name 1712f8369d7dSTobias Sarnowski substr($class, 1), 1713f8369d7dSTobias Sarnowski // get classes for element as array 1714f8369d7dSTobias Sarnowski explode(' ', $node->getAttribute('class') ) 1715f8369d7dSTobias Sarnowski ); 1716f8369d7dSTobias Sarnowski } 1717f8369d7dSTobias Sarnowski } 1718f8369d7dSTobias Sarnowski /** 1719f8369d7dSTobias Sarnowski * @access private 1720f8369d7dSTobias Sarnowski */ 1721f8369d7dSTobias Sarnowski protected function runQuery($XQuery, $selector = null, $compare = null) { 1722f8369d7dSTobias Sarnowski if ($compare && ! method_exists($this, $compare)) 1723f8369d7dSTobias Sarnowski return false; 1724f8369d7dSTobias Sarnowski $stack = array(); 1725f8369d7dSTobias Sarnowski if (! $this->elements) 1726f8369d7dSTobias Sarnowski $this->debug('Stack empty, skipping...'); 1727f8369d7dSTobias Sarnowski// var_dump($this->elements[0]->nodeType); 1728f8369d7dSTobias Sarnowski // element, document 1729f8369d7dSTobias Sarnowski foreach($this->stack(array(1, 9, 13)) as $k => $stackNode) { 1730f8369d7dSTobias Sarnowski $detachAfter = false; 1731f8369d7dSTobias Sarnowski // to work on detached nodes we need temporary place them somewhere 1732f8369d7dSTobias Sarnowski // thats because context xpath queries sucks ;] 1733f8369d7dSTobias Sarnowski $testNode = $stackNode; 1734f8369d7dSTobias Sarnowski while ($testNode) { 1735f8369d7dSTobias Sarnowski if (! $testNode->parentNode && ! $this->isRoot($testNode)) { 1736f8369d7dSTobias Sarnowski $this->root->appendChild($testNode); 1737f8369d7dSTobias Sarnowski $detachAfter = $testNode; 1738f8369d7dSTobias Sarnowski break; 1739f8369d7dSTobias Sarnowski } 1740f8369d7dSTobias Sarnowski $testNode = isset($testNode->parentNode) 1741f8369d7dSTobias Sarnowski ? $testNode->parentNode 1742f8369d7dSTobias Sarnowski : null; 1743f8369d7dSTobias Sarnowski } 1744f8369d7dSTobias Sarnowski // XXX tmp ? 1745f8369d7dSTobias Sarnowski $xpath = $this->documentWrapper->isXHTML 1746f8369d7dSTobias Sarnowski ? $this->getNodeXpath($stackNode, 'html') 1747f8369d7dSTobias Sarnowski : $this->getNodeXpath($stackNode); 1748f8369d7dSTobias Sarnowski // FIXME pseudoclasses-only query, support XML 1749f8369d7dSTobias Sarnowski $query = $XQuery == '//' && $xpath == '/html[1]' 1750f8369d7dSTobias Sarnowski ? '//*' 1751f8369d7dSTobias Sarnowski : $xpath.$XQuery; 1752f8369d7dSTobias Sarnowski $this->debug("XPATH: {$query}"); 1753f8369d7dSTobias Sarnowski // run query, get elements 1754f8369d7dSTobias Sarnowski $nodes = $this->xpath->query($query); 1755f8369d7dSTobias Sarnowski $this->debug("QUERY FETCHED"); 1756f8369d7dSTobias Sarnowski if (! $nodes->length ) 1757f8369d7dSTobias Sarnowski $this->debug('Nothing found'); 1758f8369d7dSTobias Sarnowski $debug = array(); 1759f8369d7dSTobias Sarnowski foreach($nodes as $node) { 1760f8369d7dSTobias Sarnowski $matched = false; 1761f8369d7dSTobias Sarnowski if ( $compare) { 1762f8369d7dSTobias Sarnowski phpQuery::$debug ? 1763f8369d7dSTobias Sarnowski $this->debug("Found: ".$this->whois( $node ).", comparing with {$compare}()") 1764f8369d7dSTobias Sarnowski : null; 1765f8369d7dSTobias Sarnowski $phpQueryDebug = phpQuery::$debug; 1766f8369d7dSTobias Sarnowski phpQuery::$debug = false; 1767f8369d7dSTobias Sarnowski // TODO ??? use phpQuery::callbackRun() 1768f8369d7dSTobias Sarnowski if (call_user_func_array(array($this, $compare), array($selector, $node))) 1769f8369d7dSTobias Sarnowski $matched = true; 1770f8369d7dSTobias Sarnowski phpQuery::$debug = $phpQueryDebug; 1771f8369d7dSTobias Sarnowski } else { 1772f8369d7dSTobias Sarnowski $matched = true; 1773f8369d7dSTobias Sarnowski } 1774f8369d7dSTobias Sarnowski if ( $matched) { 1775f8369d7dSTobias Sarnowski if (phpQuery::$debug) 1776f8369d7dSTobias Sarnowski $debug[] = $this->whois( $node ); 1777f8369d7dSTobias Sarnowski $stack[] = $node; 1778f8369d7dSTobias Sarnowski } 1779f8369d7dSTobias Sarnowski } 1780f8369d7dSTobias Sarnowski if (phpQuery::$debug) { 1781f8369d7dSTobias Sarnowski $this->debug("Matched ".count($debug).": ".implode(', ', $debug)); 1782f8369d7dSTobias Sarnowski } 1783f8369d7dSTobias Sarnowski if ($detachAfter) 1784f8369d7dSTobias Sarnowski $this->root->removeChild($detachAfter); 1785f8369d7dSTobias Sarnowski } 1786f8369d7dSTobias Sarnowski $this->elements = $stack; 1787f8369d7dSTobias Sarnowski } 1788f8369d7dSTobias Sarnowski /** 1789f8369d7dSTobias Sarnowski * Enter description here... 1790f8369d7dSTobias Sarnowski * 1791f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 1792f8369d7dSTobias Sarnowski */ 1793f8369d7dSTobias Sarnowski public function find($selectors, $context = null, $noHistory = false) { 1794f8369d7dSTobias Sarnowski if (!$noHistory) 1795f8369d7dSTobias Sarnowski // backup last stack /for end()/ 1796f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 1797f8369d7dSTobias Sarnowski // allow to define context 1798f8369d7dSTobias Sarnowski // TODO combine code below with phpQuery::pq() context guessing code 1799f8369d7dSTobias Sarnowski // as generic function 1800f8369d7dSTobias Sarnowski if ($context) { 1801f8369d7dSTobias Sarnowski if (! is_array($context) && $context instanceof DOMELEMENT) 1802f8369d7dSTobias Sarnowski $this->elements = array($context); 1803f8369d7dSTobias Sarnowski else if (is_array($context)) { 1804f8369d7dSTobias Sarnowski $this->elements = array(); 1805f8369d7dSTobias Sarnowski foreach ($context as $c) 1806f8369d7dSTobias Sarnowski if ($c instanceof DOMELEMENT) 1807f8369d7dSTobias Sarnowski $this->elements[] = $c; 1808f8369d7dSTobias Sarnowski } else if ( $context instanceof self ) 1809f8369d7dSTobias Sarnowski $this->elements = $context->elements; 1810f8369d7dSTobias Sarnowski } 1811f8369d7dSTobias Sarnowski $queries = $this->parseSelector($selectors); 1812f8369d7dSTobias Sarnowski $this->debug(array('FIND', $selectors, $queries)); 1813f8369d7dSTobias Sarnowski $XQuery = ''; 1814f8369d7dSTobias Sarnowski // remember stack state because of multi-queries 1815f8369d7dSTobias Sarnowski $oldStack = $this->elements; 1816f8369d7dSTobias Sarnowski // here we will be keeping found elements 1817f8369d7dSTobias Sarnowski $stack = array(); 1818f8369d7dSTobias Sarnowski foreach($queries as $selector) { 1819f8369d7dSTobias Sarnowski $this->elements = $oldStack; 1820f8369d7dSTobias Sarnowski $delimiterBefore = false; 1821f8369d7dSTobias Sarnowski foreach($selector as $s) { 1822f8369d7dSTobias Sarnowski // TAG 1823f8369d7dSTobias Sarnowski $isTag = extension_loaded('mbstring') && phpQuery::$mbstringSupport 1824f8369d7dSTobias Sarnowski ? mb_ereg_match('^[\w|\||-]+$', $s) || $s == '*' 1825f8369d7dSTobias Sarnowski : preg_match('@^[\w|\||-]+$@', $s) || $s == '*'; 1826f8369d7dSTobias Sarnowski if ($isTag) { 1827f8369d7dSTobias Sarnowski if ($this->isXML()) { 1828f8369d7dSTobias Sarnowski // namespace support 1829f8369d7dSTobias Sarnowski if (mb_strpos($s, '|') !== false) { 1830f8369d7dSTobias Sarnowski $ns = $tag = null; 1831f8369d7dSTobias Sarnowski list($ns, $tag) = explode('|', $s); 1832f8369d7dSTobias Sarnowski $XQuery .= "$ns:$tag"; 1833f8369d7dSTobias Sarnowski } else if ($s == '*') { 1834f8369d7dSTobias Sarnowski $XQuery .= "*"; 1835f8369d7dSTobias Sarnowski } else { 1836f8369d7dSTobias Sarnowski $XQuery .= "*[local-name()='$s']"; 1837f8369d7dSTobias Sarnowski } 1838f8369d7dSTobias Sarnowski } else { 1839f8369d7dSTobias Sarnowski $XQuery .= $s; 1840f8369d7dSTobias Sarnowski } 1841f8369d7dSTobias Sarnowski // ID 1842f8369d7dSTobias Sarnowski } else if ($s[0] == '#') { 1843f8369d7dSTobias Sarnowski if ($delimiterBefore) 1844f8369d7dSTobias Sarnowski $XQuery .= '*'; 1845f8369d7dSTobias Sarnowski $XQuery .= "[@id='".substr($s, 1)."']"; 1846f8369d7dSTobias Sarnowski // ATTRIBUTES 1847f8369d7dSTobias Sarnowski } else if ($s[0] == '[') { 1848f8369d7dSTobias Sarnowski if ($delimiterBefore) 1849f8369d7dSTobias Sarnowski $XQuery .= '*'; 1850f8369d7dSTobias Sarnowski // strip side brackets 1851f8369d7dSTobias Sarnowski $attr = trim($s, ']['); 1852f8369d7dSTobias Sarnowski $execute = false; 1853f8369d7dSTobias Sarnowski // attr with specifed value 1854f8369d7dSTobias Sarnowski if (mb_strpos($s, '=')) { 1855f8369d7dSTobias Sarnowski $value = null; 1856f8369d7dSTobias Sarnowski list($attr, $value) = explode('=', $attr); 1857f8369d7dSTobias Sarnowski $value = trim($value, "'\""); 1858f8369d7dSTobias Sarnowski if ($this->isRegexp($attr)) { 1859f8369d7dSTobias Sarnowski // cut regexp character 1860f8369d7dSTobias Sarnowski $attr = substr($attr, 0, -1); 1861f8369d7dSTobias Sarnowski $execute = true; 1862f8369d7dSTobias Sarnowski $XQuery .= "[@{$attr}]"; 1863f8369d7dSTobias Sarnowski } else { 1864f8369d7dSTobias Sarnowski $XQuery .= "[@{$attr}='{$value}']"; 1865f8369d7dSTobias Sarnowski } 1866f8369d7dSTobias Sarnowski // attr without specified value 1867f8369d7dSTobias Sarnowski } else { 1868f8369d7dSTobias Sarnowski $XQuery .= "[@{$attr}]"; 1869f8369d7dSTobias Sarnowski } 1870f8369d7dSTobias Sarnowski if ($execute) { 1871f8369d7dSTobias Sarnowski $this->runQuery($XQuery, $s, 'is'); 1872f8369d7dSTobias Sarnowski $XQuery = ''; 1873f8369d7dSTobias Sarnowski if (! $this->length()) 1874f8369d7dSTobias Sarnowski break; 1875f8369d7dSTobias Sarnowski } 1876f8369d7dSTobias Sarnowski // CLASSES 1877f8369d7dSTobias Sarnowski } else if ($s[0] == '.') { 1878f8369d7dSTobias Sarnowski // TODO use return $this->find("./self::*[contains(concat(\" \",@class,\" \"), \" $class \")]"); 1879f8369d7dSTobias Sarnowski // thx wizDom ;) 1880f8369d7dSTobias Sarnowski if ($delimiterBefore) 1881f8369d7dSTobias Sarnowski $XQuery .= '*'; 1882f8369d7dSTobias Sarnowski $XQuery .= '[@class]'; 1883f8369d7dSTobias Sarnowski $this->runQuery($XQuery, $s, 'matchClasses'); 1884f8369d7dSTobias Sarnowski $XQuery = ''; 1885f8369d7dSTobias Sarnowski if (! $this->length() ) 1886f8369d7dSTobias Sarnowski break; 1887f8369d7dSTobias Sarnowski // ~ General Sibling Selector 1888f8369d7dSTobias Sarnowski } else if ($s[0] == '~') { 1889f8369d7dSTobias Sarnowski $this->runQuery($XQuery); 1890f8369d7dSTobias Sarnowski $XQuery = ''; 1891f8369d7dSTobias Sarnowski $this->elements = $this 1892f8369d7dSTobias Sarnowski ->siblings( 1893f8369d7dSTobias Sarnowski substr($s, 1) 1894f8369d7dSTobias Sarnowski )->elements; 1895f8369d7dSTobias Sarnowski if (! $this->length() ) 1896f8369d7dSTobias Sarnowski break; 1897f8369d7dSTobias Sarnowski // + Adjacent sibling selectors 1898f8369d7dSTobias Sarnowski } else if ($s[0] == '+') { 1899f8369d7dSTobias Sarnowski // TODO /following-sibling:: 1900f8369d7dSTobias Sarnowski $this->runQuery($XQuery); 1901f8369d7dSTobias Sarnowski $XQuery = ''; 1902f8369d7dSTobias Sarnowski $subSelector = substr($s, 1); 1903f8369d7dSTobias Sarnowski $subElements = $this->elements; 1904f8369d7dSTobias Sarnowski $this->elements = array(); 1905f8369d7dSTobias Sarnowski foreach($subElements as $node) { 1906f8369d7dSTobias Sarnowski // search first DOMElement sibling 1907f8369d7dSTobias Sarnowski $test = $node->nextSibling; 1908f8369d7dSTobias Sarnowski while($test && ! ($test instanceof DOMELEMENT)) 1909f8369d7dSTobias Sarnowski $test = $test->nextSibling; 1910f8369d7dSTobias Sarnowski if ($test && $this->is($subSelector, $test)) 1911f8369d7dSTobias Sarnowski $this->elements[] = $test; 1912f8369d7dSTobias Sarnowski } 1913f8369d7dSTobias Sarnowski if (! $this->length() ) 1914f8369d7dSTobias Sarnowski break; 1915f8369d7dSTobias Sarnowski // PSEUDO CLASSES 1916f8369d7dSTobias Sarnowski } else if ($s[0] == ':') { 1917f8369d7dSTobias Sarnowski // TODO optimization for :first :last 1918f8369d7dSTobias Sarnowski if ($XQuery) { 1919f8369d7dSTobias Sarnowski $this->runQuery($XQuery); 1920f8369d7dSTobias Sarnowski $XQuery = ''; 1921f8369d7dSTobias Sarnowski } 1922f8369d7dSTobias Sarnowski if (! $this->length()) 1923f8369d7dSTobias Sarnowski break; 1924f8369d7dSTobias Sarnowski $this->pseudoClasses($s); 1925f8369d7dSTobias Sarnowski if (! $this->length()) 1926f8369d7dSTobias Sarnowski break; 1927f8369d7dSTobias Sarnowski // DIRECT DESCENDANDS 1928f8369d7dSTobias Sarnowski } else if ($s == '>') { 1929f8369d7dSTobias Sarnowski $XQuery .= '/'; 1930f8369d7dSTobias Sarnowski $delimiterBefore = 2; 1931f8369d7dSTobias Sarnowski // ALL DESCENDANDS 1932f8369d7dSTobias Sarnowski } else if ($s == ' ') { 1933f8369d7dSTobias Sarnowski $XQuery .= '//'; 1934f8369d7dSTobias Sarnowski $delimiterBefore = 2; 1935f8369d7dSTobias Sarnowski // ERRORS 1936f8369d7dSTobias Sarnowski } else { 1937f8369d7dSTobias Sarnowski phpQuery::debug("Unrecognized token '$s'"); 1938f8369d7dSTobias Sarnowski } 1939f8369d7dSTobias Sarnowski $delimiterBefore = $delimiterBefore === 2; 1940f8369d7dSTobias Sarnowski } 1941f8369d7dSTobias Sarnowski // run query if any 1942f8369d7dSTobias Sarnowski if ($XQuery && $XQuery != '//') { 1943f8369d7dSTobias Sarnowski $this->runQuery($XQuery); 1944f8369d7dSTobias Sarnowski $XQuery = ''; 1945f8369d7dSTobias Sarnowski } 1946f8369d7dSTobias Sarnowski foreach($this->elements as $node) 1947f8369d7dSTobias Sarnowski if (! $this->elementsContainsNode($node, $stack)) 1948f8369d7dSTobias Sarnowski $stack[] = $node; 1949f8369d7dSTobias Sarnowski } 1950f8369d7dSTobias Sarnowski $this->elements = $stack; 1951f8369d7dSTobias Sarnowski return $this->newInstance(); 1952f8369d7dSTobias Sarnowski } 1953f8369d7dSTobias Sarnowski /** 1954f8369d7dSTobias Sarnowski * @todo create API for classes with pseudoselectors 1955f8369d7dSTobias Sarnowski * @access private 1956f8369d7dSTobias Sarnowski */ 1957f8369d7dSTobias Sarnowski protected function pseudoClasses($class) { 1958f8369d7dSTobias Sarnowski // TODO clean args parsing ? 1959f8369d7dSTobias Sarnowski $class = ltrim($class, ':'); 1960f8369d7dSTobias Sarnowski $haveArgs = mb_strpos($class, '('); 1961f8369d7dSTobias Sarnowski if ($haveArgs !== false) { 1962f8369d7dSTobias Sarnowski $args = substr($class, $haveArgs+1, -1); 1963f8369d7dSTobias Sarnowski $class = substr($class, 0, $haveArgs); 1964f8369d7dSTobias Sarnowski } 1965f8369d7dSTobias Sarnowski switch($class) { 1966f8369d7dSTobias Sarnowski case 'even': 1967f8369d7dSTobias Sarnowski case 'odd': 1968f8369d7dSTobias Sarnowski $stack = array(); 1969f8369d7dSTobias Sarnowski foreach($this->elements as $i => $node) { 1970f8369d7dSTobias Sarnowski if ($class == 'even' && ($i%2) == 0) 1971f8369d7dSTobias Sarnowski $stack[] = $node; 1972f8369d7dSTobias Sarnowski else if ( $class == 'odd' && $i % 2 ) 1973f8369d7dSTobias Sarnowski $stack[] = $node; 1974f8369d7dSTobias Sarnowski } 1975f8369d7dSTobias Sarnowski $this->elements = $stack; 1976f8369d7dSTobias Sarnowski break; 1977f8369d7dSTobias Sarnowski case 'eq': 1978f8369d7dSTobias Sarnowski $k = intval($args); 1979f8369d7dSTobias Sarnowski $this->elements = isset( $this->elements[$k] ) 1980f8369d7dSTobias Sarnowski ? array( $this->elements[$k] ) 1981f8369d7dSTobias Sarnowski : array(); 1982f8369d7dSTobias Sarnowski break; 1983f8369d7dSTobias Sarnowski case 'gt': 1984f8369d7dSTobias Sarnowski $this->elements = array_slice($this->elements, $args+1); 1985f8369d7dSTobias Sarnowski break; 1986f8369d7dSTobias Sarnowski case 'lt': 1987f8369d7dSTobias Sarnowski $this->elements = array_slice($this->elements, 0, $args+1); 1988f8369d7dSTobias Sarnowski break; 1989f8369d7dSTobias Sarnowski case 'first': 1990f8369d7dSTobias Sarnowski if (isset($this->elements[0])) 1991f8369d7dSTobias Sarnowski $this->elements = array($this->elements[0]); 1992f8369d7dSTobias Sarnowski break; 1993f8369d7dSTobias Sarnowski case 'last': 1994f8369d7dSTobias Sarnowski if ($this->elements) 1995f8369d7dSTobias Sarnowski $this->elements = array($this->elements[count($this->elements)-1]); 1996f8369d7dSTobias Sarnowski break; 1997f8369d7dSTobias Sarnowski /*case 'parent': 1998f8369d7dSTobias Sarnowski $stack = array(); 1999f8369d7dSTobias Sarnowski foreach($this->elements as $node) { 2000f8369d7dSTobias Sarnowski if ( $node->childNodes->length ) 2001f8369d7dSTobias Sarnowski $stack[] = $node; 2002f8369d7dSTobias Sarnowski } 2003f8369d7dSTobias Sarnowski $this->elements = $stack; 2004f8369d7dSTobias Sarnowski break;*/ 2005f8369d7dSTobias Sarnowski case 'contains': 2006f8369d7dSTobias Sarnowski $text = trim($args, "\"'"); 2007f8369d7dSTobias Sarnowski $stack = array(); 2008f8369d7dSTobias Sarnowski foreach($this->elements as $node) { 2009f8369d7dSTobias Sarnowski if (mb_stripos($node->textContent, $text) === false) 2010f8369d7dSTobias Sarnowski continue; 2011f8369d7dSTobias Sarnowski $stack[] = $node; 2012f8369d7dSTobias Sarnowski } 2013f8369d7dSTobias Sarnowski $this->elements = $stack; 2014f8369d7dSTobias Sarnowski break; 2015f8369d7dSTobias Sarnowski case 'not': 2016f8369d7dSTobias Sarnowski $selector = self::unQuote($args); 2017f8369d7dSTobias Sarnowski $this->elements = $this->not($selector)->stack(); 2018f8369d7dSTobias Sarnowski break; 2019f8369d7dSTobias Sarnowski case 'slice': 2020f8369d7dSTobias Sarnowski // TODO jQuery difference ? 2021f8369d7dSTobias Sarnowski $args = explode(',', 2022f8369d7dSTobias Sarnowski str_replace(', ', ',', trim($args, "\"'")) 2023f8369d7dSTobias Sarnowski ); 2024f8369d7dSTobias Sarnowski $start = $args[0]; 2025f8369d7dSTobias Sarnowski $end = isset($args[1]) 2026f8369d7dSTobias Sarnowski ? $args[1] 2027f8369d7dSTobias Sarnowski : null; 2028f8369d7dSTobias Sarnowski if ($end > 0) 2029f8369d7dSTobias Sarnowski $end = $end-$start; 2030f8369d7dSTobias Sarnowski $this->elements = array_slice($this->elements, $start, $end); 2031f8369d7dSTobias Sarnowski break; 2032f8369d7dSTobias Sarnowski case 'has': 2033f8369d7dSTobias Sarnowski $selector = trim($args, "\"'"); 2034f8369d7dSTobias Sarnowski $stack = array(); 2035f8369d7dSTobias Sarnowski foreach($this->stack(1) as $el) { 2036f8369d7dSTobias Sarnowski if ($this->find($selector, $el, true)->length) 2037f8369d7dSTobias Sarnowski $stack[] = $el; 2038f8369d7dSTobias Sarnowski } 2039f8369d7dSTobias Sarnowski $this->elements = $stack; 2040f8369d7dSTobias Sarnowski break; 2041f8369d7dSTobias Sarnowski case 'submit': 2042f8369d7dSTobias Sarnowski case 'reset': 2043f8369d7dSTobias Sarnowski $this->elements = phpQuery::merge( 2044f8369d7dSTobias Sarnowski $this->map(array($this, 'is'), 2045f8369d7dSTobias Sarnowski "input[type=$class]", new CallbackParam() 2046f8369d7dSTobias Sarnowski ), 2047f8369d7dSTobias Sarnowski $this->map(array($this, 'is'), 2048f8369d7dSTobias Sarnowski "button[type=$class]", new CallbackParam() 2049f8369d7dSTobias Sarnowski ) 2050f8369d7dSTobias Sarnowski ); 2051f8369d7dSTobias Sarnowski break; 2052f8369d7dSTobias Sarnowski// $stack = array(); 2053f8369d7dSTobias Sarnowski// foreach($this->elements as $node) 2054f8369d7dSTobias Sarnowski// if ($node->is('input[type=submit]') || $node->is('button[type=submit]')) 2055f8369d7dSTobias Sarnowski// $stack[] = $el; 2056f8369d7dSTobias Sarnowski// $this->elements = $stack; 2057f8369d7dSTobias Sarnowski case 'input': 2058f8369d7dSTobias Sarnowski $this->elements = $this->map( 2059f8369d7dSTobias Sarnowski array($this, 'is'), 2060f8369d7dSTobias Sarnowski 'input', new CallbackParam() 2061f8369d7dSTobias Sarnowski )->elements; 2062f8369d7dSTobias Sarnowski break; 2063f8369d7dSTobias Sarnowski case 'password': 2064f8369d7dSTobias Sarnowski case 'checkbox': 2065f8369d7dSTobias Sarnowski case 'radio': 2066f8369d7dSTobias Sarnowski case 'hidden': 2067f8369d7dSTobias Sarnowski case 'image': 2068f8369d7dSTobias Sarnowski case 'file': 2069f8369d7dSTobias Sarnowski $this->elements = $this->map( 2070f8369d7dSTobias Sarnowski array($this, 'is'), 2071f8369d7dSTobias Sarnowski "input[type=$class]", new CallbackParam() 2072f8369d7dSTobias Sarnowski )->elements; 2073f8369d7dSTobias Sarnowski break; 2074f8369d7dSTobias Sarnowski case 'parent': 2075f8369d7dSTobias Sarnowski $this->elements = $this->map( 2076a3095052SOscar Merida function ($node) { 2077f8369d7dSTobias Sarnowski return $node instanceof DOMELEMENT && $node->childNodes->length 2078a3095052SOscar Merida ? $node : null; 2079a3095052SOscar Merida } 2080f8369d7dSTobias Sarnowski )->elements; 2081f8369d7dSTobias Sarnowski break; 2082f8369d7dSTobias Sarnowski case 'empty': 2083f8369d7dSTobias Sarnowski $this->elements = $this->map( 2084a3095052SOscar Merida function ($node) { 2085f8369d7dSTobias Sarnowski return $node instanceof DOMELEMENT && $node->childNodes->length 2086a3095052SOscar Merida ? null : $node; 2087a3095052SOscar Merida } 2088f8369d7dSTobias Sarnowski )->elements; 2089f8369d7dSTobias Sarnowski break; 2090f8369d7dSTobias Sarnowski case 'disabled': 2091f8369d7dSTobias Sarnowski case 'selected': 2092f8369d7dSTobias Sarnowski case 'checked': 2093f8369d7dSTobias Sarnowski $this->elements = $this->map( 2094f8369d7dSTobias Sarnowski array($this, 'is'), 2095f8369d7dSTobias Sarnowski "[$class]", new CallbackParam() 2096f8369d7dSTobias Sarnowski )->elements; 2097f8369d7dSTobias Sarnowski break; 2098f8369d7dSTobias Sarnowski case 'enabled': 2099f8369d7dSTobias Sarnowski $this->elements = $this->map( 2100a3095052SOscar Merida function ($node) { 2101a3095052SOscar Merida return pq($node)->not(":disabled") ? $node : null; 2102a3095052SOscar Merida } 2103f8369d7dSTobias Sarnowski )->elements; 2104f8369d7dSTobias Sarnowski break; 2105f8369d7dSTobias Sarnowski case 'header': 2106f8369d7dSTobias Sarnowski $this->elements = $this->map( 2107a3095052SOscar Merida function ($node) { 2108a3095052SOscar Merida $isHeader = isset($node->tagName) && in_array($node->tagName, array( 2109f8369d7dSTobias Sarnowski "h1", "h2", "h3", "h4", "h5", "h6", "h7" 2110f8369d7dSTobias Sarnowski )); 2111f8369d7dSTobias Sarnowski return $isHeader 2112f8369d7dSTobias Sarnowski ? $node 2113a3095052SOscar Merida : null; 2114a3095052SOscar Merida } 2115f8369d7dSTobias Sarnowski )->elements; 2116f8369d7dSTobias Sarnowski// $this->elements = $this->map( 2117f8369d7dSTobias Sarnowski// create_function('$node', '$node = pq($node); 2118f8369d7dSTobias Sarnowski// return $node->is("h1") 2119f8369d7dSTobias Sarnowski// || $node->is("h2") 2120f8369d7dSTobias Sarnowski// || $node->is("h3") 2121f8369d7dSTobias Sarnowski// || $node->is("h4") 2122f8369d7dSTobias Sarnowski// || $node->is("h5") 2123f8369d7dSTobias Sarnowski// || $node->is("h6") 2124f8369d7dSTobias Sarnowski// || $node->is("h7") 2125f8369d7dSTobias Sarnowski// ? $node 2126f8369d7dSTobias Sarnowski// : null;') 2127f8369d7dSTobias Sarnowski// )->elements; 2128f8369d7dSTobias Sarnowski break; 2129f8369d7dSTobias Sarnowski case 'only-child': 2130f8369d7dSTobias Sarnowski $this->elements = $this->map( 2131a3095052SOscar Merida function ($node) { 2132a3095052SOscar Merida return pq($node)->siblings()->size() == 0 ? $node : null; 2133a3095052SOscar Merida } 2134f8369d7dSTobias Sarnowski )->elements; 2135f8369d7dSTobias Sarnowski break; 2136f8369d7dSTobias Sarnowski case 'first-child': 2137f8369d7dSTobias Sarnowski $this->elements = $this->map( 2138a3095052SOscar Merida function ($node) { 2139a3095052SOscar Merida return pq($node)->prevAll()->size() == 0 ? $node : null; 2140a3095052SOscar Merida } 2141f8369d7dSTobias Sarnowski )->elements; 2142f8369d7dSTobias Sarnowski break; 2143f8369d7dSTobias Sarnowski case 'last-child': 2144f8369d7dSTobias Sarnowski $this->elements = $this->map( 2145a3095052SOscar Merida function ($node) { 2146a3095052SOscar Merida return pq($node)->nextAll()->size() == 0 ? $node : null; 2147a3095052SOscar Merida } 2148f8369d7dSTobias Sarnowski )->elements; 2149f8369d7dSTobias Sarnowski break; 2150f8369d7dSTobias Sarnowski case 'nth-child': 2151f8369d7dSTobias Sarnowski $param = trim($args, "\"'"); 2152f8369d7dSTobias Sarnowski if (! $param) 2153f8369d7dSTobias Sarnowski break; 2154f8369d7dSTobias Sarnowski // nth-child(n+b) to nth-child(1n+b) 215563b6cc52SSyntaxseed if ($param[0] == 'n') 2156f8369d7dSTobias Sarnowski $param = '1'.$param; 2157f8369d7dSTobias Sarnowski // :nth-child(index/even/odd/equation) 2158f8369d7dSTobias Sarnowski if ($param == 'even' || $param == 'odd') 2159f8369d7dSTobias Sarnowski $mapped = $this->map( 2160a3095052SOscar Merida function ($node, $param) { 2161a3095052SOscar Merida $index = pq($node)->prevAll()->size() + 1; 2162f8369d7dSTobias Sarnowski if ($param == "even" && ($index % 2) == 0) 2163f8369d7dSTobias Sarnowski return $node; 2164f8369d7dSTobias Sarnowski else if ($param == "odd" && $index % 2 == 1) 2165f8369d7dSTobias Sarnowski return $node; 2166f8369d7dSTobias Sarnowski else 2167a3095052SOscar Merida return null; 2168a3095052SOscar Merida }, new CallbackParam(), $param 2169f8369d7dSTobias Sarnowski ); 217063b6cc52SSyntaxseed else if (mb_strlen($param) > 1 && $param[1] == 'n') 2171f8369d7dSTobias Sarnowski // an+b 2172f8369d7dSTobias Sarnowski $mapped = $this->map( 2173a3095052SOscar Merida function ($node, $param) { 2174a3095052SOscar Merida $prevs = pq($node)->prevAll()->size(); 2175f8369d7dSTobias Sarnowski $index = 1 + $prevs; 2176f8369d7dSTobias Sarnowski $b = mb_strlen($param) > 3 2177a3095052SOscar Merida ? $param[3] 2178f8369d7dSTobias Sarnowski : 0; 2179a3095052SOscar Merida $a = $param[0]; 2180a3095052SOscar Merida if ($b && $param[2] == "-") 2181f8369d7dSTobias Sarnowski $b = -$b; 2182f8369d7dSTobias Sarnowski if ($a > 0) { 2183f8369d7dSTobias Sarnowski return ($index - $b) % $a == 0 2184f8369d7dSTobias Sarnowski ? $node 2185f8369d7dSTobias Sarnowski : null; 2186f8369d7dSTobias Sarnowski phpQuery::debug($a . "*" . floor($index / $a) . "+$b-1 == " . ($a * floor($index / $a) + $b - 1) . " ?= $prevs"); 2187f8369d7dSTobias Sarnowski return $a * floor($index / $a) + $b - 1 == $prevs 2188f8369d7dSTobias Sarnowski ? $node 2189f8369d7dSTobias Sarnowski : null; 2190a3095052SOscar Merida } else if ($a == 0) { 2191f8369d7dSTobias Sarnowski return $index == $b 2192f8369d7dSTobias Sarnowski ? $node 2193f8369d7dSTobias Sarnowski : null; 2194a3095052SOscar Merida } else { 2195f8369d7dSTobias Sarnowski // negative value 2196f8369d7dSTobias Sarnowski return $index <= $b 2197f8369d7dSTobias Sarnowski ? $node 2198f8369d7dSTobias Sarnowski : null; 2199a3095052SOscar Merida } 2200f8369d7dSTobias Sarnowski// if (! $b) 2201f8369d7dSTobias Sarnowski// return $index%$a == 0 2202f8369d7dSTobias Sarnowski// ? $node 2203f8369d7dSTobias Sarnowski// : null; 2204f8369d7dSTobias Sarnowski// else 2205f8369d7dSTobias Sarnowski// return ($index-$b)%$a == 0 2206f8369d7dSTobias Sarnowski// ? $node 2207f8369d7dSTobias Sarnowski// : null; 2208a3095052SOscar Merida }, 2209f8369d7dSTobias Sarnowski new CallbackParam(), $param 2210f8369d7dSTobias Sarnowski ); 2211f8369d7dSTobias Sarnowski else 2212f8369d7dSTobias Sarnowski // index 2213f8369d7dSTobias Sarnowski $mapped = $this->map( 2214a3095052SOscar Merida function ($node, $index) { 2215a3095052SOscar Merida $prevs = pq($node)->prevAll()->size(); 2216f8369d7dSTobias Sarnowski if ($prevs && $prevs == $index - 1) 2217f8369d7dSTobias Sarnowski return $node; 2218f8369d7dSTobias Sarnowski else if (!$prevs && $index == 1) 2219f8369d7dSTobias Sarnowski return $node; 2220f8369d7dSTobias Sarnowski else 2221a3095052SOscar Merida return null; 2222a3095052SOscar Merida }, 2223f8369d7dSTobias Sarnowski new CallbackParam(), $param 2224f8369d7dSTobias Sarnowski ); 2225f8369d7dSTobias Sarnowski $this->elements = $mapped->elements; 2226f8369d7dSTobias Sarnowski break; 2227f8369d7dSTobias Sarnowski default: 2228f8369d7dSTobias Sarnowski $this->debug("Unknown pseudoclass '{$class}', skipping..."); 2229f8369d7dSTobias Sarnowski } 2230f8369d7dSTobias Sarnowski } 2231f8369d7dSTobias Sarnowski /** 2232f8369d7dSTobias Sarnowski * @access private 2233f8369d7dSTobias Sarnowski */ 2234e6a9d76fSSyntaxseed protected function pseudoClassParam($paramsString) { 2235f8369d7dSTobias Sarnowski // TODO; 2236f8369d7dSTobias Sarnowski } 2237f8369d7dSTobias Sarnowski /** 2238f8369d7dSTobias Sarnowski * Enter description here... 2239f8369d7dSTobias Sarnowski * 2240f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2241f8369d7dSTobias Sarnowski */ 2242f8369d7dSTobias Sarnowski public function is($selector, $nodes = null) { 2243f8369d7dSTobias Sarnowski phpQuery::debug(array("Is:", $selector)); 2244f8369d7dSTobias Sarnowski if (! $selector) 2245f8369d7dSTobias Sarnowski return false; 2246f8369d7dSTobias Sarnowski $oldStack = $this->elements; 2247f8369d7dSTobias Sarnowski $returnArray = false; 2248f8369d7dSTobias Sarnowski if ($nodes && is_array($nodes)) { 2249f8369d7dSTobias Sarnowski $this->elements = $nodes; 2250f8369d7dSTobias Sarnowski } else if ($nodes) 2251f8369d7dSTobias Sarnowski $this->elements = array($nodes); 2252f8369d7dSTobias Sarnowski $this->filter($selector, true); 2253f8369d7dSTobias Sarnowski $stack = $this->elements; 2254f8369d7dSTobias Sarnowski $this->elements = $oldStack; 2255f8369d7dSTobias Sarnowski if ($nodes) 2256f8369d7dSTobias Sarnowski return $stack ? $stack : null; 2257f8369d7dSTobias Sarnowski return (bool)count($stack); 2258f8369d7dSTobias Sarnowski } 2259f8369d7dSTobias Sarnowski /** 2260f8369d7dSTobias Sarnowski * Enter description here... 2261f8369d7dSTobias Sarnowski * jQuery difference. 2262f8369d7dSTobias Sarnowski * 2263f8369d7dSTobias Sarnowski * Callback: 2264f8369d7dSTobias Sarnowski * - $index int 2265f8369d7dSTobias Sarnowski * - $node DOMNode 2266f8369d7dSTobias Sarnowski * 2267f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2268f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Traversing/filter 2269f8369d7dSTobias Sarnowski */ 2270f8369d7dSTobias Sarnowski public function filterCallback($callback, $_skipHistory = false) { 2271f8369d7dSTobias Sarnowski if (! $_skipHistory) { 2272f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 2273f8369d7dSTobias Sarnowski $this->debug("Filtering by callback"); 2274f8369d7dSTobias Sarnowski } 2275f8369d7dSTobias Sarnowski $newStack = array(); 2276f8369d7dSTobias Sarnowski foreach($this->elements as $index => $node) { 2277f8369d7dSTobias Sarnowski $result = phpQuery::callbackRun($callback, array($index, $node)); 2278f8369d7dSTobias Sarnowski if (is_null($result) || (! is_null($result) && $result)) 2279f8369d7dSTobias Sarnowski $newStack[] = $node; 2280f8369d7dSTobias Sarnowski } 2281f8369d7dSTobias Sarnowski $this->elements = $newStack; 2282f8369d7dSTobias Sarnowski return $_skipHistory 2283f8369d7dSTobias Sarnowski ? $this 2284f8369d7dSTobias Sarnowski : $this->newInstance(); 2285f8369d7dSTobias Sarnowski } 2286f8369d7dSTobias Sarnowski /** 2287f8369d7dSTobias Sarnowski * Enter description here... 2288f8369d7dSTobias Sarnowski * 2289f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2290f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Traversing/filter 2291f8369d7dSTobias Sarnowski */ 2292f8369d7dSTobias Sarnowski public function filter($selectors, $_skipHistory = false) { 2293f8369d7dSTobias Sarnowski if ($selectors instanceof Callback OR $selectors instanceof Closure) 2294f8369d7dSTobias Sarnowski return $this->filterCallback($selectors, $_skipHistory); 2295f8369d7dSTobias Sarnowski if (! $_skipHistory) 2296f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 2297f8369d7dSTobias Sarnowski $notSimpleSelector = array(' ', '>', '~', '+', '/'); 2298f8369d7dSTobias Sarnowski if (! is_array($selectors)) 2299f8369d7dSTobias Sarnowski $selectors = $this->parseSelector($selectors); 2300f8369d7dSTobias Sarnowski if (! $_skipHistory) 2301f8369d7dSTobias Sarnowski $this->debug(array("Filtering:", $selectors)); 2302f8369d7dSTobias Sarnowski $finalStack = array(); 2303f8369d7dSTobias Sarnowski foreach($selectors as $selector) { 2304f8369d7dSTobias Sarnowski $stack = array(); 2305f8369d7dSTobias Sarnowski if (! $selector) 2306f8369d7dSTobias Sarnowski break; 2307f8369d7dSTobias Sarnowski // avoid first space or / 2308f8369d7dSTobias Sarnowski if (in_array($selector[0], $notSimpleSelector)) 2309f8369d7dSTobias Sarnowski $selector = array_slice($selector, 1); 2310f8369d7dSTobias Sarnowski // PER NODE selector chunks 2311f8369d7dSTobias Sarnowski foreach($this->stack() as $node) { 2312f8369d7dSTobias Sarnowski $break = false; 2313f8369d7dSTobias Sarnowski foreach($selector as $s) { 2314f8369d7dSTobias Sarnowski if (!($node instanceof DOMELEMENT)) { 2315f8369d7dSTobias Sarnowski // all besides DOMElement 2316f8369d7dSTobias Sarnowski if ( $s[0] == '[') { 2317f8369d7dSTobias Sarnowski $attr = trim($s, '[]'); 2318f8369d7dSTobias Sarnowski if ( mb_strpos($attr, '=')) { 2319f8369d7dSTobias Sarnowski list( $attr, $val ) = explode('=', $attr); 2320f8369d7dSTobias Sarnowski if ($attr == 'nodeType' && $node->nodeType != $val) 2321f8369d7dSTobias Sarnowski $break = true; 2322f8369d7dSTobias Sarnowski } 2323f8369d7dSTobias Sarnowski } else 2324f8369d7dSTobias Sarnowski $break = true; 2325f8369d7dSTobias Sarnowski } else { 2326f8369d7dSTobias Sarnowski // DOMElement only 2327f8369d7dSTobias Sarnowski // ID 2328f8369d7dSTobias Sarnowski if ( $s[0] == '#') { 2329f8369d7dSTobias Sarnowski if ( $node->getAttribute('id') != substr($s, 1) ) 2330f8369d7dSTobias Sarnowski $break = true; 2331f8369d7dSTobias Sarnowski // CLASSES 2332f8369d7dSTobias Sarnowski } else if ( $s[0] == '.') { 2333f8369d7dSTobias Sarnowski if (! $this->matchClasses( $s, $node ) ) 2334f8369d7dSTobias Sarnowski $break = true; 2335f8369d7dSTobias Sarnowski // ATTRS 2336f8369d7dSTobias Sarnowski } else if ( $s[0] == '[') { 2337f8369d7dSTobias Sarnowski // strip side brackets 2338f8369d7dSTobias Sarnowski $attr = trim($s, '[]'); 2339f8369d7dSTobias Sarnowski if (mb_strpos($attr, '=')) { 2340f8369d7dSTobias Sarnowski list($attr, $val) = explode('=', $attr); 2341f8369d7dSTobias Sarnowski $val = self::unQuote($val); 2342f8369d7dSTobias Sarnowski if ($attr == 'nodeType') { 2343f8369d7dSTobias Sarnowski if ($val != $node->nodeType) 2344f8369d7dSTobias Sarnowski $break = true; 2345f8369d7dSTobias Sarnowski } else if ($this->isRegexp($attr)) { 2346f8369d7dSTobias Sarnowski $val = extension_loaded('mbstring') && phpQuery::$mbstringSupport 2347f8369d7dSTobias Sarnowski ? quotemeta(trim($val, '"\'')) 2348f8369d7dSTobias Sarnowski : preg_quote(trim($val, '"\''), '@'); 2349f8369d7dSTobias Sarnowski // switch last character 2350f8369d7dSTobias Sarnowski switch( substr($attr, -1)) { 2351f8369d7dSTobias Sarnowski // quotemeta used insted of preg_quote 2352f8369d7dSTobias Sarnowski // http://code.google.com/p/phpquery/issues/detail?id=76 2353f8369d7dSTobias Sarnowski case '^': 2354f8369d7dSTobias Sarnowski $pattern = '^'.$val; 2355f8369d7dSTobias Sarnowski break; 2356f8369d7dSTobias Sarnowski case '*': 2357f8369d7dSTobias Sarnowski $pattern = '.*'.$val.'.*'; 2358f8369d7dSTobias Sarnowski break; 2359f8369d7dSTobias Sarnowski case '$': 2360f8369d7dSTobias Sarnowski $pattern = '.*'.$val.'$'; 2361f8369d7dSTobias Sarnowski break; 2362f8369d7dSTobias Sarnowski } 2363f8369d7dSTobias Sarnowski // cut last character 2364f8369d7dSTobias Sarnowski $attr = substr($attr, 0, -1); 2365f8369d7dSTobias Sarnowski $isMatch = extension_loaded('mbstring') && phpQuery::$mbstringSupport 2366f8369d7dSTobias Sarnowski ? mb_ereg_match($pattern, $node->getAttribute($attr)) 2367f8369d7dSTobias Sarnowski : preg_match("@{$pattern}@", $node->getAttribute($attr)); 2368f8369d7dSTobias Sarnowski if (! $isMatch) 2369f8369d7dSTobias Sarnowski $break = true; 2370f8369d7dSTobias Sarnowski } else if ($node->getAttribute($attr) != $val) 2371f8369d7dSTobias Sarnowski $break = true; 2372f8369d7dSTobias Sarnowski } else if (! $node->hasAttribute($attr)) 2373f8369d7dSTobias Sarnowski $break = true; 2374f8369d7dSTobias Sarnowski // PSEUDO CLASSES 2375f8369d7dSTobias Sarnowski } else if ( $s[0] == ':') { 2376f8369d7dSTobias Sarnowski // skip 2377f8369d7dSTobias Sarnowski // TAG 2378f8369d7dSTobias Sarnowski } else if (trim($s)) { 2379f8369d7dSTobias Sarnowski if ($s != '*') { 2380f8369d7dSTobias Sarnowski // TODO namespaces 2381f8369d7dSTobias Sarnowski if (isset($node->tagName)) { 2382f8369d7dSTobias Sarnowski if ($node->tagName != $s) 2383f8369d7dSTobias Sarnowski $break = true; 2384f8369d7dSTobias Sarnowski } else if ($s == 'html' && ! $this->isRoot($node)) 2385f8369d7dSTobias Sarnowski $break = true; 2386f8369d7dSTobias Sarnowski } 2387f8369d7dSTobias Sarnowski // AVOID NON-SIMPLE SELECTORS 2388f8369d7dSTobias Sarnowski } else if (in_array($s, $notSimpleSelector)) { 2389f8369d7dSTobias Sarnowski $break = true; 2390f8369d7dSTobias Sarnowski $this->debug(array('Skipping non simple selector', $selector)); 2391f8369d7dSTobias Sarnowski } 2392f8369d7dSTobias Sarnowski } 2393f8369d7dSTobias Sarnowski if ($break) 2394f8369d7dSTobias Sarnowski break; 2395f8369d7dSTobias Sarnowski } 2396f8369d7dSTobias Sarnowski // if element passed all chunks of selector - add it to new stack 2397f8369d7dSTobias Sarnowski if (! $break ) 2398f8369d7dSTobias Sarnowski $stack[] = $node; 2399f8369d7dSTobias Sarnowski } 2400f8369d7dSTobias Sarnowski $tmpStack = $this->elements; 2401f8369d7dSTobias Sarnowski $this->elements = $stack; 2402f8369d7dSTobias Sarnowski // PER ALL NODES selector chunks 2403f8369d7dSTobias Sarnowski foreach($selector as $s) 2404f8369d7dSTobias Sarnowski // PSEUDO CLASSES 2405f8369d7dSTobias Sarnowski if ($s[0] == ':') 2406f8369d7dSTobias Sarnowski $this->pseudoClasses($s); 2407f8369d7dSTobias Sarnowski foreach($this->elements as $node) 2408f8369d7dSTobias Sarnowski // XXX it should be merged without duplicates 2409f8369d7dSTobias Sarnowski // but jQuery doesnt do that 2410f8369d7dSTobias Sarnowski $finalStack[] = $node; 2411f8369d7dSTobias Sarnowski $this->elements = $tmpStack; 2412f8369d7dSTobias Sarnowski } 2413f8369d7dSTobias Sarnowski $this->elements = $finalStack; 2414f8369d7dSTobias Sarnowski if ($_skipHistory) { 2415f8369d7dSTobias Sarnowski return $this; 2416f8369d7dSTobias Sarnowski } else { 2417f8369d7dSTobias Sarnowski $this->debug("Stack length after filter(): ".count($finalStack)); 2418f8369d7dSTobias Sarnowski return $this->newInstance(); 2419f8369d7dSTobias Sarnowski } 2420f8369d7dSTobias Sarnowski } 2421f8369d7dSTobias Sarnowski /** 2422f8369d7dSTobias Sarnowski * 2423f8369d7dSTobias Sarnowski * @param $value 2424f8369d7dSTobias Sarnowski * @return unknown_type 2425f8369d7dSTobias Sarnowski * @TODO implement in all methods using passed parameters 2426f8369d7dSTobias Sarnowski */ 2427f8369d7dSTobias Sarnowski protected static function unQuote($value) { 2428f8369d7dSTobias Sarnowski return $value[0] == '\'' || $value[0] == '"' 2429f8369d7dSTobias Sarnowski ? substr($value, 1, -1) 2430f8369d7dSTobias Sarnowski : $value; 2431f8369d7dSTobias Sarnowski } 2432f8369d7dSTobias Sarnowski /** 2433f8369d7dSTobias Sarnowski * Enter description here... 2434f8369d7dSTobias Sarnowski * 2435f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Ajax/load 2436f8369d7dSTobias Sarnowski * @return phpQuery|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2437f8369d7dSTobias Sarnowski * @todo Support $selector 2438f8369d7dSTobias Sarnowski */ 2439f8369d7dSTobias Sarnowski public function load($url, $data = null, $callback = null) { 2440f8369d7dSTobias Sarnowski if ($data && ! is_array($data)) { 2441f8369d7dSTobias Sarnowski $callback = $data; 2442f8369d7dSTobias Sarnowski $data = null; 2443f8369d7dSTobias Sarnowski } 2444f8369d7dSTobias Sarnowski if (mb_strpos($url, ' ') !== false) { 2445f8369d7dSTobias Sarnowski $matches = null; 2446f8369d7dSTobias Sarnowski if (extension_loaded('mbstring') && phpQuery::$mbstringSupport) 2447f8369d7dSTobias Sarnowski mb_ereg('^([^ ]+) (.*)$', $url, $matches); 2448f8369d7dSTobias Sarnowski else 2449f8369d7dSTobias Sarnowski preg_match('^([^ ]+) (.*)$', $url, $matches); 2450f8369d7dSTobias Sarnowski $url = $matches[1]; 2451f8369d7dSTobias Sarnowski $selector = $matches[2]; 2452f8369d7dSTobias Sarnowski // FIXME this sucks, pass as callback param 2453f8369d7dSTobias Sarnowski $this->_loadSelector = $selector; 2454f8369d7dSTobias Sarnowski } 2455f8369d7dSTobias Sarnowski $ajax = array( 2456f8369d7dSTobias Sarnowski 'url' => $url, 2457f8369d7dSTobias Sarnowski 'type' => $data ? 'POST' : 'GET', 2458f8369d7dSTobias Sarnowski 'data' => $data, 2459f8369d7dSTobias Sarnowski 'complete' => $callback, 2460e6a9d76fSSyntaxseed 'success' => array($this, 'loadSuccess') 2461f8369d7dSTobias Sarnowski ); 2462f8369d7dSTobias Sarnowski phpQuery::ajax($ajax); 2463f8369d7dSTobias Sarnowski return $this; 2464f8369d7dSTobias Sarnowski } 2465f8369d7dSTobias Sarnowski /** 2466f8369d7dSTobias Sarnowski * @access private 2467f8369d7dSTobias Sarnowski * @param $html 2468f8369d7dSTobias Sarnowski * @return unknown_type 2469f8369d7dSTobias Sarnowski */ 2470e6a9d76fSSyntaxseed public function loadSuccess($html) { 2471f8369d7dSTobias Sarnowski if ($this->_loadSelector) { 2472f8369d7dSTobias Sarnowski $html = phpQuery::newDocument($html)->find($this->_loadSelector); 2473f8369d7dSTobias Sarnowski unset($this->_loadSelector); 2474f8369d7dSTobias Sarnowski } 2475f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 2476f8369d7dSTobias Sarnowski phpQuery::pq($node, $this->getDocumentID()) 2477f8369d7dSTobias Sarnowski ->markup($html); 2478f8369d7dSTobias Sarnowski } 2479f8369d7dSTobias Sarnowski } 2480f8369d7dSTobias Sarnowski /** 2481f8369d7dSTobias Sarnowski * Enter description here... 2482f8369d7dSTobias Sarnowski * 2483f8369d7dSTobias Sarnowski * @return phpQuery|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2484f8369d7dSTobias Sarnowski * @todo 2485f8369d7dSTobias Sarnowski */ 2486f8369d7dSTobias Sarnowski public function css() { 2487f8369d7dSTobias Sarnowski // TODO 2488f8369d7dSTobias Sarnowski return $this; 2489f8369d7dSTobias Sarnowski } 2490f8369d7dSTobias Sarnowski /** 2491f8369d7dSTobias Sarnowski * @todo 2492f8369d7dSTobias Sarnowski * 2493f8369d7dSTobias Sarnowski */ 2494f8369d7dSTobias Sarnowski public function show(){ 2495f8369d7dSTobias Sarnowski // TODO 2496f8369d7dSTobias Sarnowski return $this; 2497f8369d7dSTobias Sarnowski } 2498f8369d7dSTobias Sarnowski /** 2499f8369d7dSTobias Sarnowski * @todo 2500f8369d7dSTobias Sarnowski * 2501f8369d7dSTobias Sarnowski */ 2502f8369d7dSTobias Sarnowski public function hide(){ 2503f8369d7dSTobias Sarnowski // TODO 2504f8369d7dSTobias Sarnowski return $this; 2505f8369d7dSTobias Sarnowski } 2506f8369d7dSTobias Sarnowski /** 2507f8369d7dSTobias Sarnowski * Trigger a type of event on every matched element. 2508f8369d7dSTobias Sarnowski * 2509f8369d7dSTobias Sarnowski * @param unknown_type $type 2510f8369d7dSTobias Sarnowski * @param unknown_type $data 2511f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2512f8369d7dSTobias Sarnowski * @TODO support more than event in $type (space-separated) 2513f8369d7dSTobias Sarnowski */ 2514f8369d7dSTobias Sarnowski public function trigger($type, $data = array()) { 2515f8369d7dSTobias Sarnowski foreach($this->elements as $node) 2516f8369d7dSTobias Sarnowski phpQueryEvents::trigger($this->getDocumentID(), $type, $data, $node); 2517f8369d7dSTobias Sarnowski return $this; 2518f8369d7dSTobias Sarnowski } 2519f8369d7dSTobias Sarnowski /** 2520f8369d7dSTobias Sarnowski * This particular method triggers all bound event handlers on an element (for a specific event type) WITHOUT executing the browsers default actions. 2521f8369d7dSTobias Sarnowski * 2522f8369d7dSTobias Sarnowski * @param unknown_type $type 2523f8369d7dSTobias Sarnowski * @param unknown_type $data 2524f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2525f8369d7dSTobias Sarnowski * @TODO 2526f8369d7dSTobias Sarnowski */ 2527f8369d7dSTobias Sarnowski public function triggerHandler($type, $data = array()) { 2528f8369d7dSTobias Sarnowski // TODO; 2529f8369d7dSTobias Sarnowski } 2530f8369d7dSTobias Sarnowski /** 2531f8369d7dSTobias Sarnowski * Binds a handler to one or more events (like click) for each matched element. 2532f8369d7dSTobias Sarnowski * Can also bind custom events. 2533f8369d7dSTobias Sarnowski * 2534f8369d7dSTobias Sarnowski * @param unknown_type $type 2535f8369d7dSTobias Sarnowski * @param unknown_type $data Optional 2536f8369d7dSTobias Sarnowski * @param unknown_type $callback 2537f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2538f8369d7dSTobias Sarnowski * @TODO support '!' (exclusive) events 2539f8369d7dSTobias Sarnowski * @TODO support more than event in $type (space-separated) 2540f8369d7dSTobias Sarnowski */ 2541f8369d7dSTobias Sarnowski public function bind($type, $data, $callback = null) { 2542f8369d7dSTobias Sarnowski // TODO check if $data is callable, not using is_callable 2543f8369d7dSTobias Sarnowski if (! isset($callback)) { 2544f8369d7dSTobias Sarnowski $callback = $data; 2545f8369d7dSTobias Sarnowski $data = null; 2546f8369d7dSTobias Sarnowski } 2547f8369d7dSTobias Sarnowski foreach($this->elements as $node) 2548f8369d7dSTobias Sarnowski phpQueryEvents::add($this->getDocumentID(), $node, $type, $data, $callback); 2549f8369d7dSTobias Sarnowski return $this; 2550f8369d7dSTobias Sarnowski } 2551f8369d7dSTobias Sarnowski /** 2552f8369d7dSTobias Sarnowski * Enter description here... 2553f8369d7dSTobias Sarnowski * 2554f8369d7dSTobias Sarnowski * @param unknown_type $type 2555f8369d7dSTobias Sarnowski * @param unknown_type $callback 2556f8369d7dSTobias Sarnowski * @return unknown 2557f8369d7dSTobias Sarnowski * @TODO namespace events 2558f8369d7dSTobias Sarnowski * @TODO support more than event in $type (space-separated) 2559f8369d7dSTobias Sarnowski */ 2560f8369d7dSTobias Sarnowski public function unbind($type = null, $callback = null) { 2561f8369d7dSTobias Sarnowski foreach($this->elements as $node) 2562f8369d7dSTobias Sarnowski phpQueryEvents::remove($this->getDocumentID(), $node, $type, $callback); 2563f8369d7dSTobias Sarnowski return $this; 2564f8369d7dSTobias Sarnowski } 2565f8369d7dSTobias Sarnowski /** 2566f8369d7dSTobias Sarnowski * Enter description here... 2567f8369d7dSTobias Sarnowski * 2568f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2569f8369d7dSTobias Sarnowski */ 2570f8369d7dSTobias Sarnowski public function change($callback = null) { 2571f8369d7dSTobias Sarnowski if ($callback) 2572f8369d7dSTobias Sarnowski return $this->bind('change', $callback); 2573f8369d7dSTobias Sarnowski return $this->trigger('change'); 2574f8369d7dSTobias Sarnowski } 2575f8369d7dSTobias Sarnowski /** 2576f8369d7dSTobias Sarnowski * Enter description here... 2577f8369d7dSTobias Sarnowski * 2578f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2579f8369d7dSTobias Sarnowski */ 2580f8369d7dSTobias Sarnowski public function submit($callback = null) { 2581f8369d7dSTobias Sarnowski if ($callback) 2582f8369d7dSTobias Sarnowski return $this->bind('submit', $callback); 2583f8369d7dSTobias Sarnowski return $this->trigger('submit'); 2584f8369d7dSTobias Sarnowski } 2585f8369d7dSTobias Sarnowski /** 2586f8369d7dSTobias Sarnowski * Enter description here... 2587f8369d7dSTobias Sarnowski * 2588f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2589f8369d7dSTobias Sarnowski */ 2590f8369d7dSTobias Sarnowski public function click($callback = null) { 2591f8369d7dSTobias Sarnowski if ($callback) 2592f8369d7dSTobias Sarnowski return $this->bind('click', $callback); 2593f8369d7dSTobias Sarnowski return $this->trigger('click'); 2594f8369d7dSTobias Sarnowski } 2595f8369d7dSTobias Sarnowski /** 2596f8369d7dSTobias Sarnowski * Enter description here... 2597f8369d7dSTobias Sarnowski * 2598f8369d7dSTobias Sarnowski * @param String|phpQuery 2599f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2600f8369d7dSTobias Sarnowski */ 2601f8369d7dSTobias Sarnowski public function wrapAllOld($wrapper) { 2602f8369d7dSTobias Sarnowski $wrapper = pq($wrapper)->_clone(); 2603f8369d7dSTobias Sarnowski if (! $wrapper->length() || ! $this->length() ) 2604f8369d7dSTobias Sarnowski return $this; 2605f8369d7dSTobias Sarnowski $wrapper->insertBefore($this->elements[0]); 2606f8369d7dSTobias Sarnowski $deepest = $wrapper->elements[0]; 2607f8369d7dSTobias Sarnowski while($deepest->firstChild && $deepest->firstChild instanceof DOMELEMENT) 2608f8369d7dSTobias Sarnowski $deepest = $deepest->firstChild; 2609f8369d7dSTobias Sarnowski pq($deepest)->append($this); 2610f8369d7dSTobias Sarnowski return $this; 2611f8369d7dSTobias Sarnowski } 2612f8369d7dSTobias Sarnowski /** 2613f8369d7dSTobias Sarnowski * Enter description here... 2614f8369d7dSTobias Sarnowski * 2615f8369d7dSTobias Sarnowski * TODO testme... 2616f8369d7dSTobias Sarnowski * @param String|phpQuery 2617f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2618f8369d7dSTobias Sarnowski */ 2619f8369d7dSTobias Sarnowski public function wrapAll($wrapper) { 2620f8369d7dSTobias Sarnowski if (! $this->length()) 2621f8369d7dSTobias Sarnowski return $this; 2622f8369d7dSTobias Sarnowski return phpQuery::pq($wrapper, $this->getDocumentID()) 2623f8369d7dSTobias Sarnowski ->clone() 2624f8369d7dSTobias Sarnowski ->insertBefore($this->get(0)) 2625f8369d7dSTobias Sarnowski ->map(array($this, '___wrapAllCallback')) 2626f8369d7dSTobias Sarnowski ->append($this); 2627f8369d7dSTobias Sarnowski } 2628f8369d7dSTobias Sarnowski /** 2629f8369d7dSTobias Sarnowski * 2630f8369d7dSTobias Sarnowski * @param $node 2631f8369d7dSTobias Sarnowski * @return unknown_type 2632f8369d7dSTobias Sarnowski * @access private 2633f8369d7dSTobias Sarnowski */ 2634f8369d7dSTobias Sarnowski public function ___wrapAllCallback($node) { 2635f8369d7dSTobias Sarnowski $deepest = $node; 2636f8369d7dSTobias Sarnowski while($deepest->firstChild && $deepest->firstChild instanceof DOMELEMENT) 2637f8369d7dSTobias Sarnowski $deepest = $deepest->firstChild; 2638f8369d7dSTobias Sarnowski return $deepest; 2639f8369d7dSTobias Sarnowski } 2640f8369d7dSTobias Sarnowski /** 2641f8369d7dSTobias Sarnowski * Enter description here... 2642f8369d7dSTobias Sarnowski * NON JQUERY METHOD 2643f8369d7dSTobias Sarnowski * 2644f8369d7dSTobias Sarnowski * @param String|phpQuery 2645f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2646f8369d7dSTobias Sarnowski */ 2647f8369d7dSTobias Sarnowski public function wrapAllPHP($codeBefore, $codeAfter) { 2648f8369d7dSTobias Sarnowski return $this 2649f8369d7dSTobias Sarnowski ->slice(0, 1) 2650f8369d7dSTobias Sarnowski ->beforePHP($codeBefore) 2651f8369d7dSTobias Sarnowski ->end() 2652f8369d7dSTobias Sarnowski ->slice(-1) 2653f8369d7dSTobias Sarnowski ->afterPHP($codeAfter) 2654f8369d7dSTobias Sarnowski ->end(); 2655f8369d7dSTobias Sarnowski } 2656f8369d7dSTobias Sarnowski /** 2657f8369d7dSTobias Sarnowski * Enter description here... 2658f8369d7dSTobias Sarnowski * 2659f8369d7dSTobias Sarnowski * @param String|phpQuery 2660f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2661f8369d7dSTobias Sarnowski */ 2662f8369d7dSTobias Sarnowski public function wrap($wrapper) { 2663f8369d7dSTobias Sarnowski foreach($this->stack() as $node) 2664f8369d7dSTobias Sarnowski phpQuery::pq($node, $this->getDocumentID())->wrapAll($wrapper); 2665f8369d7dSTobias Sarnowski return $this; 2666f8369d7dSTobias Sarnowski } 2667f8369d7dSTobias Sarnowski /** 2668f8369d7dSTobias Sarnowski * Enter description here... 2669f8369d7dSTobias Sarnowski * 2670f8369d7dSTobias Sarnowski * @param String|phpQuery 2671f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2672f8369d7dSTobias Sarnowski */ 2673f8369d7dSTobias Sarnowski public function wrapPHP($codeBefore, $codeAfter) { 2674f8369d7dSTobias Sarnowski foreach($this->stack() as $node) 2675f8369d7dSTobias Sarnowski phpQuery::pq($node, $this->getDocumentID())->wrapAllPHP($codeBefore, $codeAfter); 2676f8369d7dSTobias Sarnowski return $this; 2677f8369d7dSTobias Sarnowski } 2678f8369d7dSTobias Sarnowski /** 2679f8369d7dSTobias Sarnowski * Enter description here... 2680f8369d7dSTobias Sarnowski * 2681f8369d7dSTobias Sarnowski * @param String|phpQuery 2682f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2683f8369d7dSTobias Sarnowski */ 2684f8369d7dSTobias Sarnowski public function wrapInner($wrapper) { 2685f8369d7dSTobias Sarnowski foreach($this->stack() as $node) 2686f8369d7dSTobias Sarnowski phpQuery::pq($node, $this->getDocumentID())->contents()->wrapAll($wrapper); 2687f8369d7dSTobias Sarnowski return $this; 2688f8369d7dSTobias Sarnowski } 2689f8369d7dSTobias Sarnowski /** 2690f8369d7dSTobias Sarnowski * Enter description here... 2691f8369d7dSTobias Sarnowski * 2692f8369d7dSTobias Sarnowski * @param String|phpQuery 2693f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2694f8369d7dSTobias Sarnowski */ 2695f8369d7dSTobias Sarnowski public function wrapInnerPHP($codeBefore, $codeAfter) { 2696f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) 2697f8369d7dSTobias Sarnowski phpQuery::pq($node, $this->getDocumentID())->contents() 2698f8369d7dSTobias Sarnowski ->wrapAllPHP($codeBefore, $codeAfter); 2699f8369d7dSTobias Sarnowski return $this; 2700f8369d7dSTobias Sarnowski } 2701f8369d7dSTobias Sarnowski /** 2702f8369d7dSTobias Sarnowski * Enter description here... 2703f8369d7dSTobias Sarnowski * 2704f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2705f8369d7dSTobias Sarnowski * @testme Support for text nodes 2706f8369d7dSTobias Sarnowski */ 2707f8369d7dSTobias Sarnowski public function contents() { 2708f8369d7dSTobias Sarnowski $stack = array(); 2709f8369d7dSTobias Sarnowski foreach($this->stack(1) as $el) { 2710f8369d7dSTobias Sarnowski // FIXME (fixed) http://code.google.com/p/phpquery/issues/detail?id=56 2711f8369d7dSTobias Sarnowski// if (! isset($el->childNodes)) 2712f8369d7dSTobias Sarnowski// continue; 2713f8369d7dSTobias Sarnowski foreach($el->childNodes as $node) { 2714f8369d7dSTobias Sarnowski $stack[] = $node; 2715f8369d7dSTobias Sarnowski } 2716f8369d7dSTobias Sarnowski } 2717f8369d7dSTobias Sarnowski return $this->newInstance($stack); 2718f8369d7dSTobias Sarnowski } 2719f8369d7dSTobias Sarnowski /** 2720f8369d7dSTobias Sarnowski * Enter description here... 2721f8369d7dSTobias Sarnowski * 2722f8369d7dSTobias Sarnowski * jQuery difference. 2723f8369d7dSTobias Sarnowski * 2724f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2725f8369d7dSTobias Sarnowski */ 2726f8369d7dSTobias Sarnowski public function contentsUnwrap() { 2727f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 2728f8369d7dSTobias Sarnowski if (! $node->parentNode ) 2729f8369d7dSTobias Sarnowski continue; 2730f8369d7dSTobias Sarnowski $childNodes = array(); 2731f8369d7dSTobias Sarnowski // any modification in DOM tree breaks childNodes iteration, so cache them first 2732f8369d7dSTobias Sarnowski foreach($node->childNodes as $chNode ) 2733f8369d7dSTobias Sarnowski $childNodes[] = $chNode; 2734f8369d7dSTobias Sarnowski foreach($childNodes as $chNode ) 2735f8369d7dSTobias Sarnowski// $node->parentNode->appendChild($chNode); 2736f8369d7dSTobias Sarnowski $node->parentNode->insertBefore($chNode, $node); 2737f8369d7dSTobias Sarnowski $node->parentNode->removeChild($node); 2738f8369d7dSTobias Sarnowski } 2739f8369d7dSTobias Sarnowski return $this; 2740f8369d7dSTobias Sarnowski } 2741f8369d7dSTobias Sarnowski /** 2742f8369d7dSTobias Sarnowski * Enter description here... 2743f8369d7dSTobias Sarnowski * 2744f8369d7dSTobias Sarnowski * jQuery difference. 2745f8369d7dSTobias Sarnowski */ 2746f8369d7dSTobias Sarnowski public function switchWith($markup) { 2747f8369d7dSTobias Sarnowski $markup = pq($markup, $this->getDocumentID()); 2748f8369d7dSTobias Sarnowski $content = null; 2749f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 2750f8369d7dSTobias Sarnowski pq($node) 2751f8369d7dSTobias Sarnowski ->contents()->toReference($content)->end() 2752f8369d7dSTobias Sarnowski ->replaceWith($markup->clone()->append($content)); 2753f8369d7dSTobias Sarnowski } 2754f8369d7dSTobias Sarnowski return $this; 2755f8369d7dSTobias Sarnowski } 2756f8369d7dSTobias Sarnowski /** 2757f8369d7dSTobias Sarnowski * Enter description here... 2758f8369d7dSTobias Sarnowski * 2759f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2760f8369d7dSTobias Sarnowski */ 2761f8369d7dSTobias Sarnowski public function eq($num) { 2762f8369d7dSTobias Sarnowski $oldStack = $this->elements; 2763f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 2764f8369d7dSTobias Sarnowski $this->elements = array(); 2765f8369d7dSTobias Sarnowski if ( isset($oldStack[$num]) ) 2766f8369d7dSTobias Sarnowski $this->elements[] = $oldStack[$num]; 2767f8369d7dSTobias Sarnowski return $this->newInstance(); 2768f8369d7dSTobias Sarnowski } 2769f8369d7dSTobias Sarnowski /** 2770f8369d7dSTobias Sarnowski * Enter description here... 2771f8369d7dSTobias Sarnowski * 2772f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2773f8369d7dSTobias Sarnowski */ 2774f8369d7dSTobias Sarnowski public function size() { 2775f8369d7dSTobias Sarnowski return count($this->elements); 2776f8369d7dSTobias Sarnowski } 2777f8369d7dSTobias Sarnowski /** 2778f8369d7dSTobias Sarnowski * Enter description here... 2779f8369d7dSTobias Sarnowski * 2780f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2781f8369d7dSTobias Sarnowski * @deprecated Use length as attribute 2782f8369d7dSTobias Sarnowski */ 2783f8369d7dSTobias Sarnowski public function length() { 2784f8369d7dSTobias Sarnowski return $this->size(); 2785f8369d7dSTobias Sarnowski } 2786f8369d7dSTobias Sarnowski public function count() { 2787f8369d7dSTobias Sarnowski return $this->size(); 2788f8369d7dSTobias Sarnowski } 2789f8369d7dSTobias Sarnowski /** 2790f8369d7dSTobias Sarnowski * Enter description here... 2791f8369d7dSTobias Sarnowski * 2792f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2793f8369d7dSTobias Sarnowski * @todo $level 2794f8369d7dSTobias Sarnowski */ 2795f8369d7dSTobias Sarnowski public function end($level = 1) { 2796f8369d7dSTobias Sarnowski// $this->elements = array_pop( $this->history ); 2797f8369d7dSTobias Sarnowski// return $this; 2798f8369d7dSTobias Sarnowski// $this->previous->DOM = $this->DOM; 2799f8369d7dSTobias Sarnowski// $this->previous->XPath = $this->XPath; 2800f8369d7dSTobias Sarnowski return $this->previous 2801f8369d7dSTobias Sarnowski ? $this->previous 2802f8369d7dSTobias Sarnowski : $this; 2803f8369d7dSTobias Sarnowski } 2804f8369d7dSTobias Sarnowski /** 2805f8369d7dSTobias Sarnowski * Enter description here... 2806f8369d7dSTobias Sarnowski * Normal use ->clone() . 2807f8369d7dSTobias Sarnowski * 2808f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2809f8369d7dSTobias Sarnowski * @access private 2810f8369d7dSTobias Sarnowski */ 2811f8369d7dSTobias Sarnowski public function _clone() { 2812f8369d7dSTobias Sarnowski $newStack = array(); 2813f8369d7dSTobias Sarnowski //pr(array('copy... ', $this->whois())); 2814f8369d7dSTobias Sarnowski //$this->dumpHistory('copy'); 2815f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 2816f8369d7dSTobias Sarnowski foreach($this->elements as $node) { 2817f8369d7dSTobias Sarnowski $newStack[] = $node->cloneNode(true); 2818f8369d7dSTobias Sarnowski } 2819f8369d7dSTobias Sarnowski $this->elements = $newStack; 2820f8369d7dSTobias Sarnowski return $this->newInstance(); 2821f8369d7dSTobias Sarnowski } 2822f8369d7dSTobias Sarnowski /** 2823f8369d7dSTobias Sarnowski * Enter description here... 2824f8369d7dSTobias Sarnowski * 2825f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2826f8369d7dSTobias Sarnowski */ 2827f8369d7dSTobias Sarnowski public function replaceWithPHP($code) { 2828f8369d7dSTobias Sarnowski return $this->replaceWith(phpQuery::php($code)); 2829f8369d7dSTobias Sarnowski } 2830f8369d7dSTobias Sarnowski /** 2831f8369d7dSTobias Sarnowski * Enter description here... 2832f8369d7dSTobias Sarnowski * 2833f8369d7dSTobias Sarnowski * @param String|phpQuery $content 2834f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Manipulation/replaceWith#content 2835f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2836f8369d7dSTobias Sarnowski */ 2837f8369d7dSTobias Sarnowski public function replaceWith($content) { 2838f8369d7dSTobias Sarnowski return $this->after($content)->remove(); 2839f8369d7dSTobias Sarnowski } 2840f8369d7dSTobias Sarnowski /** 2841f8369d7dSTobias Sarnowski * Enter description here... 2842f8369d7dSTobias Sarnowski * 2843f8369d7dSTobias Sarnowski * @param String $selector 2844f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2845f8369d7dSTobias Sarnowski * @todo this works ? 2846f8369d7dSTobias Sarnowski */ 2847f8369d7dSTobias Sarnowski public function replaceAll($selector) { 2848f8369d7dSTobias Sarnowski foreach(phpQuery::pq($selector, $this->getDocumentID()) as $node) 2849f8369d7dSTobias Sarnowski phpQuery::pq($node, $this->getDocumentID()) 2850f8369d7dSTobias Sarnowski ->after($this->_clone()) 2851f8369d7dSTobias Sarnowski ->remove(); 2852f8369d7dSTobias Sarnowski return $this; 2853f8369d7dSTobias Sarnowski } 2854f8369d7dSTobias Sarnowski /** 2855f8369d7dSTobias Sarnowski * Enter description here... 2856f8369d7dSTobias Sarnowski * 2857f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2858f8369d7dSTobias Sarnowski */ 2859f8369d7dSTobias Sarnowski public function remove($selector = null) { 2860f8369d7dSTobias Sarnowski $loop = $selector 2861f8369d7dSTobias Sarnowski ? $this->filter($selector)->elements 2862f8369d7dSTobias Sarnowski : $this->elements; 2863f8369d7dSTobias Sarnowski foreach($loop as $node) { 2864f8369d7dSTobias Sarnowski if (! $node->parentNode ) 2865f8369d7dSTobias Sarnowski continue; 2866f8369d7dSTobias Sarnowski if (isset($node->tagName)) 2867f8369d7dSTobias Sarnowski $this->debug("Removing '{$node->tagName}'"); 2868f8369d7dSTobias Sarnowski $node->parentNode->removeChild($node); 2869f8369d7dSTobias Sarnowski // Mutation event 2870f8369d7dSTobias Sarnowski $event = new DOMEvent(array( 2871f8369d7dSTobias Sarnowski 'target' => $node, 2872f8369d7dSTobias Sarnowski 'type' => 'DOMNodeRemoved' 2873f8369d7dSTobias Sarnowski )); 2874f8369d7dSTobias Sarnowski phpQueryEvents::trigger($this->getDocumentID(), 2875f8369d7dSTobias Sarnowski $event->type, array($event), $node 2876f8369d7dSTobias Sarnowski ); 2877f8369d7dSTobias Sarnowski } 2878f8369d7dSTobias Sarnowski return $this; 2879f8369d7dSTobias Sarnowski } 2880f8369d7dSTobias Sarnowski protected function markupEvents($newMarkup, $oldMarkup, $node) { 2881f8369d7dSTobias Sarnowski if ($node->tagName == 'textarea' && $newMarkup != $oldMarkup) { 2882f8369d7dSTobias Sarnowski $event = new DOMEvent(array( 2883f8369d7dSTobias Sarnowski 'target' => $node, 2884f8369d7dSTobias Sarnowski 'type' => 'change' 2885f8369d7dSTobias Sarnowski )); 2886f8369d7dSTobias Sarnowski phpQueryEvents::trigger($this->getDocumentID(), 2887f8369d7dSTobias Sarnowski $event->type, array($event), $node 2888f8369d7dSTobias Sarnowski ); 2889f8369d7dSTobias Sarnowski } 2890f8369d7dSTobias Sarnowski } 2891f8369d7dSTobias Sarnowski /** 2892f8369d7dSTobias Sarnowski * jQuey difference 2893f8369d7dSTobias Sarnowski * 2894f8369d7dSTobias Sarnowski * @param $markup 2895f8369d7dSTobias Sarnowski * @return unknown_type 2896f8369d7dSTobias Sarnowski * @TODO trigger change event for textarea 2897f8369d7dSTobias Sarnowski */ 2898f8369d7dSTobias Sarnowski public function markup($markup = null, $callback1 = null, $callback2 = null, $callback3 = null) { 2899f8369d7dSTobias Sarnowski $args = func_get_args(); 2900f8369d7dSTobias Sarnowski if ($this->documentWrapper->isXML) 2901f8369d7dSTobias Sarnowski return call_user_func_array(array($this, 'xml'), $args); 2902f8369d7dSTobias Sarnowski else 2903f8369d7dSTobias Sarnowski return call_user_func_array(array($this, 'html'), $args); 2904f8369d7dSTobias Sarnowski } 2905f8369d7dSTobias Sarnowski /** 2906f8369d7dSTobias Sarnowski * jQuey difference 2907f8369d7dSTobias Sarnowski * 2908f8369d7dSTobias Sarnowski * @param $markup 2909f8369d7dSTobias Sarnowski * @return unknown_type 2910f8369d7dSTobias Sarnowski */ 2911f8369d7dSTobias Sarnowski public function markupOuter($callback1 = null, $callback2 = null, $callback3 = null) { 2912f8369d7dSTobias Sarnowski $args = func_get_args(); 2913f8369d7dSTobias Sarnowski if ($this->documentWrapper->isXML) 2914f8369d7dSTobias Sarnowski return call_user_func_array(array($this, 'xmlOuter'), $args); 2915f8369d7dSTobias Sarnowski else 2916f8369d7dSTobias Sarnowski return call_user_func_array(array($this, 'htmlOuter'), $args); 2917f8369d7dSTobias Sarnowski } 2918f8369d7dSTobias Sarnowski /** 2919f8369d7dSTobias Sarnowski * Enter description here... 2920f8369d7dSTobias Sarnowski * 2921f8369d7dSTobias Sarnowski * @param unknown_type $html 2922f8369d7dSTobias Sarnowski * @return string|phpQuery|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2923f8369d7dSTobias Sarnowski * @TODO force html result 2924f8369d7dSTobias Sarnowski */ 2925f8369d7dSTobias Sarnowski public function html($html = null, $callback1 = null, $callback2 = null, $callback3 = null) { 2926f8369d7dSTobias Sarnowski if (isset($html)) { 2927f8369d7dSTobias Sarnowski // INSERT 2928f8369d7dSTobias Sarnowski $nodes = $this->documentWrapper->import($html); 2929f8369d7dSTobias Sarnowski $this->empty(); 2930f8369d7dSTobias Sarnowski foreach($this->stack(1) as $alreadyAdded => $node) { 2931f8369d7dSTobias Sarnowski // for now, limit events for textarea 2932f8369d7dSTobias Sarnowski if (($this->isXHTML() || $this->isHTML()) && $node->tagName == 'textarea') 2933f8369d7dSTobias Sarnowski $oldHtml = pq($node, $this->getDocumentID())->markup(); 2934f8369d7dSTobias Sarnowski foreach($nodes as $newNode) { 2935f8369d7dSTobias Sarnowski $node->appendChild($alreadyAdded 2936f8369d7dSTobias Sarnowski ? $newNode->cloneNode(true) 2937f8369d7dSTobias Sarnowski : $newNode 2938f8369d7dSTobias Sarnowski ); 2939f8369d7dSTobias Sarnowski } 2940f8369d7dSTobias Sarnowski // for now, limit events for textarea 2941f8369d7dSTobias Sarnowski if (($this->isXHTML() || $this->isHTML()) && $node->tagName == 'textarea') 2942f8369d7dSTobias Sarnowski $this->markupEvents($html, $oldHtml, $node); 2943f8369d7dSTobias Sarnowski } 2944f8369d7dSTobias Sarnowski return $this; 2945f8369d7dSTobias Sarnowski } else { 2946f8369d7dSTobias Sarnowski // FETCH 2947f8369d7dSTobias Sarnowski $return = $this->documentWrapper->markup($this->elements, true); 2948f8369d7dSTobias Sarnowski $args = func_get_args(); 2949f8369d7dSTobias Sarnowski foreach(array_slice($args, 1) as $callback) { 2950f8369d7dSTobias Sarnowski $return = phpQuery::callbackRun($callback, array($return)); 2951f8369d7dSTobias Sarnowski } 2952f8369d7dSTobias Sarnowski return $return; 2953f8369d7dSTobias Sarnowski } 2954f8369d7dSTobias Sarnowski } 2955f8369d7dSTobias Sarnowski /** 2956f8369d7dSTobias Sarnowski * @TODO force xml result 2957f8369d7dSTobias Sarnowski */ 2958f8369d7dSTobias Sarnowski public function xml($xml = null, $callback1 = null, $callback2 = null, $callback3 = null) { 2959f8369d7dSTobias Sarnowski $args = func_get_args(); 2960f8369d7dSTobias Sarnowski return call_user_func_array(array($this, 'html'), $args); 2961f8369d7dSTobias Sarnowski } 2962f8369d7dSTobias Sarnowski /** 2963f8369d7dSTobias Sarnowski * Enter description here... 2964f8369d7dSTobias Sarnowski * @TODO force html result 2965f8369d7dSTobias Sarnowski * 2966f8369d7dSTobias Sarnowski * @return String 2967f8369d7dSTobias Sarnowski */ 2968f8369d7dSTobias Sarnowski public function htmlOuter($callback1 = null, $callback2 = null, $callback3 = null) { 2969f8369d7dSTobias Sarnowski $markup = $this->documentWrapper->markup($this->elements); 2970f8369d7dSTobias Sarnowski // pass thou callbacks 2971f8369d7dSTobias Sarnowski $args = func_get_args(); 2972f8369d7dSTobias Sarnowski foreach($args as $callback) { 2973f8369d7dSTobias Sarnowski $markup = phpQuery::callbackRun($callback, array($markup)); 2974f8369d7dSTobias Sarnowski } 2975f8369d7dSTobias Sarnowski return $markup; 2976f8369d7dSTobias Sarnowski } 2977f8369d7dSTobias Sarnowski /** 2978f8369d7dSTobias Sarnowski * @TODO force xml result 2979f8369d7dSTobias Sarnowski */ 2980f8369d7dSTobias Sarnowski public function xmlOuter($callback1 = null, $callback2 = null, $callback3 = null) { 2981f8369d7dSTobias Sarnowski $args = func_get_args(); 2982f8369d7dSTobias Sarnowski return call_user_func_array(array($this, 'htmlOuter'), $args); 2983f8369d7dSTobias Sarnowski } 2984f8369d7dSTobias Sarnowski public function __toString() { 2985f8369d7dSTobias Sarnowski return $this->markupOuter(); 2986f8369d7dSTobias Sarnowski } 2987f8369d7dSTobias Sarnowski /** 2988f8369d7dSTobias Sarnowski * Just like html(), but returns markup with VALID (dangerous) PHP tags. 2989f8369d7dSTobias Sarnowski * 2990f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 2991f8369d7dSTobias Sarnowski * @todo support returning markup with PHP tags when called without param 2992f8369d7dSTobias Sarnowski */ 2993f8369d7dSTobias Sarnowski public function php($code = null) { 2994f8369d7dSTobias Sarnowski return $this->markupPHP($code); 2995f8369d7dSTobias Sarnowski } 2996f8369d7dSTobias Sarnowski /** 2997f8369d7dSTobias Sarnowski * Enter description here... 2998f8369d7dSTobias Sarnowski * 2999f8369d7dSTobias Sarnowski * @param $code 3000f8369d7dSTobias Sarnowski * @return unknown_type 3001f8369d7dSTobias Sarnowski */ 3002f8369d7dSTobias Sarnowski public function markupPHP($code = null) { 3003f8369d7dSTobias Sarnowski return isset($code) 3004f8369d7dSTobias Sarnowski ? $this->markup(phpQuery::php($code)) 3005f8369d7dSTobias Sarnowski : phpQuery::markupToPHP($this->markup()); 3006f8369d7dSTobias Sarnowski } 3007f8369d7dSTobias Sarnowski /** 3008f8369d7dSTobias Sarnowski * Enter description here... 3009f8369d7dSTobias Sarnowski * 3010f8369d7dSTobias Sarnowski * @param $code 3011f8369d7dSTobias Sarnowski * @return unknown_type 3012f8369d7dSTobias Sarnowski */ 3013f8369d7dSTobias Sarnowski public function markupOuterPHP() { 3014f8369d7dSTobias Sarnowski return phpQuery::markupToPHP($this->markupOuter()); 3015f8369d7dSTobias Sarnowski } 3016f8369d7dSTobias Sarnowski /** 3017f8369d7dSTobias Sarnowski * Enter description here... 3018f8369d7dSTobias Sarnowski * 3019f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3020f8369d7dSTobias Sarnowski */ 3021f8369d7dSTobias Sarnowski public function children($selector = null) { 3022f8369d7dSTobias Sarnowski $stack = array(); 3023f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3024f8369d7dSTobias Sarnowski// foreach($node->getElementsByTagName('*') as $newNode) { 3025f8369d7dSTobias Sarnowski foreach($node->childNodes as $newNode) { 3026f8369d7dSTobias Sarnowski if ($newNode->nodeType != 1) 3027f8369d7dSTobias Sarnowski continue; 3028f8369d7dSTobias Sarnowski if ($selector && ! $this->is($selector, $newNode)) 3029f8369d7dSTobias Sarnowski continue; 3030f8369d7dSTobias Sarnowski if ($this->elementsContainsNode($newNode, $stack)) 3031f8369d7dSTobias Sarnowski continue; 3032f8369d7dSTobias Sarnowski $stack[] = $newNode; 3033f8369d7dSTobias Sarnowski } 3034f8369d7dSTobias Sarnowski } 3035f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 3036f8369d7dSTobias Sarnowski $this->elements = $stack; 3037f8369d7dSTobias Sarnowski return $this->newInstance(); 3038f8369d7dSTobias Sarnowski } 3039f8369d7dSTobias Sarnowski /** 3040f8369d7dSTobias Sarnowski * Enter description here... 3041f8369d7dSTobias Sarnowski * 3042f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3043f8369d7dSTobias Sarnowski */ 3044f8369d7dSTobias Sarnowski public function ancestors($selector = null) { 3045f8369d7dSTobias Sarnowski return $this->children( $selector ); 3046f8369d7dSTobias Sarnowski } 3047f8369d7dSTobias Sarnowski /** 3048f8369d7dSTobias Sarnowski * Enter description here... 3049f8369d7dSTobias Sarnowski * 3050f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3051f8369d7dSTobias Sarnowski */ 3052f8369d7dSTobias Sarnowski public function append( $content) { 3053f8369d7dSTobias Sarnowski return $this->insert($content, __FUNCTION__); 3054f8369d7dSTobias Sarnowski } 3055f8369d7dSTobias Sarnowski /** 3056f8369d7dSTobias Sarnowski * Enter description here... 3057f8369d7dSTobias Sarnowski * 3058f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3059f8369d7dSTobias Sarnowski */ 3060f8369d7dSTobias Sarnowski public function appendPHP( $content) { 3061f8369d7dSTobias Sarnowski return $this->insert("<php><!-- {$content} --></php>", 'append'); 3062f8369d7dSTobias Sarnowski } 3063f8369d7dSTobias Sarnowski /** 3064f8369d7dSTobias Sarnowski * Enter description here... 3065f8369d7dSTobias Sarnowski * 3066f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3067f8369d7dSTobias Sarnowski */ 3068f8369d7dSTobias Sarnowski public function appendTo( $seletor) { 3069f8369d7dSTobias Sarnowski return $this->insert($seletor, __FUNCTION__); 3070f8369d7dSTobias Sarnowski } 3071f8369d7dSTobias Sarnowski /** 3072f8369d7dSTobias Sarnowski * Enter description here... 3073f8369d7dSTobias Sarnowski * 3074f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3075f8369d7dSTobias Sarnowski */ 3076f8369d7dSTobias Sarnowski public function prepend( $content) { 3077f8369d7dSTobias Sarnowski return $this->insert($content, __FUNCTION__); 3078f8369d7dSTobias Sarnowski } 3079f8369d7dSTobias Sarnowski /** 3080f8369d7dSTobias Sarnowski * Enter description here... 3081f8369d7dSTobias Sarnowski * 3082f8369d7dSTobias Sarnowski * @todo accept many arguments, which are joined, arrays maybe also 3083f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3084f8369d7dSTobias Sarnowski */ 3085f8369d7dSTobias Sarnowski public function prependPHP( $content) { 3086f8369d7dSTobias Sarnowski return $this->insert("<php><!-- {$content} --></php>", 'prepend'); 3087f8369d7dSTobias Sarnowski } 3088f8369d7dSTobias Sarnowski /** 3089f8369d7dSTobias Sarnowski * Enter description here... 3090f8369d7dSTobias Sarnowski * 3091f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3092f8369d7dSTobias Sarnowski */ 3093f8369d7dSTobias Sarnowski public function prependTo( $seletor) { 3094f8369d7dSTobias Sarnowski return $this->insert($seletor, __FUNCTION__); 3095f8369d7dSTobias Sarnowski } 3096f8369d7dSTobias Sarnowski /** 3097f8369d7dSTobias Sarnowski * Enter description here... 3098f8369d7dSTobias Sarnowski * 3099f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3100f8369d7dSTobias Sarnowski */ 3101f8369d7dSTobias Sarnowski public function before($content) { 3102f8369d7dSTobias Sarnowski return $this->insert($content, __FUNCTION__); 3103f8369d7dSTobias Sarnowski } 3104f8369d7dSTobias Sarnowski /** 3105f8369d7dSTobias Sarnowski * Enter description here... 3106f8369d7dSTobias Sarnowski * 3107f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3108f8369d7dSTobias Sarnowski */ 3109f8369d7dSTobias Sarnowski public function beforePHP( $content) { 3110f8369d7dSTobias Sarnowski return $this->insert("<php><!-- {$content} --></php>", 'before'); 3111f8369d7dSTobias Sarnowski } 3112f8369d7dSTobias Sarnowski /** 3113f8369d7dSTobias Sarnowski * Enter description here... 3114f8369d7dSTobias Sarnowski * 3115f8369d7dSTobias Sarnowski * @param String|phpQuery 3116f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3117f8369d7dSTobias Sarnowski */ 3118f8369d7dSTobias Sarnowski public function insertBefore( $seletor) { 3119f8369d7dSTobias Sarnowski return $this->insert($seletor, __FUNCTION__); 3120f8369d7dSTobias Sarnowski } 3121f8369d7dSTobias Sarnowski /** 3122f8369d7dSTobias Sarnowski * Enter description here... 3123f8369d7dSTobias Sarnowski * 3124f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3125f8369d7dSTobias Sarnowski */ 3126f8369d7dSTobias Sarnowski public function after( $content) { 3127f8369d7dSTobias Sarnowski return $this->insert($content, __FUNCTION__); 3128f8369d7dSTobias Sarnowski } 3129f8369d7dSTobias Sarnowski /** 3130f8369d7dSTobias Sarnowski * Enter description here... 3131f8369d7dSTobias Sarnowski * 3132f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3133f8369d7dSTobias Sarnowski */ 3134f8369d7dSTobias Sarnowski public function afterPHP( $content) { 3135f8369d7dSTobias Sarnowski return $this->insert("<php><!-- {$content} --></php>", 'after'); 3136f8369d7dSTobias Sarnowski } 3137f8369d7dSTobias Sarnowski /** 3138f8369d7dSTobias Sarnowski * Enter description here... 3139f8369d7dSTobias Sarnowski * 3140f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3141f8369d7dSTobias Sarnowski */ 3142f8369d7dSTobias Sarnowski public function insertAfter( $seletor) { 3143f8369d7dSTobias Sarnowski return $this->insert($seletor, __FUNCTION__); 3144f8369d7dSTobias Sarnowski } 3145f8369d7dSTobias Sarnowski /** 3146f8369d7dSTobias Sarnowski * Internal insert method. Don't use it. 3147f8369d7dSTobias Sarnowski * 3148f8369d7dSTobias Sarnowski * @param unknown_type $target 3149f8369d7dSTobias Sarnowski * @param unknown_type $type 3150f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3151f8369d7dSTobias Sarnowski * @access private 3152f8369d7dSTobias Sarnowski */ 3153f8369d7dSTobias Sarnowski public function insert($target, $type) { 3154f8369d7dSTobias Sarnowski $this->debug("Inserting data with '{$type}'"); 3155f8369d7dSTobias Sarnowski $to = false; 3156f8369d7dSTobias Sarnowski switch( $type) { 3157f8369d7dSTobias Sarnowski case 'appendTo': 3158f8369d7dSTobias Sarnowski case 'prependTo': 3159f8369d7dSTobias Sarnowski case 'insertBefore': 3160f8369d7dSTobias Sarnowski case 'insertAfter': 3161f8369d7dSTobias Sarnowski $to = true; 3162f8369d7dSTobias Sarnowski } 3163f8369d7dSTobias Sarnowski switch(gettype($target)) { 3164f8369d7dSTobias Sarnowski case 'string': 3165f8369d7dSTobias Sarnowski $insertFrom = $insertTo = array(); 3166f8369d7dSTobias Sarnowski if ($to) { 3167f8369d7dSTobias Sarnowski // INSERT TO 3168f8369d7dSTobias Sarnowski $insertFrom = $this->elements; 3169f8369d7dSTobias Sarnowski if (phpQuery::isMarkup($target)) { 3170f8369d7dSTobias Sarnowski // $target is new markup, import it 3171f8369d7dSTobias Sarnowski $insertTo = $this->documentWrapper->import($target); 3172f8369d7dSTobias Sarnowski // insert into selected element 3173f8369d7dSTobias Sarnowski } else { 3174f8369d7dSTobias Sarnowski // $tagret is a selector 3175f8369d7dSTobias Sarnowski $thisStack = $this->elements; 3176f8369d7dSTobias Sarnowski $this->toRoot(); 3177f8369d7dSTobias Sarnowski $insertTo = $this->find($target)->elements; 3178f8369d7dSTobias Sarnowski $this->elements = $thisStack; 3179f8369d7dSTobias Sarnowski } 3180f8369d7dSTobias Sarnowski } else { 3181f8369d7dSTobias Sarnowski // INSERT FROM 3182f8369d7dSTobias Sarnowski $insertTo = $this->elements; 3183f8369d7dSTobias Sarnowski $insertFrom = $this->documentWrapper->import($target); 3184f8369d7dSTobias Sarnowski } 3185f8369d7dSTobias Sarnowski break; 3186f8369d7dSTobias Sarnowski case 'object': 3187f8369d7dSTobias Sarnowski $insertFrom = $insertTo = array(); 3188f8369d7dSTobias Sarnowski // phpQuery 3189f8369d7dSTobias Sarnowski if ($target instanceof self) { 3190f8369d7dSTobias Sarnowski if ($to) { 3191f8369d7dSTobias Sarnowski $insertTo = $target->elements; 3192f8369d7dSTobias Sarnowski if ($this->documentFragment && $this->stackIsRoot()) 3193f8369d7dSTobias Sarnowski // get all body children 3194f8369d7dSTobias Sarnowski// $loop = $this->find('body > *')->elements; 3195f8369d7dSTobias Sarnowski // TODO test it, test it hard... 3196f8369d7dSTobias Sarnowski// $loop = $this->newInstance($this->root)->find('> *')->elements; 3197f8369d7dSTobias Sarnowski $loop = $this->root->childNodes; 3198f8369d7dSTobias Sarnowski else 3199f8369d7dSTobias Sarnowski $loop = $this->elements; 3200f8369d7dSTobias Sarnowski // import nodes if needed 3201f8369d7dSTobias Sarnowski $insertFrom = $this->getDocumentID() == $target->getDocumentID() 3202f8369d7dSTobias Sarnowski ? $loop 3203f8369d7dSTobias Sarnowski : $target->documentWrapper->import($loop); 3204f8369d7dSTobias Sarnowski } else { 3205f8369d7dSTobias Sarnowski $insertTo = $this->elements; 3206f8369d7dSTobias Sarnowski if ( $target->documentFragment && $target->stackIsRoot() ) 3207f8369d7dSTobias Sarnowski // get all body children 3208f8369d7dSTobias Sarnowski// $loop = $target->find('body > *')->elements; 3209f8369d7dSTobias Sarnowski $loop = $target->root->childNodes; 3210f8369d7dSTobias Sarnowski else 3211f8369d7dSTobias Sarnowski $loop = $target->elements; 3212f8369d7dSTobias Sarnowski // import nodes if needed 3213f8369d7dSTobias Sarnowski $insertFrom = $this->getDocumentID() == $target->getDocumentID() 3214f8369d7dSTobias Sarnowski ? $loop 3215f8369d7dSTobias Sarnowski : $this->documentWrapper->import($loop); 3216f8369d7dSTobias Sarnowski } 3217f8369d7dSTobias Sarnowski // DOMNODE 3218f8369d7dSTobias Sarnowski } elseif ($target instanceof DOMNODE) { 3219f8369d7dSTobias Sarnowski // import node if needed 3220f8369d7dSTobias Sarnowski// if ( $target->ownerDocument != $this->DOM ) 3221f8369d7dSTobias Sarnowski// $target = $this->DOM->importNode($target, true); 3222f8369d7dSTobias Sarnowski if ( $to) { 3223f8369d7dSTobias Sarnowski $insertTo = array($target); 3224f8369d7dSTobias Sarnowski if ($this->documentFragment && $this->stackIsRoot()) 3225f8369d7dSTobias Sarnowski // get all body children 3226f8369d7dSTobias Sarnowski $loop = $this->root->childNodes; 3227f8369d7dSTobias Sarnowski// $loop = $this->find('body > *')->elements; 3228f8369d7dSTobias Sarnowski else 3229f8369d7dSTobias Sarnowski $loop = $this->elements; 3230f8369d7dSTobias Sarnowski foreach($loop as $fromNode) 3231f8369d7dSTobias Sarnowski // import nodes if needed 3232f8369d7dSTobias Sarnowski $insertFrom[] = ! $fromNode->ownerDocument->isSameNode($target->ownerDocument) 3233f8369d7dSTobias Sarnowski ? $target->ownerDocument->importNode($fromNode, true) 3234f8369d7dSTobias Sarnowski : $fromNode; 3235f8369d7dSTobias Sarnowski } else { 3236f8369d7dSTobias Sarnowski // import node if needed 3237f8369d7dSTobias Sarnowski if (! $target->ownerDocument->isSameNode($this->document)) 3238f8369d7dSTobias Sarnowski $target = $this->document->importNode($target, true); 3239f8369d7dSTobias Sarnowski $insertTo = $this->elements; 3240f8369d7dSTobias Sarnowski $insertFrom[] = $target; 3241f8369d7dSTobias Sarnowski } 3242f8369d7dSTobias Sarnowski } 3243f8369d7dSTobias Sarnowski break; 3244f8369d7dSTobias Sarnowski } 3245f8369d7dSTobias Sarnowski phpQuery::debug("From ".count($insertFrom)."; To ".count($insertTo)." nodes"); 3246f8369d7dSTobias Sarnowski foreach($insertTo as $insertNumber => $toNode) { 3247f8369d7dSTobias Sarnowski // we need static relative elements in some cases 3248f8369d7dSTobias Sarnowski switch( $type) { 3249f8369d7dSTobias Sarnowski case 'prependTo': 3250f8369d7dSTobias Sarnowski case 'prepend': 3251f8369d7dSTobias Sarnowski $firstChild = $toNode->firstChild; 3252f8369d7dSTobias Sarnowski break; 3253f8369d7dSTobias Sarnowski case 'insertAfter': 3254f8369d7dSTobias Sarnowski case 'after': 3255f8369d7dSTobias Sarnowski $nextSibling = $toNode->nextSibling; 3256f8369d7dSTobias Sarnowski break; 3257f8369d7dSTobias Sarnowski } 3258f8369d7dSTobias Sarnowski foreach($insertFrom as $fromNode) { 3259f8369d7dSTobias Sarnowski // clone if inserted already before 3260f8369d7dSTobias Sarnowski $insert = $insertNumber 3261f8369d7dSTobias Sarnowski ? $fromNode->cloneNode(true) 3262f8369d7dSTobias Sarnowski : $fromNode; 3263f8369d7dSTobias Sarnowski switch($type) { 3264f8369d7dSTobias Sarnowski case 'appendTo': 3265f8369d7dSTobias Sarnowski case 'append': 3266f8369d7dSTobias Sarnowski// $toNode->insertBefore( 3267f8369d7dSTobias Sarnowski// $fromNode, 3268f8369d7dSTobias Sarnowski// $toNode->lastChild->nextSibling 3269f8369d7dSTobias Sarnowski// ); 3270f8369d7dSTobias Sarnowski $toNode->appendChild($insert); 3271f8369d7dSTobias Sarnowski $eventTarget = $insert; 3272f8369d7dSTobias Sarnowski break; 3273f8369d7dSTobias Sarnowski case 'prependTo': 3274f8369d7dSTobias Sarnowski case 'prepend': 3275f8369d7dSTobias Sarnowski $toNode->insertBefore( 3276f8369d7dSTobias Sarnowski $insert, 3277f8369d7dSTobias Sarnowski $firstChild 3278f8369d7dSTobias Sarnowski ); 3279f8369d7dSTobias Sarnowski break; 3280f8369d7dSTobias Sarnowski case 'insertBefore': 3281f8369d7dSTobias Sarnowski case 'before': 3282f8369d7dSTobias Sarnowski if (! $toNode->parentNode) 3283f8369d7dSTobias Sarnowski throw new Exception("No parentNode, can't do {$type}()"); 3284f8369d7dSTobias Sarnowski else 3285f8369d7dSTobias Sarnowski $toNode->parentNode->insertBefore( 3286f8369d7dSTobias Sarnowski $insert, 3287f8369d7dSTobias Sarnowski $toNode 3288f8369d7dSTobias Sarnowski ); 3289f8369d7dSTobias Sarnowski break; 3290f8369d7dSTobias Sarnowski case 'insertAfter': 3291f8369d7dSTobias Sarnowski case 'after': 3292f8369d7dSTobias Sarnowski if (! $toNode->parentNode) 3293f8369d7dSTobias Sarnowski throw new Exception("No parentNode, can't do {$type}()"); 3294f8369d7dSTobias Sarnowski else 3295f8369d7dSTobias Sarnowski $toNode->parentNode->insertBefore( 3296f8369d7dSTobias Sarnowski $insert, 3297f8369d7dSTobias Sarnowski $nextSibling 3298f8369d7dSTobias Sarnowski ); 3299f8369d7dSTobias Sarnowski break; 3300f8369d7dSTobias Sarnowski } 3301f8369d7dSTobias Sarnowski // Mutation event 3302f8369d7dSTobias Sarnowski $event = new DOMEvent(array( 3303f8369d7dSTobias Sarnowski 'target' => $insert, 3304f8369d7dSTobias Sarnowski 'type' => 'DOMNodeInserted' 3305f8369d7dSTobias Sarnowski )); 3306f8369d7dSTobias Sarnowski phpQueryEvents::trigger($this->getDocumentID(), 3307f8369d7dSTobias Sarnowski $event->type, array($event), $insert 3308f8369d7dSTobias Sarnowski ); 3309f8369d7dSTobias Sarnowski } 3310f8369d7dSTobias Sarnowski } 3311f8369d7dSTobias Sarnowski return $this; 3312f8369d7dSTobias Sarnowski } 3313f8369d7dSTobias Sarnowski /** 3314f8369d7dSTobias Sarnowski * Enter description here... 3315f8369d7dSTobias Sarnowski * 3316f8369d7dSTobias Sarnowski * @return Int 3317f8369d7dSTobias Sarnowski */ 3318f8369d7dSTobias Sarnowski public function index($subject) { 3319f8369d7dSTobias Sarnowski $index = -1; 3320f8369d7dSTobias Sarnowski $subject = $subject instanceof phpQueryObject 3321f8369d7dSTobias Sarnowski ? $subject->elements[0] 3322f8369d7dSTobias Sarnowski : $subject; 3323f8369d7dSTobias Sarnowski foreach($this->newInstance() as $k => $node) { 3324f8369d7dSTobias Sarnowski if ($node->isSameNode($subject)) 3325f8369d7dSTobias Sarnowski $index = $k; 3326f8369d7dSTobias Sarnowski } 3327f8369d7dSTobias Sarnowski return $index; 3328f8369d7dSTobias Sarnowski } 3329f8369d7dSTobias Sarnowski /** 3330f8369d7dSTobias Sarnowski * Enter description here... 3331f8369d7dSTobias Sarnowski * 3332f8369d7dSTobias Sarnowski * @param unknown_type $start 3333f8369d7dSTobias Sarnowski * @param unknown_type $end 3334f8369d7dSTobias Sarnowski * 3335f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3336f8369d7dSTobias Sarnowski * @testme 3337f8369d7dSTobias Sarnowski */ 3338f8369d7dSTobias Sarnowski public function slice($start, $end = null) { 3339f8369d7dSTobias Sarnowski// $last = count($this->elements)-1; 3340f8369d7dSTobias Sarnowski// $end = $end 3341f8369d7dSTobias Sarnowski// ? min($end, $last) 3342f8369d7dSTobias Sarnowski// : $last; 3343f8369d7dSTobias Sarnowski// if ($start < 0) 3344f8369d7dSTobias Sarnowski// $start = $last+$start; 3345f8369d7dSTobias Sarnowski// if ($start > $last) 3346f8369d7dSTobias Sarnowski// return array(); 3347f8369d7dSTobias Sarnowski if ($end > 0) 3348f8369d7dSTobias Sarnowski $end = $end-$start; 3349f8369d7dSTobias Sarnowski return $this->newInstance( 3350f8369d7dSTobias Sarnowski array_slice($this->elements, $start, $end) 3351f8369d7dSTobias Sarnowski ); 3352f8369d7dSTobias Sarnowski } 3353f8369d7dSTobias Sarnowski /** 3354f8369d7dSTobias Sarnowski * Enter description here... 3355f8369d7dSTobias Sarnowski * 3356f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3357f8369d7dSTobias Sarnowski */ 3358f8369d7dSTobias Sarnowski public function reverse() { 3359f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 3360f8369d7dSTobias Sarnowski $this->elements = array_reverse($this->elements); 3361f8369d7dSTobias Sarnowski return $this->newInstance(); 3362f8369d7dSTobias Sarnowski } 3363f8369d7dSTobias Sarnowski /** 3364f8369d7dSTobias Sarnowski * Return joined text content. 3365f8369d7dSTobias Sarnowski * @return String 3366f8369d7dSTobias Sarnowski */ 3367f8369d7dSTobias Sarnowski public function text($text = null, $callback1 = null, $callback2 = null, $callback3 = null) { 3368f8369d7dSTobias Sarnowski if (isset($text)) 3369f8369d7dSTobias Sarnowski return $this->html(htmlspecialchars($text)); 3370f8369d7dSTobias Sarnowski $args = func_get_args(); 3371f8369d7dSTobias Sarnowski $args = array_slice($args, 1); 3372f8369d7dSTobias Sarnowski $return = ''; 3373f8369d7dSTobias Sarnowski foreach($this->elements as $node) { 3374f8369d7dSTobias Sarnowski $text = $node->textContent; 3375f8369d7dSTobias Sarnowski if (count($this->elements) > 1 && $text) 3376f8369d7dSTobias Sarnowski $text .= "\n"; 3377f8369d7dSTobias Sarnowski foreach($args as $callback) { 3378f8369d7dSTobias Sarnowski $text = phpQuery::callbackRun($callback, array($text)); 3379f8369d7dSTobias Sarnowski } 3380f8369d7dSTobias Sarnowski $return .= $text; 3381f8369d7dSTobias Sarnowski } 3382f8369d7dSTobias Sarnowski return $return; 3383f8369d7dSTobias Sarnowski } 3384f8369d7dSTobias Sarnowski /** 3385f8369d7dSTobias Sarnowski * Enter description here... 3386f8369d7dSTobias Sarnowski * 3387f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3388f8369d7dSTobias Sarnowski */ 3389f8369d7dSTobias Sarnowski public function plugin($class, $file = null) { 3390f8369d7dSTobias Sarnowski phpQuery::plugin($class, $file); 3391f8369d7dSTobias Sarnowski return $this; 3392f8369d7dSTobias Sarnowski } 3393f8369d7dSTobias Sarnowski /** 3394f8369d7dSTobias Sarnowski * Deprecated, use $pq->plugin() instead. 3395f8369d7dSTobias Sarnowski * 3396f8369d7dSTobias Sarnowski * @deprecated 3397f8369d7dSTobias Sarnowski * @param $class 3398f8369d7dSTobias Sarnowski * @param $file 3399f8369d7dSTobias Sarnowski * @return unknown_type 3400f8369d7dSTobias Sarnowski */ 3401f8369d7dSTobias Sarnowski public static function extend($class, $file = null) { 3402f8369d7dSTobias Sarnowski return $this->plugin($class, $file); 3403f8369d7dSTobias Sarnowski } 3404f8369d7dSTobias Sarnowski /** 3405f8369d7dSTobias Sarnowski * 3406f8369d7dSTobias Sarnowski * @access private 3407f8369d7dSTobias Sarnowski * @param $method 3408f8369d7dSTobias Sarnowski * @param $args 3409f8369d7dSTobias Sarnowski * @return unknown_type 3410f8369d7dSTobias Sarnowski */ 3411f8369d7dSTobias Sarnowski public function __call($method, $args) { 3412f8369d7dSTobias Sarnowski $aliasMethods = array('clone', 'empty'); 3413f8369d7dSTobias Sarnowski if (isset(phpQuery::$extendMethods[$method])) { 3414f8369d7dSTobias Sarnowski array_unshift($args, $this); 3415f8369d7dSTobias Sarnowski return phpQuery::callbackRun( 3416f8369d7dSTobias Sarnowski phpQuery::$extendMethods[$method], $args 3417f8369d7dSTobias Sarnowski ); 3418f8369d7dSTobias Sarnowski } else if (isset(phpQuery::$pluginsMethods[$method])) { 3419f8369d7dSTobias Sarnowski array_unshift($args, $this); 3420f8369d7dSTobias Sarnowski $class = phpQuery::$pluginsMethods[$method]; 3421f8369d7dSTobias Sarnowski $realClass = "phpQueryObjectPlugin_$class"; 3422f8369d7dSTobias Sarnowski $return = call_user_func_array( 3423f8369d7dSTobias Sarnowski array($realClass, $method), 3424f8369d7dSTobias Sarnowski $args 3425f8369d7dSTobias Sarnowski ); 3426f8369d7dSTobias Sarnowski // XXX deprecate ? 3427f8369d7dSTobias Sarnowski return is_null($return) 3428f8369d7dSTobias Sarnowski ? $this 3429f8369d7dSTobias Sarnowski : $return; 3430f8369d7dSTobias Sarnowski } else if (in_array($method, $aliasMethods)) { 3431f8369d7dSTobias Sarnowski return call_user_func_array(array($this, '_'.$method), $args); 3432f8369d7dSTobias Sarnowski } else 3433f8369d7dSTobias Sarnowski throw new Exception("Method '{$method}' doesnt exist"); 3434f8369d7dSTobias Sarnowski } 3435f8369d7dSTobias Sarnowski /** 3436f8369d7dSTobias Sarnowski * Safe rename of next(). 3437f8369d7dSTobias Sarnowski * 3438f8369d7dSTobias Sarnowski * Use it ONLY when need to call next() on an iterated object (in same time). 3439f8369d7dSTobias Sarnowski * Normaly there is no need to do such thing ;) 3440f8369d7dSTobias Sarnowski * 3441f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3442f8369d7dSTobias Sarnowski * @access private 3443f8369d7dSTobias Sarnowski */ 3444f8369d7dSTobias Sarnowski public function _next($selector = null) { 3445f8369d7dSTobias Sarnowski return $this->newInstance( 3446f8369d7dSTobias Sarnowski $this->getElementSiblings('nextSibling', $selector, true) 3447f8369d7dSTobias Sarnowski ); 3448f8369d7dSTobias Sarnowski } 3449f8369d7dSTobias Sarnowski /** 3450f8369d7dSTobias Sarnowski * Use prev() and next(). 3451f8369d7dSTobias Sarnowski * 3452f8369d7dSTobias Sarnowski * @deprecated 3453f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3454f8369d7dSTobias Sarnowski * @access private 3455f8369d7dSTobias Sarnowski */ 3456f8369d7dSTobias Sarnowski public function _prev($selector = null) { 3457f8369d7dSTobias Sarnowski return $this->prev($selector); 3458f8369d7dSTobias Sarnowski } 3459f8369d7dSTobias Sarnowski /** 3460f8369d7dSTobias Sarnowski * Enter description here... 3461f8369d7dSTobias Sarnowski * 3462f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3463f8369d7dSTobias Sarnowski */ 3464f8369d7dSTobias Sarnowski public function prev($selector = null) { 3465f8369d7dSTobias Sarnowski return $this->newInstance( 3466f8369d7dSTobias Sarnowski $this->getElementSiblings('previousSibling', $selector, true) 3467f8369d7dSTobias Sarnowski ); 3468f8369d7dSTobias Sarnowski } 3469f8369d7dSTobias Sarnowski /** 3470f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3471f8369d7dSTobias Sarnowski * @todo 3472f8369d7dSTobias Sarnowski */ 3473f8369d7dSTobias Sarnowski public function prevAll($selector = null) { 3474f8369d7dSTobias Sarnowski return $this->newInstance( 3475f8369d7dSTobias Sarnowski $this->getElementSiblings('previousSibling', $selector) 3476f8369d7dSTobias Sarnowski ); 3477f8369d7dSTobias Sarnowski } 3478f8369d7dSTobias Sarnowski /** 3479f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3480f8369d7dSTobias Sarnowski * @todo FIXME: returns source elements insted of next siblings 3481f8369d7dSTobias Sarnowski */ 3482f8369d7dSTobias Sarnowski public function nextAll($selector = null) { 3483f8369d7dSTobias Sarnowski return $this->newInstance( 3484f8369d7dSTobias Sarnowski $this->getElementSiblings('nextSibling', $selector) 3485f8369d7dSTobias Sarnowski ); 3486f8369d7dSTobias Sarnowski } 3487f8369d7dSTobias Sarnowski /** 3488f8369d7dSTobias Sarnowski * @access private 3489f8369d7dSTobias Sarnowski */ 3490f8369d7dSTobias Sarnowski protected function getElementSiblings($direction, $selector = null, $limitToOne = false) { 3491f8369d7dSTobias Sarnowski $stack = array(); 3492f8369d7dSTobias Sarnowski $count = 0; 3493f8369d7dSTobias Sarnowski foreach($this->stack() as $node) { 3494f8369d7dSTobias Sarnowski $test = $node; 3495f8369d7dSTobias Sarnowski while( isset($test->{$direction}) && $test->{$direction}) { 3496f8369d7dSTobias Sarnowski $test = $test->{$direction}; 3497f8369d7dSTobias Sarnowski if (! $test instanceof DOMELEMENT) 3498f8369d7dSTobias Sarnowski continue; 3499f8369d7dSTobias Sarnowski $stack[] = $test; 3500f8369d7dSTobias Sarnowski if ($limitToOne) 3501f8369d7dSTobias Sarnowski break; 3502f8369d7dSTobias Sarnowski } 3503f8369d7dSTobias Sarnowski } 3504f8369d7dSTobias Sarnowski if ($selector) { 3505f8369d7dSTobias Sarnowski $stackOld = $this->elements; 3506f8369d7dSTobias Sarnowski $this->elements = $stack; 3507f8369d7dSTobias Sarnowski $stack = $this->filter($selector, true)->stack(); 3508f8369d7dSTobias Sarnowski $this->elements = $stackOld; 3509f8369d7dSTobias Sarnowski } 3510f8369d7dSTobias Sarnowski return $stack; 3511f8369d7dSTobias Sarnowski } 3512f8369d7dSTobias Sarnowski /** 3513f8369d7dSTobias Sarnowski * Enter description here... 3514f8369d7dSTobias Sarnowski * 3515f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3516f8369d7dSTobias Sarnowski */ 3517f8369d7dSTobias Sarnowski public function siblings($selector = null) { 3518f8369d7dSTobias Sarnowski $stack = array(); 3519f8369d7dSTobias Sarnowski $siblings = array_merge( 3520f8369d7dSTobias Sarnowski $this->getElementSiblings('previousSibling', $selector), 3521f8369d7dSTobias Sarnowski $this->getElementSiblings('nextSibling', $selector) 3522f8369d7dSTobias Sarnowski ); 3523f8369d7dSTobias Sarnowski foreach($siblings as $node) { 3524f8369d7dSTobias Sarnowski if (! $this->elementsContainsNode($node, $stack)) 3525f8369d7dSTobias Sarnowski $stack[] = $node; 3526f8369d7dSTobias Sarnowski } 3527f8369d7dSTobias Sarnowski return $this->newInstance($stack); 3528f8369d7dSTobias Sarnowski } 3529f8369d7dSTobias Sarnowski /** 3530f8369d7dSTobias Sarnowski * Enter description here... 3531f8369d7dSTobias Sarnowski * 3532f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3533f8369d7dSTobias Sarnowski */ 3534f8369d7dSTobias Sarnowski public function not($selector = null) { 3535f8369d7dSTobias Sarnowski if (is_string($selector)) 3536f8369d7dSTobias Sarnowski phpQuery::debug(array('not', $selector)); 3537f8369d7dSTobias Sarnowski else 3538f8369d7dSTobias Sarnowski phpQuery::debug('not'); 3539f8369d7dSTobias Sarnowski $stack = array(); 3540f8369d7dSTobias Sarnowski if ($selector instanceof self || $selector instanceof DOMNODE) { 3541f8369d7dSTobias Sarnowski foreach($this->stack() as $node) { 3542f8369d7dSTobias Sarnowski if ($selector instanceof self) { 3543f8369d7dSTobias Sarnowski $matchFound = false; 3544f8369d7dSTobias Sarnowski foreach($selector->stack() as $notNode) { 3545f8369d7dSTobias Sarnowski if ($notNode->isSameNode($node)) 3546f8369d7dSTobias Sarnowski $matchFound = true; 3547f8369d7dSTobias Sarnowski } 3548f8369d7dSTobias Sarnowski if (! $matchFound) 3549f8369d7dSTobias Sarnowski $stack[] = $node; 3550f8369d7dSTobias Sarnowski } else if ($selector instanceof DOMNODE) { 3551f8369d7dSTobias Sarnowski if (! $selector->isSameNode($node)) 3552f8369d7dSTobias Sarnowski $stack[] = $node; 3553f8369d7dSTobias Sarnowski } else { 3554f8369d7dSTobias Sarnowski if (! $this->is($selector)) 3555f8369d7dSTobias Sarnowski $stack[] = $node; 3556f8369d7dSTobias Sarnowski } 3557f8369d7dSTobias Sarnowski } 3558f8369d7dSTobias Sarnowski } else { 3559f8369d7dSTobias Sarnowski $orgStack = $this->stack(); 3560f8369d7dSTobias Sarnowski $matched = $this->filter($selector, true)->stack(); 3561f8369d7dSTobias Sarnowski// $matched = array(); 3562f8369d7dSTobias Sarnowski// // simulate OR in filter() instead of AND 5y 3563f8369d7dSTobias Sarnowski// foreach($this->parseSelector($selector) as $s) { 3564f8369d7dSTobias Sarnowski// $matched = array_merge($matched, 3565f8369d7dSTobias Sarnowski// $this->filter(array($s))->stack() 3566f8369d7dSTobias Sarnowski// ); 3567f8369d7dSTobias Sarnowski// } 3568f8369d7dSTobias Sarnowski foreach($orgStack as $node) 3569f8369d7dSTobias Sarnowski if (! $this->elementsContainsNode($node, $matched)) 3570f8369d7dSTobias Sarnowski $stack[] = $node; 3571f8369d7dSTobias Sarnowski } 3572f8369d7dSTobias Sarnowski return $this->newInstance($stack); 3573f8369d7dSTobias Sarnowski } 3574f8369d7dSTobias Sarnowski /** 3575f8369d7dSTobias Sarnowski * Enter description here... 3576f8369d7dSTobias Sarnowski * 3577f8369d7dSTobias Sarnowski * @param string|phpQueryObject 3578f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3579f8369d7dSTobias Sarnowski */ 3580f8369d7dSTobias Sarnowski public function add($selector = null) { 3581f8369d7dSTobias Sarnowski if (! $selector) 3582f8369d7dSTobias Sarnowski return $this; 3583f8369d7dSTobias Sarnowski $stack = array(); 3584f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 3585f8369d7dSTobias Sarnowski $found = phpQuery::pq($selector, $this->getDocumentID()); 3586f8369d7dSTobias Sarnowski $this->merge($found->elements); 3587f8369d7dSTobias Sarnowski return $this->newInstance(); 3588f8369d7dSTobias Sarnowski } 3589f8369d7dSTobias Sarnowski /** 3590f8369d7dSTobias Sarnowski * @access private 3591f8369d7dSTobias Sarnowski */ 3592f8369d7dSTobias Sarnowski protected function merge() { 3593f8369d7dSTobias Sarnowski foreach(func_get_args() as $nodes) 3594f8369d7dSTobias Sarnowski foreach($nodes as $newNode ) 3595f8369d7dSTobias Sarnowski if (! $this->elementsContainsNode($newNode) ) 3596f8369d7dSTobias Sarnowski $this->elements[] = $newNode; 3597f8369d7dSTobias Sarnowski } 3598f8369d7dSTobias Sarnowski /** 3599f8369d7dSTobias Sarnowski * @access private 3600f8369d7dSTobias Sarnowski * TODO refactor to stackContainsNode 3601f8369d7dSTobias Sarnowski */ 3602f8369d7dSTobias Sarnowski protected function elementsContainsNode($nodeToCheck, $elementsStack = null) { 3603f8369d7dSTobias Sarnowski $loop = ! is_null($elementsStack) 3604f8369d7dSTobias Sarnowski ? $elementsStack 3605f8369d7dSTobias Sarnowski : $this->elements; 3606f8369d7dSTobias Sarnowski foreach($loop as $node) { 3607f8369d7dSTobias Sarnowski if ( $node->isSameNode( $nodeToCheck ) ) 3608f8369d7dSTobias Sarnowski return true; 3609f8369d7dSTobias Sarnowski } 3610f8369d7dSTobias Sarnowski return false; 3611f8369d7dSTobias Sarnowski } 3612f8369d7dSTobias Sarnowski /** 3613f8369d7dSTobias Sarnowski * Enter description here... 3614f8369d7dSTobias Sarnowski * 3615f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3616f8369d7dSTobias Sarnowski */ 3617f8369d7dSTobias Sarnowski public function parent($selector = null) { 3618f8369d7dSTobias Sarnowski $stack = array(); 3619f8369d7dSTobias Sarnowski foreach($this->elements as $node ) 3620f8369d7dSTobias Sarnowski if ( $node->parentNode && ! $this->elementsContainsNode($node->parentNode, $stack) ) 3621f8369d7dSTobias Sarnowski $stack[] = $node->parentNode; 3622f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 3623f8369d7dSTobias Sarnowski $this->elements = $stack; 3624f8369d7dSTobias Sarnowski if ( $selector ) 3625f8369d7dSTobias Sarnowski $this->filter($selector, true); 3626f8369d7dSTobias Sarnowski return $this->newInstance(); 3627f8369d7dSTobias Sarnowski } 3628f8369d7dSTobias Sarnowski /** 3629f8369d7dSTobias Sarnowski * Enter description here... 3630f8369d7dSTobias Sarnowski * 3631f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3632f8369d7dSTobias Sarnowski */ 3633f8369d7dSTobias Sarnowski public function parents($selector = null) { 3634f8369d7dSTobias Sarnowski $stack = array(); 3635f8369d7dSTobias Sarnowski if (! $this->elements ) 3636f8369d7dSTobias Sarnowski $this->debug('parents() - stack empty'); 3637f8369d7dSTobias Sarnowski foreach($this->elements as $node) { 3638f8369d7dSTobias Sarnowski $test = $node; 3639f8369d7dSTobias Sarnowski while( $test->parentNode) { 3640f8369d7dSTobias Sarnowski $test = $test->parentNode; 3641f8369d7dSTobias Sarnowski if ($this->isRoot($test)) 3642f8369d7dSTobias Sarnowski break; 3643f8369d7dSTobias Sarnowski if (! $this->elementsContainsNode($test, $stack)) { 3644f8369d7dSTobias Sarnowski $stack[] = $test; 3645f8369d7dSTobias Sarnowski continue; 3646f8369d7dSTobias Sarnowski } 3647f8369d7dSTobias Sarnowski } 3648f8369d7dSTobias Sarnowski } 3649f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 3650f8369d7dSTobias Sarnowski $this->elements = $stack; 3651f8369d7dSTobias Sarnowski if ( $selector ) 3652f8369d7dSTobias Sarnowski $this->filter($selector, true); 3653f8369d7dSTobias Sarnowski return $this->newInstance(); 3654f8369d7dSTobias Sarnowski } 3655f8369d7dSTobias Sarnowski /** 3656f8369d7dSTobias Sarnowski * Internal stack iterator. 3657f8369d7dSTobias Sarnowski * 3658f8369d7dSTobias Sarnowski * @access private 3659f8369d7dSTobias Sarnowski */ 3660f8369d7dSTobias Sarnowski public function stack($nodeTypes = null) { 3661f8369d7dSTobias Sarnowski if (!isset($nodeTypes)) 3662f8369d7dSTobias Sarnowski return $this->elements; 3663f8369d7dSTobias Sarnowski if (!is_array($nodeTypes)) 3664f8369d7dSTobias Sarnowski $nodeTypes = array($nodeTypes); 3665f8369d7dSTobias Sarnowski $return = array(); 3666f8369d7dSTobias Sarnowski foreach($this->elements as $node) { 3667f8369d7dSTobias Sarnowski if (in_array($node->nodeType, $nodeTypes)) 3668f8369d7dSTobias Sarnowski $return[] = $node; 3669f8369d7dSTobias Sarnowski } 3670f8369d7dSTobias Sarnowski return $return; 3671f8369d7dSTobias Sarnowski } 3672f8369d7dSTobias Sarnowski // TODO phpdoc; $oldAttr is result of hasAttribute, before any changes 3673f8369d7dSTobias Sarnowski protected function attrEvents($attr, $oldAttr, $oldValue, $node) { 3674f8369d7dSTobias Sarnowski // skip events for XML documents 3675f8369d7dSTobias Sarnowski if (! $this->isXHTML() && ! $this->isHTML()) 3676f8369d7dSTobias Sarnowski return; 3677f8369d7dSTobias Sarnowski $event = null; 3678f8369d7dSTobias Sarnowski // identify 3679f8369d7dSTobias Sarnowski $isInputValue = $node->tagName == 'input' 3680f8369d7dSTobias Sarnowski && ( 3681f8369d7dSTobias Sarnowski in_array($node->getAttribute('type'), 3682f8369d7dSTobias Sarnowski array('text', 'password', 'hidden')) 3683f8369d7dSTobias Sarnowski || !$node->getAttribute('type') 3684f8369d7dSTobias Sarnowski ); 3685f8369d7dSTobias Sarnowski $isRadio = $node->tagName == 'input' 3686f8369d7dSTobias Sarnowski && $node->getAttribute('type') == 'radio'; 3687f8369d7dSTobias Sarnowski $isCheckbox = $node->tagName == 'input' 3688f8369d7dSTobias Sarnowski && $node->getAttribute('type') == 'checkbox'; 3689f8369d7dSTobias Sarnowski $isOption = $node->tagName == 'option'; 3690f8369d7dSTobias Sarnowski if ($isInputValue && $attr == 'value' && $oldValue != $node->getAttribute($attr)) { 3691f8369d7dSTobias Sarnowski $event = new DOMEvent(array( 3692f8369d7dSTobias Sarnowski 'target' => $node, 3693f8369d7dSTobias Sarnowski 'type' => 'change' 3694f8369d7dSTobias Sarnowski )); 3695f8369d7dSTobias Sarnowski } else if (($isRadio || $isCheckbox) && $attr == 'checked' && ( 3696f8369d7dSTobias Sarnowski // check 3697f8369d7dSTobias Sarnowski (! $oldAttr && $node->hasAttribute($attr)) 3698f8369d7dSTobias Sarnowski // un-check 3699f8369d7dSTobias Sarnowski || (! $node->hasAttribute($attr) && $oldAttr) 3700f8369d7dSTobias Sarnowski )) { 3701f8369d7dSTobias Sarnowski $event = new DOMEvent(array( 3702f8369d7dSTobias Sarnowski 'target' => $node, 3703f8369d7dSTobias Sarnowski 'type' => 'change' 3704f8369d7dSTobias Sarnowski )); 3705f8369d7dSTobias Sarnowski } else if ($isOption && $node->parentNode && $attr == 'selected' && ( 3706f8369d7dSTobias Sarnowski // select 3707f8369d7dSTobias Sarnowski (! $oldAttr && $node->hasAttribute($attr)) 3708f8369d7dSTobias Sarnowski // un-select 3709f8369d7dSTobias Sarnowski || (! $node->hasAttribute($attr) && $oldAttr) 3710f8369d7dSTobias Sarnowski )) { 3711f8369d7dSTobias Sarnowski $event = new DOMEvent(array( 3712f8369d7dSTobias Sarnowski 'target' => $node->parentNode, 3713f8369d7dSTobias Sarnowski 'type' => 'change' 3714f8369d7dSTobias Sarnowski )); 3715f8369d7dSTobias Sarnowski } 3716f8369d7dSTobias Sarnowski if ($event) { 3717f8369d7dSTobias Sarnowski phpQueryEvents::trigger($this->getDocumentID(), 3718f8369d7dSTobias Sarnowski $event->type, array($event), $node 3719f8369d7dSTobias Sarnowski ); 3720f8369d7dSTobias Sarnowski } 3721f8369d7dSTobias Sarnowski } 3722f8369d7dSTobias Sarnowski public function attr($attr = null, $value = null) { 3723f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3724f8369d7dSTobias Sarnowski if (! is_null($value)) { 3725f8369d7dSTobias Sarnowski $loop = $attr == '*' 3726f8369d7dSTobias Sarnowski ? $this->getNodeAttrs($node) 3727f8369d7dSTobias Sarnowski : array($attr); 3728f8369d7dSTobias Sarnowski foreach($loop as $a) { 3729f8369d7dSTobias Sarnowski $oldValue = $node->getAttribute($a); 3730f8369d7dSTobias Sarnowski $oldAttr = $node->hasAttribute($a); 3731f8369d7dSTobias Sarnowski // TODO raises an error when charset other than UTF-8 3732f8369d7dSTobias Sarnowski // while document's charset is also not UTF-8 3733f8369d7dSTobias Sarnowski @$node->setAttribute($a, $value); 3734f8369d7dSTobias Sarnowski $this->attrEvents($a, $oldAttr, $oldValue, $node); 3735f8369d7dSTobias Sarnowski } 3736f8369d7dSTobias Sarnowski } else if ($attr == '*') { 3737f8369d7dSTobias Sarnowski // jQuery difference 3738f8369d7dSTobias Sarnowski $return = array(); 3739f8369d7dSTobias Sarnowski foreach($node->attributes as $n => $v) 3740f8369d7dSTobias Sarnowski $return[$n] = $v->value; 3741f8369d7dSTobias Sarnowski return $return; 3742f8369d7dSTobias Sarnowski } else 3743f8369d7dSTobias Sarnowski return $node->hasAttribute($attr) 3744f8369d7dSTobias Sarnowski ? $node->getAttribute($attr) 3745f8369d7dSTobias Sarnowski : null; 3746f8369d7dSTobias Sarnowski } 3747f8369d7dSTobias Sarnowski return is_null($value) 3748f8369d7dSTobias Sarnowski ? '' : $this; 3749f8369d7dSTobias Sarnowski } 3750f8369d7dSTobias Sarnowski /** 3751f8369d7dSTobias Sarnowski * @access private 3752f8369d7dSTobias Sarnowski */ 3753f8369d7dSTobias Sarnowski protected function getNodeAttrs($node) { 3754f8369d7dSTobias Sarnowski $return = array(); 3755f8369d7dSTobias Sarnowski foreach($node->attributes as $n => $o) 3756f8369d7dSTobias Sarnowski $return[] = $n; 3757f8369d7dSTobias Sarnowski return $return; 3758f8369d7dSTobias Sarnowski } 3759f8369d7dSTobias Sarnowski /** 3760f8369d7dSTobias Sarnowski * Enter description here... 3761f8369d7dSTobias Sarnowski * 3762f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3763f8369d7dSTobias Sarnowski * @todo check CDATA ??? 3764f8369d7dSTobias Sarnowski */ 3765f8369d7dSTobias Sarnowski public function attrPHP($attr, $code) { 3766f8369d7dSTobias Sarnowski if (! is_null($code)) { 3767f8369d7dSTobias Sarnowski $value = '<'.'?php '.$code.' ?'.'>'; 3768f8369d7dSTobias Sarnowski // TODO tempolary solution 3769f8369d7dSTobias Sarnowski // http://code.google.com/p/phpquery/issues/detail?id=17 3770f8369d7dSTobias Sarnowski// if (function_exists('mb_detect_encoding') && mb_detect_encoding($value) == 'ASCII') 3771f8369d7dSTobias Sarnowski// $value = mb_convert_encoding($value, 'UTF-8', 'HTML-ENTITIES'); 3772f8369d7dSTobias Sarnowski } 3773f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3774f8369d7dSTobias Sarnowski if (! is_null($code)) { 3775f8369d7dSTobias Sarnowski// $attrNode = $this->DOM->createAttribute($attr); 3776f8369d7dSTobias Sarnowski $node->setAttribute($attr, $value); 3777f8369d7dSTobias Sarnowski// $attrNode->value = $value; 3778f8369d7dSTobias Sarnowski// $node->appendChild($attrNode); 3779f8369d7dSTobias Sarnowski } else if ( $attr == '*') { 3780f8369d7dSTobias Sarnowski // jQuery diff 3781f8369d7dSTobias Sarnowski $return = array(); 3782f8369d7dSTobias Sarnowski foreach($node->attributes as $n => $v) 3783f8369d7dSTobias Sarnowski $return[$n] = $v->value; 3784f8369d7dSTobias Sarnowski return $return; 3785f8369d7dSTobias Sarnowski } else 3786f8369d7dSTobias Sarnowski return $node->getAttribute($attr); 3787f8369d7dSTobias Sarnowski } 3788f8369d7dSTobias Sarnowski return $this; 3789f8369d7dSTobias Sarnowski } 3790f8369d7dSTobias Sarnowski /** 3791f8369d7dSTobias Sarnowski * Enter description here... 3792f8369d7dSTobias Sarnowski * 3793f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3794f8369d7dSTobias Sarnowski */ 3795f8369d7dSTobias Sarnowski public function removeAttr($attr) { 3796f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3797f8369d7dSTobias Sarnowski $loop = $attr == '*' 3798f8369d7dSTobias Sarnowski ? $this->getNodeAttrs($node) 3799f8369d7dSTobias Sarnowski : array($attr); 3800f8369d7dSTobias Sarnowski foreach($loop as $a) { 3801f8369d7dSTobias Sarnowski $oldValue = $node->getAttribute($a); 3802f8369d7dSTobias Sarnowski $node->removeAttribute($a); 3803f8369d7dSTobias Sarnowski $this->attrEvents($a, $oldValue, null, $node); 3804f8369d7dSTobias Sarnowski } 3805f8369d7dSTobias Sarnowski } 3806f8369d7dSTobias Sarnowski return $this; 3807f8369d7dSTobias Sarnowski } 3808f8369d7dSTobias Sarnowski /** 3809f8369d7dSTobias Sarnowski * Return form element value. 3810f8369d7dSTobias Sarnowski * 3811f8369d7dSTobias Sarnowski * @return String Fields value. 3812f8369d7dSTobias Sarnowski */ 3813f8369d7dSTobias Sarnowski public function val($val = null) { 3814f8369d7dSTobias Sarnowski if (! isset($val)) { 3815f8369d7dSTobias Sarnowski if ($this->eq(0)->is('select')) { 3816f8369d7dSTobias Sarnowski $selected = $this->eq(0)->find('option[selected=selected]'); 3817f8369d7dSTobias Sarnowski if ($selected->is('[value]')) 3818f8369d7dSTobias Sarnowski return $selected->attr('value'); 3819f8369d7dSTobias Sarnowski else 3820f8369d7dSTobias Sarnowski return $selected->text(); 3821f8369d7dSTobias Sarnowski } else if ($this->eq(0)->is('textarea')) 3822f8369d7dSTobias Sarnowski return $this->eq(0)->markup(); 3823f8369d7dSTobias Sarnowski else 3824f8369d7dSTobias Sarnowski return $this->eq(0)->attr('value'); 3825f8369d7dSTobias Sarnowski } else { 3826f8369d7dSTobias Sarnowski $_val = null; 3827f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3828f8369d7dSTobias Sarnowski $node = pq($node, $this->getDocumentID()); 3829f8369d7dSTobias Sarnowski if (is_array($val) && in_array($node->attr('type'), array('checkbox', 'radio'))) { 3830f8369d7dSTobias Sarnowski $isChecked = in_array($node->attr('value'), $val) 3831f8369d7dSTobias Sarnowski || in_array($node->attr('name'), $val); 3832f8369d7dSTobias Sarnowski if ($isChecked) 3833f8369d7dSTobias Sarnowski $node->attr('checked', 'checked'); 3834f8369d7dSTobias Sarnowski else 3835f8369d7dSTobias Sarnowski $node->removeAttr('checked'); 3836f8369d7dSTobias Sarnowski } else if ($node->get(0)->tagName == 'select') { 3837f8369d7dSTobias Sarnowski if (! isset($_val)) { 3838f8369d7dSTobias Sarnowski $_val = array(); 3839f8369d7dSTobias Sarnowski if (! is_array($val)) 3840f8369d7dSTobias Sarnowski $_val = array((string)$val); 3841f8369d7dSTobias Sarnowski else 3842f8369d7dSTobias Sarnowski foreach($val as $v) 3843f8369d7dSTobias Sarnowski $_val[] = $v; 3844f8369d7dSTobias Sarnowski } 3845f8369d7dSTobias Sarnowski foreach($node['option']->stack(1) as $option) { 3846f8369d7dSTobias Sarnowski $option = pq($option, $this->getDocumentID()); 3847f8369d7dSTobias Sarnowski $selected = false; 3848f8369d7dSTobias Sarnowski // XXX: workaround for string comparsion, see issue #96 3849f8369d7dSTobias Sarnowski // http://code.google.com/p/phpquery/issues/detail?id=96 3850f8369d7dSTobias Sarnowski $selected = is_null($option->attr('value')) 3851f8369d7dSTobias Sarnowski ? in_array($option->markup(), $_val) 3852f8369d7dSTobias Sarnowski : in_array($option->attr('value'), $_val); 3853f8369d7dSTobias Sarnowski// $optionValue = $option->attr('value'); 3854f8369d7dSTobias Sarnowski// $optionText = $option->text(); 3855f8369d7dSTobias Sarnowski// $optionTextLenght = mb_strlen($optionText); 3856f8369d7dSTobias Sarnowski// foreach($_val as $v) 3857f8369d7dSTobias Sarnowski// if ($optionValue == $v) 3858f8369d7dSTobias Sarnowski// $selected = true; 3859f8369d7dSTobias Sarnowski// else if ($optionText == $v && $optionTextLenght == mb_strlen($v)) 3860f8369d7dSTobias Sarnowski// $selected = true; 3861f8369d7dSTobias Sarnowski if ($selected) 3862f8369d7dSTobias Sarnowski $option->attr('selected', 'selected'); 3863f8369d7dSTobias Sarnowski else 3864f8369d7dSTobias Sarnowski $option->removeAttr('selected'); 3865f8369d7dSTobias Sarnowski } 3866f8369d7dSTobias Sarnowski } else if ($node->get(0)->tagName == 'textarea') 3867f8369d7dSTobias Sarnowski $node->markup($val); 3868f8369d7dSTobias Sarnowski else 3869f8369d7dSTobias Sarnowski $node->attr('value', $val); 3870f8369d7dSTobias Sarnowski } 3871f8369d7dSTobias Sarnowski } 3872f8369d7dSTobias Sarnowski return $this; 3873f8369d7dSTobias Sarnowski } 3874f8369d7dSTobias Sarnowski /** 3875f8369d7dSTobias Sarnowski * Enter description here... 3876f8369d7dSTobias Sarnowski * 3877f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3878f8369d7dSTobias Sarnowski */ 3879f8369d7dSTobias Sarnowski public function andSelf() { 3880f8369d7dSTobias Sarnowski if ( $this->previous ) 3881f8369d7dSTobias Sarnowski $this->elements = array_merge($this->elements, $this->previous->elements); 3882f8369d7dSTobias Sarnowski return $this; 3883f8369d7dSTobias Sarnowski } 3884f8369d7dSTobias Sarnowski /** 3885f8369d7dSTobias Sarnowski * Enter description here... 3886f8369d7dSTobias Sarnowski * 3887f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3888f8369d7dSTobias Sarnowski */ 3889f8369d7dSTobias Sarnowski public function addClass( $className) { 3890f8369d7dSTobias Sarnowski if (! $className) 3891f8369d7dSTobias Sarnowski return $this; 3892f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3893f8369d7dSTobias Sarnowski if (! $this->is(".$className", $node)) 3894f8369d7dSTobias Sarnowski $node->setAttribute( 3895f8369d7dSTobias Sarnowski 'class', 3896f8369d7dSTobias Sarnowski trim($node->getAttribute('class').' '.$className) 3897f8369d7dSTobias Sarnowski ); 3898f8369d7dSTobias Sarnowski } 3899f8369d7dSTobias Sarnowski return $this; 3900f8369d7dSTobias Sarnowski } 3901f8369d7dSTobias Sarnowski /** 3902f8369d7dSTobias Sarnowski * Enter description here... 3903f8369d7dSTobias Sarnowski * 3904f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3905f8369d7dSTobias Sarnowski */ 3906f8369d7dSTobias Sarnowski public function addClassPHP( $className) { 3907f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3908f8369d7dSTobias Sarnowski $classes = $node->getAttribute('class'); 3909f8369d7dSTobias Sarnowski $newValue = $classes 3910f8369d7dSTobias Sarnowski ? $classes.' <'.'?php '.$className.' ?'.'>' 3911f8369d7dSTobias Sarnowski : '<'.'?php '.$className.' ?'.'>'; 3912f8369d7dSTobias Sarnowski $node->setAttribute('class', $newValue); 3913f8369d7dSTobias Sarnowski } 3914f8369d7dSTobias Sarnowski return $this; 3915f8369d7dSTobias Sarnowski } 3916f8369d7dSTobias Sarnowski /** 3917f8369d7dSTobias Sarnowski * Enter description here... 3918f8369d7dSTobias Sarnowski * 3919f8369d7dSTobias Sarnowski * @param string $className 3920f8369d7dSTobias Sarnowski * @return bool 3921f8369d7dSTobias Sarnowski */ 3922f8369d7dSTobias Sarnowski public function hasClass($className) { 3923f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3924f8369d7dSTobias Sarnowski if ( $this->is(".$className", $node)) 3925f8369d7dSTobias Sarnowski return true; 3926f8369d7dSTobias Sarnowski } 3927f8369d7dSTobias Sarnowski return false; 3928f8369d7dSTobias Sarnowski } 3929f8369d7dSTobias Sarnowski /** 3930f8369d7dSTobias Sarnowski * Enter description here... 3931f8369d7dSTobias Sarnowski * 3932f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3933f8369d7dSTobias Sarnowski */ 3934f8369d7dSTobias Sarnowski public function removeClass($className) { 3935f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3936f8369d7dSTobias Sarnowski $classes = explode( ' ', $node->getAttribute('class')); 3937f8369d7dSTobias Sarnowski if ( in_array($className, $classes)) { 3938f8369d7dSTobias Sarnowski $classes = array_diff($classes, array($className)); 3939f8369d7dSTobias Sarnowski if ( $classes ) 3940f8369d7dSTobias Sarnowski $node->setAttribute('class', implode(' ', $classes)); 3941f8369d7dSTobias Sarnowski else 3942f8369d7dSTobias Sarnowski $node->removeAttribute('class'); 3943f8369d7dSTobias Sarnowski } 3944f8369d7dSTobias Sarnowski } 3945f8369d7dSTobias Sarnowski return $this; 3946f8369d7dSTobias Sarnowski } 3947f8369d7dSTobias Sarnowski /** 3948f8369d7dSTobias Sarnowski * Enter description here... 3949f8369d7dSTobias Sarnowski * 3950f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3951f8369d7dSTobias Sarnowski */ 3952f8369d7dSTobias Sarnowski public function toggleClass($className) { 3953f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3954f8369d7dSTobias Sarnowski if ( $this->is( $node, '.'.$className )) 3955f8369d7dSTobias Sarnowski $this->removeClass($className); 3956f8369d7dSTobias Sarnowski else 3957f8369d7dSTobias Sarnowski $this->addClass($className); 3958f8369d7dSTobias Sarnowski } 3959f8369d7dSTobias Sarnowski return $this; 3960f8369d7dSTobias Sarnowski } 3961f8369d7dSTobias Sarnowski /** 3962f8369d7dSTobias Sarnowski * Proper name without underscore (just ->empty()) also works. 3963f8369d7dSTobias Sarnowski * 3964f8369d7dSTobias Sarnowski * Removes all child nodes from the set of matched elements. 3965f8369d7dSTobias Sarnowski * 3966f8369d7dSTobias Sarnowski * Example: 3967f8369d7dSTobias Sarnowski * pq("p")._empty() 3968f8369d7dSTobias Sarnowski * 3969f8369d7dSTobias Sarnowski * HTML: 3970f8369d7dSTobias Sarnowski * <p>Hello, <span>Person</span> <a href="#">and person</a></p> 3971f8369d7dSTobias Sarnowski * 3972f8369d7dSTobias Sarnowski * Result: 3973f8369d7dSTobias Sarnowski * [ <p></p> ] 3974f8369d7dSTobias Sarnowski * 3975f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3976f8369d7dSTobias Sarnowski * @access private 3977f8369d7dSTobias Sarnowski */ 3978f8369d7dSTobias Sarnowski public function _empty() { 3979f8369d7dSTobias Sarnowski foreach($this->stack(1) as $node) { 3980f8369d7dSTobias Sarnowski // thx to 'dave at dgx dot cz' 3981f8369d7dSTobias Sarnowski $node->nodeValue = ''; 3982f8369d7dSTobias Sarnowski } 3983f8369d7dSTobias Sarnowski return $this; 3984f8369d7dSTobias Sarnowski } 3985f8369d7dSTobias Sarnowski /** 3986f8369d7dSTobias Sarnowski * Enter description here... 3987f8369d7dSTobias Sarnowski * 3988f8369d7dSTobias Sarnowski * @param array|string $callback Expects $node as first param, $index as second 3989f8369d7dSTobias Sarnowski * @param array $scope External variables passed to callback. Use compact('varName1', 'varName2'...) and extract($scope) 3990f8369d7dSTobias Sarnowski * @param array $arg1 Will ba passed as third and futher args to callback. 3991f8369d7dSTobias Sarnowski * @param array $arg2 Will ba passed as fourth and futher args to callback, and so on... 3992f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 3993f8369d7dSTobias Sarnowski */ 3994f8369d7dSTobias Sarnowski public function each($callback, $param1 = null, $param2 = null, $param3 = null) { 3995f8369d7dSTobias Sarnowski $paramStructure = null; 3996f8369d7dSTobias Sarnowski if (func_num_args() > 1) { 3997f8369d7dSTobias Sarnowski $paramStructure = func_get_args(); 3998f8369d7dSTobias Sarnowski $paramStructure = array_slice($paramStructure, 1); 3999f8369d7dSTobias Sarnowski } 4000f8369d7dSTobias Sarnowski foreach($this->elements as $v) 4001f8369d7dSTobias Sarnowski phpQuery::callbackRun($callback, array($v), $paramStructure); 4002f8369d7dSTobias Sarnowski return $this; 4003f8369d7dSTobias Sarnowski } 4004f8369d7dSTobias Sarnowski /** 4005f8369d7dSTobias Sarnowski * Run callback on actual object. 4006f8369d7dSTobias Sarnowski * 4007f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4008f8369d7dSTobias Sarnowski */ 4009f8369d7dSTobias Sarnowski public function callback($callback, $param1 = null, $param2 = null, $param3 = null) { 4010f8369d7dSTobias Sarnowski $params = func_get_args(); 4011f8369d7dSTobias Sarnowski $params[0] = $this; 4012f8369d7dSTobias Sarnowski phpQuery::callbackRun($callback, $params); 4013f8369d7dSTobias Sarnowski return $this; 4014f8369d7dSTobias Sarnowski } 4015f8369d7dSTobias Sarnowski /** 4016f8369d7dSTobias Sarnowski * Enter description here... 4017f8369d7dSTobias Sarnowski * 4018f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4019f8369d7dSTobias Sarnowski * @todo add $scope and $args as in each() ??? 4020f8369d7dSTobias Sarnowski */ 4021f8369d7dSTobias Sarnowski public function map($callback, $param1 = null, $param2 = null, $param3 = null) { 4022f8369d7dSTobias Sarnowski// $stack = array(); 4023f8369d7dSTobias Sarnowski//// foreach($this->newInstance() as $node) { 4024f8369d7dSTobias Sarnowski// foreach($this->newInstance() as $node) { 4025f8369d7dSTobias Sarnowski// $result = call_user_func($callback, $node); 4026f8369d7dSTobias Sarnowski// if ($result) 4027f8369d7dSTobias Sarnowski// $stack[] = $result; 4028f8369d7dSTobias Sarnowski// } 4029f8369d7dSTobias Sarnowski $params = func_get_args(); 4030f8369d7dSTobias Sarnowski array_unshift($params, $this->elements); 4031f8369d7dSTobias Sarnowski return $this->newInstance( 4032f8369d7dSTobias Sarnowski call_user_func_array(array('phpQuery', 'map'), $params) 4033f8369d7dSTobias Sarnowski// phpQuery::map($this->elements, $callback) 4034f8369d7dSTobias Sarnowski ); 4035f8369d7dSTobias Sarnowski } 4036f8369d7dSTobias Sarnowski /** 4037f8369d7dSTobias Sarnowski * Enter description here... 4038f8369d7dSTobias Sarnowski * 4039f8369d7dSTobias Sarnowski * @param <type> $key 4040f8369d7dSTobias Sarnowski * @param <type> $value 4041f8369d7dSTobias Sarnowski */ 4042f8369d7dSTobias Sarnowski public function data($key, $value = null) { 4043f8369d7dSTobias Sarnowski if (! isset($value)) { 4044f8369d7dSTobias Sarnowski // TODO? implement specific jQuery behavior od returning parent values 4045f8369d7dSTobias Sarnowski // is child which we look up doesn't exist 4046f8369d7dSTobias Sarnowski return phpQuery::data($this->get(0), $key, $value, $this->getDocumentID()); 4047f8369d7dSTobias Sarnowski } else { 4048f8369d7dSTobias Sarnowski foreach($this as $node) 4049f8369d7dSTobias Sarnowski phpQuery::data($node, $key, $value, $this->getDocumentID()); 4050f8369d7dSTobias Sarnowski return $this; 4051f8369d7dSTobias Sarnowski } 4052f8369d7dSTobias Sarnowski } 4053f8369d7dSTobias Sarnowski /** 4054f8369d7dSTobias Sarnowski * Enter description here... 4055f8369d7dSTobias Sarnowski * 4056f8369d7dSTobias Sarnowski * @param <type> $key 4057f8369d7dSTobias Sarnowski */ 4058f8369d7dSTobias Sarnowski public function removeData($key) { 4059f8369d7dSTobias Sarnowski foreach($this as $node) 4060f8369d7dSTobias Sarnowski phpQuery::removeData($node, $key, $this->getDocumentID()); 4061f8369d7dSTobias Sarnowski return $this; 4062f8369d7dSTobias Sarnowski } 4063f8369d7dSTobias Sarnowski // INTERFACE IMPLEMENTATIONS 4064f8369d7dSTobias Sarnowski 4065f8369d7dSTobias Sarnowski // ITERATOR INTERFACE 4066f8369d7dSTobias Sarnowski /** 4067f8369d7dSTobias Sarnowski * @access private 4068f8369d7dSTobias Sarnowski */ 4069f8369d7dSTobias Sarnowski public function rewind(){ 4070f8369d7dSTobias Sarnowski $this->debug('iterating foreach'); 4071f8369d7dSTobias Sarnowski// phpQuery::selectDocument($this->getDocumentID()); 4072f8369d7dSTobias Sarnowski $this->elementsBackup = $this->elements; 4073f8369d7dSTobias Sarnowski $this->elementsInterator = $this->elements; 4074f8369d7dSTobias Sarnowski $this->valid = isset( $this->elements[0] ) 4075f8369d7dSTobias Sarnowski ? 1 : 0; 4076f8369d7dSTobias Sarnowski// $this->elements = $this->valid 4077f8369d7dSTobias Sarnowski// ? array($this->elements[0]) 4078f8369d7dSTobias Sarnowski// : array(); 4079f8369d7dSTobias Sarnowski $this->current = 0; 4080f8369d7dSTobias Sarnowski } 4081f8369d7dSTobias Sarnowski /** 4082f8369d7dSTobias Sarnowski * @access private 4083f8369d7dSTobias Sarnowski */ 4084f8369d7dSTobias Sarnowski public function current(){ 4085f8369d7dSTobias Sarnowski return $this->elementsInterator[ $this->current ]; 4086f8369d7dSTobias Sarnowski } 4087f8369d7dSTobias Sarnowski /** 4088f8369d7dSTobias Sarnowski * @access private 4089f8369d7dSTobias Sarnowski */ 4090f8369d7dSTobias Sarnowski public function key(){ 4091f8369d7dSTobias Sarnowski return $this->current; 4092f8369d7dSTobias Sarnowski } 4093f8369d7dSTobias Sarnowski /** 4094f8369d7dSTobias Sarnowski * Double-function method. 4095f8369d7dSTobias Sarnowski * 4096f8369d7dSTobias Sarnowski * First: main iterator interface method. 4097f8369d7dSTobias Sarnowski * Second: Returning next sibling, alias for _next(). 4098f8369d7dSTobias Sarnowski * 4099f8369d7dSTobias Sarnowski * Proper functionality is choosed automagicaly. 4100f8369d7dSTobias Sarnowski * 4101f8369d7dSTobias Sarnowski * @see phpQueryObject::_next() 4102f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4103f8369d7dSTobias Sarnowski */ 4104f8369d7dSTobias Sarnowski public function next($cssSelector = null){ 4105f8369d7dSTobias Sarnowski// if ($cssSelector || $this->valid) 4106f8369d7dSTobias Sarnowski// return $this->_next($cssSelector); 4107f8369d7dSTobias Sarnowski $this->valid = isset( $this->elementsInterator[ $this->current+1 ] ) 4108f8369d7dSTobias Sarnowski ? true 4109f8369d7dSTobias Sarnowski : false; 4110f8369d7dSTobias Sarnowski if (! $this->valid && $this->elementsInterator) { 4111f8369d7dSTobias Sarnowski $this->elementsInterator = null; 4112f8369d7dSTobias Sarnowski } else if ($this->valid) { 4113f8369d7dSTobias Sarnowski $this->current++; 4114f8369d7dSTobias Sarnowski } else { 4115f8369d7dSTobias Sarnowski return $this->_next($cssSelector); 4116f8369d7dSTobias Sarnowski } 4117f8369d7dSTobias Sarnowski } 4118f8369d7dSTobias Sarnowski /** 4119f8369d7dSTobias Sarnowski * @access private 4120f8369d7dSTobias Sarnowski */ 4121f8369d7dSTobias Sarnowski public function valid(){ 4122f8369d7dSTobias Sarnowski return $this->valid; 4123f8369d7dSTobias Sarnowski } 4124f8369d7dSTobias Sarnowski // ITERATOR INTERFACE END 4125f8369d7dSTobias Sarnowski // ARRAYACCESS INTERFACE 4126f8369d7dSTobias Sarnowski /** 4127f8369d7dSTobias Sarnowski * @access private 4128f8369d7dSTobias Sarnowski */ 4129f8369d7dSTobias Sarnowski public function offsetExists($offset) { 4130f8369d7dSTobias Sarnowski return $this->find($offset)->size() > 0; 4131f8369d7dSTobias Sarnowski } 4132f8369d7dSTobias Sarnowski /** 4133f8369d7dSTobias Sarnowski * @access private 4134f8369d7dSTobias Sarnowski */ 4135f8369d7dSTobias Sarnowski public function offsetGet($offset) { 4136f8369d7dSTobias Sarnowski return $this->find($offset); 4137f8369d7dSTobias Sarnowski } 4138f8369d7dSTobias Sarnowski /** 4139f8369d7dSTobias Sarnowski * @access private 4140f8369d7dSTobias Sarnowski */ 4141f8369d7dSTobias Sarnowski public function offsetSet($offset, $value) { 4142f8369d7dSTobias Sarnowski// $this->find($offset)->replaceWith($value); 4143f8369d7dSTobias Sarnowski $this->find($offset)->html($value); 4144f8369d7dSTobias Sarnowski } 4145f8369d7dSTobias Sarnowski /** 4146f8369d7dSTobias Sarnowski * @access private 4147f8369d7dSTobias Sarnowski */ 4148f8369d7dSTobias Sarnowski public function offsetUnset($offset) { 4149f8369d7dSTobias Sarnowski // empty 4150f8369d7dSTobias Sarnowski throw new Exception("Can't do unset, use array interface only for calling queries and replacing HTML."); 4151f8369d7dSTobias Sarnowski } 4152f8369d7dSTobias Sarnowski // ARRAYACCESS INTERFACE END 4153f8369d7dSTobias Sarnowski /** 4154f8369d7dSTobias Sarnowski * Returns node's XPath. 4155f8369d7dSTobias Sarnowski * 4156f8369d7dSTobias Sarnowski * @param unknown_type $oneNode 4157f8369d7dSTobias Sarnowski * @return string 4158f8369d7dSTobias Sarnowski * @TODO use native getNodePath is avaible 4159f8369d7dSTobias Sarnowski * @access private 4160f8369d7dSTobias Sarnowski */ 4161f8369d7dSTobias Sarnowski protected function getNodeXpath($oneNode = null, $namespace = null) { 4162f8369d7dSTobias Sarnowski $return = array(); 4163f8369d7dSTobias Sarnowski $loop = $oneNode 4164f8369d7dSTobias Sarnowski ? array($oneNode) 4165f8369d7dSTobias Sarnowski : $this->elements; 4166f8369d7dSTobias Sarnowski// if ($namespace) 4167f8369d7dSTobias Sarnowski// $namespace .= ':'; 4168f8369d7dSTobias Sarnowski foreach($loop as $node) { 4169f8369d7dSTobias Sarnowski if ($node instanceof DOMDOCUMENT) { 4170f8369d7dSTobias Sarnowski $return[] = ''; 4171f8369d7dSTobias Sarnowski continue; 4172f8369d7dSTobias Sarnowski } 4173f8369d7dSTobias Sarnowski $xpath = array(); 4174f8369d7dSTobias Sarnowski while(! ($node instanceof DOMDOCUMENT)) { 4175f8369d7dSTobias Sarnowski $i = 1; 4176f8369d7dSTobias Sarnowski $sibling = $node; 4177f8369d7dSTobias Sarnowski while($sibling->previousSibling) { 4178f8369d7dSTobias Sarnowski $sibling = $sibling->previousSibling; 4179f8369d7dSTobias Sarnowski $isElement = $sibling instanceof DOMELEMENT; 4180f8369d7dSTobias Sarnowski if ($isElement && $sibling->tagName == $node->tagName) 4181f8369d7dSTobias Sarnowski $i++; 4182f8369d7dSTobias Sarnowski } 4183f8369d7dSTobias Sarnowski $xpath[] = $this->isXML() 4184f8369d7dSTobias Sarnowski ? "*[local-name()='{$node->tagName}'][{$i}]" 4185f8369d7dSTobias Sarnowski : "{$node->tagName}[{$i}]"; 4186f8369d7dSTobias Sarnowski $node = $node->parentNode; 4187f8369d7dSTobias Sarnowski } 4188f8369d7dSTobias Sarnowski $xpath = join('/', array_reverse($xpath)); 4189f8369d7dSTobias Sarnowski $return[] = '/'.$xpath; 4190f8369d7dSTobias Sarnowski } 4191f8369d7dSTobias Sarnowski return $oneNode 4192f8369d7dSTobias Sarnowski ? $return[0] 4193f8369d7dSTobias Sarnowski : $return; 4194f8369d7dSTobias Sarnowski } 4195f8369d7dSTobias Sarnowski // HELPERS 4196f8369d7dSTobias Sarnowski public function whois($oneNode = null) { 4197f8369d7dSTobias Sarnowski $return = array(); 4198f8369d7dSTobias Sarnowski $loop = $oneNode 4199f8369d7dSTobias Sarnowski ? array( $oneNode ) 4200f8369d7dSTobias Sarnowski : $this->elements; 4201f8369d7dSTobias Sarnowski foreach($loop as $node) { 4202f8369d7dSTobias Sarnowski if (isset($node->tagName)) { 4203f8369d7dSTobias Sarnowski $tag = in_array($node->tagName, array('php', 'js')) 4204f8369d7dSTobias Sarnowski ? strtoupper($node->tagName) 4205f8369d7dSTobias Sarnowski : $node->tagName; 4206f8369d7dSTobias Sarnowski $return[] = $tag 4207f8369d7dSTobias Sarnowski .($node->getAttribute('id') 4208f8369d7dSTobias Sarnowski ? '#'.$node->getAttribute('id'):'') 4209f8369d7dSTobias Sarnowski .($node->getAttribute('class') 42100edda900SAndreas Gohr ? '.'.join('.', explode(' ', $node->getAttribute('class'))):'') 4211f8369d7dSTobias Sarnowski .($node->getAttribute('name') 4212f8369d7dSTobias Sarnowski ? '[name="'.$node->getAttribute('name').'"]':'') 4213f8369d7dSTobias Sarnowski .($node->getAttribute('value') && strpos($node->getAttribute('value'), '<'.'?php') === false 4214f8369d7dSTobias Sarnowski ? '[value="'.substr(str_replace("\n", '', $node->getAttribute('value')), 0, 15).'"]':'') 4215f8369d7dSTobias Sarnowski .($node->getAttribute('value') && strpos($node->getAttribute('value'), '<'.'?php') !== false 4216f8369d7dSTobias Sarnowski ? '[value=PHP]':'') 4217f8369d7dSTobias Sarnowski .($node->getAttribute('selected') 4218f8369d7dSTobias Sarnowski ? '[selected]':'') 4219f8369d7dSTobias Sarnowski .($node->getAttribute('checked') 4220f8369d7dSTobias Sarnowski ? '[checked]':'') 4221f8369d7dSTobias Sarnowski ; 4222f8369d7dSTobias Sarnowski } else if ($node instanceof DOMTEXT) { 4223f8369d7dSTobias Sarnowski if (trim($node->textContent)) 4224f8369d7dSTobias Sarnowski $return[] = 'Text:'.substr(str_replace("\n", ' ', $node->textContent), 0, 15); 4225f8369d7dSTobias Sarnowski } else { 4226f8369d7dSTobias Sarnowski 4227f8369d7dSTobias Sarnowski } 4228f8369d7dSTobias Sarnowski } 4229f8369d7dSTobias Sarnowski return $oneNode && isset($return[0]) 4230f8369d7dSTobias Sarnowski ? $return[0] 4231f8369d7dSTobias Sarnowski : $return; 4232f8369d7dSTobias Sarnowski } 4233f8369d7dSTobias Sarnowski /** 4234f8369d7dSTobias Sarnowski * Dump htmlOuter and preserve chain. Usefull for debugging. 4235f8369d7dSTobias Sarnowski * 4236f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4237f8369d7dSTobias Sarnowski * 4238f8369d7dSTobias Sarnowski */ 4239f8369d7dSTobias Sarnowski public function dump() { 4240f8369d7dSTobias Sarnowski print 'DUMP #'.(phpQuery::$dumpCount++).' '; 4241f8369d7dSTobias Sarnowski $debug = phpQuery::$debug; 4242f8369d7dSTobias Sarnowski phpQuery::$debug = false; 4243f8369d7dSTobias Sarnowski// print __FILE__.':'.__LINE__."\n"; 4244f8369d7dSTobias Sarnowski var_dump($this->htmlOuter()); 4245f8369d7dSTobias Sarnowski return $this; 4246f8369d7dSTobias Sarnowski } 4247f8369d7dSTobias Sarnowski public function dumpWhois() { 4248f8369d7dSTobias Sarnowski print 'DUMP #'.(phpQuery::$dumpCount++).' '; 4249f8369d7dSTobias Sarnowski $debug = phpQuery::$debug; 4250f8369d7dSTobias Sarnowski phpQuery::$debug = false; 4251f8369d7dSTobias Sarnowski// print __FILE__.':'.__LINE__."\n"; 4252f8369d7dSTobias Sarnowski var_dump('whois', $this->whois()); 4253f8369d7dSTobias Sarnowski phpQuery::$debug = $debug; 4254f8369d7dSTobias Sarnowski return $this; 4255f8369d7dSTobias Sarnowski } 4256f8369d7dSTobias Sarnowski public function dumpLength() { 4257f8369d7dSTobias Sarnowski print 'DUMP #'.(phpQuery::$dumpCount++).' '; 4258f8369d7dSTobias Sarnowski $debug = phpQuery::$debug; 4259f8369d7dSTobias Sarnowski phpQuery::$debug = false; 4260f8369d7dSTobias Sarnowski// print __FILE__.':'.__LINE__."\n"; 4261f8369d7dSTobias Sarnowski var_dump('length', $this->length()); 4262f8369d7dSTobias Sarnowski phpQuery::$debug = $debug; 4263f8369d7dSTobias Sarnowski return $this; 4264f8369d7dSTobias Sarnowski } 4265f8369d7dSTobias Sarnowski public function dumpTree($html = true, $title = true) { 4266f8369d7dSTobias Sarnowski $output = $title 4267f8369d7dSTobias Sarnowski ? 'DUMP #'.(phpQuery::$dumpCount++)." \n" : ''; 4268f8369d7dSTobias Sarnowski $debug = phpQuery::$debug; 4269f8369d7dSTobias Sarnowski phpQuery::$debug = false; 4270f8369d7dSTobias Sarnowski foreach($this->stack() as $node) 4271e32b1b0fSSyntaxseed $output .= $this->dumpTreeInternal($node); 4272f8369d7dSTobias Sarnowski phpQuery::$debug = $debug; 4273f8369d7dSTobias Sarnowski print $html 4274f8369d7dSTobias Sarnowski ? nl2br(str_replace(' ', ' ', $output)) 4275f8369d7dSTobias Sarnowski : $output; 4276f8369d7dSTobias Sarnowski return $this; 4277f8369d7dSTobias Sarnowski } 4278e32b1b0fSSyntaxseed private function dumpTreeInternal($node, $intend = 0) { 4279f8369d7dSTobias Sarnowski $whois = $this->whois($node); 4280f8369d7dSTobias Sarnowski $return = ''; 4281f8369d7dSTobias Sarnowski if ($whois) 4282f8369d7dSTobias Sarnowski $return .= str_repeat(' - ', $intend).$whois."\n"; 4283f8369d7dSTobias Sarnowski if (isset($node->childNodes)) 4284f8369d7dSTobias Sarnowski foreach($node->childNodes as $chNode) 4285e32b1b0fSSyntaxseed $return .= $this->dumpTreeInternal($chNode, $intend+1); 4286f8369d7dSTobias Sarnowski return $return; 4287f8369d7dSTobias Sarnowski } 4288f8369d7dSTobias Sarnowski /** 4289f8369d7dSTobias Sarnowski * Dump htmlOuter and stop script execution. Usefull for debugging. 4290f8369d7dSTobias Sarnowski * 4291f8369d7dSTobias Sarnowski */ 4292f8369d7dSTobias Sarnowski public function dumpDie() { 4293f8369d7dSTobias Sarnowski print __FILE__.':'.__LINE__; 4294f8369d7dSTobias Sarnowski var_dump($this->htmlOuter()); 4295f8369d7dSTobias Sarnowski die(); 4296f8369d7dSTobias Sarnowski } 4297f8369d7dSTobias Sarnowski} 4298f8369d7dSTobias Sarnowski 4299f8369d7dSTobias Sarnowski 4300f8369d7dSTobias Sarnowski// -- Multibyte Compatibility functions --------------------------------------- 4301f8369d7dSTobias Sarnowski// http://svn.iphonewebdev.com/lace/lib/mb_compat.php 4302f8369d7dSTobias Sarnowski 4303f8369d7dSTobias Sarnowski/** 4304f8369d7dSTobias Sarnowski * mb_internal_encoding() 4305f8369d7dSTobias Sarnowski * 4306f8369d7dSTobias Sarnowski * Included for mbstring pseudo-compatability. 4307f8369d7dSTobias Sarnowski */ 4308f8369d7dSTobias Sarnowskiif (!function_exists('mb_internal_encoding')) 4309f8369d7dSTobias Sarnowski{ 4310f8369d7dSTobias Sarnowski function mb_internal_encoding($enc) {return true; } 4311f8369d7dSTobias Sarnowski} 4312f8369d7dSTobias Sarnowski 4313f8369d7dSTobias Sarnowski/** 4314f8369d7dSTobias Sarnowski * mb_regex_encoding() 4315f8369d7dSTobias Sarnowski * 4316f8369d7dSTobias Sarnowski * Included for mbstring pseudo-compatability. 4317f8369d7dSTobias Sarnowski */ 4318f8369d7dSTobias Sarnowskiif (!function_exists('mb_regex_encoding')) 4319f8369d7dSTobias Sarnowski{ 4320f8369d7dSTobias Sarnowski function mb_regex_encoding($enc) {return true; } 4321f8369d7dSTobias Sarnowski} 4322f8369d7dSTobias Sarnowski 4323f8369d7dSTobias Sarnowski/** 4324f8369d7dSTobias Sarnowski * mb_strlen() 4325f8369d7dSTobias Sarnowski * 4326f8369d7dSTobias Sarnowski * Included for mbstring pseudo-compatability. 4327f8369d7dSTobias Sarnowski */ 4328f8369d7dSTobias Sarnowskiif (!function_exists('mb_strlen')) 4329f8369d7dSTobias Sarnowski{ 4330f8369d7dSTobias Sarnowski function mb_strlen($str) 4331f8369d7dSTobias Sarnowski { 4332f8369d7dSTobias Sarnowski return strlen($str); 4333f8369d7dSTobias Sarnowski } 4334f8369d7dSTobias Sarnowski} 4335f8369d7dSTobias Sarnowski 4336f8369d7dSTobias Sarnowski/** 4337f8369d7dSTobias Sarnowski * mb_strpos() 4338f8369d7dSTobias Sarnowski * 4339f8369d7dSTobias Sarnowski * Included for mbstring pseudo-compatability. 4340f8369d7dSTobias Sarnowski */ 4341f8369d7dSTobias Sarnowskiif (!function_exists('mb_strpos')) 4342f8369d7dSTobias Sarnowski{ 4343f8369d7dSTobias Sarnowski function mb_strpos($haystack, $needle, $offset=0) 4344f8369d7dSTobias Sarnowski { 4345f8369d7dSTobias Sarnowski return strpos($haystack, $needle, $offset); 4346f8369d7dSTobias Sarnowski } 4347f8369d7dSTobias Sarnowski} 4348f8369d7dSTobias Sarnowski/** 4349f8369d7dSTobias Sarnowski * mb_stripos() 4350f8369d7dSTobias Sarnowski * 4351f8369d7dSTobias Sarnowski * Included for mbstring pseudo-compatability. 4352f8369d7dSTobias Sarnowski */ 4353f8369d7dSTobias Sarnowskiif (!function_exists('mb_stripos')) 4354f8369d7dSTobias Sarnowski{ 4355f8369d7dSTobias Sarnowski function mb_stripos($haystack, $needle, $offset=0) 4356f8369d7dSTobias Sarnowski { 4357f8369d7dSTobias Sarnowski return stripos($haystack, $needle, $offset); 4358f8369d7dSTobias Sarnowski } 4359f8369d7dSTobias Sarnowski} 4360f8369d7dSTobias Sarnowski 4361f8369d7dSTobias Sarnowski/** 4362f8369d7dSTobias Sarnowski * mb_substr() 4363f8369d7dSTobias Sarnowski * 4364f8369d7dSTobias Sarnowski * Included for mbstring pseudo-compatability. 4365f8369d7dSTobias Sarnowski */ 4366f8369d7dSTobias Sarnowskiif (!function_exists('mb_substr')) 4367f8369d7dSTobias Sarnowski{ 4368f8369d7dSTobias Sarnowski function mb_substr($str, $start, $length=0) 4369f8369d7dSTobias Sarnowski { 4370f8369d7dSTobias Sarnowski return substr($str, $start, $length); 4371f8369d7dSTobias Sarnowski } 4372f8369d7dSTobias Sarnowski} 4373f8369d7dSTobias Sarnowski 4374f8369d7dSTobias Sarnowski/** 4375f8369d7dSTobias Sarnowski * mb_substr_count() 4376f8369d7dSTobias Sarnowski * 4377f8369d7dSTobias Sarnowski * Included for mbstring pseudo-compatability. 4378f8369d7dSTobias Sarnowski */ 4379f8369d7dSTobias Sarnowskiif (!function_exists('mb_substr_count')) 4380f8369d7dSTobias Sarnowski{ 4381f8369d7dSTobias Sarnowski function mb_substr_count($haystack, $needle) 4382f8369d7dSTobias Sarnowski { 4383f8369d7dSTobias Sarnowski return substr_count($haystack, $needle); 4384f8369d7dSTobias Sarnowski } 4385f8369d7dSTobias Sarnowski} 4386f8369d7dSTobias Sarnowski 4387f8369d7dSTobias Sarnowski 4388f8369d7dSTobias Sarnowski/** 4389f8369d7dSTobias Sarnowski * Static namespace for phpQuery functions. 4390f8369d7dSTobias Sarnowski * 4391f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 4392f8369d7dSTobias Sarnowski * @package phpQuery 4393f8369d7dSTobias Sarnowski */ 4394f8369d7dSTobias Sarnowskiabstract class phpQuery { 4395f8369d7dSTobias Sarnowski /** 4396f8369d7dSTobias Sarnowski * XXX: Workaround for mbstring problems 4397f8369d7dSTobias Sarnowski * 4398f8369d7dSTobias Sarnowski * @var bool 4399f8369d7dSTobias Sarnowski */ 4400f8369d7dSTobias Sarnowski public static $mbstringSupport = true; 4401f8369d7dSTobias Sarnowski public static $debug = false; 4402f8369d7dSTobias Sarnowski public static $documents = array(); 4403f8369d7dSTobias Sarnowski public static $defaultDocumentID = null; 4404f8369d7dSTobias Sarnowski// public static $defaultDoctype = 'html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"'; 4405f8369d7dSTobias Sarnowski /** 4406f8369d7dSTobias Sarnowski * Applies only to HTML. 4407f8369d7dSTobias Sarnowski * 4408f8369d7dSTobias Sarnowski * @var unknown_type 4409f8369d7dSTobias Sarnowski */ 4410f8369d7dSTobias Sarnowski public static $defaultDoctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 4411f8369d7dSTobias Sarnowski"http://www.w3.org/TR/html4/loose.dtd">'; 4412f8369d7dSTobias Sarnowski public static $defaultCharset = 'UTF-8'; 4413f8369d7dSTobias Sarnowski /** 4414f8369d7dSTobias Sarnowski * Static namespace for plugins. 4415f8369d7dSTobias Sarnowski * 4416f8369d7dSTobias Sarnowski * @var object 4417f8369d7dSTobias Sarnowski */ 4418f8369d7dSTobias Sarnowski public static $plugins = array(); 4419f8369d7dSTobias Sarnowski /** 4420f8369d7dSTobias Sarnowski * List of loaded plugins. 4421f8369d7dSTobias Sarnowski * 4422f8369d7dSTobias Sarnowski * @var unknown_type 4423f8369d7dSTobias Sarnowski */ 4424f8369d7dSTobias Sarnowski public static $pluginsLoaded = array(); 4425f8369d7dSTobias Sarnowski public static $pluginsMethods = array(); 4426f8369d7dSTobias Sarnowski public static $pluginsStaticMethods = array(); 4427f8369d7dSTobias Sarnowski public static $extendMethods = array(); 4428f8369d7dSTobias Sarnowski /** 4429f8369d7dSTobias Sarnowski * @TODO implement 4430f8369d7dSTobias Sarnowski */ 4431f8369d7dSTobias Sarnowski public static $extendStaticMethods = array(); 4432f8369d7dSTobias Sarnowski /** 4433f8369d7dSTobias Sarnowski * Hosts allowed for AJAX connections. 4434f8369d7dSTobias Sarnowski * Dot '.' means $_SERVER['HTTP_HOST'] (if any). 4435f8369d7dSTobias Sarnowski * 4436f8369d7dSTobias Sarnowski * @var array 4437f8369d7dSTobias Sarnowski */ 4438f8369d7dSTobias Sarnowski public static $ajaxAllowedHosts = array( 4439f8369d7dSTobias Sarnowski '.' 4440f8369d7dSTobias Sarnowski ); 4441f8369d7dSTobias Sarnowski /** 4442f8369d7dSTobias Sarnowski * AJAX settings. 4443f8369d7dSTobias Sarnowski * 4444f8369d7dSTobias Sarnowski * @var array 4445f8369d7dSTobias Sarnowski * XXX should it be static or not ? 4446f8369d7dSTobias Sarnowski */ 4447f8369d7dSTobias Sarnowski public static $ajaxSettings = array( 4448f8369d7dSTobias Sarnowski 'url' => '',//TODO 4449f8369d7dSTobias Sarnowski 'global' => true, 4450f8369d7dSTobias Sarnowski 'type' => "GET", 4451f8369d7dSTobias Sarnowski 'timeout' => null, 4452f8369d7dSTobias Sarnowski 'contentType' => "application/x-www-form-urlencoded", 4453f8369d7dSTobias Sarnowski 'processData' => true, 4454f8369d7dSTobias Sarnowski// 'async' => true, 4455f8369d7dSTobias Sarnowski 'data' => null, 4456f8369d7dSTobias Sarnowski 'username' => null, 4457f8369d7dSTobias Sarnowski 'password' => null, 4458f8369d7dSTobias Sarnowski 'accepts' => array( 4459f8369d7dSTobias Sarnowski 'xml' => "application/xml, text/xml", 4460f8369d7dSTobias Sarnowski 'html' => "text/html", 4461f8369d7dSTobias Sarnowski 'script' => "text/javascript, application/javascript", 4462f8369d7dSTobias Sarnowski 'json' => "application/json, text/javascript", 4463f8369d7dSTobias Sarnowski 'text' => "text/plain", 4464f8369d7dSTobias Sarnowski '_default' => "*/*" 4465f8369d7dSTobias Sarnowski ) 4466f8369d7dSTobias Sarnowski ); 4467f8369d7dSTobias Sarnowski public static $lastModified = null; 4468f8369d7dSTobias Sarnowski public static $active = 0; 4469f8369d7dSTobias Sarnowski public static $dumpCount = 0; 4470f8369d7dSTobias Sarnowski /** 4471f8369d7dSTobias Sarnowski * Multi-purpose function. 4472f8369d7dSTobias Sarnowski * Use pq() as shortcut. 4473f8369d7dSTobias Sarnowski * 4474f8369d7dSTobias Sarnowski * In below examples, $pq is any result of pq(); function. 4475f8369d7dSTobias Sarnowski * 4476f8369d7dSTobias Sarnowski * 1. Import markup into existing document (without any attaching): 4477f8369d7dSTobias Sarnowski * - Import into selected document: 4478f8369d7dSTobias Sarnowski * pq('<div/>') // DOESNT accept text nodes at beginning of input string ! 4479f8369d7dSTobias Sarnowski * - Import into document with ID from $pq->getDocumentID(): 4480f8369d7dSTobias Sarnowski * pq('<div/>', $pq->getDocumentID()) 4481f8369d7dSTobias Sarnowski * - Import into same document as DOMNode belongs to: 4482f8369d7dSTobias Sarnowski * pq('<div/>', DOMNode) 4483f8369d7dSTobias Sarnowski * - Import into document from phpQuery object: 4484f8369d7dSTobias Sarnowski * pq('<div/>', $pq) 4485f8369d7dSTobias Sarnowski * 4486f8369d7dSTobias Sarnowski * 2. Run query: 4487f8369d7dSTobias Sarnowski * - Run query on last selected document: 4488f8369d7dSTobias Sarnowski * pq('div.myClass') 4489f8369d7dSTobias Sarnowski * - Run query on document with ID from $pq->getDocumentID(): 4490f8369d7dSTobias Sarnowski * pq('div.myClass', $pq->getDocumentID()) 4491f8369d7dSTobias Sarnowski * - Run query on same document as DOMNode belongs to and use node(s)as root for query: 4492f8369d7dSTobias Sarnowski * pq('div.myClass', DOMNode) 4493f8369d7dSTobias Sarnowski * - Run query on document from phpQuery object 4494f8369d7dSTobias Sarnowski * and use object's stack as root node(s) for query: 4495f8369d7dSTobias Sarnowski * pq('div.myClass', $pq) 4496f8369d7dSTobias Sarnowski * 4497f8369d7dSTobias Sarnowski * @param string|DOMNode|DOMNodeList|array $arg1 HTML markup, CSS Selector, DOMNode or array of DOMNodes 4498f8369d7dSTobias Sarnowski * @param string|phpQueryObject|DOMNode $context DOM ID from $pq->getDocumentID(), phpQuery object (determines also query root) or DOMNode (determines also query root) 4499f8369d7dSTobias Sarnowski * 4500f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery|QueryTemplatesPhpQuery|false 4501f8369d7dSTobias Sarnowski * phpQuery object or false in case of error. 4502f8369d7dSTobias Sarnowski */ 4503f8369d7dSTobias Sarnowski public static function pq($arg1, $context = null) { 4504f8369d7dSTobias Sarnowski if ($arg1 instanceof DOMNODE && ! isset($context)) { 4505f8369d7dSTobias Sarnowski foreach(phpQuery::$documents as $documentWrapper) { 4506f8369d7dSTobias Sarnowski $compare = $arg1 instanceof DOMDocument 4507f8369d7dSTobias Sarnowski ? $arg1 : $arg1->ownerDocument; 4508f8369d7dSTobias Sarnowski if ($documentWrapper->document->isSameNode($compare)) 4509f8369d7dSTobias Sarnowski $context = $documentWrapper->id; 4510f8369d7dSTobias Sarnowski } 4511f8369d7dSTobias Sarnowski } 4512f8369d7dSTobias Sarnowski if (! $context) { 4513f8369d7dSTobias Sarnowski $domId = self::$defaultDocumentID; 4514f8369d7dSTobias Sarnowski if (! $domId) 4515f8369d7dSTobias Sarnowski throw new Exception("Can't use last created DOM, because there isn't any. Use phpQuery::newDocument() first."); 4516f8369d7dSTobias Sarnowski// } else if (is_object($context) && ($context instanceof PHPQUERY || is_subclass_of($context, 'phpQueryObject'))) 4517f8369d7dSTobias Sarnowski } else if (is_object($context) && $context instanceof phpQueryObject) 4518f8369d7dSTobias Sarnowski $domId = $context->getDocumentID(); 4519f8369d7dSTobias Sarnowski else if ($context instanceof DOMDOCUMENT) { 4520f8369d7dSTobias Sarnowski $domId = self::getDocumentID($context); 4521f8369d7dSTobias Sarnowski if (! $domId) { 4522f8369d7dSTobias Sarnowski //throw new Exception('Orphaned DOMDocument'); 4523f8369d7dSTobias Sarnowski $domId = self::newDocument($context)->getDocumentID(); 4524f8369d7dSTobias Sarnowski } 4525f8369d7dSTobias Sarnowski } else if ($context instanceof DOMNODE) { 4526f8369d7dSTobias Sarnowski $domId = self::getDocumentID($context); 4527f8369d7dSTobias Sarnowski if (! $domId) { 4528f8369d7dSTobias Sarnowski throw new Exception('Orphaned DOMNode'); 4529f8369d7dSTobias Sarnowski// $domId = self::newDocument($context->ownerDocument); 4530f8369d7dSTobias Sarnowski } 4531f8369d7dSTobias Sarnowski } else 4532f8369d7dSTobias Sarnowski $domId = $context; 4533f8369d7dSTobias Sarnowski if ($arg1 instanceof phpQueryObject) { 4534f8369d7dSTobias Sarnowski// if (is_object($arg1) && (get_class($arg1) == 'phpQueryObject' || $arg1 instanceof PHPQUERY || is_subclass_of($arg1, 'phpQueryObject'))) { 4535f8369d7dSTobias Sarnowski /** 4536f8369d7dSTobias Sarnowski * Return $arg1 or import $arg1 stack if document differs: 4537f8369d7dSTobias Sarnowski * pq(pq('<div/>')) 4538f8369d7dSTobias Sarnowski */ 4539f8369d7dSTobias Sarnowski if ($arg1->getDocumentID() == $domId) 4540f8369d7dSTobias Sarnowski return $arg1; 4541f8369d7dSTobias Sarnowski $class = get_class($arg1); 4542f8369d7dSTobias Sarnowski // support inheritance by passing old object to overloaded constructor 4543f8369d7dSTobias Sarnowski $phpQuery = $class != 'phpQuery' 4544f8369d7dSTobias Sarnowski ? new $class($arg1, $domId) 4545f8369d7dSTobias Sarnowski : new phpQueryObject($domId); 4546f8369d7dSTobias Sarnowski $phpQuery->elements = array(); 4547f8369d7dSTobias Sarnowski foreach($arg1->elements as $node) 4548f8369d7dSTobias Sarnowski $phpQuery->elements[] = $phpQuery->document->importNode($node, true); 4549f8369d7dSTobias Sarnowski return $phpQuery; 4550f8369d7dSTobias Sarnowski } else if ($arg1 instanceof DOMNODE || (is_array($arg1) && isset($arg1[0]) && $arg1[0] instanceof DOMNODE)) { 4551f8369d7dSTobias Sarnowski /* 4552f8369d7dSTobias Sarnowski * Wrap DOM nodes with phpQuery object, import into document when needed: 4553f8369d7dSTobias Sarnowski * pq(array($domNode1, $domNode2)) 4554f8369d7dSTobias Sarnowski */ 4555f8369d7dSTobias Sarnowski $phpQuery = new phpQueryObject($domId); 4556f8369d7dSTobias Sarnowski if (!($arg1 instanceof DOMNODELIST) && ! is_array($arg1)) 4557f8369d7dSTobias Sarnowski $arg1 = array($arg1); 4558f8369d7dSTobias Sarnowski $phpQuery->elements = array(); 4559f8369d7dSTobias Sarnowski foreach($arg1 as $node) { 4560f8369d7dSTobias Sarnowski $sameDocument = $node->ownerDocument instanceof DOMDOCUMENT 4561f8369d7dSTobias Sarnowski && ! $node->ownerDocument->isSameNode($phpQuery->document); 4562f8369d7dSTobias Sarnowski $phpQuery->elements[] = $sameDocument 4563f8369d7dSTobias Sarnowski ? $phpQuery->document->importNode($node, true) 4564f8369d7dSTobias Sarnowski : $node; 4565f8369d7dSTobias Sarnowski } 4566f8369d7dSTobias Sarnowski return $phpQuery; 4567f8369d7dSTobias Sarnowski } else if (self::isMarkup($arg1)) { 4568f8369d7dSTobias Sarnowski /** 4569f8369d7dSTobias Sarnowski * Import HTML: 4570f8369d7dSTobias Sarnowski * pq('<div/>') 4571f8369d7dSTobias Sarnowski */ 4572f8369d7dSTobias Sarnowski $phpQuery = new phpQueryObject($domId); 4573f8369d7dSTobias Sarnowski return $phpQuery->newInstance( 4574f8369d7dSTobias Sarnowski $phpQuery->documentWrapper->import($arg1) 4575f8369d7dSTobias Sarnowski ); 4576f8369d7dSTobias Sarnowski } else { 4577f8369d7dSTobias Sarnowski /** 4578f8369d7dSTobias Sarnowski * Run CSS query: 4579f8369d7dSTobias Sarnowski * pq('div.myClass') 4580f8369d7dSTobias Sarnowski */ 4581f8369d7dSTobias Sarnowski $phpQuery = new phpQueryObject($domId); 4582f8369d7dSTobias Sarnowski// if ($context && ($context instanceof PHPQUERY || is_subclass_of($context, 'phpQueryObject'))) 4583f8369d7dSTobias Sarnowski if ($context && $context instanceof phpQueryObject) 4584f8369d7dSTobias Sarnowski $phpQuery->elements = $context->elements; 4585f8369d7dSTobias Sarnowski else if ($context && $context instanceof DOMNODELIST) { 4586f8369d7dSTobias Sarnowski $phpQuery->elements = array(); 4587f8369d7dSTobias Sarnowski foreach($context as $node) 4588f8369d7dSTobias Sarnowski $phpQuery->elements[] = $node; 4589f8369d7dSTobias Sarnowski } else if ($context && $context instanceof DOMNODE) 4590f8369d7dSTobias Sarnowski $phpQuery->elements = array($context); 4591f8369d7dSTobias Sarnowski return $phpQuery->find($arg1); 4592f8369d7dSTobias Sarnowski } 4593f8369d7dSTobias Sarnowski } 4594f8369d7dSTobias Sarnowski /** 4595f8369d7dSTobias Sarnowski * Sets default document to $id. Document has to be loaded prior 4596f8369d7dSTobias Sarnowski * to using this method. 4597f8369d7dSTobias Sarnowski * $id can be retrived via getDocumentID() or getDocumentIDRef(). 4598f8369d7dSTobias Sarnowski * 4599f8369d7dSTobias Sarnowski * @param unknown_type $id 4600f8369d7dSTobias Sarnowski */ 4601f8369d7dSTobias Sarnowski public static function selectDocument($id) { 4602f8369d7dSTobias Sarnowski $id = self::getDocumentID($id); 4603f8369d7dSTobias Sarnowski self::debug("Selecting document '$id' as default one"); 4604f8369d7dSTobias Sarnowski self::$defaultDocumentID = self::getDocumentID($id); 4605f8369d7dSTobias Sarnowski } 4606f8369d7dSTobias Sarnowski /** 4607f8369d7dSTobias Sarnowski * Returns document with id $id or last used as phpQueryObject. 4608f8369d7dSTobias Sarnowski * $id can be retrived via getDocumentID() or getDocumentIDRef(). 4609f8369d7dSTobias Sarnowski * Chainable. 4610f8369d7dSTobias Sarnowski * 4611f8369d7dSTobias Sarnowski * @see phpQuery::selectDocument() 4612f8369d7dSTobias Sarnowski * @param unknown_type $id 4613f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4614f8369d7dSTobias Sarnowski */ 4615f8369d7dSTobias Sarnowski public static function getDocument($id = null) { 4616f8369d7dSTobias Sarnowski if ($id) 4617f8369d7dSTobias Sarnowski phpQuery::selectDocument($id); 4618f8369d7dSTobias Sarnowski else 4619f8369d7dSTobias Sarnowski $id = phpQuery::$defaultDocumentID; 4620f8369d7dSTobias Sarnowski return new phpQueryObject($id); 4621f8369d7dSTobias Sarnowski } 4622f8369d7dSTobias Sarnowski /** 4623f8369d7dSTobias Sarnowski * Creates new document from markup. 4624f8369d7dSTobias Sarnowski * Chainable. 4625f8369d7dSTobias Sarnowski * 4626*6b8df285SAndreas Gohr * @deprecated Use \DOMWrap\Document instead 4627f8369d7dSTobias Sarnowski * @param unknown_type $markup 4628f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4629f8369d7dSTobias Sarnowski */ 4630f8369d7dSTobias Sarnowski public static function newDocument($markup = null, $contentType = null) { 4631f8369d7dSTobias Sarnowski if (! $markup) 4632f8369d7dSTobias Sarnowski $markup = ''; 4633f8369d7dSTobias Sarnowski $documentID = phpQuery::createDocumentWrapper($markup, $contentType); 4634f8369d7dSTobias Sarnowski return new phpQueryObject($documentID); 4635f8369d7dSTobias Sarnowski } 4636f8369d7dSTobias Sarnowski /** 4637f8369d7dSTobias Sarnowski * Creates new document from markup. 4638f8369d7dSTobias Sarnowski * Chainable. 4639f8369d7dSTobias Sarnowski * 4640f8369d7dSTobias Sarnowski * @param unknown_type $markup 4641f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4642f8369d7dSTobias Sarnowski */ 4643f8369d7dSTobias Sarnowski public static function newDocumentHTML($markup = null, $charset = null) { 4644f8369d7dSTobias Sarnowski $contentType = $charset 4645f8369d7dSTobias Sarnowski ? ";charset=$charset" 4646f8369d7dSTobias Sarnowski : ''; 4647f8369d7dSTobias Sarnowski return self::newDocument($markup, "text/html{$contentType}"); 4648f8369d7dSTobias Sarnowski } 4649f8369d7dSTobias Sarnowski /** 4650f8369d7dSTobias Sarnowski * Creates new document from markup. 4651f8369d7dSTobias Sarnowski * Chainable. 4652f8369d7dSTobias Sarnowski * 4653f8369d7dSTobias Sarnowski * @param unknown_type $markup 4654f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4655f8369d7dSTobias Sarnowski */ 4656f8369d7dSTobias Sarnowski public static function newDocumentXML($markup = null, $charset = null) { 4657f8369d7dSTobias Sarnowski $contentType = $charset 4658f8369d7dSTobias Sarnowski ? ";charset=$charset" 4659f8369d7dSTobias Sarnowski : ''; 4660f8369d7dSTobias Sarnowski return self::newDocument($markup, "text/xml{$contentType}"); 4661f8369d7dSTobias Sarnowski } 4662f8369d7dSTobias Sarnowski /** 4663f8369d7dSTobias Sarnowski * Creates new document from markup. 4664f8369d7dSTobias Sarnowski * Chainable. 4665f8369d7dSTobias Sarnowski * 4666f8369d7dSTobias Sarnowski * @param unknown_type $markup 4667f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4668f8369d7dSTobias Sarnowski */ 4669f8369d7dSTobias Sarnowski public static function newDocumentXHTML($markup = null, $charset = null) { 4670f8369d7dSTobias Sarnowski $contentType = $charset 4671f8369d7dSTobias Sarnowski ? ";charset=$charset" 4672f8369d7dSTobias Sarnowski : ''; 4673f8369d7dSTobias Sarnowski return self::newDocument($markup, "application/xhtml+xml{$contentType}"); 4674f8369d7dSTobias Sarnowski } 4675f8369d7dSTobias Sarnowski /** 4676f8369d7dSTobias Sarnowski * Creates new document from markup. 4677f8369d7dSTobias Sarnowski * Chainable. 4678f8369d7dSTobias Sarnowski * 4679f8369d7dSTobias Sarnowski * @param unknown_type $markup 4680f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4681f8369d7dSTobias Sarnowski */ 4682f8369d7dSTobias Sarnowski public static function newDocumentPHP($markup = null, $contentType = "text/html") { 4683f8369d7dSTobias Sarnowski // TODO pass charset to phpToMarkup if possible (use DOMDocumentWrapper function) 4684f8369d7dSTobias Sarnowski $markup = phpQuery::phpToMarkup($markup, self::$defaultCharset); 4685f8369d7dSTobias Sarnowski return self::newDocument($markup, $contentType); 4686f8369d7dSTobias Sarnowski } 4687f8369d7dSTobias Sarnowski public static function phpToMarkup($php, $charset = 'utf-8') { 4688f8369d7dSTobias Sarnowski $regexes = array( 4689f8369d7dSTobias Sarnowski '@(<(?!\\?)(?:[^>]|\\?>)+\\w+\\s*=\\s*)(\')([^\']*)<'.'?php?(.*?)(?:\\?>)([^\']*)\'@s', 4690f8369d7dSTobias Sarnowski '@(<(?!\\?)(?:[^>]|\\?>)+\\w+\\s*=\\s*)(")([^"]*)<'.'?php?(.*?)(?:\\?>)([^"]*)"@s', 4691f8369d7dSTobias Sarnowski ); 4692f8369d7dSTobias Sarnowski foreach($regexes as $regex) 4693f8369d7dSTobias Sarnowski while (preg_match($regex, $php, $matches)) { 4694f8369d7dSTobias Sarnowski $php = preg_replace_callback( 4695f8369d7dSTobias Sarnowski $regex, 4696f8369d7dSTobias Sarnowski// create_function('$m, $charset = "'.$charset.'"', 4697f8369d7dSTobias Sarnowski// 'return $m[1].$m[2] 4698f8369d7dSTobias Sarnowski// .htmlspecialchars("<"."?php".$m[4]."?".">", ENT_QUOTES|ENT_NOQUOTES, $charset) 4699f8369d7dSTobias Sarnowski// .$m[5].$m[2];' 4700f8369d7dSTobias Sarnowski// ), 4701f8369d7dSTobias Sarnowski array('phpQuery', '_phpToMarkupCallback'), 4702f8369d7dSTobias Sarnowski $php 4703f8369d7dSTobias Sarnowski ); 4704f8369d7dSTobias Sarnowski } 4705f8369d7dSTobias Sarnowski $regex = '@(^|>[^<]*)+?(<\?php(.*?)(\?>))@s'; 4706f8369d7dSTobias Sarnowski//preg_match_all($regex, $php, $matches); 4707f8369d7dSTobias Sarnowski//var_dump($matches); 4708f8369d7dSTobias Sarnowski $php = preg_replace($regex, '\\1<php><!-- \\3 --></php>', $php); 4709f8369d7dSTobias Sarnowski return $php; 4710f8369d7dSTobias Sarnowski } 4711f8369d7dSTobias Sarnowski public static function _phpToMarkupCallback($php, $charset = 'utf-8') { 4712f8369d7dSTobias Sarnowski return $m[1].$m[2] 4713f8369d7dSTobias Sarnowski .htmlspecialchars("<"."?php".$m[4]."?".">", ENT_QUOTES|ENT_NOQUOTES, $charset) 4714f8369d7dSTobias Sarnowski .$m[5].$m[2]; 4715f8369d7dSTobias Sarnowski } 4716f8369d7dSTobias Sarnowski public static function _markupToPHPCallback($m) { 4717f8369d7dSTobias Sarnowski return "<"."?php ".htmlspecialchars_decode($m[1])." ?".">"; 4718f8369d7dSTobias Sarnowski } 4719f8369d7dSTobias Sarnowski /** 4720f8369d7dSTobias Sarnowski * Converts document markup containing PHP code generated by phpQuery::php() 4721f8369d7dSTobias Sarnowski * into valid (executable) PHP code syntax. 4722f8369d7dSTobias Sarnowski * 4723f8369d7dSTobias Sarnowski * @param string|phpQueryObject $content 4724f8369d7dSTobias Sarnowski * @return string PHP code. 4725f8369d7dSTobias Sarnowski */ 4726f8369d7dSTobias Sarnowski public static function markupToPHP($content) { 4727f8369d7dSTobias Sarnowski if ($content instanceof phpQueryObject) 4728f8369d7dSTobias Sarnowski $content = $content->markupOuter(); 4729f8369d7dSTobias Sarnowski /* <php>...</php> to <?php...? > */ 4730f8369d7dSTobias Sarnowski $content = preg_replace_callback( 4731f8369d7dSTobias Sarnowski '@<php>\s*<!--(.*?)-->\s*</php>@s', 4732f8369d7dSTobias Sarnowski// create_function('$m', 4733f8369d7dSTobias Sarnowski// 'return "<'.'?php ".htmlspecialchars_decode($m[1])." ?'.'>";' 4734f8369d7dSTobias Sarnowski// ), 4735f8369d7dSTobias Sarnowski array('phpQuery', '_markupToPHPCallback'), 4736f8369d7dSTobias Sarnowski $content 4737f8369d7dSTobias Sarnowski ); 4738f8369d7dSTobias Sarnowski /* <node attr='< ?php ? >'> extra space added to save highlighters */ 4739f8369d7dSTobias Sarnowski $regexes = array( 4740f8369d7dSTobias Sarnowski '@(<(?!\\?)(?:[^>]|\\?>)+\\w+\\s*=\\s*)(\')([^\']*)(?:<|%3C)\\?(?:php)?(.*?)(?:\\?(?:>|%3E))([^\']*)\'@s', 4741f8369d7dSTobias Sarnowski '@(<(?!\\?)(?:[^>]|\\?>)+\\w+\\s*=\\s*)(")([^"]*)(?:<|%3C)\\?(?:php)?(.*?)(?:\\?(?:>|%3E))([^"]*)"@s', 4742f8369d7dSTobias Sarnowski ); 4743f8369d7dSTobias Sarnowski foreach($regexes as $regex) 4744f8369d7dSTobias Sarnowski while (preg_match($regex, $content)) 4745f8369d7dSTobias Sarnowski $content = preg_replace_callback( 4746f8369d7dSTobias Sarnowski $regex, 4747a3095052SOscar Merida function ($m) { 4748a3095052SOscar Merida return $m[1] . $m[2] . $m[3] . '<?php ' 4749f8369d7dSTobias Sarnowski . str_replace( 4750f8369d7dSTobias Sarnowski array("%20", "%3E", "%09", " ", "	", "%7B", "%24", "%7D", "%22", "%5B", "%5D"), 4751a3095052SOscar Merida array(" ", ">", " ", "\n", " ", "{", "$", "}", '"', "[", "]"), 4752f8369d7dSTobias Sarnowski htmlspecialchars_decode($m[4]) 4753f8369d7dSTobias Sarnowski ) 4754a3095052SOscar Merida . " ?>" . $m[5] . $m[2]; 4755a3095052SOscar Merida }, 4756f8369d7dSTobias Sarnowski $content 4757f8369d7dSTobias Sarnowski ); 4758f8369d7dSTobias Sarnowski return $content; 4759f8369d7dSTobias Sarnowski } 4760f8369d7dSTobias Sarnowski /** 4761f8369d7dSTobias Sarnowski * Creates new document from file $file. 4762f8369d7dSTobias Sarnowski * Chainable. 4763f8369d7dSTobias Sarnowski * 4764f8369d7dSTobias Sarnowski * @param string $file URLs allowed. See File wrapper page at php.net for more supported sources. 4765f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4766f8369d7dSTobias Sarnowski */ 4767f8369d7dSTobias Sarnowski public static function newDocumentFile($file, $contentType = null) { 4768f8369d7dSTobias Sarnowski $documentID = self::createDocumentWrapper( 4769f8369d7dSTobias Sarnowski file_get_contents($file), $contentType 4770f8369d7dSTobias Sarnowski ); 4771f8369d7dSTobias Sarnowski return new phpQueryObject($documentID); 4772f8369d7dSTobias Sarnowski } 4773f8369d7dSTobias Sarnowski /** 4774f8369d7dSTobias Sarnowski * Creates new document from markup. 4775f8369d7dSTobias Sarnowski * Chainable. 4776f8369d7dSTobias Sarnowski * 4777f8369d7dSTobias Sarnowski * @param unknown_type $markup 4778f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4779f8369d7dSTobias Sarnowski */ 4780f8369d7dSTobias Sarnowski public static function newDocumentFileHTML($file, $charset = null) { 4781f8369d7dSTobias Sarnowski $contentType = $charset 4782f8369d7dSTobias Sarnowski ? ";charset=$charset" 4783f8369d7dSTobias Sarnowski : ''; 4784f8369d7dSTobias Sarnowski return self::newDocumentFile($file, "text/html{$contentType}"); 4785f8369d7dSTobias Sarnowski } 4786f8369d7dSTobias Sarnowski /** 4787f8369d7dSTobias Sarnowski * Creates new document from markup. 4788f8369d7dSTobias Sarnowski * Chainable. 4789f8369d7dSTobias Sarnowski * 4790f8369d7dSTobias Sarnowski * @param unknown_type $markup 4791f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4792f8369d7dSTobias Sarnowski */ 4793f8369d7dSTobias Sarnowski public static function newDocumentFileXML($file, $charset = null) { 4794f8369d7dSTobias Sarnowski $contentType = $charset 4795f8369d7dSTobias Sarnowski ? ";charset=$charset" 4796f8369d7dSTobias Sarnowski : ''; 4797f8369d7dSTobias Sarnowski return self::newDocumentFile($file, "text/xml{$contentType}"); 4798f8369d7dSTobias Sarnowski } 4799f8369d7dSTobias Sarnowski /** 4800f8369d7dSTobias Sarnowski * Creates new document from markup. 4801f8369d7dSTobias Sarnowski * Chainable. 4802f8369d7dSTobias Sarnowski * 4803f8369d7dSTobias Sarnowski * @param unknown_type $markup 4804f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4805f8369d7dSTobias Sarnowski */ 4806f8369d7dSTobias Sarnowski public static function newDocumentFileXHTML($file, $charset = null) { 4807f8369d7dSTobias Sarnowski $contentType = $charset 4808f8369d7dSTobias Sarnowski ? ";charset=$charset" 4809f8369d7dSTobias Sarnowski : ''; 4810f8369d7dSTobias Sarnowski return self::newDocumentFile($file, "application/xhtml+xml{$contentType}"); 4811f8369d7dSTobias Sarnowski } 4812f8369d7dSTobias Sarnowski /** 4813f8369d7dSTobias Sarnowski * Creates new document from markup. 4814f8369d7dSTobias Sarnowski * Chainable. 4815f8369d7dSTobias Sarnowski * 4816f8369d7dSTobias Sarnowski * @param unknown_type $markup 4817f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4818f8369d7dSTobias Sarnowski */ 4819f8369d7dSTobias Sarnowski public static function newDocumentFilePHP($file, $contentType = null) { 4820f8369d7dSTobias Sarnowski return self::newDocumentPHP(file_get_contents($file), $contentType); 4821f8369d7dSTobias Sarnowski } 4822f8369d7dSTobias Sarnowski /** 4823f8369d7dSTobias Sarnowski * Reuses existing DOMDocument object. 4824f8369d7dSTobias Sarnowski * Chainable. 4825f8369d7dSTobias Sarnowski * 4826f8369d7dSTobias Sarnowski * @param $document DOMDocument 4827f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 4828f8369d7dSTobias Sarnowski * @TODO support DOMDocument 4829f8369d7dSTobias Sarnowski */ 4830f8369d7dSTobias Sarnowski public static function loadDocument($document) { 4831f8369d7dSTobias Sarnowski // TODO 4832f8369d7dSTobias Sarnowski die('TODO loadDocument'); 4833f8369d7dSTobias Sarnowski } 4834f8369d7dSTobias Sarnowski /** 4835f8369d7dSTobias Sarnowski * Enter description here... 4836f8369d7dSTobias Sarnowski * 4837f8369d7dSTobias Sarnowski * @param unknown_type $html 4838f8369d7dSTobias Sarnowski * @param unknown_type $domId 4839f8369d7dSTobias Sarnowski * @return unknown New DOM ID 4840f8369d7dSTobias Sarnowski * @todo support PHP tags in input 4841f8369d7dSTobias Sarnowski * @todo support passing DOMDocument object from self::loadDocument 4842f8369d7dSTobias Sarnowski */ 4843f8369d7dSTobias Sarnowski protected static function createDocumentWrapper($html, $contentType = null, $documentID = null) { 4844f8369d7dSTobias Sarnowski if (function_exists('domxml_open_mem')) 4845f8369d7dSTobias Sarnowski throw new Exception("Old PHP4 DOM XML extension detected. phpQuery won't work until this extension is enabled."); 4846f8369d7dSTobias Sarnowski// $id = $documentID 4847f8369d7dSTobias Sarnowski// ? $documentID 4848f8369d7dSTobias Sarnowski// : md5(microtime()); 4849f8369d7dSTobias Sarnowski $document = null; 4850f8369d7dSTobias Sarnowski if ($html instanceof DOMDOCUMENT) { 4851f8369d7dSTobias Sarnowski if (self::getDocumentID($html)) { 4852f8369d7dSTobias Sarnowski // document already exists in phpQuery::$documents, make a copy 4853f8369d7dSTobias Sarnowski $document = clone $html; 4854f8369d7dSTobias Sarnowski } else { 4855f8369d7dSTobias Sarnowski // new document, add it to phpQuery::$documents 4856f8369d7dSTobias Sarnowski $wrapper = new DOMDocumentWrapper($html, $contentType, $documentID); 4857f8369d7dSTobias Sarnowski } 4858f8369d7dSTobias Sarnowski } else { 4859f8369d7dSTobias Sarnowski $wrapper = new DOMDocumentWrapper($html, $contentType, $documentID); 4860f8369d7dSTobias Sarnowski } 4861f8369d7dSTobias Sarnowski// $wrapper->id = $id; 4862f8369d7dSTobias Sarnowski // bind document 4863f8369d7dSTobias Sarnowski phpQuery::$documents[$wrapper->id] = $wrapper; 4864f8369d7dSTobias Sarnowski // remember last loaded document 4865f8369d7dSTobias Sarnowski phpQuery::selectDocument($wrapper->id); 4866f8369d7dSTobias Sarnowski return $wrapper->id; 4867f8369d7dSTobias Sarnowski } 4868f8369d7dSTobias Sarnowski /** 4869f8369d7dSTobias Sarnowski * Extend class namespace. 4870f8369d7dSTobias Sarnowski * 4871f8369d7dSTobias Sarnowski * @param string|array $target 4872f8369d7dSTobias Sarnowski * @param array $source 4873f8369d7dSTobias Sarnowski * @TODO support string $source 4874f8369d7dSTobias Sarnowski * @return unknown_type 4875f8369d7dSTobias Sarnowski */ 4876f8369d7dSTobias Sarnowski public static function extend($target, $source) { 4877f8369d7dSTobias Sarnowski switch($target) { 4878f8369d7dSTobias Sarnowski case 'phpQueryObject': 4879f8369d7dSTobias Sarnowski $targetRef = &self::$extendMethods; 4880f8369d7dSTobias Sarnowski $targetRef2 = &self::$pluginsMethods; 4881f8369d7dSTobias Sarnowski break; 4882f8369d7dSTobias Sarnowski case 'phpQuery': 4883f8369d7dSTobias Sarnowski $targetRef = &self::$extendStaticMethods; 4884f8369d7dSTobias Sarnowski $targetRef2 = &self::$pluginsStaticMethods; 4885f8369d7dSTobias Sarnowski break; 4886f8369d7dSTobias Sarnowski default: 4887f8369d7dSTobias Sarnowski throw new Exception("Unsupported \$target type"); 4888f8369d7dSTobias Sarnowski } 4889f8369d7dSTobias Sarnowski if (is_string($source)) 4890f8369d7dSTobias Sarnowski $source = array($source => $source); 4891f8369d7dSTobias Sarnowski foreach($source as $method => $callback) { 4892f8369d7dSTobias Sarnowski if (isset($targetRef[$method])) { 4893f8369d7dSTobias Sarnowski// throw new Exception 4894f8369d7dSTobias Sarnowski self::debug("Duplicate method '{$method}', can\'t extend '{$target}'"); 4895f8369d7dSTobias Sarnowski continue; 4896f8369d7dSTobias Sarnowski } 4897f8369d7dSTobias Sarnowski if (isset($targetRef2[$method])) { 4898f8369d7dSTobias Sarnowski// throw new Exception 4899f8369d7dSTobias Sarnowski self::debug("Duplicate method '{$method}' from plugin '{$targetRef2[$method]}'," 4900f8369d7dSTobias Sarnowski ." can\'t extend '{$target}'"); 4901f8369d7dSTobias Sarnowski continue; 4902f8369d7dSTobias Sarnowski } 4903f8369d7dSTobias Sarnowski $targetRef[$method] = $callback; 4904f8369d7dSTobias Sarnowski } 4905f8369d7dSTobias Sarnowski return true; 4906f8369d7dSTobias Sarnowski } 4907f8369d7dSTobias Sarnowski /** 4908f8369d7dSTobias Sarnowski * Extend phpQuery with $class from $file. 4909f8369d7dSTobias Sarnowski * 4910f8369d7dSTobias Sarnowski * @param string $class Extending class name. Real class name can be prepended phpQuery_. 4911f8369d7dSTobias Sarnowski * @param string $file Filename to include. Defaults to "{$class}.php". 4912f8369d7dSTobias Sarnowski */ 4913f8369d7dSTobias Sarnowski public static function plugin($class, $file = null) { 4914f8369d7dSTobias Sarnowski // TODO $class checked agains phpQuery_$class 4915f8369d7dSTobias Sarnowski// if (strpos($class, 'phpQuery') === 0) 4916f8369d7dSTobias Sarnowski// $class = substr($class, 8); 4917f8369d7dSTobias Sarnowski if (in_array($class, self::$pluginsLoaded)) 4918f8369d7dSTobias Sarnowski return true; 4919f8369d7dSTobias Sarnowski if (! $file) 4920f8369d7dSTobias Sarnowski $file = $class.'.php'; 4921f8369d7dSTobias Sarnowski $objectClassExists = class_exists('phpQueryObjectPlugin_'.$class); 4922f8369d7dSTobias Sarnowski $staticClassExists = class_exists('phpQueryPlugin_'.$class); 4923f8369d7dSTobias Sarnowski if (! $objectClassExists && ! $staticClassExists) 4924f8369d7dSTobias Sarnowski require_once($file); 4925f8369d7dSTobias Sarnowski self::$pluginsLoaded[] = $class; 4926f8369d7dSTobias Sarnowski // static methods 4927f8369d7dSTobias Sarnowski if (class_exists('phpQueryPlugin_'.$class)) { 4928f8369d7dSTobias Sarnowski $realClass = 'phpQueryPlugin_'.$class; 4929f8369d7dSTobias Sarnowski $vars = get_class_vars($realClass); 4930f8369d7dSTobias Sarnowski $loop = isset($vars['phpQueryMethods']) 4931f8369d7dSTobias Sarnowski && ! is_null($vars['phpQueryMethods']) 4932f8369d7dSTobias Sarnowski ? $vars['phpQueryMethods'] 4933f8369d7dSTobias Sarnowski : get_class_methods($realClass); 4934f8369d7dSTobias Sarnowski foreach($loop as $method) { 4935f8369d7dSTobias Sarnowski if ($method == '__initialize') 4936f8369d7dSTobias Sarnowski continue; 4937f8369d7dSTobias Sarnowski if (! is_callable(array($realClass, $method))) 4938f8369d7dSTobias Sarnowski continue; 4939f8369d7dSTobias Sarnowski if (isset(self::$pluginsStaticMethods[$method])) { 4940f8369d7dSTobias Sarnowski throw new Exception("Duplicate method '{$method}' from plugin '{$c}' conflicts with same method from plugin '".self::$pluginsStaticMethods[$method]."'"); 4941f8369d7dSTobias Sarnowski return; 4942f8369d7dSTobias Sarnowski } 4943f8369d7dSTobias Sarnowski self::$pluginsStaticMethods[$method] = $class; 4944f8369d7dSTobias Sarnowski } 4945f8369d7dSTobias Sarnowski if (method_exists($realClass, '__initialize')) 4946f8369d7dSTobias Sarnowski call_user_func_array(array($realClass, '__initialize'), array()); 4947f8369d7dSTobias Sarnowski } 4948f8369d7dSTobias Sarnowski // object methods 4949f8369d7dSTobias Sarnowski if (class_exists('phpQueryObjectPlugin_'.$class)) { 4950f8369d7dSTobias Sarnowski $realClass = 'phpQueryObjectPlugin_'.$class; 4951f8369d7dSTobias Sarnowski $vars = get_class_vars($realClass); 4952f8369d7dSTobias Sarnowski $loop = isset($vars['phpQueryMethods']) 4953f8369d7dSTobias Sarnowski && ! is_null($vars['phpQueryMethods']) 4954f8369d7dSTobias Sarnowski ? $vars['phpQueryMethods'] 4955f8369d7dSTobias Sarnowski : get_class_methods($realClass); 4956f8369d7dSTobias Sarnowski foreach($loop as $method) { 4957f8369d7dSTobias Sarnowski if (! is_callable(array($realClass, $method))) 4958f8369d7dSTobias Sarnowski continue; 4959f8369d7dSTobias Sarnowski if (isset(self::$pluginsMethods[$method])) { 4960f8369d7dSTobias Sarnowski throw new Exception("Duplicate method '{$method}' from plugin '{$c}' conflicts with same method from plugin '".self::$pluginsMethods[$method]."'"); 4961f8369d7dSTobias Sarnowski continue; 4962f8369d7dSTobias Sarnowski } 4963f8369d7dSTobias Sarnowski self::$pluginsMethods[$method] = $class; 4964f8369d7dSTobias Sarnowski } 4965f8369d7dSTobias Sarnowski } 4966f8369d7dSTobias Sarnowski return true; 4967f8369d7dSTobias Sarnowski } 4968f8369d7dSTobias Sarnowski /** 4969f8369d7dSTobias Sarnowski * Unloades all or specified document from memory. 4970f8369d7dSTobias Sarnowski * 4971f8369d7dSTobias Sarnowski * @param mixed $documentID @see phpQuery::getDocumentID() for supported types. 4972f8369d7dSTobias Sarnowski */ 4973f8369d7dSTobias Sarnowski public static function unloadDocuments($id = null) { 4974f8369d7dSTobias Sarnowski if (isset($id)) { 4975f8369d7dSTobias Sarnowski if ($id = self::getDocumentID($id)) 4976f8369d7dSTobias Sarnowski unset(phpQuery::$documents[$id]); 4977f8369d7dSTobias Sarnowski } else { 4978f8369d7dSTobias Sarnowski foreach(phpQuery::$documents as $k => $v) { 4979f8369d7dSTobias Sarnowski unset(phpQuery::$documents[$k]); 4980f8369d7dSTobias Sarnowski } 4981f8369d7dSTobias Sarnowski } 4982f8369d7dSTobias Sarnowski } 4983f8369d7dSTobias Sarnowski /** 4984f8369d7dSTobias Sarnowski * Parses phpQuery object or HTML result against PHP tags and makes them active. 4985f8369d7dSTobias Sarnowski * 4986f8369d7dSTobias Sarnowski * @param phpQuery|string $content 4987f8369d7dSTobias Sarnowski * @deprecated 4988f8369d7dSTobias Sarnowski * @return string 4989f8369d7dSTobias Sarnowski */ 4990f8369d7dSTobias Sarnowski public static function unsafePHPTags($content) { 4991f8369d7dSTobias Sarnowski return self::markupToPHP($content); 4992f8369d7dSTobias Sarnowski } 4993f8369d7dSTobias Sarnowski public static function DOMNodeListToArray($DOMNodeList) { 4994f8369d7dSTobias Sarnowski $array = array(); 4995f8369d7dSTobias Sarnowski if (! $DOMNodeList) 4996f8369d7dSTobias Sarnowski return $array; 4997f8369d7dSTobias Sarnowski foreach($DOMNodeList as $node) 4998f8369d7dSTobias Sarnowski $array[] = $node; 4999f8369d7dSTobias Sarnowski return $array; 5000f8369d7dSTobias Sarnowski } 5001f8369d7dSTobias Sarnowski /** 5002f8369d7dSTobias Sarnowski * Checks if $input is HTML string, which has to start with '<'. 5003f8369d7dSTobias Sarnowski * 5004f8369d7dSTobias Sarnowski * @deprecated 5005f8369d7dSTobias Sarnowski * @param String $input 5006f8369d7dSTobias Sarnowski * @return Bool 5007f8369d7dSTobias Sarnowski * @todo still used ? 5008f8369d7dSTobias Sarnowski */ 5009f8369d7dSTobias Sarnowski public static function isMarkup($input) { 5010f8369d7dSTobias Sarnowski return ! is_array($input) && substr(trim($input), 0, 1) == '<'; 5011f8369d7dSTobias Sarnowski } 5012f8369d7dSTobias Sarnowski public static function debug($text) { 5013f8369d7dSTobias Sarnowski if (self::$debug) 5014f8369d7dSTobias Sarnowski print var_dump($text); 5015f8369d7dSTobias Sarnowski } 5016f8369d7dSTobias Sarnowski /** 5017f8369d7dSTobias Sarnowski * Make an AJAX request. 5018f8369d7dSTobias Sarnowski * 5019f8369d7dSTobias Sarnowski * @param array See $options http://docs.jquery.com/Ajax/jQuery.ajax#toptions 5020f8369d7dSTobias Sarnowski * Additional options are: 5021f8369d7dSTobias Sarnowski * 'document' - document for global events, @see phpQuery::getDocumentID() 5022f8369d7dSTobias Sarnowski * 'referer' - implemented 5023f8369d7dSTobias Sarnowski * 'requested_with' - TODO; not implemented (X-Requested-With) 5024f8369d7dSTobias Sarnowski * @return Zend_Http_Client 5025f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Ajax/jQuery.ajax 5026f8369d7dSTobias Sarnowski * 5027f8369d7dSTobias Sarnowski * @TODO $options['cache'] 5028f8369d7dSTobias Sarnowski * @TODO $options['processData'] 5029f8369d7dSTobias Sarnowski * @TODO $options['xhr'] 5030f8369d7dSTobias Sarnowski * @TODO $options['data'] as string 5031f8369d7dSTobias Sarnowski * @TODO XHR interface 5032f8369d7dSTobias Sarnowski */ 5033f8369d7dSTobias Sarnowski public static function ajax($options = array(), $xhr = null) { 5034f8369d7dSTobias Sarnowski $options = array_merge( 5035f8369d7dSTobias Sarnowski self::$ajaxSettings, $options 5036f8369d7dSTobias Sarnowski ); 5037f8369d7dSTobias Sarnowski $documentID = isset($options['document']) 5038f8369d7dSTobias Sarnowski ? self::getDocumentID($options['document']) 5039f8369d7dSTobias Sarnowski : null; 5040f8369d7dSTobias Sarnowski if ($xhr) { 5041f8369d7dSTobias Sarnowski // reuse existing XHR object, but clean it up 5042f8369d7dSTobias Sarnowski $client = $xhr; 5043f8369d7dSTobias Sarnowski// $client->setParameterPost(null); 5044f8369d7dSTobias Sarnowski// $client->setParameterGet(null); 5045f8369d7dSTobias Sarnowski $client->setAuth(false); 5046f8369d7dSTobias Sarnowski $client->setHeaders("If-Modified-Since", null); 5047f8369d7dSTobias Sarnowski $client->setHeaders("Referer", null); 5048f8369d7dSTobias Sarnowski $client->resetParameters(); 5049f8369d7dSTobias Sarnowski } else { 5050f8369d7dSTobias Sarnowski // create new XHR object 5051f8369d7dSTobias Sarnowski require_once('Zend/Http/Client.php'); 5052f8369d7dSTobias Sarnowski $client = new Zend_Http_Client(); 5053f8369d7dSTobias Sarnowski $client->setCookieJar(); 5054f8369d7dSTobias Sarnowski } 5055f8369d7dSTobias Sarnowski if (isset($options['timeout'])) 5056f8369d7dSTobias Sarnowski $client->setConfig(array( 5057f8369d7dSTobias Sarnowski 'timeout' => $options['timeout'], 5058f8369d7dSTobias Sarnowski )); 5059f8369d7dSTobias Sarnowski// 'maxredirects' => 0, 5060f8369d7dSTobias Sarnowski foreach(self::$ajaxAllowedHosts as $k => $host) 5061f8369d7dSTobias Sarnowski if ($host == '.' && isset($_SERVER['HTTP_HOST'])) 5062f8369d7dSTobias Sarnowski self::$ajaxAllowedHosts[$k] = $_SERVER['HTTP_HOST']; 5063f8369d7dSTobias Sarnowski $host = parse_url($options['url'], PHP_URL_HOST); 5064f8369d7dSTobias Sarnowski if (! in_array($host, self::$ajaxAllowedHosts)) { 5065f8369d7dSTobias Sarnowski throw new Exception("Request not permitted, host '$host' not present in " 5066f8369d7dSTobias Sarnowski ."phpQuery::\$ajaxAllowedHosts"); 5067f8369d7dSTobias Sarnowski } 5068f8369d7dSTobias Sarnowski // JSONP 5069f8369d7dSTobias Sarnowski $jsre = "/=\\?(&|$)/"; 5070f8369d7dSTobias Sarnowski if (isset($options['dataType']) && $options['dataType'] == 'jsonp') { 5071f8369d7dSTobias Sarnowski $jsonpCallbackParam = $options['jsonp'] 5072f8369d7dSTobias Sarnowski ? $options['jsonp'] : 'callback'; 5073f8369d7dSTobias Sarnowski if (strtolower($options['type']) == 'get') { 5074f8369d7dSTobias Sarnowski if (! preg_match($jsre, $options['url'])) { 5075f8369d7dSTobias Sarnowski $sep = strpos($options['url'], '?') 5076f8369d7dSTobias Sarnowski ? '&' : '?'; 5077f8369d7dSTobias Sarnowski $options['url'] .= "$sep$jsonpCallbackParam=?"; 5078f8369d7dSTobias Sarnowski } 5079f8369d7dSTobias Sarnowski } else if ($options['data']) { 5080f8369d7dSTobias Sarnowski $jsonp = false; 5081f8369d7dSTobias Sarnowski foreach($options['data'] as $n => $v) { 5082f8369d7dSTobias Sarnowski if ($v == '?') 5083f8369d7dSTobias Sarnowski $jsonp = true; 5084f8369d7dSTobias Sarnowski } 5085f8369d7dSTobias Sarnowski if (! $jsonp) { 5086f8369d7dSTobias Sarnowski $options['data'][$jsonpCallbackParam] = '?'; 5087f8369d7dSTobias Sarnowski } 5088f8369d7dSTobias Sarnowski } 5089f8369d7dSTobias Sarnowski $options['dataType'] = 'json'; 5090f8369d7dSTobias Sarnowski } 5091f8369d7dSTobias Sarnowski if (isset($options['dataType']) && $options['dataType'] == 'json') { 5092f8369d7dSTobias Sarnowski $jsonpCallback = 'json_'.md5(microtime()); 5093f8369d7dSTobias Sarnowski $jsonpData = $jsonpUrl = false; 5094f8369d7dSTobias Sarnowski if ($options['data']) { 5095f8369d7dSTobias Sarnowski foreach($options['data'] as $n => $v) { 5096f8369d7dSTobias Sarnowski if ($v == '?') 5097f8369d7dSTobias Sarnowski $jsonpData = $n; 5098f8369d7dSTobias Sarnowski } 5099f8369d7dSTobias Sarnowski } 5100f8369d7dSTobias Sarnowski if (preg_match($jsre, $options['url'])) 5101f8369d7dSTobias Sarnowski $jsonpUrl = true; 5102f8369d7dSTobias Sarnowski if ($jsonpData !== false || $jsonpUrl) { 5103f8369d7dSTobias Sarnowski // remember callback name for httpData() 5104f8369d7dSTobias Sarnowski $options['_jsonp'] = $jsonpCallback; 5105f8369d7dSTobias Sarnowski if ($jsonpData !== false) 5106f8369d7dSTobias Sarnowski $options['data'][$jsonpData] = $jsonpCallback; 5107f8369d7dSTobias Sarnowski if ($jsonpUrl) 5108f8369d7dSTobias Sarnowski $options['url'] = preg_replace($jsre, "=$jsonpCallback\\1", $options['url']); 5109f8369d7dSTobias Sarnowski } 5110f8369d7dSTobias Sarnowski } 5111f8369d7dSTobias Sarnowski $client->setUri($options['url']); 5112f8369d7dSTobias Sarnowski $client->setMethod(strtoupper($options['type'])); 5113f8369d7dSTobias Sarnowski if (isset($options['referer']) && $options['referer']) 5114f8369d7dSTobias Sarnowski $client->setHeaders('Referer', $options['referer']); 5115f8369d7dSTobias Sarnowski $client->setHeaders(array( 5116f8369d7dSTobias Sarnowski// 'content-type' => $options['contentType'], 5117f8369d7dSTobias Sarnowski 'User-Agent' => 'Mozilla/5.0 (X11; U; Linux x86; en-US; rv:1.9.0.5) Gecko' 5118f8369d7dSTobias Sarnowski .'/2008122010 Firefox/3.0.5', 5119f8369d7dSTobias Sarnowski // TODO custom charset 5120f8369d7dSTobias Sarnowski 'Accept-Charset' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 5121f8369d7dSTobias Sarnowski// 'Connection' => 'keep-alive', 5122f8369d7dSTobias Sarnowski// 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 5123f8369d7dSTobias Sarnowski 'Accept-Language' => 'en-us,en;q=0.5', 5124f8369d7dSTobias Sarnowski )); 5125f8369d7dSTobias Sarnowski if ($options['username']) 5126f8369d7dSTobias Sarnowski $client->setAuth($options['username'], $options['password']); 5127f8369d7dSTobias Sarnowski if (isset($options['ifModified']) && $options['ifModified']) 5128f8369d7dSTobias Sarnowski $client->setHeaders("If-Modified-Since", 5129f8369d7dSTobias Sarnowski self::$lastModified 5130f8369d7dSTobias Sarnowski ? self::$lastModified 5131f8369d7dSTobias Sarnowski : "Thu, 01 Jan 1970 00:00:00 GMT" 5132f8369d7dSTobias Sarnowski ); 5133f8369d7dSTobias Sarnowski $client->setHeaders("Accept", 5134f8369d7dSTobias Sarnowski isset($options['dataType']) 5135f8369d7dSTobias Sarnowski && isset(self::$ajaxSettings['accepts'][ $options['dataType'] ]) 5136f8369d7dSTobias Sarnowski ? self::$ajaxSettings['accepts'][ $options['dataType'] ].", */*" 5137f8369d7dSTobias Sarnowski : self::$ajaxSettings['accepts']['_default'] 5138f8369d7dSTobias Sarnowski ); 5139f8369d7dSTobias Sarnowski // TODO $options['processData'] 5140f8369d7dSTobias Sarnowski if ($options['data'] instanceof phpQueryObject) { 5141f8369d7dSTobias Sarnowski $serialized = $options['data']->serializeArray($options['data']); 5142f8369d7dSTobias Sarnowski $options['data'] = array(); 5143f8369d7dSTobias Sarnowski foreach($serialized as $r) 5144f8369d7dSTobias Sarnowski $options['data'][ $r['name'] ] = $r['value']; 5145f8369d7dSTobias Sarnowski } 5146f8369d7dSTobias Sarnowski if (strtolower($options['type']) == 'get') { 5147f8369d7dSTobias Sarnowski $client->setParameterGet($options['data']); 5148f8369d7dSTobias Sarnowski } else if (strtolower($options['type']) == 'post') { 5149f8369d7dSTobias Sarnowski $client->setEncType($options['contentType']); 5150f8369d7dSTobias Sarnowski $client->setParameterPost($options['data']); 5151f8369d7dSTobias Sarnowski } 5152f8369d7dSTobias Sarnowski if (self::$active == 0 && $options['global']) 5153f8369d7dSTobias Sarnowski phpQueryEvents::trigger($documentID, 'ajaxStart'); 5154f8369d7dSTobias Sarnowski self::$active++; 5155f8369d7dSTobias Sarnowski // beforeSend callback 5156f8369d7dSTobias Sarnowski if (isset($options['beforeSend']) && $options['beforeSend']) 5157f8369d7dSTobias Sarnowski phpQuery::callbackRun($options['beforeSend'], array($client)); 5158f8369d7dSTobias Sarnowski // ajaxSend event 5159f8369d7dSTobias Sarnowski if ($options['global']) 5160f8369d7dSTobias Sarnowski phpQueryEvents::trigger($documentID, 'ajaxSend', array($client, $options)); 5161f8369d7dSTobias Sarnowski if (phpQuery::$debug) { 5162f8369d7dSTobias Sarnowski self::debug("{$options['type']}: {$options['url']}\n"); 5163f8369d7dSTobias Sarnowski self::debug("Options: <pre>".var_export($options, true)."</pre>\n"); 5164f8369d7dSTobias Sarnowski// if ($client->getCookieJar()) 5165f8369d7dSTobias Sarnowski// self::debug("Cookies: <pre>".var_export($client->getCookieJar()->getMatchingCookies($options['url']), true)."</pre>\n"); 5166f8369d7dSTobias Sarnowski } 5167f8369d7dSTobias Sarnowski // request 5168f8369d7dSTobias Sarnowski $response = $client->request(); 5169f8369d7dSTobias Sarnowski if (phpQuery::$debug) { 5170f8369d7dSTobias Sarnowski self::debug('Status: '.$response->getStatus().' / '.$response->getMessage()); 5171f8369d7dSTobias Sarnowski self::debug($client->getLastRequest()); 5172f8369d7dSTobias Sarnowski self::debug($response->getHeaders()); 5173f8369d7dSTobias Sarnowski } 5174f8369d7dSTobias Sarnowski if ($response->isSuccessful()) { 5175f8369d7dSTobias Sarnowski // XXX tempolary 5176f8369d7dSTobias Sarnowski self::$lastModified = $response->getHeader('Last-Modified'); 5177f8369d7dSTobias Sarnowski $data = self::httpData($response->getBody(), $options['dataType'], $options); 5178f8369d7dSTobias Sarnowski if (isset($options['success']) && $options['success']) 5179f8369d7dSTobias Sarnowski phpQuery::callbackRun($options['success'], array($data, $response->getStatus(), $options)); 5180f8369d7dSTobias Sarnowski if ($options['global']) 5181f8369d7dSTobias Sarnowski phpQueryEvents::trigger($documentID, 'ajaxSuccess', array($client, $options)); 5182f8369d7dSTobias Sarnowski } else { 5183f8369d7dSTobias Sarnowski if (isset($options['error']) && $options['error']) 5184f8369d7dSTobias Sarnowski phpQuery::callbackRun($options['error'], array($client, $response->getStatus(), $response->getMessage())); 5185f8369d7dSTobias Sarnowski if ($options['global']) 5186f8369d7dSTobias Sarnowski phpQueryEvents::trigger($documentID, 'ajaxError', array($client, /*$response->getStatus(),*/$response->getMessage(), $options)); 5187f8369d7dSTobias Sarnowski } 5188f8369d7dSTobias Sarnowski if (isset($options['complete']) && $options['complete']) 5189f8369d7dSTobias Sarnowski phpQuery::callbackRun($options['complete'], array($client, $response->getStatus())); 5190f8369d7dSTobias Sarnowski if ($options['global']) 5191f8369d7dSTobias Sarnowski phpQueryEvents::trigger($documentID, 'ajaxComplete', array($client, $options)); 5192f8369d7dSTobias Sarnowski if ($options['global'] && ! --self::$active) 5193f8369d7dSTobias Sarnowski phpQueryEvents::trigger($documentID, 'ajaxStop'); 5194f8369d7dSTobias Sarnowski return $client; 5195f8369d7dSTobias Sarnowski// if (is_null($domId)) 5196f8369d7dSTobias Sarnowski// $domId = self::$defaultDocumentID ? self::$defaultDocumentID : false; 5197f8369d7dSTobias Sarnowski// return new phpQueryAjaxResponse($response, $domId); 5198f8369d7dSTobias Sarnowski } 5199f8369d7dSTobias Sarnowski protected static function httpData($data, $type, $options) { 5200f8369d7dSTobias Sarnowski if (isset($options['dataFilter']) && $options['dataFilter']) 5201f8369d7dSTobias Sarnowski $data = self::callbackRun($options['dataFilter'], array($data, $type)); 5202f8369d7dSTobias Sarnowski if (is_string($data)) { 5203f8369d7dSTobias Sarnowski if ($type == "json") { 5204f8369d7dSTobias Sarnowski if (isset($options['_jsonp']) && $options['_jsonp']) { 5205f8369d7dSTobias Sarnowski $data = preg_replace('/^\s*\w+\((.*)\)\s*$/s', '$1', $data); 5206f8369d7dSTobias Sarnowski } 5207f8369d7dSTobias Sarnowski $data = self::parseJSON($data); 5208f8369d7dSTobias Sarnowski } 5209f8369d7dSTobias Sarnowski } 5210f8369d7dSTobias Sarnowski return $data; 5211f8369d7dSTobias Sarnowski } 5212f8369d7dSTobias Sarnowski /** 5213f8369d7dSTobias Sarnowski * Enter description here... 5214f8369d7dSTobias Sarnowski * 5215f8369d7dSTobias Sarnowski * @param array|phpQuery $data 5216f8369d7dSTobias Sarnowski * 5217f8369d7dSTobias Sarnowski */ 5218f8369d7dSTobias Sarnowski public static function param($data) { 5219f8369d7dSTobias Sarnowski return http_build_query($data, null, '&'); 5220f8369d7dSTobias Sarnowski } 5221f8369d7dSTobias Sarnowski public static function get($url, $data = null, $callback = null, $type = null) { 5222f8369d7dSTobias Sarnowski if (!is_array($data)) { 5223f8369d7dSTobias Sarnowski $callback = $data; 5224f8369d7dSTobias Sarnowski $data = null; 5225f8369d7dSTobias Sarnowski } 5226f8369d7dSTobias Sarnowski // TODO some array_values on this shit 5227f8369d7dSTobias Sarnowski return phpQuery::ajax(array( 5228f8369d7dSTobias Sarnowski 'type' => 'GET', 5229f8369d7dSTobias Sarnowski 'url' => $url, 5230f8369d7dSTobias Sarnowski 'data' => $data, 5231f8369d7dSTobias Sarnowski 'success' => $callback, 5232f8369d7dSTobias Sarnowski 'dataType' => $type, 5233f8369d7dSTobias Sarnowski )); 5234f8369d7dSTobias Sarnowski } 5235f8369d7dSTobias Sarnowski public static function post($url, $data = null, $callback = null, $type = null) { 5236f8369d7dSTobias Sarnowski if (!is_array($data)) { 5237f8369d7dSTobias Sarnowski $callback = $data; 5238f8369d7dSTobias Sarnowski $data = null; 5239f8369d7dSTobias Sarnowski } 5240f8369d7dSTobias Sarnowski return phpQuery::ajax(array( 5241f8369d7dSTobias Sarnowski 'type' => 'POST', 5242f8369d7dSTobias Sarnowski 'url' => $url, 5243f8369d7dSTobias Sarnowski 'data' => $data, 5244f8369d7dSTobias Sarnowski 'success' => $callback, 5245f8369d7dSTobias Sarnowski 'dataType' => $type, 5246f8369d7dSTobias Sarnowski )); 5247f8369d7dSTobias Sarnowski } 5248f8369d7dSTobias Sarnowski public static function getJSON($url, $data = null, $callback = null) { 5249f8369d7dSTobias Sarnowski if (!is_array($data)) { 5250f8369d7dSTobias Sarnowski $callback = $data; 5251f8369d7dSTobias Sarnowski $data = null; 5252f8369d7dSTobias Sarnowski } 5253f8369d7dSTobias Sarnowski // TODO some array_values on this shit 5254f8369d7dSTobias Sarnowski return phpQuery::ajax(array( 5255f8369d7dSTobias Sarnowski 'type' => 'GET', 5256f8369d7dSTobias Sarnowski 'url' => $url, 5257f8369d7dSTobias Sarnowski 'data' => $data, 5258f8369d7dSTobias Sarnowski 'success' => $callback, 5259f8369d7dSTobias Sarnowski 'dataType' => 'json', 5260f8369d7dSTobias Sarnowski )); 5261f8369d7dSTobias Sarnowski } 5262f8369d7dSTobias Sarnowski public static function ajaxSetup($options) { 5263f8369d7dSTobias Sarnowski self::$ajaxSettings = array_merge( 5264f8369d7dSTobias Sarnowski self::$ajaxSettings, 5265f8369d7dSTobias Sarnowski $options 5266f8369d7dSTobias Sarnowski ); 5267f8369d7dSTobias Sarnowski } 5268f8369d7dSTobias Sarnowski public static function ajaxAllowHost($host1, $host2 = null, $host3 = null) { 5269f8369d7dSTobias Sarnowski $loop = is_array($host1) 5270f8369d7dSTobias Sarnowski ? $host1 5271f8369d7dSTobias Sarnowski : func_get_args(); 5272f8369d7dSTobias Sarnowski foreach($loop as $host) { 5273f8369d7dSTobias Sarnowski if ($host && ! in_array($host, phpQuery::$ajaxAllowedHosts)) { 5274f8369d7dSTobias Sarnowski phpQuery::$ajaxAllowedHosts[] = $host; 5275f8369d7dSTobias Sarnowski } 5276f8369d7dSTobias Sarnowski } 5277f8369d7dSTobias Sarnowski } 5278f8369d7dSTobias Sarnowski public static function ajaxAllowURL($url1, $url2 = null, $url3 = null) { 5279f8369d7dSTobias Sarnowski $loop = is_array($url1) 5280f8369d7dSTobias Sarnowski ? $url1 5281f8369d7dSTobias Sarnowski : func_get_args(); 5282f8369d7dSTobias Sarnowski foreach($loop as $url) 5283f8369d7dSTobias Sarnowski phpQuery::ajaxAllowHost(parse_url($url, PHP_URL_HOST)); 5284f8369d7dSTobias Sarnowski } 5285f8369d7dSTobias Sarnowski /** 5286f8369d7dSTobias Sarnowski * Returns JSON representation of $data. 5287f8369d7dSTobias Sarnowski * 5288f8369d7dSTobias Sarnowski * @static 5289f8369d7dSTobias Sarnowski * @param mixed $data 5290f8369d7dSTobias Sarnowski * @return string 5291f8369d7dSTobias Sarnowski */ 5292f8369d7dSTobias Sarnowski public static function toJSON($data) { 5293f8369d7dSTobias Sarnowski if (function_exists('json_encode')) 5294f8369d7dSTobias Sarnowski return json_encode($data); 5295f8369d7dSTobias Sarnowski require_once('Zend/Json/Encoder.php'); 5296f8369d7dSTobias Sarnowski return Zend_Json_Encoder::encode($data); 5297f8369d7dSTobias Sarnowski } 5298f8369d7dSTobias Sarnowski /** 5299f8369d7dSTobias Sarnowski * Parses JSON into proper PHP type. 5300f8369d7dSTobias Sarnowski * 5301f8369d7dSTobias Sarnowski * @static 5302f8369d7dSTobias Sarnowski * @param string $json 5303f8369d7dSTobias Sarnowski * @return mixed 5304f8369d7dSTobias Sarnowski */ 5305f8369d7dSTobias Sarnowski public static function parseJSON($json) { 5306f8369d7dSTobias Sarnowski if (function_exists('json_decode')) { 5307f8369d7dSTobias Sarnowski $return = json_decode(trim($json), true); 5308f8369d7dSTobias Sarnowski // json_decode and UTF8 issues 5309f8369d7dSTobias Sarnowski if (isset($return)) 5310f8369d7dSTobias Sarnowski return $return; 5311f8369d7dSTobias Sarnowski } 5312f8369d7dSTobias Sarnowski require_once('Zend/Json/Decoder.php'); 5313f8369d7dSTobias Sarnowski return Zend_Json_Decoder::decode($json); 5314f8369d7dSTobias Sarnowski } 5315f8369d7dSTobias Sarnowski /** 5316f8369d7dSTobias Sarnowski * Returns source's document ID. 5317f8369d7dSTobias Sarnowski * 5318f8369d7dSTobias Sarnowski * @param $source DOMNode|phpQueryObject 5319f8369d7dSTobias Sarnowski * @return string 5320f8369d7dSTobias Sarnowski */ 5321f8369d7dSTobias Sarnowski public static function getDocumentID($source) { 5322f8369d7dSTobias Sarnowski if ($source instanceof DOMDOCUMENT) { 5323f8369d7dSTobias Sarnowski foreach(phpQuery::$documents as $id => $document) { 5324f8369d7dSTobias Sarnowski if ($source->isSameNode($document->document)) 5325f8369d7dSTobias Sarnowski return $id; 5326f8369d7dSTobias Sarnowski } 5327f8369d7dSTobias Sarnowski } else if ($source instanceof DOMNODE) { 5328f8369d7dSTobias Sarnowski foreach(phpQuery::$documents as $id => $document) { 5329f8369d7dSTobias Sarnowski if ($source->ownerDocument->isSameNode($document->document)) 5330f8369d7dSTobias Sarnowski return $id; 5331f8369d7dSTobias Sarnowski } 5332f8369d7dSTobias Sarnowski } else if ($source instanceof phpQueryObject) 5333f8369d7dSTobias Sarnowski return $source->getDocumentID(); 5334f8369d7dSTobias Sarnowski else if (is_string($source) && isset(phpQuery::$documents[$source])) 5335f8369d7dSTobias Sarnowski return $source; 5336f8369d7dSTobias Sarnowski } 5337f8369d7dSTobias Sarnowski /** 5338f8369d7dSTobias Sarnowski * Get DOMDocument object related to $source. 5339f8369d7dSTobias Sarnowski * Returns null if such document doesn't exist. 5340f8369d7dSTobias Sarnowski * 5341f8369d7dSTobias Sarnowski * @param $source DOMNode|phpQueryObject|string 5342f8369d7dSTobias Sarnowski * @return string 5343f8369d7dSTobias Sarnowski */ 5344f8369d7dSTobias Sarnowski public static function getDOMDocument($source) { 5345f8369d7dSTobias Sarnowski if ($source instanceof DOMDOCUMENT) 5346f8369d7dSTobias Sarnowski return $source; 5347f8369d7dSTobias Sarnowski $source = self::getDocumentID($source); 5348f8369d7dSTobias Sarnowski return $source 5349f8369d7dSTobias Sarnowski ? self::$documents[$id]['document'] 5350f8369d7dSTobias Sarnowski : null; 5351f8369d7dSTobias Sarnowski } 5352f8369d7dSTobias Sarnowski 5353f8369d7dSTobias Sarnowski // UTILITIES 5354f8369d7dSTobias Sarnowski // http://docs.jquery.com/Utilities 5355f8369d7dSTobias Sarnowski 5356f8369d7dSTobias Sarnowski /** 5357f8369d7dSTobias Sarnowski * 5358f8369d7dSTobias Sarnowski * @return unknown_type 5359f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Utilities/jQuery.makeArray 5360f8369d7dSTobias Sarnowski */ 5361f8369d7dSTobias Sarnowski public static function makeArray($obj) { 5362f8369d7dSTobias Sarnowski $array = array(); 5363f8369d7dSTobias Sarnowski if (is_object($object) && $object instanceof DOMNODELIST) { 5364f8369d7dSTobias Sarnowski foreach($object as $value) 5365f8369d7dSTobias Sarnowski $array[] = $value; 5366f8369d7dSTobias Sarnowski } else if (is_object($object) && ! ($object instanceof Iterator)) { 5367f8369d7dSTobias Sarnowski foreach(get_object_vars($object) as $name => $value) 5368f8369d7dSTobias Sarnowski $array[0][$name] = $value; 5369f8369d7dSTobias Sarnowski } else { 5370f8369d7dSTobias Sarnowski foreach($object as $name => $value) 5371f8369d7dSTobias Sarnowski $array[0][$name] = $value; 5372f8369d7dSTobias Sarnowski } 5373f8369d7dSTobias Sarnowski return $array; 5374f8369d7dSTobias Sarnowski } 5375f8369d7dSTobias Sarnowski public static function inArray($value, $array) { 5376f8369d7dSTobias Sarnowski return in_array($value, $array); 5377f8369d7dSTobias Sarnowski } 5378f8369d7dSTobias Sarnowski /** 5379f8369d7dSTobias Sarnowski * 5380f8369d7dSTobias Sarnowski * @param $object 5381f8369d7dSTobias Sarnowski * @param $callback 5382f8369d7dSTobias Sarnowski * @return unknown_type 5383f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Utilities/jQuery.each 5384f8369d7dSTobias Sarnowski */ 5385f8369d7dSTobias Sarnowski public static function each($object, $callback, $param1 = null, $param2 = null, $param3 = null) { 5386f8369d7dSTobias Sarnowski $paramStructure = null; 5387f8369d7dSTobias Sarnowski if (func_num_args() > 2) { 5388f8369d7dSTobias Sarnowski $paramStructure = func_get_args(); 5389f8369d7dSTobias Sarnowski $paramStructure = array_slice($paramStructure, 2); 5390f8369d7dSTobias Sarnowski } 5391f8369d7dSTobias Sarnowski if (is_object($object) && ! ($object instanceof Iterator)) { 5392f8369d7dSTobias Sarnowski foreach(get_object_vars($object) as $name => $value) 5393f8369d7dSTobias Sarnowski phpQuery::callbackRun($callback, array($name, $value), $paramStructure); 5394f8369d7dSTobias Sarnowski } else { 5395f8369d7dSTobias Sarnowski foreach($object as $name => $value) 5396f8369d7dSTobias Sarnowski phpQuery::callbackRun($callback, array($name, $value), $paramStructure); 5397f8369d7dSTobias Sarnowski } 5398f8369d7dSTobias Sarnowski } 5399f8369d7dSTobias Sarnowski /** 5400f8369d7dSTobias Sarnowski * 5401f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Utilities/jQuery.map 5402f8369d7dSTobias Sarnowski */ 5403f8369d7dSTobias Sarnowski public static function map($array, $callback, $param1 = null, $param2 = null, $param3 = null) { 5404f8369d7dSTobias Sarnowski $result = array(); 5405f8369d7dSTobias Sarnowski $paramStructure = null; 5406f8369d7dSTobias Sarnowski if (func_num_args() > 2) { 5407f8369d7dSTobias Sarnowski $paramStructure = func_get_args(); 5408f8369d7dSTobias Sarnowski $paramStructure = array_slice($paramStructure, 2); 5409f8369d7dSTobias Sarnowski } 5410f8369d7dSTobias Sarnowski foreach($array as $v) { 5411f8369d7dSTobias Sarnowski $vv = phpQuery::callbackRun($callback, array($v), $paramStructure); 5412f8369d7dSTobias Sarnowski// $callbackArgs = $args; 5413f8369d7dSTobias Sarnowski// foreach($args as $i => $arg) { 5414f8369d7dSTobias Sarnowski// $callbackArgs[$i] = $arg instanceof CallbackParam 5415f8369d7dSTobias Sarnowski// ? $v 5416f8369d7dSTobias Sarnowski// : $arg; 5417f8369d7dSTobias Sarnowski// } 5418f8369d7dSTobias Sarnowski// $vv = call_user_func_array($callback, $callbackArgs); 5419f8369d7dSTobias Sarnowski if (is_array($vv)) { 5420f8369d7dSTobias Sarnowski foreach($vv as $vvv) 5421f8369d7dSTobias Sarnowski $result[] = $vvv; 5422f8369d7dSTobias Sarnowski } else if ($vv !== null) { 5423f8369d7dSTobias Sarnowski $result[] = $vv; 5424f8369d7dSTobias Sarnowski } 5425f8369d7dSTobias Sarnowski } 5426f8369d7dSTobias Sarnowski return $result; 5427f8369d7dSTobias Sarnowski } 5428f8369d7dSTobias Sarnowski /** 5429f8369d7dSTobias Sarnowski * 5430f8369d7dSTobias Sarnowski * @param $callback Callback 5431f8369d7dSTobias Sarnowski * @param $params 5432f8369d7dSTobias Sarnowski * @param $paramStructure 5433f8369d7dSTobias Sarnowski * @return unknown_type 5434f8369d7dSTobias Sarnowski */ 5435f8369d7dSTobias Sarnowski public static function callbackRun($callback, $params = array(), $paramStructure = null) { 5436f8369d7dSTobias Sarnowski if (! $callback) 5437f8369d7dSTobias Sarnowski return; 5438f8369d7dSTobias Sarnowski if ($callback instanceof CallbackParameterToReference) { 5439f8369d7dSTobias Sarnowski // TODO support ParamStructure to select which $param push to reference 5440f8369d7dSTobias Sarnowski if (isset($params[0])) 5441f8369d7dSTobias Sarnowski $callback->callback = $params[0]; 5442f8369d7dSTobias Sarnowski return true; 5443f8369d7dSTobias Sarnowski } 5444f8369d7dSTobias Sarnowski if ($callback instanceof Callback) { 5445f8369d7dSTobias Sarnowski $paramStructure = $callback->params; 5446f8369d7dSTobias Sarnowski $callback = $callback->callback; 5447f8369d7dSTobias Sarnowski } 5448f8369d7dSTobias Sarnowski if (! $paramStructure) 5449f8369d7dSTobias Sarnowski return call_user_func_array($callback, $params); 5450f8369d7dSTobias Sarnowski $p = 0; 5451f8369d7dSTobias Sarnowski foreach($paramStructure as $i => $v) { 5452f8369d7dSTobias Sarnowski $paramStructure[$i] = $v instanceof CallbackParam 5453f8369d7dSTobias Sarnowski ? $params[$p++] 5454f8369d7dSTobias Sarnowski : $v; 5455f8369d7dSTobias Sarnowski } 5456f8369d7dSTobias Sarnowski return call_user_func_array($callback, $paramStructure); 5457f8369d7dSTobias Sarnowski } 5458f8369d7dSTobias Sarnowski /** 5459f8369d7dSTobias Sarnowski * Merge 2 phpQuery objects. 5460f8369d7dSTobias Sarnowski * @param array $one 5461f8369d7dSTobias Sarnowski * @param array $two 5462f8369d7dSTobias Sarnowski * @protected 5463f8369d7dSTobias Sarnowski * @todo node lists, phpQueryObject 5464f8369d7dSTobias Sarnowski */ 5465f8369d7dSTobias Sarnowski public static function merge($one, $two) { 5466f8369d7dSTobias Sarnowski $elements = $one->elements; 5467f8369d7dSTobias Sarnowski foreach($two->elements as $node) { 5468f8369d7dSTobias Sarnowski $exists = false; 5469f8369d7dSTobias Sarnowski foreach($elements as $node2) { 5470f8369d7dSTobias Sarnowski if ($node2->isSameNode($node)) 5471f8369d7dSTobias Sarnowski $exists = true; 5472f8369d7dSTobias Sarnowski } 5473f8369d7dSTobias Sarnowski if (! $exists) 5474f8369d7dSTobias Sarnowski $elements[] = $node; 5475f8369d7dSTobias Sarnowski } 5476f8369d7dSTobias Sarnowski return $elements; 5477f8369d7dSTobias Sarnowski// $one = $one->newInstance(); 5478f8369d7dSTobias Sarnowski// $one->elements = $elements; 5479f8369d7dSTobias Sarnowski// return $one; 5480f8369d7dSTobias Sarnowski } 5481f8369d7dSTobias Sarnowski /** 5482f8369d7dSTobias Sarnowski * 5483f8369d7dSTobias Sarnowski * @param $array 5484f8369d7dSTobias Sarnowski * @param $callback 5485f8369d7dSTobias Sarnowski * @param $invert 5486f8369d7dSTobias Sarnowski * @return unknown_type 5487f8369d7dSTobias Sarnowski * @link http://docs.jquery.com/Utilities/jQuery.grep 5488f8369d7dSTobias Sarnowski */ 5489f8369d7dSTobias Sarnowski public static function grep($array, $callback, $invert = false) { 5490f8369d7dSTobias Sarnowski $result = array(); 5491f8369d7dSTobias Sarnowski foreach($array as $k => $v) { 5492f8369d7dSTobias Sarnowski $r = call_user_func_array($callback, array($v, $k)); 5493f8369d7dSTobias Sarnowski if ($r === !(bool)$invert) 5494f8369d7dSTobias Sarnowski $result[] = $v; 5495f8369d7dSTobias Sarnowski } 5496f8369d7dSTobias Sarnowski return $result; 5497f8369d7dSTobias Sarnowski } 5498f8369d7dSTobias Sarnowski public static function unique($array) { 5499f8369d7dSTobias Sarnowski return array_unique($array); 5500f8369d7dSTobias Sarnowski } 5501f8369d7dSTobias Sarnowski /** 5502f8369d7dSTobias Sarnowski * 5503f8369d7dSTobias Sarnowski * @param $function 5504f8369d7dSTobias Sarnowski * @return unknown_type 5505f8369d7dSTobias Sarnowski * @TODO there are problems with non-static methods, second parameter pass it 5506f8369d7dSTobias Sarnowski * but doesnt verify is method is really callable 5507f8369d7dSTobias Sarnowski */ 5508f8369d7dSTobias Sarnowski public static function isFunction($function) { 5509f8369d7dSTobias Sarnowski return is_callable($function); 5510f8369d7dSTobias Sarnowski } 5511f8369d7dSTobias Sarnowski public static function trim($str) { 5512f8369d7dSTobias Sarnowski return trim($str); 5513f8369d7dSTobias Sarnowski } 5514f8369d7dSTobias Sarnowski /* PLUGINS NAMESPACE */ 5515f8369d7dSTobias Sarnowski /** 5516f8369d7dSTobias Sarnowski * 5517f8369d7dSTobias Sarnowski * @param $url 5518f8369d7dSTobias Sarnowski * @param $callback 5519f8369d7dSTobias Sarnowski * @param $param1 5520f8369d7dSTobias Sarnowski * @param $param2 5521f8369d7dSTobias Sarnowski * @param $param3 5522f8369d7dSTobias Sarnowski * @return phpQueryObject 5523f8369d7dSTobias Sarnowski */ 5524f8369d7dSTobias Sarnowski public static function browserGet($url, $callback, $param1 = null, $param2 = null, $param3 = null) { 5525f8369d7dSTobias Sarnowski if (self::plugin('WebBrowser')) { 5526f8369d7dSTobias Sarnowski $params = func_get_args(); 5527f8369d7dSTobias Sarnowski return self::callbackRun(array(self::$plugins, 'browserGet'), $params); 5528f8369d7dSTobias Sarnowski } else { 5529f8369d7dSTobias Sarnowski self::debug('WebBrowser plugin not available...'); 5530f8369d7dSTobias Sarnowski } 5531f8369d7dSTobias Sarnowski } 5532f8369d7dSTobias Sarnowski /** 5533f8369d7dSTobias Sarnowski * 5534f8369d7dSTobias Sarnowski * @param $url 5535f8369d7dSTobias Sarnowski * @param $data 5536f8369d7dSTobias Sarnowski * @param $callback 5537f8369d7dSTobias Sarnowski * @param $param1 5538f8369d7dSTobias Sarnowski * @param $param2 5539f8369d7dSTobias Sarnowski * @param $param3 5540f8369d7dSTobias Sarnowski * @return phpQueryObject 5541f8369d7dSTobias Sarnowski */ 5542f8369d7dSTobias Sarnowski public static function browserPost($url, $data, $callback, $param1 = null, $param2 = null, $param3 = null) { 5543f8369d7dSTobias Sarnowski if (self::plugin('WebBrowser')) { 5544f8369d7dSTobias Sarnowski $params = func_get_args(); 5545f8369d7dSTobias Sarnowski return self::callbackRun(array(self::$plugins, 'browserPost'), $params); 5546f8369d7dSTobias Sarnowski } else { 5547f8369d7dSTobias Sarnowski self::debug('WebBrowser plugin not available...'); 5548f8369d7dSTobias Sarnowski } 5549f8369d7dSTobias Sarnowski } 5550f8369d7dSTobias Sarnowski /** 5551f8369d7dSTobias Sarnowski * 5552f8369d7dSTobias Sarnowski * @param $ajaxSettings 5553f8369d7dSTobias Sarnowski * @param $callback 5554f8369d7dSTobias Sarnowski * @param $param1 5555f8369d7dSTobias Sarnowski * @param $param2 5556f8369d7dSTobias Sarnowski * @param $param3 5557f8369d7dSTobias Sarnowski * @return phpQueryObject 5558f8369d7dSTobias Sarnowski */ 5559f8369d7dSTobias Sarnowski public static function browser($ajaxSettings, $callback, $param1 = null, $param2 = null, $param3 = null) { 5560f8369d7dSTobias Sarnowski if (self::plugin('WebBrowser')) { 5561f8369d7dSTobias Sarnowski $params = func_get_args(); 5562f8369d7dSTobias Sarnowski return self::callbackRun(array(self::$plugins, 'browser'), $params); 5563f8369d7dSTobias Sarnowski } else { 5564f8369d7dSTobias Sarnowski self::debug('WebBrowser plugin not available...'); 5565f8369d7dSTobias Sarnowski } 5566f8369d7dSTobias Sarnowski } 5567f8369d7dSTobias Sarnowski /** 5568f8369d7dSTobias Sarnowski * 5569f8369d7dSTobias Sarnowski * @param $code 5570f8369d7dSTobias Sarnowski * @return string 5571f8369d7dSTobias Sarnowski */ 5572f8369d7dSTobias Sarnowski public static function php($code) { 5573f8369d7dSTobias Sarnowski return self::code('php', $code); 5574f8369d7dSTobias Sarnowski } 5575f8369d7dSTobias Sarnowski /** 5576f8369d7dSTobias Sarnowski * 5577f8369d7dSTobias Sarnowski * @param $type 5578f8369d7dSTobias Sarnowski * @param $code 5579f8369d7dSTobias Sarnowski * @return string 5580f8369d7dSTobias Sarnowski */ 5581f8369d7dSTobias Sarnowski public static function code($type, $code) { 5582f8369d7dSTobias Sarnowski return "<$type><!-- ".trim($code)." --></$type>"; 5583f8369d7dSTobias Sarnowski } 5584f8369d7dSTobias Sarnowski 5585f8369d7dSTobias Sarnowski public static function __callStatic($method, $params) { 5586f8369d7dSTobias Sarnowski return call_user_func_array( 5587f8369d7dSTobias Sarnowski array(phpQuery::$plugins, $method), 5588f8369d7dSTobias Sarnowski $params 5589f8369d7dSTobias Sarnowski ); 5590f8369d7dSTobias Sarnowski } 5591f8369d7dSTobias Sarnowski protected static function dataSetupNode($node, $documentID) { 5592f8369d7dSTobias Sarnowski // search are return if alredy exists 5593f8369d7dSTobias Sarnowski foreach(phpQuery::$documents[$documentID]->dataNodes as $dataNode) { 5594f8369d7dSTobias Sarnowski if ($node->isSameNode($dataNode)) 5595f8369d7dSTobias Sarnowski return $dataNode; 5596f8369d7dSTobias Sarnowski } 5597f8369d7dSTobias Sarnowski // if doesn't, add it 5598f8369d7dSTobias Sarnowski phpQuery::$documents[$documentID]->dataNodes[] = $node; 5599f8369d7dSTobias Sarnowski return $node; 5600f8369d7dSTobias Sarnowski } 5601f8369d7dSTobias Sarnowski protected static function dataRemoveNode($node, $documentID) { 5602f8369d7dSTobias Sarnowski // search are return if alredy exists 5603f8369d7dSTobias Sarnowski foreach(phpQuery::$documents[$documentID]->dataNodes as $k => $dataNode) { 5604f8369d7dSTobias Sarnowski if ($node->isSameNode($dataNode)) { 5605f8369d7dSTobias Sarnowski unset(self::$documents[$documentID]->dataNodes[$k]); 5606f8369d7dSTobias Sarnowski unset(self::$documents[$documentID]->data[ $dataNode->dataID ]); 5607f8369d7dSTobias Sarnowski } 5608f8369d7dSTobias Sarnowski } 5609f8369d7dSTobias Sarnowski } 5610f8369d7dSTobias Sarnowski public static function data($node, $name, $data, $documentID = null) { 5611f8369d7dSTobias Sarnowski if (! $documentID) 5612f8369d7dSTobias Sarnowski // TODO check if this works 5613f8369d7dSTobias Sarnowski $documentID = self::getDocumentID($node); 5614f8369d7dSTobias Sarnowski $document = phpQuery::$documents[$documentID]; 5615f8369d7dSTobias Sarnowski $node = self::dataSetupNode($node, $documentID); 5616f8369d7dSTobias Sarnowski if (! isset($node->dataID)) 5617f8369d7dSTobias Sarnowski $node->dataID = ++phpQuery::$documents[$documentID]->uuid; 5618f8369d7dSTobias Sarnowski $id = $node->dataID; 5619f8369d7dSTobias Sarnowski if (! isset($document->data[$id])) 5620f8369d7dSTobias Sarnowski $document->data[$id] = array(); 5621f8369d7dSTobias Sarnowski if (! is_null($data)) 5622f8369d7dSTobias Sarnowski $document->data[$id][$name] = $data; 5623f8369d7dSTobias Sarnowski if ($name) { 5624f8369d7dSTobias Sarnowski if (isset($document->data[$id][$name])) 5625f8369d7dSTobias Sarnowski return $document->data[$id][$name]; 5626f8369d7dSTobias Sarnowski } else 5627f8369d7dSTobias Sarnowski return $id; 5628f8369d7dSTobias Sarnowski } 5629f8369d7dSTobias Sarnowski public static function removeData($node, $name, $documentID) { 5630f8369d7dSTobias Sarnowski if (! $documentID) 5631f8369d7dSTobias Sarnowski // TODO check if this works 5632f8369d7dSTobias Sarnowski $documentID = self::getDocumentID($node); 5633f8369d7dSTobias Sarnowski $document = phpQuery::$documents[$documentID]; 5634f8369d7dSTobias Sarnowski $node = self::dataSetupNode($node, $documentID); 5635f8369d7dSTobias Sarnowski $id = $node->dataID; 5636f8369d7dSTobias Sarnowski if ($name) { 5637f8369d7dSTobias Sarnowski if (isset($document->data[$id][$name])) 5638f8369d7dSTobias Sarnowski unset($document->data[$id][$name]); 5639f8369d7dSTobias Sarnowski $name = null; 5640f8369d7dSTobias Sarnowski foreach($document->data[$id] as $name) 5641f8369d7dSTobias Sarnowski break; 5642f8369d7dSTobias Sarnowski if (! $name) 5643f8369d7dSTobias Sarnowski self::removeData($node, $name, $documentID); 5644f8369d7dSTobias Sarnowski } else { 5645f8369d7dSTobias Sarnowski self::dataRemoveNode($node, $documentID); 5646f8369d7dSTobias Sarnowski } 5647f8369d7dSTobias Sarnowski } 5648f8369d7dSTobias Sarnowski} 5649f8369d7dSTobias Sarnowski/** 5650f8369d7dSTobias Sarnowski * Plugins static namespace class. 5651f8369d7dSTobias Sarnowski * 5652f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 5653f8369d7dSTobias Sarnowski * @package phpQuery 5654f8369d7dSTobias Sarnowski * @todo move plugin methods here (as statics) 5655f8369d7dSTobias Sarnowski */ 5656f8369d7dSTobias Sarnowskiclass phpQueryPlugins { 5657f8369d7dSTobias Sarnowski public function __call($method, $args) { 5658f8369d7dSTobias Sarnowski if (isset(phpQuery::$extendStaticMethods[$method])) { 5659f8369d7dSTobias Sarnowski $return = call_user_func_array( 5660f8369d7dSTobias Sarnowski phpQuery::$extendStaticMethods[$method], 5661f8369d7dSTobias Sarnowski $args 5662f8369d7dSTobias Sarnowski ); 5663f8369d7dSTobias Sarnowski } else if (isset(phpQuery::$pluginsStaticMethods[$method])) { 5664f8369d7dSTobias Sarnowski $class = phpQuery::$pluginsStaticMethods[$method]; 5665f8369d7dSTobias Sarnowski $realClass = "phpQueryPlugin_$class"; 5666f8369d7dSTobias Sarnowski $return = call_user_func_array( 5667f8369d7dSTobias Sarnowski array($realClass, $method), 5668f8369d7dSTobias Sarnowski $args 5669f8369d7dSTobias Sarnowski ); 5670f8369d7dSTobias Sarnowski return isset($return) 5671f8369d7dSTobias Sarnowski ? $return 5672f8369d7dSTobias Sarnowski : $this; 5673f8369d7dSTobias Sarnowski } else 5674f8369d7dSTobias Sarnowski throw new Exception("Method '{$method}' doesnt exist"); 5675f8369d7dSTobias Sarnowski } 5676f8369d7dSTobias Sarnowski} 5677f8369d7dSTobias Sarnowski/** 5678f8369d7dSTobias Sarnowski * Shortcut to phpQuery::pq($arg1, $context) 5679f8369d7dSTobias Sarnowski * Chainable. 5680f8369d7dSTobias Sarnowski * 5681f8369d7dSTobias Sarnowski * @see phpQuery::pq() 5682f8369d7dSTobias Sarnowski * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery 5683f8369d7dSTobias Sarnowski * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> 5684f8369d7dSTobias Sarnowski * @package phpQuery 5685f8369d7dSTobias Sarnowski */ 5686f8369d7dSTobias Sarnowskifunction pq($arg1, $context = null) { 5687f8369d7dSTobias Sarnowski $args = func_get_args(); 5688f8369d7dSTobias Sarnowski return call_user_func_array( 5689f8369d7dSTobias Sarnowski array('phpQuery', 'pq'), 5690f8369d7dSTobias Sarnowski $args 5691f8369d7dSTobias Sarnowski ); 5692f8369d7dSTobias Sarnowski} 5693f8369d7dSTobias Sarnowski// add plugins dir and Zend framework to include path 5694f8369d7dSTobias Sarnowskiset_include_path( 5695f8369d7dSTobias Sarnowski get_include_path() 5696f8369d7dSTobias Sarnowski .PATH_SEPARATOR.dirname(__FILE__).'/phpQuery/' 5697f8369d7dSTobias Sarnowski .PATH_SEPARATOR.dirname(__FILE__).'/phpQuery/plugins/' 5698f8369d7dSTobias Sarnowski); 5699f8369d7dSTobias Sarnowski// why ? no __call nor __get for statics in php... 5700f8369d7dSTobias Sarnowski// XXX __callStatic will be available in PHP 5.3 5701f8369d7dSTobias SarnowskiphpQuery::$plugins = new phpQueryPlugins(); 5702f8369d7dSTobias Sarnowski// include bootstrap file (personal library config) 5703f8369d7dSTobias Sarnowskiif (file_exists(dirname(__FILE__).'/phpQuery/bootstrap.php')) 5704f8369d7dSTobias Sarnowski require_once dirname(__FILE__).'/phpQuery/bootstrap.php'; 5705