From 1e11b8b531d4d6429b1258079a612530ea499244 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 11 Nov 2009 03:05:33 -0600 Subject: [PATCH] fusejs: Fix a lot of errors related to the DOM unit tests. [jddalton] --- src/dom/dom.js | 2 +- src/dom/element/element.js | 207 +++++++++++++++++++---------------- src/dom/element/position.js | 10 +- src/dom/element/style.js | 2 +- src/dom/element/traversal.js | 5 +- src/dom/features.js | 2 +- src/dom/form/field.js | 25 +++-- src/dom/form/form.js | 7 +- src/dom/node.js | 12 +- src/lang/array.js | 2 +- src/lang/class.js | 22 ++-- 11 files changed, 162 insertions(+), 134 deletions(-) diff --git a/src/dom/dom.js b/src/dom/dom.js index 60899c0..eb21c1e 100644 --- a/src/dom/dom.js +++ b/src/dom/dom.js @@ -4,7 +4,7 @@ Fuse.addNS('Dom.Data'); Data['1'] = { }; - Data['2'] = { }; + Data['2'] = { 'nodes': { } }; Fuse._doc = global.document; Fuse._div = Fuse._doc.createElement('DiV'); diff --git a/src/dom/element/element.js b/src/dom/element/element.js index 2603fec..52f1aba 100644 --- a/src/dom/element/element.js +++ b/src/dom/element/element.js @@ -54,38 +54,45 @@ return T; })(), - TAG_NAME_CLASSES = { - 'A': 'Anchor', - 'CAPTION': 'TableCaption', - 'COL': 'TableCol', - 'COLGROUP': 'TableCol', - 'DEL': 'Mod', - 'DIR': 'Directory', - 'DL': 'DList', - 'H1': 'Heading', - 'H2': 'Heading', - 'H3': 'Heading', - 'H4': 'Heading', - 'H5': 'Heading', - 'H6': 'Heading', - 'IFRAME': 'IFrame', - 'IMG': 'Image', - 'INS': 'Mod', - 'FIELDSET': 'FieldSet', - 'FRAMESET': 'FrameSet', - 'OL': 'OList', - 'OPTGROUP': 'OptGroup', - 'P': 'Paragraph', - 'Q': 'Quote', - 'TBODY': 'TableSection', - 'TD': 'TableCell', - 'TEXTAREA': 'TextArea', - 'TH': 'TableCell', - 'TFOOT': 'TableSection', - 'THEAD': 'TableSection', - 'TR': 'TableRow', - 'UL': 'UList' - }, + TAG_NAME_CLASSES = (function() { + var T = { + 'A': 'AnchorElement', + 'CAPTION': 'TableCaptionElement', + 'COL': 'TableColElement', + 'DEL': 'ModElement', + 'DIR': 'DirectoryElement', + 'DL': 'DListElement', + 'H1': 'HeadingElement', + 'IFRAME': 'IFrameElement', + 'IMG': 'ImageElement', + 'INS': 'ModElement', + 'FIELDSET': 'FieldSetElement', + 'FRAMESET': 'FrameSetElement', + 'OL': 'OListElement', + 'OPTGROUP': 'OptGroupElement', + 'P': 'ParagraphElement', + 'Q': 'QuoteElement', + 'TBODY': 'TableSectionElement', + 'TD': 'TableCellElement', + 'TEXTAREA': 'TextAreaElement', + 'TR': 'TableRowElement', + 'UL': 'UListElement' + }; + + T['H2'] = + T['H3'] = + T['H4'] = + T['H5'] = + T['H6'] = T['H1']; + + T['TFOOT'] = + T['THEAD'] = T['TBODY']; + + T['TH'] = T['TD']; + T['COLGROUP'] = T['COL']; + + return T; + })(), doc = Fuse._doc, @@ -97,8 +104,6 @@ matchTagName= /^<([^> ]+)/, - Decorator = function() { }, - Dom = Fuse.Dom; @@ -113,43 +118,48 @@ // http://dev.rubyonrails.org/ticket/10548 function create(tagName, attributes, context) { - var complexTag, data, element, fragment, id, html, length, nodes, result; + var complexTag, data, element, fragment, id, length, + result = null; // caching html strings is not supported at the moment if (tagName.charAt(0) == '<') { - // support
format tags context = attributes; - complexTag = tagName.match(matchComplexTag); - if (!complexTag) { - html = tagName; - fragment = Dom.getFragmentFromString(html, context); - length = fragment.childNodes.length; + // support `
x
` format tags + if (!(complexTag = tagName.match(matchComplexTag))) { + fragment = Dom.getFragmentFromString(tagName, context); + length = fragment.childNodes.length; - // single element return decorated element - if (length < 2) - result = fromElement(fragment.removeChild(fragment.firstChild)); // multiple elements return a NodeList - else { + if (length > 1) { result = NodeList(); - while (length--) - result[length] = fromElement(fragment.removeChild(fragment.lastChild)); + while (length--) { + element = fragment.removeChild(fragment.lastChild); + Decorator.prototype = getOrCreateTagClass(element.nodeName).plugin; + result[length] = new Decorator(element); + } + // single element return decorated element + } else { + element = fragment.removeChild(fragment.firstChild); + Decorator.prototype = getOrCreateTagClass(element.nodeName).plugin; + result = new Decorator(element); } return result; } - else tagName = complexTag[1]; + + // support `
` format tags + tagName = complexTag[1]; } - context = context || doc; - id = context === doc ? '1' : getFuseId(getWindow(context).frameElement); - data = Data[id]; - nodes = data.nodes || (data.nodes = { }); - element = nodes[tagName]; + context || (context = doc); + id = context === doc ? '2' : getFuseId(getWindow(context).frameElement); + data = Data[id].nodes; + element = data[tagName] || (data[tagName] = context.createElement(tagName)); - if (!element) - element = nodes[tagName] = context.createElement(tagName); + // avoid adding the new element to the data cache + Decorator.prototype = getOrCreateTagClass(element.nodeName).plugin; + element = new Decorator(element.cloneNode(false)); - element = fromElement(element.cloneNode(false)); return attributes ? element.writeAttribute(attributes) : element; @@ -165,38 +175,44 @@ .extend(statics, plugins, mixins); } + function Decorator(element) { + this.raw = element; + this.style = element.style; + this.tagName = element.tagName; + this.nodeName = element.nodeName; + this.nodeType = ELEMENT_NODE; + this.childNodes = element.childNodes; + this.initialize && this.initialize(); + } + function fromElement(element) { // return if already a decorator if (element.raw) return element; - var decorated, tagClass, - id = getFuseId(element), - data = Data[id]; - // return cached if available + var id = getFuseId(element), data = Data[id]; if (data.decorator) return data.decorator; - Decorator.prototype = - getOrCreateTagClass(element.nodeName).plugin; - - data.decorator = - decorated = new Decorator; - - data.node = - decorated.raw = element; - decorated.style = element.style; - decorated.tagName = element.tagName; - decorated.nodeName = element.nodeName; - - return decorated; + data.node = element; + Decorator.prototype = getOrCreateTagClass(element.nodeName).plugin; + return (data.decorator = new Decorator(element)); } function getOrCreateTagClass(tagName) { - var tagClassName = (TAG_NAME_CLASSES[tagName.toUpperCase()] || - capitalize.call(tagName)) + 'Element', - tagClass = Dom[tagClassName]; + var upperCased, tagClass, tagClassName = TAG_NAME_CLASSES[tagName]; + + if (!tagClassName) { + upperCased = tagName.toUpperCase(); + tagClassName = TAG_NAME_CLASSES[upperCased]; - if (!tagClass) { + if (!tagClassName) { + TAG_NAME_CLASSES[upperCased] = + tagClassName = capitalize.call(tagName) + 'Element'; + } + TAG_NAME_CLASSES[tagName] = tagClassName; + } + + if (!(tagClass = Dom[tagClassName])) { (tagClass = Dom[tagClassName] = Class(Element, { 'constructor': function(element) { @@ -235,10 +251,10 @@ // 2) WebKit and KHTML throw when creating contextual fragments from // orphaned elements. try { - context = context || Fuse._body || Fuse._docEl; + context = context || Fuse._doc; var cache = getFragmentCache(context.ownerDocument || context), range = cache.range; - range.selectNode(context.firstChild); + range.selectNode(context.body || context.firstChild); return range.createContextualFragment(html); } catch (e) { return getFromDocumentFragment(html, context, cache); @@ -246,11 +262,11 @@ } function getFromDocumentFragment(html, context, cache) { - context = context || Fuse._body || Fuse._docEl; + context = context || Fuse._doc; cache = cache || getFragmentCache(context.ownerDocument || context); var node = cache.node, nodeName = context.nodeType === DOCUMENT_NODE - ? FROM_STRING_CHILDRENS_PARENT_KEYS[tagName.match(matchTagName)[1].toUpperCase()] + ? FROM_STRING_CHILDRENS_PARENT_KEYS[html.match(matchTagName)[1].toUpperCase()] : getNodeName(context), wrapping = FROM_STRING_PARENT_WRAPPERS[nodeName]; @@ -368,8 +384,8 @@ setScriptText = (function() { function setScriptText(element, text) { - element.removeChild(element.firstChild); - element.appendChild(textNode.cloneNode(false)).data = text; + (element.firstChild || element.appendChild(textNode.cloneNode(false))) + .data = text || ''; } if (Feature('ELEMENT_SCRIPT_HAS_TEXT_PROPERTY')) @@ -460,7 +476,8 @@ insertions = insertions._object; content = insertions.raw || insertions; - if (isString(content) || INSERTABLE_NODE_TYPES[content.nodeType] || + if (isString(content) || isNumber(content) || + INSERTABLE_NODE_TYPES[content.nodeType] || content.toElement || content.toHTML) insertions = { 'bottom': content }; } @@ -473,7 +490,7 @@ if (content && content != '') { if (content.toElement) content = content.toElement(); if (INSERTABLE_NODE_TYPES[content.nodeType]) { - insertContent(element, content); + insertContent(element, content.raw || content); continue; } content = Obj.toHTML(content); @@ -501,6 +518,8 @@ if (content.toElement) content = content.toElement(); else if (INSERTABLE_NODE_TYPES[content.nodeType]) { + content = content.raw || content; + } else { html = Obj.toHTML(content); stripped = html.stripScripts(); content = stripped == '' ? '' : @@ -529,7 +548,7 @@ content = content.toElement(); if (INSERTABLE_NODE_TYPES[content.nodeType]) { element.innerHTML = ''; - element.appendChild(content); + element.appendChild(content.raw || content); } else { content = Obj.toHTML(content); @@ -563,8 +582,10 @@ } else element.innerHTML = ''; if (content && content != '') { - if (content.toElement) content = content.toElement(); - if (INSERTABLE_NODE_TYPES[content.nodeType]) element.appendChild(content); + if (content.toElement) + content = content.toElement(); + if (INSERTABLE_NODE_TYPES[content.nodeType]) + element.appendChild(content.raw || content); else { content = Obj.toHTML(content); stripped = content.stripScripts(); @@ -708,18 +729,18 @@ }; plugin.wrap = function wrap(wrapper, attributes) { - var element = this.raw || this; + var rawWrapper, element = this.raw || this; if (isString(wrapper)) wrapper = Element.create(wrapper, attributes); - if (isElement(wrapper = wrapper.raw || Fuse.get(wrapper))) + if (isElement(wrapper) && (wrapper = Fuse.get(wrapper))) wrapper.writeAttribute(attributes); else wrapper = Element.create('div', wrapper); - wrapper = wrapper.raw; + rawWrapper = wrapper.raw; if (element.parentNode) - element.parentNode.replaceChild(wrapper, element); - wrapper.appendChild(element); + element.parentNode.replaceChild(rawWrapper, element); + rawWrapper.appendChild(element); return wrapper; }; diff --git a/src/dom/element/position.js b/src/dom/element/position.js index e32d18b..1e5b5f5 100644 --- a/src/dom/element/position.js +++ b/src/dom/element/position.js @@ -177,7 +177,7 @@ elemDisplay, elemOffset, elemPos, elemVis, srcBackup, appendCSS = ';display:block;visibility:hidden;', cumulativeOffset = plugin.cumulativeOffset, - elemStyle = element.style, + elemStyle = this.style, srcStyle = source.style, elemIsHidden = !isVisible.call(this), srcIsHidden = !isVisible.call(source); @@ -302,16 +302,16 @@ if (!plugin.isVisible.call(this)) { elemStyle = element.style; backup = elemStyle.cssText; - s.cssText += ';display:block;visibility:hidden;'; + elemStyle.cssText += ';display:block;visibility:hidden;'; result = getOffset(element, ancestor); - s.cssText = backup; + elemStyle.cssText = backup; } else result = getOffset(element, ancestor); return result; } - var getOffset = function(ancestor) { + var getOffset = function(element, ancestor) { var offsetParent, position, valueT, valueL; if (BODY_OFFSETS_INHERIT_ITS_MARGINS === null) BODY_OFFSETS_INHERIT_ITS_MARGINS = Bug('BODY_OFFSETS_INHERIT_ITS_MARGINS'); @@ -349,7 +349,7 @@ if (ancestor) return __getOffset(element, ancestor); - if (!isDetached.call(this)) { + if (!isDetached.call(element)) { doc = getDocument(element); info = Fuse._info; rect = element.getBoundingClientRect(); diff --git a/src/dom/element/style.js b/src/dom/element/style.js index 94c1806..464ca8e 100644 --- a/src/dom/element/style.js +++ b/src/dom/element/style.js @@ -78,7 +78,7 @@ if (hasOpacity) { opacity = styles.opacity; - plugin.setOpacity.call(opacity); + plugin.setOpacity.call(this, opacity); delete styles.opacity; } diff --git a/src/dom/element/traversal.js b/src/dom/element/traversal.js index 64e3628..434727e 100644 --- a/src/dom/element/traversal.js +++ b/src/dom/element/traversal.js @@ -202,7 +202,8 @@ if (firstNode === firstElement) firstDescendant = function firstDescendant() { - return fromElement((this.raw || this).firstElementChild); + var element = (this.raw || this).firstElementChild; + return element && fromElement(element); }; return firstDescendant; @@ -260,7 +261,7 @@ (function() { function collect(decorator, property, selectors) { var match, element = decorator.raw || decorator, - i = 0, results = []; + i = 0, results = NodeList(); if (element = element[property]) { if (selectors && selectors.length) { diff --git a/src/dom/features.js b/src/dom/features.js index 762816a..3c43361 100644 --- a/src/dom/features.js +++ b/src/dom/features.js @@ -339,7 +339,7 @@ script = doc.createElement('SCRIPT'); try { - script.appendChild(doc.createTextNode(code)); + script.appendChild(doc.createTextNode('').cloneNode(false)).data = code; } catch (e) { hasText = 'text' in script; } diff --git a/src/dom/form/field.js b/src/dom/form/field.js index 910ffca..a1a4274 100644 --- a/src/dom/form/field.js +++ b/src/dom/form/field.js @@ -141,6 +141,10 @@ return this; }; + selectPlugin.initialize = function initialize() { + this.options = this.raw.options; + }; + selectPlugin.getValue = function getValue() { var i, node, element = this.raw || this, result = null; if (element.type === 'select-one') { @@ -187,14 +191,15 @@ optionPlugin.getValue = getOptionValue; // prevent JScript bug with named function expressions - var activate = nil, - clear = nil, - disable = nil, - enable = nil, - focus = nil, - getValue = nil, - present = nil, - select = nil, - setValue = nil, - serialize = nil; + var initialize = nil, + activate = nil, + clear = nil, + disable = nil, + enable = nil, + focus = nil, + getValue = nil, + present = nil, + select = nil, + setValue = nil, + serialize = nil; })(Fuse.Dom); diff --git a/src/dom/form/form.js b/src/dom/form/form.js index bd1cef0..7522c60 100644 --- a/src/dom/form/form.js +++ b/src/dom/form/form.js @@ -38,6 +38,10 @@ } } + plugin.initialize = function initialize() { + this.options = this.raw.options; + }; + plugin.disable = function disable() { eachElement(this, function(node) { node.disabled = true; }); return this; @@ -221,7 +225,8 @@ }; // prevent JScript bug with named function expressions - var disable = nil, + var initialize = nil, + disable = nil, enable = nil, findFirstElement = nil, focusFirstElement = nil, diff --git a/src/dom/node.js b/src/dom/node.js index 4d76008..7b6d2df 100644 --- a/src/dom/node.js +++ b/src/dom/node.js @@ -55,12 +55,15 @@ node = this.raw || this, win = getWindow(node); - if (node == win) { + if (node.getFuseId) { + return node.getFuseId(); + } + else if (node == win) { if (retWindowId) { id = '1'; if (node != global) { id = getFuseId(win.frameElement) + '-1'; - Data[id] = Data[id] || { }; + Data[id] || (Data[id] = { }); } } return id; @@ -68,12 +71,9 @@ else if (node.nodeType === DOCUMENT_NODE) { if (node === Fuse._doc) return '2'; id = getFuseId(win.frameElement) + '-2'; - Data[id] = Data[id] || { }; + Data[id] || (Data[id] = { 'nodes': { } }); return id; } - else if (node.getFuseId) - return node.getFuseId(); - return (node.getFuseId = createIdGetter())(); } diff --git a/src/lang/array.js b/src/lang/array.js index c91d541..3482751 100644 --- a/src/lang/array.js +++ b/src/lang/array.js @@ -237,7 +237,7 @@ plugin.invoke = function invoke(method) { if (this == null) throw new TypeError; - var args, i = 0, results = List(), object = Object(this), + var args, i = 0, results = Fuse.Array(), object = Object(this), length = object.length >>> 0, funcProto = Function.prototype; if (arguments.length < 2) { diff --git a/src/lang/class.js b/src/lang/class.js index 5f9380d..f4d2521 100644 --- a/src/lang/class.js +++ b/src/lang/class.js @@ -76,21 +76,18 @@ Class.Methods = { }; - (function(methods) { - methods.extend = function extend() { + (function() { + function extend(statics, plugins, mixins) { var i, otherMethod, - args = arguments, - argLength = args.length, - Klass = this, prototype = Klass.prototype, superProto = Klass.superclass && Klass.superclass.prototype, subclasses = Klass.subclasses, - subLength = subclasses.length, + subLength = subclasses.length; - statics = argLength > 1 ? args[0] : null, - plugins = argLength < 3 ? args[argLength - 1] : args[1], - mixins = argLength > 2 ? args[2] : null; + if (!plugins && !mixins) { + plugins = statics; statics = null; + } if (statics) eachKey(statics, function(method, key) { Klass[key] = method; }); @@ -122,11 +119,10 @@ }); return Klass; - }; + } - // prevent JScript bug with named function expressions - var extend = nil; - })(Class.Methods); + Class.Methods.extend = extend; + })(); /*--------------------------------------------------------------------------*/