/* * HTMLElement - DOM Level 2 */ $w.__defineGetter__("HTMLElement", function(){ return function(){ throw new Error("Object cannot be created in this context"); }; }); var Element = function(node){ var $dom = node, $id = createGUID(); $w.__defineGetter__("Element", function(){ var $dom, $id; return function(elem){ $dom = elem; $id = createGUID(); __extend__(this, new DOMNode($dom)); // A lot of the methods defined below belong in HTML specific // subclasses. This is already unwieldy since most of these //methods are meant for general xml consumption __extend__(this, { get nodeName(){ return this.tagName; }, get tagName(){ return $dom.getTagName().toUpperCase(); }, toString: function(){ return "<" + this.tagName + (this.id ? "#" + this.id : "" ) + ">"; }, get outerHTML(){ var ret = "<" + this.tagName, attr = this.attributes; for ( var i in attr ) ret += " " + i + "='" + attr[i] + "'"; if ( this.childNodes.length || this.nodeName == "SCRIPT" ) ret += ">" + this.childNodes.outerHTML + ""; else ret += "/>"; return ret; }, get attributes(){ var attr = {}, attrs = $dom.getAttributes(); for ( var i = 0; i < attrs.getLength(); i++ ){ attr[ attrs.item(i).nodeName ] = attrs.item(i).nodeValue; }return attr; }, get innerHTML(){ return this.childNodes.outerHTML; }, set innerHTML(html){ html = html.replace(/<\/?([A-Z]+)/g, function(m){ return m.toLowerCase(); }).replace(/ /g, " "); var dom = new DOMParser().parseFromString("" + html + ""); var nodes = this.ownerDocument.importNode( dom.documentElement, true ).childNodes; while (this.firstChild){ this.removeChild( this.firstChild ); } for ( var i = 0; i < nodes.length; i++ ) this.appendChild( nodes[i] ); }, get textContent(){ function nav(nodes){ var str = ""; for ( var i = 0; i < nodes.length; i++ ){ if ( nodes[i].nodeType == 3 ){ str += nodes[i].nodeValue; }else if ( nodes[i].nodeType == 1 ){ str += nav(nodes[i].childNodes); } } return str; } return nav(this.childNodes); }, set textContent(text){ while (this.firstChild) this.removeChild( this.firstChild ); this.appendChild( this.ownerDocument.createTextNode(text)); }, style: {}, clientHeight: 0, clientWidth: 0, offsetHeight: 0, offsetWidth: 0, get disabled() { var val = this.getAttribute("disabled"); return val != "false" && !!val; }, set disabled(val) { return this.setAttribute("disabled",val); }, get checked() { var val = this.getAttribute("checked"); return val != "false" && !!val; }, set checked(val) { return this.setAttribute("checked",val); }, get selected() { if ( !this._selectDone ) { this._selectDone = true; if ( this.nodeName == "OPTION" && !this.parentNode.getAttribute("multiple") ) { var opt = this.parentNode.getElementsByTagName("option"); if ( this == opt[0] ) { var select = true; for ( var i = 1; i < opt.length; i++ ){ if ( opt[i].selected ) { select = false; break; } } if ( select ){ this.selected = true; } } } } var val = this.getAttribute("selected"); return val != "false" && !!val; }, set selected(val) { return this.setAttribute("selected",val); }, get className() { return this.getAttribute("class") || ""; }, set className(val) { return this.setAttribute("class", val.replace(/(^\s*|\s*$)/g,"")); }, get type() { return this.getAttribute("type") || ""; }, set type(val) { return this.setAttribute("type",val); }, get defaultValue() { return this.getAttribute("defaultValue") || ""; }, set defaultValue(val) { return this.setAttribute("defaultValue",val); }, get value() { return this.getAttribute("value") || ""; }, set value(val) { return this.setAttribute("value",val); }, get src() { return this.getAttribute("src") || ""; }, set src(val) { return this.setAttribute("src",val); }, get id() { return this.getAttribute("id") || ""; }, set id(val) { return this.setAttribute("id",val); }, getAttribute: function(name){ return $dom.hasAttribute(name) ? new String( $dom.getAttribute(name) ) : null; }, setAttribute: function(name,value){ $dom.setAttribute(name,value); }, removeAttribute: function(name){ $dom.removeAttribute(name); }, get childNodes(){ return new DOMNodeList( $dom.getChildNodes() ); }, get firstChild(){ return makeNode( $dom.getFirstChild() ); }, get lastChild(){ return makeNode( $dom.getLastChild() ); }, appendChild: function(node){ //Because the dom implementation is private in scope now, //we will need to fix these to use some innerHtml etc //if required $dom.appendChild( $nodeImplCache[node.__guid__] ); }, insertBefore: function(node,before){ $dom.insertBefore( $nodeImplCache[node.__guid__], before ? $nodeImplCache[before.__guid__] : before ); execScripts( node ); function execScripts( node ) { if ( node.nodeName == "SCRIPT" ) { if ( !node.getAttribute("src") ) { eval.call( window, node.textContent ); } } else { var scripts = node.getElementsByTagName("script"); for ( var i = 0; i < scripts.length; i++ ) { execScripts( node ); } } } }, removeChild: function(node){ $dom.removeChild( $nodeImplCache[node.__guid__] ); }, getElementsByTagName: function(name){ // why can't we just do ?: //var elems = $dom.getElementsByTagName(name), ret = []; var elems = $dom.getElementsByTagName("*"), ret = []; ret.item = function(i){ return this[i]; }; ret.getLength = function(){ return this.length; }; for ( var i = 0; i < elems.length; i++ ) { var elem = elems.item(i); if ( elem.getAttribute("name") == name ) ret.push( elem ); }return new DOMNodeList( ret ); }, addEventListener: window.addEventListener, removeEventListener: window.removeEventListener, dispatchEvent: window.dispatchEvent, click: function(){ var event = document.createEvent(); event.initEvent("click"); this.dispatchEvent(event); }, submit: function(){ var event = document.createEvent(); event.initEvent("submit"); this.dispatchEvent(event); }, focus: function(){ var event = document.createEvent(); event.initEvent("focus"); this.dispatchEvent(event); }, blur: function(){ var event = document.createEvent(); event.initEvent("blur"); this.dispatchEvent(event); }, get contentWindow(){ return this.nodeName == "IFRAME" ? { document: this.contentDocument } : null; }, get contentDocument(){ if ( this.nodeName == "IFRAME" ) { if ( !this._doc ) this._doc = HTMLtoDOM(""); return this._doc; } else { return null; } }, get __guid__(){return $id;} }); //All this constructor stuff belond in the HTML subclasses //and even more generally in the HTML specific element //subclass otherwise its going to become a mess this.style = { get opacity(){ return this._opacity; }, set opacity(val){ this._opacity = val + ""; } }; // Load CSS info var styles = (this.getAttribute("style") || "").split(/\s*;\s*/); for ( var i = 0; i < styles.length; i++ ) { var style = styles[i].split(/\s*:\s*/); if ( style.length == 2 ) this.style[ style[0] ] = style[1]; } if ( this.nodeName == "FORM" ) { this.__defineGetter__("elements", function(){ return this.getElementsByTagName("*"); }); this.__defineGetter__("length", function(){ var elems = this.elements; for ( var i = 0; i < elems.length; i++ ) { this[i] = elems[i]; } return elems.length; }); } if ( this.nodeName == "SELECT" ) { this.__defineGetter__("options", function(){ return this.getElementsByTagName("option"); }); } this.defaultValue = this.value; return this; }; });