UNPKG

can

Version:

MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.

1,196 lines (940 loc) 30 kB
/* --- name: Element description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. license: MIT-style license. requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder] provides: [Element, Elements, $, $$, IFrame, Selectors] ... */ var Element = this.Element = function(tag, props){ var konstructor = Element.Constructors[tag]; if (konstructor) return konstructor(props); if (typeof tag != 'string') return document.id(tag).set(props); if (!props) props = {}; if (!(/^[\w-]+$/).test(tag)){ var parsed = Slick.parse(tag).expressions[0][0]; tag = (parsed.tag == '*') ? 'div' : parsed.tag; if (parsed.id && props.id == null) props.id = parsed.id; var attributes = parsed.attributes; if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){ attr = attributes[i]; if (props[attr.key] != null) continue; if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value; else if (!attr.value && !attr.operator) props[attr.key] = true; } if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' '); } return document.newElement(tag, props); }; if (Browser.Element){ Element.prototype = Browser.Element.prototype; // IE8 and IE9 require the wrapping. Element.prototype._fireEvent = (function(fireEvent){ return function(type, event){ return fireEvent.call(this, type, event); }; })(Element.prototype.fireEvent); } new Type('Element', Element).mirror(function(name){ if (Array.prototype[name]) return; var obj = {}; obj[name] = function(){ var results = [], args = arguments, elements = true; for (var i = 0, l = this.length; i < l; i++){ var element = this[i], result = results[i] = element[name].apply(element, args); elements = (elements && typeOf(result) == 'element'); } return (elements) ? new Elements(results) : results; }; Elements.implement(obj); }); if (!Browser.Element){ Element.parent = Object; Element.Prototype = { '$constructor': Element, '$family': Function.from('element').hide() }; Element.mirror(function(name, method){ Element.Prototype[name] = method; }); } Element.Constructors = {}; //<1.2compat> Element.Constructors = new Hash; //</1.2compat> var IFrame = new Type('IFrame', function(){ var params = Array.link(arguments, { properties: Type.isObject, iframe: function(obj){ return (obj != null); } }); var props = params.properties || {}, iframe; if (params.iframe) iframe = document.id(params.iframe); var onload = props.onload || function(){}; delete props.onload; props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick(); iframe = new Element(iframe || 'iframe', props); var onLoad = function(){ onload.call(iframe.contentWindow); }; if (window.frames[props.id]) onLoad(); else iframe.addListener('load', onLoad); return iframe; }); var Elements = this.Elements = function(nodes){ if (nodes && nodes.length){ var uniques = {}, node; for (var i = 0; node = nodes[i++];){ var uid = Slick.uidOf(node); if (!uniques[uid]){ uniques[uid] = true; this.push(node); } } } }; Elements.prototype = {length: 0}; Elements.parent = Array; new Type('Elements', Elements).implement({ filter: function(filter, bind){ if (!filter) return this; return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){ return item.match(filter); } : filter, bind)); }.protect(), push: function(){ var length = this.length; for (var i = 0, l = arguments.length; i < l; i++){ var item = document.id(arguments[i]); if (item) this[length++] = item; } return (this.length = length); }.protect(), unshift: function(){ var items = []; for (var i = 0, l = arguments.length; i < l; i++){ var item = document.id(arguments[i]); if (item) items.push(item); } return Array.prototype.unshift.apply(this, items); }.protect(), concat: function(){ var newElements = new Elements(this); for (var i = 0, l = arguments.length; i < l; i++){ var item = arguments[i]; if (Type.isEnumerable(item)) newElements.append(item); else newElements.push(item); } return newElements; }.protect(), append: function(collection){ for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]); return this; }.protect(), empty: function(){ while (this.length) delete this[--this.length]; return this; }.protect() }); //<1.2compat> Elements.alias('extend', 'append'); //</1.2compat> (function(){ // FF, IE var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2}; splice.call(object, 1, 1); if (object[1] == 1) Elements.implement('splice', function(){ var length = this.length; var result = splice.apply(this, arguments); while (length >= this.length) delete this[length--]; return result; }.protect()); Array.forEachMethod(function(method, name){ Elements.implement(name, method); }); Array.mirror(Elements); /*<ltIE8>*/ var createElementAcceptsHTML; try { createElementAcceptsHTML = (document.createElement('<input name=x>').name == 'x'); } catch (e){} var escapeQuotes = function(html){ return ('' + html).replace(/&/g, '&amp;').replace(/"/g, '&quot;'); }; /*</ltIE8>*/ /*<ltIE9>*/ // #2479 - IE8 Cannot set HTML of style element var canChangeStyleHTML = (function(){ var div = document.createElement('style'), flag = false; try { div.innerHTML = '#justTesing{margin: 0px;}'; flag = !!div.innerHTML; } catch(e){} return flag; })(); /*</ltIE9>*/ Document.implement({ newElement: function(tag, props){ if (props){ if (props.checked != null) props.defaultChecked = props.checked; if ((props.type == 'checkbox' || props.type == 'radio') && props.value == null) props.value = 'on'; /*<ltIE9>*/ // IE needs the type to be set before changing content of style element if (!canChangeStyleHTML && tag == 'style'){ var styleElement = document.createElement('style'); styleElement.setAttribute('type', 'text/css'); if (props.type) delete props.type; return this.id(styleElement).set(props); } /*</ltIE9>*/ /*<ltIE8>*/// Fix for readonly name and type properties in IE < 8 if (createElementAcceptsHTML){ tag = '<' + tag; if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"'; if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"'; tag += '>'; delete props.name; delete props.type; } /*</ltIE8>*/ } return this.id(this.createElement(tag)).set(props); } }); })(); (function(){ Slick.uidOf(window); Slick.uidOf(document); Document.implement({ newTextNode: function(text){ return this.createTextNode(text); }, getDocument: function(){ return this; }, getWindow: function(){ return this.window; }, id: (function(){ var types = { string: function(id, nocash, doc){ id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1')); return (id) ? types.element(id, nocash) : null; }, element: function(el, nocash){ Slick.uidOf(el); if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){ var fireEvent = el.fireEvent; // wrapping needed in IE7, or else crash el._fireEvent = function(type, event){ return fireEvent(type, event); }; Object.append(el, Element.Prototype); } return el; }, object: function(obj, nocash, doc){ if (obj.toElement) return types.element(obj.toElement(doc), nocash); return null; } }; types.textnode = types.whitespace = types.window = types.document = function(zero){ return zero; }; return function(el, nocash, doc){ if (el && el.$family && el.uniqueNumber) return el; var type = typeOf(el); return (types[type]) ? types[type](el, nocash, doc || document) : null; }; })() }); if (window.$ == null) Window.implement('$', function(el, nc){ return document.id(el, nc, this.document); }); Window.implement({ getDocument: function(){ return this.document; }, getWindow: function(){ return this; } }); [Document, Element].invoke('implement', { getElements: function(expression){ return Slick.search(this, expression, new Elements); }, getElement: function(expression){ return document.id(Slick.find(this, expression)); } }); var contains = {contains: function(element){ return Slick.contains(this, element); }}; if (!document.contains) Document.implement(contains); if (!document.createElement('div').contains) Element.implement(contains); //<1.2compat> Element.implement('hasChild', function(element){ return this !== element && this.contains(element); }); (function(search, find, match){ this.Selectors = {}; var pseudos = this.Selectors.Pseudo = new Hash(); var addSlickPseudos = function(){ for (var name in pseudos) if (pseudos.hasOwnProperty(name)){ Slick.definePseudo(name, pseudos[name]); delete pseudos[name]; } }; Slick.search = function(context, expression, append){ addSlickPseudos(); return search.call(this, context, expression, append); }; Slick.find = function(context, expression){ addSlickPseudos(); return find.call(this, context, expression); }; Slick.match = function(node, selector){ addSlickPseudos(); return match.call(this, node, selector); }; })(Slick.search, Slick.find, Slick.match); //</1.2compat> // tree walking var injectCombinator = function(expression, combinator){ if (!expression) return combinator; expression = Object.clone(Slick.parse(expression)); var expressions = expression.expressions; for (var i = expressions.length; i--;) expressions[i][0].combinator = combinator; return expression; }; Object.forEach({ getNext: '~', getPrevious: '!~', getParent: '!' }, function(combinator, method){ Element.implement(method, function(expression){ return this.getElement(injectCombinator(expression, combinator)); }); }); Object.forEach({ getAllNext: '~', getAllPrevious: '!~', getSiblings: '~~', getChildren: '>', getParents: '!' }, function(combinator, method){ Element.implement(method, function(expression){ return this.getElements(injectCombinator(expression, combinator)); }); }); Element.implement({ getFirst: function(expression){ return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); }, getLast: function(expression){ return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); }, getWindow: function(){ return this.ownerDocument.window; }, getDocument: function(){ return this.ownerDocument; }, getElementById: function(id){ return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); }, match: function(expression){ return !expression || Slick.match(this, expression); } }); //<1.2compat> if (window.$$ == null) Window.implement('$$', function(selector){ var elements = new Elements; if (arguments.length == 1 && typeof selector == 'string') return Slick.search(this.document, selector, elements); var args = Array.flatten(arguments); for (var i = 0, l = args.length; i < l; i++){ var item = args[i]; switch (typeOf(item)){ case 'element': elements.push(item); break; case 'string': Slick.search(this.document, item, elements); } } return elements; }); //</1.2compat> if (window.$$ == null) Window.implement('$$', function(selector){ if (arguments.length == 1){ if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements); else if (Type.isEnumerable(selector)) return new Elements(selector); } return new Elements(arguments); }); // Inserters var inserters = { before: function(context, element){ var parent = element.parentNode; if (parent) parent.insertBefore(context, element); }, after: function(context, element){ var parent = element.parentNode; if (parent) parent.insertBefore(context, element.nextSibling); }, bottom: function(context, element){ element.appendChild(context); }, top: function(context, element){ element.insertBefore(context, element.firstChild); } }; inserters.inside = inserters.bottom; //<1.2compat> Object.each(inserters, function(inserter, where){ where = where.capitalize(); var methods = {}; methods['inject' + where] = function(el){ inserter(this, document.id(el, true)); return this; }; methods['grab' + where] = function(el){ inserter(document.id(el, true), this); return this; }; Element.implement(methods); }); //</1.2compat> // getProperty / setProperty var propertyGetters = {}, propertySetters = {}; // properties var properties = {}; Array.forEach([ 'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'rowSpan', 'tabIndex', 'useMap' ], function(property){ properties[property.toLowerCase()] = property; }); properties.html = 'innerHTML'; properties.text = (document.createElement('div').textContent == null) ? 'innerText': 'textContent'; Object.forEach(properties, function(real, key){ propertySetters[key] = function(node, value){ node[real] = value; }; propertyGetters[key] = function(node){ return node[real]; }; }); /*<ltIE9>*/ propertySetters.text = (function(setter){ return function(node, value){ if (node.get('tag') == 'style') node.set('html', value); else node[properties.text] = value; }; })(propertySetters.text); propertyGetters.text = (function(getter){ return function(node){ return (node.get('tag') == 'style') ? node.innerHTML : getter(node); }; })(propertyGetters.text); /*</ltIE9>*/ // Booleans var bools = [ 'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected', 'noresize', 'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay', 'loop' ]; var booleans = {}; Array.forEach(bools, function(bool){ var lower = bool.toLowerCase(); booleans[lower] = bool; propertySetters[lower] = function(node, value){ node[bool] = !!value; }; propertyGetters[lower] = function(node){ return !!node[bool]; }; }); // Special cases Object.append(propertySetters, { 'class': function(node, value){ ('className' in node) ? node.className = (value || '') : node.setAttribute('class', value); }, 'for': function(node, value){ ('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value); }, 'style': function(node, value){ (node.style) ? node.style.cssText = value : node.setAttribute('style', value); }, 'value': function(node, value){ node.value = (value != null) ? value : ''; } }); propertyGetters['class'] = function(node){ return ('className' in node) ? node.className || null : node.getAttribute('class'); }; /* <webkit> */ var el = document.createElement('button'); // IE sets type as readonly and throws try { el.type = 'button'; } catch(e){} if (el.type != 'button') propertySetters.type = function(node, value){ node.setAttribute('type', value); }; el = null; /* </webkit> */ /*<IE>*/ /*<ltIE9>*/ // #2479 - IE8 Cannot set HTML of style element var canChangeStyleHTML = (function(){ var div = document.createElement('style'), flag = false; try { div.innerHTML = '#justTesing{margin: 0px;}'; flag = !!div.innerHTML; } catch(e){} return flag; })(); /*</ltIE9>*/ var input = document.createElement('input'), volatileInputValue, html5InputSupport; // #2178 input.value = 't'; input.type = 'submit'; volatileInputValue = input.value != 't'; // #2443 - IE throws "Invalid Argument" when trying to use html5 input types try { input.value = ''; input.type = 'email'; html5InputSupport = input.type == 'email'; } catch(e){} input = null; if (volatileInputValue || !html5InputSupport) propertySetters.type = function(node, type){ try { var value = node.value; node.type = type; node.value = value; } catch (e){} }; /*</IE>*/ /* getProperty, setProperty */ /* <ltIE9> */ var pollutesGetAttribute = (function(div){ div.random = 'attribute'; return (div.getAttribute('random') == 'attribute'); })(document.createElement('div')); var hasCloneBug = (function(test){ test.innerHTML = '<object><param name="should_fix" value="the unknown" /></object>'; return test.cloneNode(true).firstChild.childNodes.length != 1; })(document.createElement('div')); /* </ltIE9> */ var hasClassList = !!document.createElement('div').classList; var classes = function(className){ var classNames = (className || '').clean().split(" "), uniques = {}; return classNames.filter(function(className){ if (className !== "" && !uniques[className]) return uniques[className] = className; }); }; var addToClassList = function(name){ this.classList.add(name); }; var removeFromClassList = function(name){ this.classList.remove(name); }; Element.implement({ setProperty: function(name, value){ var setter = propertySetters[name.toLowerCase()]; if (setter){ setter(this, value); } else { /* <ltIE9> */ var attributeWhiteList; if (pollutesGetAttribute) attributeWhiteList = this.retrieve('$attributeWhiteList', {}); /* </ltIE9> */ if (value == null){ this.removeAttribute(name); /* <ltIE9> */ if (pollutesGetAttribute) delete attributeWhiteList[name]; /* </ltIE9> */ } else { this.setAttribute(name, '' + value); /* <ltIE9> */ if (pollutesGetAttribute) attributeWhiteList[name] = true; /* </ltIE9> */ } } return this; }, setProperties: function(attributes){ for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); return this; }, getProperty: function(name){ var getter = propertyGetters[name.toLowerCase()]; if (getter) return getter(this); /* <ltIE9> */ if (pollutesGetAttribute){ var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve('$attributeWhiteList', {}); if (!attr) return null; if (attr.expando && !attributeWhiteList[name]){ var outer = this.outerHTML; // segment by the opening tag and find mention of attribute name if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null; attributeWhiteList[name] = true; } } /* </ltIE9> */ var result = Slick.getAttribute(this, name); return (!result && !Slick.hasAttribute(this, name)) ? null : result; }, getProperties: function(){ var args = Array.from(arguments); return args.map(this.getProperty, this).associate(args); }, removeProperty: function(name){ return this.setProperty(name, null); }, removeProperties: function(){ Array.each(arguments, this.removeProperty, this); return this; }, set: function(prop, value){ var property = Element.Properties[prop]; (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); }.overloadSetter(), get: function(prop){ var property = Element.Properties[prop]; return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); }.overloadGetter(), erase: function(prop){ var property = Element.Properties[prop]; (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); return this; }, hasClass: hasClassList ? function(className){ return this.classList.contains(className); } : function(className){ return classes(this.className).contains(className); }, addClass: hasClassList ? function(className){ classes(className).forEach(addToClassList, this); return this; } : function(className){ this.className = classes(className + ' ' + this.className).join(' '); return this; }, removeClass: hasClassList ? function(className){ classes(className).forEach(removeFromClassList, this); return this; } : function(className){ var classNames = classes(this.className); classes(className).forEach(classNames.erase, classNames); this.className = classNames.join(' '); return this; }, toggleClass: function(className, force){ if (force == null) force = !this.hasClass(className); return (force) ? this.addClass(className) : this.removeClass(className); }, adopt: function(){ var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length; if (length > 1) parent = fragment = document.createDocumentFragment(); for (var i = 0; i < length; i++){ var element = document.id(elements[i], true); if (element) parent.appendChild(element); } if (fragment) this.appendChild(fragment); return this; }, appendText: function(text, where){ return this.grab(this.getDocument().newTextNode(text), where); }, grab: function(el, where){ inserters[where || 'bottom'](document.id(el, true), this); return this; }, inject: function(el, where){ inserters[where || 'bottom'](this, document.id(el, true)); return this; }, replaces: function(el){ el = document.id(el, true); el.parentNode.replaceChild(this, el); return this; }, wraps: function(el, where){ el = document.id(el, true); return this.replaces(el).grab(el, where); }, getSelected: function(){ this.selectedIndex; // Safari 3.2.1 return new Elements(Array.from(this.options).filter(function(option){ return option.selected; })); }, toQueryString: function(){ var queryString = []; this.getElements('input, select, textarea').each(function(el){ var type = el.type; if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return; var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){ // IE return document.id(opt).get('value'); }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value'); Array.from(value).each(function(val){ if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val)); }); }); return queryString.join('&'); } }); // appendHTML var appendInserters = { before: 'beforeBegin', after: 'afterEnd', bottom: 'beforeEnd', top: 'afterBegin', inside: 'beforeEnd' }; Element.implement('appendHTML', ('insertAdjacentHTML' in document.createElement('div')) ? function(html, where){ this.insertAdjacentHTML(appendInserters[where || 'bottom'], html); return this; } : function(html, where){ var temp = new Element('div', {html: html}), children = temp.childNodes, fragment = temp.firstChild; if (!fragment) return this; if (children.length > 1){ fragment = document.createDocumentFragment(); for (var i = 0, l = children.length; i < l; i++){ fragment.appendChild(children[i]); } } inserters[where || 'bottom'](fragment, this); return this; }); var collected = {}, storage = {}; var get = function(uid){ return (storage[uid] || (storage[uid] = {})); }; var clean = function(item){ var uid = item.uniqueNumber; if (item.removeEvents) item.removeEvents(); if (item.clearAttributes) item.clearAttributes(); if (uid != null){ delete collected[uid]; delete storage[uid]; } return item; }; var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; Element.implement({ destroy: function(){ var children = clean(this).getElementsByTagName('*'); Array.each(children, clean); Element.dispose(this); return null; }, empty: function(){ Array.from(this.childNodes).each(Element.dispose); return this; }, dispose: function(){ return (this.parentNode) ? this.parentNode.removeChild(this) : this; }, clone: function(contents, keepid){ contents = contents !== false; var clone = this.cloneNode(contents), ce = [clone], te = [this], i; if (contents){ ce.append(Array.from(clone.getElementsByTagName('*'))); te.append(Array.from(this.getElementsByTagName('*'))); } for (i = ce.length; i--;){ var node = ce[i], element = te[i]; if (!keepid) node.removeAttribute('id'); /*<ltIE9>*/ if (node.clearAttributes){ node.clearAttributes(); node.mergeAttributes(element); node.removeAttribute('uniqueNumber'); if (node.options){ var no = node.options, eo = element.options; for (var j = no.length; j--;) no[j].selected = eo[j].selected; } } /*</ltIE9>*/ var prop = formProps[element.tagName.toLowerCase()]; if (prop && element[prop]) node[prop] = element[prop]; } /*<ltIE9>*/ if (hasCloneBug){ var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; } /*</ltIE9>*/ return document.id(clone); } }); [Element, Window, Document].invoke('implement', { addListener: function(type, fn){ if (window.attachEvent && !window.addEventListener){ collected[Slick.uidOf(this)] = this; } if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]); else this.attachEvent('on' + type, fn); return this; }, removeListener: function(type, fn){ if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]); else this.detachEvent('on' + type, fn); return this; }, retrieve: function(property, dflt){ var storage = get(Slick.uidOf(this)), prop = storage[property]; if (dflt != null && prop == null) prop = storage[property] = dflt; return prop != null ? prop : null; }, store: function(property, value){ var storage = get(Slick.uidOf(this)); storage[property] = value; return this; }, eliminate: function(property){ var storage = get(Slick.uidOf(this)); delete storage[property]; return this; } }); /*<ltIE9>*/ if (window.attachEvent && !window.addEventListener){ var gc = function(){ Object.each(collected, clean); if (window.CollectGarbage) CollectGarbage(); window.removeListener('unload', gc); }; window.addListener('unload', gc); } /*</ltIE9>*/ Element.Properties = {}; //<1.2compat> Element.Properties = new Hash; //</1.2compat> Element.Properties.style = { set: function(style){ this.style.cssText = style; }, get: function(){ return this.style.cssText; }, erase: function(){ this.style.cssText = ''; } }; Element.Properties.tag = { get: function(){ return this.tagName.toLowerCase(); } }; Element.Properties.html = { set: function(html){ if (html == null) html = ''; else if (typeOf(html) == 'array') html = html.join(''); /*<ltIE9>*/ if (this.styleSheet && !canChangeStyleHTML) this.styleSheet.cssText = html; else /*</ltIE9>*/this.innerHTML = html; }, erase: function(){ this.set('html', ''); } }; var supportsHTML5Elements = true, supportsTableInnerHTML = true, supportsTRInnerHTML = true; /*<ltIE9>*/ // technique by jdbarlett - http://jdbartlett.com/innershiv/ var div = document.createElement('div'); div.innerHTML = '<nav></nav>'; supportsHTML5Elements = (div.childNodes.length == 1); if (!supportsHTML5Elements){ var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '), fragment = document.createDocumentFragment(), l = tags.length; while (l--) fragment.createElement(tags[l]); } div = null; /*</ltIE9>*/ /*<IE>*/ supportsTableInnerHTML = Function.attempt(function(){ var table = document.createElement('table'); table.innerHTML = '<tr><td></td></tr>'; return true; }); /*<ltFF4>*/ var tr = document.createElement('tr'), html = '<td></td>'; tr.innerHTML = html; supportsTRInnerHTML = (tr.innerHTML == html); tr = null; /*</ltFF4>*/ if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements){ Element.Properties.html.set = (function(set){ var translations = { table: [1, '<table>', '</table>'], select: [1, '<select>', '</select>'], tbody: [2, '<table><tbody>', '</tbody></table>'], tr: [3, '<table><tbody><tr>', '</tr></tbody></table>'] }; translations.thead = translations.tfoot = translations.tbody; return function(html){ /*<ltIE9>*/ if (this.styleSheet) return set.call(this, html); /*</ltIE9>*/ var wrap = translations[this.get('tag')]; if (!wrap && !supportsHTML5Elements) wrap = [0, '', '']; if (!wrap) return set.call(this, html); var level = wrap[0], wrapper = document.createElement('div'), target = wrapper; if (!supportsHTML5Elements) fragment.appendChild(wrapper); wrapper.innerHTML = [wrap[1], html, wrap[2]].flatten().join(''); while (level--) target = target.firstChild; this.empty().adopt(target.childNodes); if (!supportsHTML5Elements) fragment.removeChild(wrapper); wrapper = null; }; })(Element.Properties.html.set); } /*</IE>*/ /*<ltIE9>*/ var testForm = document.createElement('form'); testForm.innerHTML = '<select><option>s</option></select>'; if (testForm.firstChild.value != 's') Element.Properties.value = { set: function(value){ var tag = this.get('tag'); if (tag != 'select') return this.setProperty('value', value); var options = this.getElements('option'); value = String(value); for (var i = 0; i < options.length; i++){ var option = options[i], attr = option.getAttributeNode('value'), optionValue = (attr && attr.specified) ? option.value : option.get('text'); if (optionValue === value) return option.selected = true; } }, get: function(){ var option = this, tag = option.get('tag'); if (tag != 'select' && tag != 'option') return this.getProperty('value'); if (tag == 'select' && !(option = option.getSelected()[0])) return ''; var attr = option.getAttributeNode('value'); return (attr && attr.specified) ? option.value : option.get('text'); } }; testForm = null; /*</ltIE9>*/ /*<IE>*/ if (document.createElement('div').getAttributeNode('id')) Element.Properties.id = { set: function(id){ this.id = this.getAttributeNode('id').value = id; }, get: function(){ return this.id || null; }, erase: function(){ this.id = this.getAttributeNode('id').value = ''; } }; /*</IE>*/ })();