]>
Commit | Line | Data |
---|---|---|
1a268ba7 NL |
1 | <?php |
2 | /** | |
3 | * JavaScript-like HTML DOM Element | |
4 | * | |
5 | * This class extends PHP's DOMElement to allow | |
6 | * users to get and set the innerHTML property of | |
3db95a85 | 7 | * HTML elements in the same way it's done in |
1a268ba7 NL |
8 | * JavaScript. |
9 | * | |
10 | * Example usage: | |
11 | * @code | |
12 | * require_once 'JSLikeHTMLElement.php'; | |
13 | * header('Content-Type: text/plain'); | |
14 | * $doc = new DOMDocument(); | |
15 | * $doc->registerNodeClass('DOMElement', 'JSLikeHTMLElement'); | |
16 | * $doc->loadHTML('<div><p>Para 1</p><p>Para 2</p></div>'); | |
17 | * $elem = $doc->getElementsByTagName('div')->item(0); | |
3db95a85 | 18 | * |
1a268ba7 NL |
19 | * // print innerHTML |
20 | * echo $elem->innerHTML; // prints '<p>Para 1</p><p>Para 2</p>' | |
21 | * echo "\n\n"; | |
3db95a85 | 22 | * |
1a268ba7 NL |
23 | * // set innerHTML |
24 | * $elem->innerHTML = '<a href="http://fivefilters.org">FiveFilters.org</a>'; | |
25 | * echo $elem->innerHTML; // prints '<a href="http://fivefilters.org">FiveFilters.org</a>' | |
26 | * echo "\n\n"; | |
3db95a85 | 27 | * |
1a268ba7 NL |
28 | * // print document (with our changes) |
29 | * echo $doc->saveXML(); | |
30 | * @endcode | |
31 | * | |
32 | * @author Keyvan Minoukadeh - http://www.keyvan.net - keyvan@keyvan.net | |
33 | * @see http://fivefilters.org (the project this was written for) | |
34 | */ | |
35 | class JSLikeHTMLElement extends DOMElement | |
36 | { | |
37 | /** | |
38 | * Used for setting innerHTML like it's done in JavaScript: | |
39 | * @code | |
40 | * $div->innerHTML = '<h2>Chapter 2</h2><p>The story begins...</p>'; | |
41 | * @endcode | |
42 | */ | |
43 | public function __set($name, $value) { | |
44 | if ($name == 'innerHTML') { | |
45 | // first, empty the element | |
46 | for ($x=$this->childNodes->length-1; $x>=0; $x--) { | |
47 | $this->removeChild($this->childNodes->item($x)); | |
48 | } | |
49 | // $value holds our new inner HTML | |
50 | if ($value != '') { | |
51 | $f = $this->ownerDocument->createDocumentFragment(); | |
52 | // appendXML() expects well-formed markup (XHTML) | |
53 | $result = @$f->appendXML($value); // @ to suppress PHP warnings | |
54 | if ($result) { | |
55 | if ($f->hasChildNodes()) $this->appendChild($f); | |
56 | } else { | |
57 | // $value is probably ill-formed | |
58 | $f = new DOMDocument(); | |
59 | $value = mb_convert_encoding($value, 'HTML-ENTITIES', 'UTF-8'); | |
60 | // Using <htmlfragment> will generate a warning, but so will bad HTML | |
61 | // (and by this point, bad HTML is what we've got). | |
3db95a85 | 62 | // We use it (and suppress the warning) because an HTML fragment will |
1a268ba7 NL |
63 | // be wrapped around <html><body> tags which we don't really want to keep. |
64 | // Note: despite the warning, if loadHTML succeeds it will return true. | |
65 | $result = @$f->loadHTML('<htmlfragment>'.$value.'</htmlfragment>'); | |
66 | if ($result) { | |
67 | $import = $f->getElementsByTagName('htmlfragment')->item(0); | |
68 | foreach ($import->childNodes as $child) { | |
69 | $importedNode = $this->ownerDocument->importNode($child, true); | |
70 | $this->appendChild($importedNode); | |
71 | } | |
72 | } else { | |
73 | // oh well, we tried, we really did. :( | |
74 | // this element is now empty | |
75 | } | |
76 | } | |
77 | } | |
78 | } else { | |
79 | $trace = debug_backtrace(); | |
80 | trigger_error('Undefined property via __set(): '.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE); | |
81 | } | |
82 | } | |
83 | ||
84 | /** | |
85 | * Used for getting innerHTML like it's done in JavaScript: | |
86 | * @code | |
87 | * $string = $div->innerHTML; | |
88 | * @endcode | |
3db95a85 | 89 | */ |
1a268ba7 NL |
90 | public function __get($name) |
91 | { | |
92 | if ($name == 'innerHTML') { | |
93 | $inner = ''; | |
94 | foreach ($this->childNodes as $child) { | |
95 | $inner .= $this->ownerDocument->saveXML($child); | |
96 | } | |
97 | return $inner; | |
98 | } | |
99 | ||
100 | $trace = debug_backtrace(); | |
101 | trigger_error('Undefined property via __get(): '.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE); | |
102 | return null; | |
103 | } | |
104 | ||
105 | public function __toString() | |
106 | { | |
107 | return '['.$this->tagName.']'; | |
108 | } | |
baa86173 | 109 | } |