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