Merge -r6634:HEAD from ../branches/dom.

* Make Element#update and Element#insert work for SELECT tags in IE and Opera. [Tobie Langel]

* Make Element#insert and Element#update better handle TABLE related elements in IE and Opera. Closes #7776, #8040, #7550, #7776, #7938. [Tobie Langel]

* Make Element#readAttribute('title') work in Opera. [Tobie Langel]

* Make Element#replace work with form elements in Firefox and Safari. Closes #8010, #7989. [dsl239, Tobie Langel]

* Add Element#wrap which wraps the element inside a new one. Closes #5732. [P. Vande, Tobie Langel]

* Make Element into a constructor: new Element(tagName, attributes). Add Element#writeAttribute which accepts a hash of attributes or a name/value pair. Closes #7476. [Mislav Marohnić, haraldmartin, Tobie Langel]

* Insertion overhaul: Add Element.insert(content[, position = 'Bottom']). Deprecate Insertion (kept for backwards compatibility). Make Ajax.Updater option.insertion accept both Insertion.Top or the now preferred 'Top'. Closes #7907. [Tobie Langel]
This commit is contained in:
Sam Stephenson 2007-05-12 05:01:56 +00:00
parent 67a4d00588
commit 83b4b337e1
11 changed files with 883 additions and 445 deletions

View File

@ -1,5 +1,19 @@
*SVN*
* Make Element#update and Element#insert work for SELECT tags in IE and Opera. [Tobie Langel]
* Make Element#insert and Element#update better handle TABLE related elements in IE and Opera. Closes #7776, #8040, #7550, #7776, #7938. [Tobie Langel]
* Make Element#readAttribute('title') work in Opera. [Tobie Langel]
* Make Element#replace work with form elements in Firefox and Safari. Closes #8010, #7989. [dsl239, Tobie Langel]
* Add Element#wrap which wraps the element inside a new one. Closes #5732. [P. Vande, Tobie Langel]
* Make Element into a constructor: new Element(tagName, attributes). Add Element#writeAttribute which accepts a hash of attributes or a name/value pair. Closes #7476. [Mislav Marohnić, haraldmartin, Tobie Langel]
* Insertion overhaul: Add Element.insert(content[, position = 'Bottom']). Deprecate Insertion (kept for backwards compatibility). Make Ajax.Updater option.insertion accept both Insertion.Top or the now preferred 'Top'. Closes #7907. [Tobie Langel]
* Refactor Element.extend and eliminate Element.extend.cache. [sam]
* Add Function#curry, Function#delay, Function#defer, and Function#wrap. Closes #8134. [Andrew Dupont, Tobie Langel, sam]

View File

@ -254,15 +254,17 @@ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
updateContent: function() {
var receiver = this.container[this.success() ? 'success' : 'failure'];
var response = this.transport.responseText;
var response = this.transport.responseText, options = this.options;
if (!this.options.evalScripts) response = response.stripScripts();
if (!options.evalScripts) response = response.stripScripts();
if (receiver = $(receiver)) {
if (this.options.insertion)
new this.options.insertion(receiver, response);
else
receiver.update(response);
if (options.insertion) {
if (typeof options.insertion == 'string')
receiver.insert(response, options.insertion);
else options.insertion(receiver, response);
}
else receiver.update(response);
}
if (this.success()) {

113
src/deprecated.js Normal file
View File

@ -0,0 +1,113 @@
/*------------------------------- DEPRECATED -------------------------------*/
var Toggle = { display: Element.toggle };
Element.Methods.childOf = Element.Methods.descendantOf;
var Insertion = {
Before: function(element, content) {
return Element.insert(element, content, 'before');
},
Top: function(element, content) {
return Element.insert(element, content, 'top');
},
Bottom: function(element, content) {
return Element.insert(element, content, 'bottom');
},
After: function(element, content) {
return Element.insert(element, content, 'after');
}
}
var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
// This should be moved to script.aculo.us; notice the deprecated methods
// further below, that map to the newer Element methods.
var Position = {
// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
// scrollable elements
includeScrollOffsets: false,
// must be called before calling withinIncludingScrolloffset, every time the
// page is scrolled
prepare: function() {
this.deltaX = window.pageXOffset
|| document.documentElement.scrollLeft
|| document.body.scrollLeft
|| 0;
this.deltaY = window.pageYOffset
|| document.documentElement.scrollTop
|| document.body.scrollTop
|| 0;
},
// caches x/y coordinate pair to use with overlap
within: function(element, x, y) {
if (this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element, x, y);
this.xcomp = x;
this.ycomp = y;
this.offset = Element.cumulativeOffset(element);
return (y >= this.offset[1] &&
y < this.offset[1] + element.offsetHeight &&
x >= this.offset[0] &&
x < this.offset[0] + element.offsetWidth);
},
withinIncludingScrolloffsets: function(element, x, y) {
var offsetcache = Element.cumulativeScrollOffset(element);
this.xcomp = x + offsetcache[0] - this.deltaX;
this.ycomp = y + offsetcache[1] - this.deltaY;
this.offset = Element.cumulativeOffset(element);
return (this.ycomp >= this.offset[1] &&
this.ycomp < this.offset[1] + element.offsetHeight &&
this.xcomp >= this.offset[0] &&
this.xcomp < this.offset[0] + element.offsetWidth);
},
// within must be called directly before
overlap: function(mode, element) {
if (!mode) return 0;
if (mode == 'vertical')
return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
element.offsetHeight;
if (mode == 'horizontal')
return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
element.offsetWidth;
},
// Deprecation layer -- use newer Element methods now (1.5.2).
cumulativeOffset: Element.Methods.cumulativeOffset,
positionedOffset: Element.Methods.positionedOffset,
absolutize: function(element) {
Position.prepare();
return Element.absolutize(element);
},
relativize: function(element) {
Position.prepare();
return Element.relativize(element);
},
realOffset: Element.Methods.cumulativeScrollOffset,
offsetParent: Element.Methods.getOffsetParent,
page: Element.Methods.viewportOffset,
clone: function(source, target, options) {
options = options || {};
return Element.clonePosition(target, source, options);
}
}
/*--------------------------------------------------------------------------*/

View File

@ -37,7 +37,24 @@ if (Prototype.BrowserFeatures.XPath) {
/*--------------------------------------------------------------------------*/
if (!window.Element) var Element = {};
(function() {
var element = this.Element;
this.Element = function(tagName, attributes) {
attributes = attributes || {};
tagName = tagName.toLowerCase();
var cache = Element.cache;
if (Prototype.Browser.IE && attributes.name) {
tagName = '<' + tagName + ' name="' + attributes.name + '">';
delete attributes.name;
return Element.writeAttribute(document.createElement(tagName), attributes);
}
if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
};
Object.extend(this.Element, element || {});
}).call(window);
Element.cache = {};
Element.Methods = {
visible: function(element) {
@ -80,7 +97,7 @@ Element.Methods = {
element.outerHTML = html.stripScripts();
} else {
var range = element.ownerDocument.createRange();
range.selectNodeContents(element);
range.selectNode(element);
element.parentNode.replaceChild(
range.createContextualFragment(html.stripScripts()), element);
}
@ -88,6 +105,36 @@ Element.Methods = {
return element;
},
insert: function(element, content, position) {
element = $(element);
position = (position || 'bottom').toLowerCase();
var t = Element._insertionTranslations[position], range;
if (content && content.ownerDocument === document) {
t.insert(element, content);
return element;
}
content = content.toString();
range = element.ownerDocument.createRange();
t.initializeRange(element, range);
t.insert(element, range.createContextualFragment(content.stripScripts()));
content.evalScripts.bind(content).defer();
return element;
},
wrap: function(element, wrapper) {
element = $(element);
wrapper = wrapper || 'div';
if (typeof wrapper == 'string') wrapper = new Element(wrapper);
else Element.extend(wrapper);
element.parentNode.replaceChild(wrapper, element);
wrapper.appendChild(element);
return element;
},
inspect: function(element) {
element = $(element);
var result = '<' + element.tagName.toLowerCase();
@ -193,7 +240,7 @@ Element.Methods = {
element = $(element);
if (Prototype.Browser.IE) {
if (!element.attributes) return null;
var t = Element._attributeTranslations;
var t = Element._attributeTranslations.read;
if (t.values[name]) return t.values[name](element, name);
if (t.names[name]) name = t.names[name];
var attribute = element.attributes[name];
@ -202,6 +249,25 @@ Element.Methods = {
return element.getAttribute(name);
},
writeAttribute: function(element, name, value) {
element = $(element);
var attributes = {}, t = Element._attributeTranslations.write;
if (typeof name == 'object') attributes = name;
else attributes[name] = value === undefined ? true : value;
for (var attr in attributes) {
var name = t.names[attr] || attr, value = attributes[attr];
if (t.values[attr]) name = t.values[attr](element, value);
if (value === false || value === null)
element.removeAttribute(name);
else if (value === true)
element.setAttribute(name, name);
else element.setAttribute(name, value);
}
return element;
},
getHeight: function(element) {
return $(element).getDimensions().height;
},
@ -387,14 +453,201 @@ Element.Methods = {
element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
element._overflow = null;
return element;
}
},
cumulativeOffset: function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
} while (element);
return Element._returnOffset(valueL, valueT);
},
positionedOffset: function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
if (element) {
if (element.tagName == 'BODY') break;
var p = Element.getStyle(element, 'position');
if (p == 'relative' || p == 'absolute') break;
}
} while (element);
return Element._returnOffset(valueL, valueT);
},
absolutize: function(element) {
element = $(element);
if (element.style.position == 'absolute') return;
// Position.prepare(); // To be done manually by Scripty when it needs it.
var offsets = element.positionedOffset();
var top = offsets[1];
var left = offsets[0];
var width = element.clientWidth;
var height = element.clientHeight;
element._originalLeft = left - parseFloat(element.style.left || 0);
element._originalTop = top - parseFloat(element.style.top || 0);
element._originalWidth = element.style.width;
element._originalHeight = element.style.height;
element.style.position = 'absolute';
element.style.top = top + 'px';
element.style.left = left + 'px';
element.style.width = width + 'px';
element.style.height = height + 'px';
return element;
},
relativize: function(element) {
element = $(element);
if (element.style.position == 'relative') return;
// Position.prepare(); // To be done manually by Scripty when it needs it.
element.style.position = 'relative';
var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
element.style.top = top + 'px';
element.style.left = left + 'px';
element.style.height = element._originalHeight;
element.style.width = element._originalWidth;
return element;
},
cumulativeScrollOffset: function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.scrollTop || 0;
valueL += element.scrollLeft || 0;
element = element.parentNode;
} while (element);
return Element._returnOffset(valueL, valueT);
},
getOffsetParent: function(element) {
if (element.offsetParent) return $(element.offsetParent);
if (element == document.body) return $(element);
while ((element = element.parentNode) && element != document.body)
if (Element.getStyle(element, 'position') != 'static')
return $(element);
return $(document.body);
},
viewportOffset: function(forElement) {
var valueT = 0, valueL = 0;
var element = forElement;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
// Safari fix
if (element.offsetParent == document.body)
if (Element.getStyle(element,'position')=='absolute') break;
} while (element = element.offsetParent);
element = forElement;
do {
if (!window.opera || element.tagName=='BODY') {
valueT -= element.scrollTop || 0;
valueL -= element.scrollLeft || 0;
}
} while (element = element.parentNode);
return Element._returnOffset(valueL, valueT);
},
clonePosition: function(element, source) {
var options = Object.extend({
setLeft: true,
setTop: true,
setWidth: true,
setHeight: true,
offsetTop: 0,
offsetLeft: 0
}, arguments[2] || {})
// find page position of source
source = $(source);
var p = source.viewportOffset();
// find coordinate system to use
element = $(element);
var delta = [0, 0];
var parent = null;
// delta [0,0] will do fine with position: fixed elements,
// position:absolute needs offsetParent deltas
if (Element.getStyle(element,'position') == 'absolute') {
parent = element.getOffsetParent();
delta = parent.getViewportOffset();
}
// correct by body offsets (fixes Safari)
if (parent == document.body) {
delta[0] -= document.body.offsetLeft;
delta[1] -= document.body.offsetTop;
}
// set position
if(options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
if(options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
if(options.setWidth) element.style.width = source.offsetWidth + 'px';
if(options.setHeight) element.style.height = source.offsetHeight + 'px';
return element;
}
};
Object.extend(Element.Methods, {
childOf: Element.Methods.descendantOf,
childElements: Element.Methods.immediateDescendants
});
Element._attributeTranslations = {
write: {
names: {
className: 'class',
htmlFor: 'for'
},
values: {}
}
};
if (!document.createRange || Prototype.Browser.Opera) {
Element.Methods.insert = function(element, content, position) {
element = $(element);
position = (position || 'bottom').toLowerCase();
var t = Element._insertionTranslations, pos = t[position], tagName;
if (content && content.ownerDocument === document) {
pos.insert(element, content);
return element;
}
content = content.toString();
tagName = ((position == 'before' || position == 'after')
? element.parentNode : element).tagName.toUpperCase();
if (t.tags[tagName]) {
var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
if (position == 'top' || position == 'after') fragments.reverse();
fragments.each(pos.insert.curry(element));
}
else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());
content.evalScripts.bind(content).defer();
return element;
}
}
if (Prototype.Browser.Opera) {
Element.Methods._getStyle = Element.Methods.getStyle;
Element.Methods.getStyle = function(element, style) {
@ -406,8 +659,14 @@ if (Prototype.Browser.Opera) {
if (Element._getStyle(element, 'position') == 'static') return null;
default: return Element._getStyle(element, style);
}
};
};
Element.Methods._readAttribute = Element.Methods.readAttribute;
Element.Methods.readAttribute = function(element, attribute) {
if (attribute == 'title') return element.title;
return Element._readAttribute(element, attribute);
};
}
else if (Prototype.Browser.IE) {
Element.Methods.getStyle = function(element, style) {
element = $(element);
@ -423,7 +682,7 @@ else if (Prototype.Browser.IE) {
if (value == 'auto') {
if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
return element['offset'+style.capitalize()] + 'px';
return element['offset' + style.capitalize()] + 'px';
return null;
}
return value;
@ -441,37 +700,67 @@ else if (Prototype.Browser.IE) {
return element;
};
// IE is missing .innerHTML support for TABLE-related elements
Element.Methods.update = function(element, html) {
element = $(element);
html = typeof html == 'undefined' ? '' : html.toString();
var tagName = element.tagName.toUpperCase();
if (['THEAD','TBODY','TR','TD'].include(tagName)) {
var div = document.createElement('div');
switch (tagName) {
case 'THEAD':
case 'TBODY':
div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>';
depth = 2;
break;
case 'TR':
div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>';
depth = 3;
break;
case 'TD':
div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>';
depth = 4;
Element._attributeTranslations = {
read: {
names: {
colspan: "colSpan",
rowspan: "rowSpan",
valign: "vAlign",
datetime: "dateTime",
accesskey: "accessKey",
tabindex: "tabIndex",
enctype: "encType",
maxlength: "maxLength",
readonly: "readOnly",
longdesc: "longDesc"
},
values: {
_getAttr: function(element, attribute) {
return element.getAttribute(attribute, 2);
},
_flag: function(element, attribute) {
return $(element).hasAttribute(attribute) ? attribute : null;
},
style: function(element) {
return element.style.cssText.toLowerCase();
},
title: function(element) {
var node = element.getAttributeNode('title');
return node.specified ? node.nodeValue : null;
}
}
$A(element.childNodes).each(function(node) { element.removeChild(node) });
depth.times(function() { div = div.firstChild });
$A(div.childNodes).each(function(node) { element.appendChild(node) });
} else {
element.innerHTML = html.stripScripts();
}
html.evalScripts.bind(html).defer();
return element;
}
};
Element._attributeTranslations.write = {
names: Object.extend({
'class': 'className',
'for': 'htmlFor'
}, Element._attributeTranslations.read.names),
values: {
checked: function(element, value) {
element.checked = !!value;
},
style: function(element, value) {
element.style.cssText = value ? value : '';
}
}
};
(function() {
Object.extend(this, {
href: this._getAttr,
src: this._getAttr,
type: this._getAttr,
disabled: this._flag,
checked: this._flag,
readonly: this._flag,
multiple: this._flag
});
}).call(Element._attributeTranslations.read.values);
}
else if (Prototype.Browser.Gecko) {
Element.Methods.setOpacity = function(element, value) {
element = $(element);
@ -481,51 +770,114 @@ else if (Prototype.Browser.Gecko) {
};
}
Element._attributeTranslations = {
names: {
colspan: "colSpan",
rowspan: "rowSpan",
valign: "vAlign",
datetime: "dateTime",
accesskey: "accessKey",
tabindex: "tabIndex",
enctype: "encType",
maxlength: "maxLength",
readonly: "readOnly",
longdesc: "longDesc"
},
values: {
_getAttr: function(element, attribute) {
return element.getAttribute(attribute, 2);
else if (Prototype.Browser.WebKit) {
// Safari returns margins on body which is incorrect if the child is absolutely
// positioned. For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
Element.Methods.cumulativeOffset = function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
if (element.offsetParent == document.body)
if (Element.getStyle(element, 'position') == 'absolute') break;
element = element.offsetParent;
} while (element);
return [valueL, valueT];
}
}
if (Prototype.Browser.IE || Prototype.Browser.Opera) {
// IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
Element.Methods.update = function(element, html) {
element = $(element);
html = typeof html == 'undefined' ? '' : html.toString();
var tagName = element.tagName.toUpperCase();
if (Element._insertionTranslations.tags[tagName]) {
$A(element.childNodes).each(function(node) { element.removeChild(node) });
Element._getContentFromAnonymousElement(tagName, html.stripScripts())
.each(function(node) { element.appendChild(node) });
}
else element.innerHTML = html.stripScripts();
html.evalScripts.bind(html).defer();
return element;
};
}
Element._returnOffset = function(l, t) {
var result = [l, t];
result.left = l;
result.top = t;
return result;
};
Element._getContentFromAnonymousElement = function(tagName, html) {
var div = new Element('div'); t = Element._insertionTranslations.tags[tagName]
div.innerHTML = t[0] + html + t[1];
t[2].times(function() { div = div.firstChild });
return $A(div.childNodes);
};
Element._insertionTranslations = {
before: {
adjacency: 'beforeBegin',
insert: function(element, node) {
element.parentNode.insertBefore(node, element);
},
_flag: function(element, attribute) {
return $(element).hasAttribute(attribute) ? attribute : null;
},
style: function(element) {
return element.style.cssText.toLowerCase();
},
title: function(element) {
var node = element.getAttributeNode('title');
return node.specified ? node.nodeValue : null;
initializeRange: function(element, range) {
range.setStartBefore(element);
}
},
top: {
adjacency: 'afterBegin',
insert: function(element, node) {
element.insertBefore(node, element.firstChild);
},
initializeRange: function(element, range) {
range.selectNodeContents(element);
range.collapse(true);
}
},
bottom: {
adjacency: 'beforeEnd',
insert: function(element, node) {
element.appendChild(node);
}
},
after: {
adjacency: 'afterEnd',
insert: function(element, node) {
element.parentNode.insertBefore(node, element.nextSibling);
},
initializeRange: function(element, range) {
range.setStartAfter(element);
}
},
tags: {
TABLE: ['<table>', '</table>', 1],
TBODY: ['<table><tbody>', '</tbody></table>', 2],
TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
SELECT: ['<select>', '</select>', 1]
}
};
(function() {
Object.extend(this, {
href: this._getAttr,
src: this._getAttr,
type: this._getAttr,
disabled: this._flag,
checked: this._flag,
readonly: this._flag,
multiple: this._flag
this.bottom.initializeRange = this.top.initializeRange;
Object.extend(this.tags, {
THEAD: this.tags.TBODY,
TFOOT: this.tags.TBODY,
TH: this.tags.TD
});
}).call(Element._attributeTranslations.values);
}).call(Element._insertionTranslations);
Element.Methods.Simulated = {
hasAttribute: function(element, attribute) {
var t = Element._attributeTranslations, node;
var t = Element._attributeTranslations.read, node;
attribute = t.names[attribute] || attribute;
node = $(element).getAttributeNode(attribute);
return node && node.specified;
@ -671,105 +1023,9 @@ Element.addMethods = function(methods) {
delete Element.ByTag;
if (Element.extend.refresh) Element.extend.refresh();
Element.cache = {};
};
var Toggle = { display: Element.toggle };
/*--------------------------------------------------------------------------*/
Abstract.Insertion = function(adjacency) {
this.adjacency = adjacency;
}
Abstract.Insertion.prototype = {
initialize: function(element, content) {
this.element = $(element);
this.content = content.stripScripts();
if (this.adjacency && this.element.insertAdjacentHTML) {
try {
this.element.insertAdjacentHTML(this.adjacency, this.content);
} catch (e) {
var tagName = this.element.tagName.toUpperCase();
if (['TBODY', 'TR'].include(tagName)) {
this.insertContent(this.contentFromAnonymousTable());
} else {
throw e;
}
}
} else {
this.range = this.element.ownerDocument.createRange();
if (this.initializeRange) this.initializeRange();
this.insertContent([this.range.createContextualFragment(this.content)]);
}
content.evalScripts.bind(content).defer();
},
contentFromAnonymousTable: function() {
var div = document.createElement('div');
div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
return $A(div.childNodes[0].childNodes[0].childNodes);
}
}
var Insertion = new Object();
Insertion.Before = Class.create();
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
initializeRange: function() {
this.range.setStartBefore(this.element);
},
insertContent: function(fragments) {
fragments.each((function(fragment) {
this.element.parentNode.insertBefore(fragment, this.element);
}).bind(this));
}
});
Insertion.Top = Class.create();
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
initializeRange: function() {
this.range.selectNodeContents(this.element);
this.range.collapse(true);
},
insertContent: function(fragments) {
fragments.reverse(false).each((function(fragment) {
this.element.insertBefore(fragment, this.element.firstChild);
}).bind(this));
}
});
Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
initializeRange: function() {
this.range.selectNodeContents(this.element);
this.range.collapse(this.element);
},
insertContent: function(fragments) {
fragments.each((function(fragment) {
this.element.appendChild(fragment);
}).bind(this));
}
});
Insertion.After = Class.create();
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
initializeRange: function() {
this.range.setStartAfter(this.element);
},
insertContent: function(fragments) {
fragments.each((function(fragment) {
this.element.parentNode.insertBefore(fragment,
this.element.nextSibling);
}).bind(this));
}
});
/*--------------------------------------------------------------------------*/
Element.ClassNames = Class.create();

View File

@ -1,4 +1,4 @@
var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead');
var $break = {};
var Enumerable = {
each: function(iterator) {

View File

@ -1,225 +0,0 @@
var Position = {
// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
// scrollable elements
includeScrollOffsets: false,
// must be called before calling withinIncludingScrolloffset, every time the
// page is scrolled
prepare: function() {
this.deltaX = window.pageXOffset
|| document.documentElement.scrollLeft
|| document.body.scrollLeft
|| 0;
this.deltaY = window.pageYOffset
|| document.documentElement.scrollTop
|| document.body.scrollTop
|| 0;
},
realOffset: function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.scrollTop || 0;
valueL += element.scrollLeft || 0;
element = element.parentNode;
} while (element);
return [valueL, valueT];
},
cumulativeOffset: function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
} while (element);
return [valueL, valueT];
},
positionedOffset: function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
if (element) {
if(element.tagName=='BODY') break;
var p = Element.getStyle(element, 'position');
if (p == 'relative' || p == 'absolute') break;
}
} while (element);
return [valueL, valueT];
},
offsetParent: function(element) {
if (element.offsetParent) return element.offsetParent;
if (element == document.body) return element;
while ((element = element.parentNode) && element != document.body)
if (Element.getStyle(element, 'position') != 'static')
return element;
return document.body;
},
// caches x/y coordinate pair to use with overlap
within: function(element, x, y) {
if (this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element, x, y);
this.xcomp = x;
this.ycomp = y;
this.offset = this.cumulativeOffset(element);
return (y >= this.offset[1] &&
y < this.offset[1] + element.offsetHeight &&
x >= this.offset[0] &&
x < this.offset[0] + element.offsetWidth);
},
withinIncludingScrolloffsets: function(element, x, y) {
var offsetcache = this.realOffset(element);
this.xcomp = x + offsetcache[0] - this.deltaX;
this.ycomp = y + offsetcache[1] - this.deltaY;
this.offset = this.cumulativeOffset(element);
return (this.ycomp >= this.offset[1] &&
this.ycomp < this.offset[1] + element.offsetHeight &&
this.xcomp >= this.offset[0] &&
this.xcomp < this.offset[0] + element.offsetWidth);
},
// within must be called directly before
overlap: function(mode, element) {
if (!mode) return 0;
if (mode == 'vertical')
return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
element.offsetHeight;
if (mode == 'horizontal')
return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
element.offsetWidth;
},
page: function(forElement) {
var valueT = 0, valueL = 0;
var element = forElement;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
// Safari fix
if (element.offsetParent == document.body)
if (Element.getStyle(element,'position')=='absolute') break;
} while (element = element.offsetParent);
element = forElement;
do {
if (!window.opera || element.tagName=='BODY') {
valueT -= element.scrollTop || 0;
valueL -= element.scrollLeft || 0;
}
} while (element = element.parentNode);
return [valueL, valueT];
},
clone: function(source, target) {
var options = Object.extend({
setLeft: true,
setTop: true,
setWidth: true,
setHeight: true,
offsetTop: 0,
offsetLeft: 0
}, arguments[2] || {})
// find page position of source
source = $(source);
var p = Position.page(source);
// find coordinate system to use
target = $(target);
var delta = [0, 0];
var parent = null;
// delta [0,0] will do fine with position: fixed elements,
// position:absolute needs offsetParent deltas
if (Element.getStyle(target,'position') == 'absolute') {
parent = Position.offsetParent(target);
delta = Position.page(parent);
}
// correct by body offsets (fixes Safari)
if (parent == document.body) {
delta[0] -= document.body.offsetLeft;
delta[1] -= document.body.offsetTop;
}
// set position
if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
if(options.setWidth) target.style.width = source.offsetWidth + 'px';
if(options.setHeight) target.style.height = source.offsetHeight + 'px';
},
absolutize: function(element) {
element = $(element);
if (element.style.position == 'absolute') return;
Position.prepare();
var offsets = Position.positionedOffset(element);
var top = offsets[1];
var left = offsets[0];
var width = element.clientWidth;
var height = element.clientHeight;
element._originalLeft = left - parseFloat(element.style.left || 0);
element._originalTop = top - parseFloat(element.style.top || 0);
element._originalWidth = element.style.width;
element._originalHeight = element.style.height;
element.style.position = 'absolute';
element.style.top = top + 'px';
element.style.left = left + 'px';
element.style.width = width + 'px';
element.style.height = height + 'px';
},
relativize: function(element) {
element = $(element);
if (element.style.position == 'relative') return;
Position.prepare();
element.style.position = 'relative';
var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
element.style.top = top + 'px';
element.style.left = left + 'px';
element.style.height = element._originalHeight;
element.style.width = element._originalWidth;
}
}
// Safari returns margins on body which is incorrect if the child is absolutely
// positioned. For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
if (Prototype.Browser.WebKit) {
Position.cumulativeOffset = function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
if (element.offsetParent == document.body)
if (Element.getStyle(element, 'position') == 'absolute') break;
element = element.offsetParent;
} while (element);
return [valueL, valueT];
}
}

2
src/prototype.js vendored
View File

@ -29,6 +29,6 @@ var Prototype = {
<%= include 'enumerable.js', 'array.js', 'hash.js', 'range.js' %>
<%= include 'ajax.js', 'dom.js', 'selector.js', 'form.js', 'event.js', 'position.js' %>
<%= include 'ajax.js', 'dom.js', 'selector.js', 'form.js', 'event.js', 'deprecated.js' %>
Element.addMethods();

View File

@ -82,7 +82,7 @@ Object.extend(String.prototype, {
},
unescapeHTML: function() {
var div = document.createElement('div');
var div = new Element('div');
div.innerHTML = this.stripTags();
return div.childNodes[0] ? (div.childNodes.length > 1 ?
$A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :

View File

@ -29,7 +29,11 @@
<script type="text/javascript" language="javascript" charset="utf-8">
// <![CDATA[
var responderCounter = 0;
// lowercase comparison because of MSIE which presents HTML tags in uppercase
var sentence = ("Pack my box with <em>five dozen</em> liquor jugs! " +
"Oh, how <strong>quickly</strong> daft jumping zebras vex...").toLowerCase();
new Test.Unit.Runner({
setup: function(){
@ -76,10 +80,6 @@
new Ajax.Updater("content", "fixtures/content.html", { method:'get' });
// lowercase comparison because of MSIE which presents HTML tags in uppercase
var sentence = ("Pack my box with <em>five dozen</em> liquor jugs! " +
"Oh, how <strong>quickly</strong> daft jumping zebras vex...").toLowerCase();
wait(1000,function(){
assertEqual(sentence, $("content").innerHTML.strip().toLowerCase());
@ -95,9 +95,22 @@
assertEqual(sentence, $("content").innerHTML.strip().toLowerCase());
assertEqual("", $("content2").innerHTML);
});
});
});
}},
testUpdaterWithInsertion: function() {with(this) {
$('content').update();
new Ajax.Updater("content", "fixtures/content.html", { method:'get', insertion: Insertion.Top });
wait(1000,function(){
assertEqual(sentence, $("content").innerHTML.strip().toLowerCase());
$('content').update();
new Ajax.Updater("content", "fixtures/content.html", { method:'get', insertion: 'bottom' });
wait(1000,function(){
assertEqual(sentence, $("content").innerHTML.strip().toLowerCase());
});
});
}},
testResponders: function(){with(this) {
// check for internal responder
assertEqual(1, Ajax.Responders.responders.length);

View File

@ -146,6 +146,7 @@
<div id="testdiv-replace-container-3"><div id="testdiv-replace-3"></div></div>
<div id="testdiv-replace-container-4"><div id="testdiv-replace-4"></div></div>
<div id="testdiv-replace-container-5"><div id="testdiv-replace-5"></div></div>
<div id="testform-replace-container"><p>some text</p><form id="testform-replace"><input id="testinput-replace" type="text" /></form><p>some text</p></div>
<div id="element_with_visible_overflow" style="overflow:visible">V</div>
<div id="element_with_hidden_overflow" style="overflow:hidden">H</div>
@ -223,6 +224,26 @@
</select>
</form>
<!-- writeAttributes -->
<p id="write_attribute_para"></a>
<a id="write_attribute_link" href="test.html"></a>
<form action="/dev/null" id="write_attribute_form" method="get" accept-charset="utf-8">
<label id="write_attribute_label"></label>
<input type="checkbox" name="write_attribute_checkbox" value="" id="write_attribute_checkbox">
<input type="checkbox" checked="checked" name="write_attribute_checked_checkbox" value="" id="write_attribute_checked_checkbox">
<input type="text" name="write_attribute_input" value="" id="write_attribute_input">
<select id="write_attribute_select">
<option>Cat</option>
<option>Dog</option>
</select>
</form>
<table id="write_attribute_table">
<tr><td id="write_attribute_td">A</td><td>B</td></tr>
<tr><td>C</td></tr>
<tr><td>D</td><td>E</td><td>F</td></tr>
</table>
<div id="dom_attribute_precedence">
<form action="blech" method="post">
<input type="submit" id="update" />
@ -267,12 +288,45 @@
<p id="test-full">content</p>
<div id="ancestor"><div id="child"><div><div id="great-grand-child"></div></div></div></div>
<div id="not-in-the-family"></div>
<div id="insertions-container"><div id="insertions-main"><p>some content.</p></div></div>
<div id="insertions-node-container"><div id="insertions-node-main"><p>some content.</p></div></div>
<div id="element-insertions-container"><div id="element-insertions-main"><p>some content.</p></div></div>
<table id="table_for_insertions"></table>
<table id="table_for_row_insertions"><tr id="row_1"></tr></table>
<form method="post" action="blah">
<select id="select_for_update" name="select_for_update">
<option>option 1</option>
<option>option 2</option>
</select>
<select id="select_for_insert_bottom" name="select_for_insert_bottom">
<option>option 1</option>
<option>option 2</option>
</select>
<select id="select_for_insert_top" name="select_for_insert_top">
<option>option 1</option>
<option>option 2</option>
</select>
</form>
<div id="wrap-container"><p id="wrap"></p></div>
<!-- Positioning methods bench -->
<div id="body_absolute" style="position: absolute; top: 10px; left: 10px">
<div id="absolute_absolute" style="position: absolute; top: 10px; left:10px"> </div>
<div id="absolute_relative" style="position: relative; top: 10px; left:10px">
<div style="height:10px">test<span id="inline">test</span></div>
<div id="absolute_relative_undefined"> </div>
</div>
</div>
<!-- Tests follow -->
<script type="text/javascript" language="javascript" charset="utf-8">
// <![CDATA[
var testVar = 'to be updated', testVar2 = '';
var getInnerHTML = function(id) {
return $(id).innerHTML.toString().toLowerCase().gsub(/[\r\n\t]/, '');
};
Element.addMethods({
hashBrowns: function(element) { return 'hash browns'; }
});
@ -313,10 +367,96 @@
assertElementsMatch(document.getElementsByClassName('B', 'class_names'), 'ul#class_names_ul.A.B', 'div.B.C.D');
assertElementsMatch(document.getElementsByClassName('B', 'class_names_ul'));
}},
testElementInsertWithHTML: function() {with(this) {
Element.insert('insertions-main', '<p><em>before</em> text</p><p>more testing</p>', 'before');
assert(getInnerHTML('insertions-container').startsWith('<p><em>before</em> text</p><p>more testing</p>'));
Element.insert('insertions-main', '<p><em>after</em> text</p><p>more testing</p>', 'after');
assert(getInnerHTML('insertions-container').endsWith('<p><em>after</em> text</p><p>more testing</p>'));
Element.insert('insertions-main', '<p><em>top</em> text.</p><p>more testing</p>', 'top');
assert(getInnerHTML('insertions-main').startsWith('<p><em>top</em> text.</p><p>more testing</p>'));
Element.insert('insertions-main', '<p><em>bottom</em> text.</p><p>more testing</p>', 'bottom');
assert(getInnerHTML('insertions-main').endsWith('<p><em>bottom</em> text.</p><p>more testing</p>'));
}},
testElementInsertWithDOMNode: function() {with(this) {
var createParagraph = function(text) {
var p = document.createElement('p');
p.appendChild(document.createTextNode(text));
return p;
}
Element.insert('insertions-node-main', createParagraph('node before'), 'before');
assert(getInnerHTML('insertions-node-container').startsWith('<p>node before</p>'));
Element.insert('insertions-node-main', createParagraph('node after'), 'after');
assert(getInnerHTML('insertions-node-container').endsWith('<p>node after</p>'));
Element.insert('insertions-node-main', createParagraph('node top'), 'top');
assert(getInnerHTML('insertions-node-main').startsWith('<p>node top</p>'));
Element.insert('insertions-node-main', createParagraph('node bottom'), 'bottom');
assert(getInnerHTML('insertions-node-main').endsWith('<p>node bottom</p>'));
assertEqual($('insertions-node-main'), $('insertions-node-main').insert(document.createElement('p')));
}},
testInsertWithTR: function() {with(this) {
new Insertion.After('second_row', '<tr id="third_row"><td>Third Row</td></tr>');
testElementInsertWithNonString: function() {with(this) {
Element.insert('insertions-main', 3, 'bottom');
assert(getInnerHTML('insertions-main').endsWith('3'));
}},
testElementInsertInTables: function() {with(this) {
Element.insert('second_row', '<tr id="third_row"><td>Third Row</td></tr>', 'after');
assert($('second_row').descendantOf('table'));
$('a_cell').insert('hello world', 'top');
assert($('a_cell').innerHTML.startsWith('hello world'));
$('a_cell').insert('<td>hi planet</td>', 'after');
assertEqual('hi planet', $('a_cell').next().innerHTML);
$('table_for_insertions').insert('<tr><td>a cell!</td></tr>');
assert($('table_for_insertions').innerHTML.gsub('\r\n', '').toLowerCase().include('<tr><td>a cell!</td></tr>'));
$('row_1').insert('<tr></tr><tr></tr><tr><td>last</td></tr>', 'after');
assertEqual('last', $A($('table_for_row_insertions').getElementsByTagName('tr')).last().lastChild.innerHTML);
}},
testElementInsertInSelect: function() {with(this) {
var selectTop = $('select_for_insert_top'), selectBottom = $('select_for_insert_bottom');
selectBottom.insert('<option value="33">option 33</option><option selected="selected">option 45</option>');
assertEqual('option 45', selectBottom.getValue());
selectTop.insert('<option value="A">option A</option><option value="B" selected="selected">option B</option>', 'top');
assertEqual(4, selectTop.options.length);
}},
testElementMethodInsert: function() {with(this) {
$('element-insertions-main').insert('some text before','before');
assert(getInnerHTML('element-insertions-container').startsWith('some text before'));
$('element-insertions-main').insert('some text after', 'after');
assert(getInnerHTML('element-insertions-container').endsWith('some text after'));
$('element-insertions-main').insert('some text top', 'top');
assert(getInnerHTML('element-insertions-main').startsWith('some text top'));
$('element-insertions-main').insert('some text bottom', 'bottom');
assert(getInnerHTML('element-insertions-main').endsWith('some text bottom'));
$('element-insertions-main').insert('some more text at the bottom');
assert(getInnerHTML('element-insertions-main').endsWith('some more text at the bottom'));
}},
testInsertionBackwardsCompatibility: function() {with(this) {
new Insertion.Before('element-insertions-main', 'some backward-compatibility testing before');
assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing before'));
new Insertion.After('element-insertions-main', 'some backward-compatibility testing after');
assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing after'));
new Insertion.Top('element-insertions-main', 'some backward-compatibility testing top');
assert(getInnerHTML('element-insertions-main').startsWith('some backward-compatibility testing top'));
new Insertion.Bottom('element-insertions-main', 'some backward-compatibility testing bottom');
assert(getInnerHTML('element-insertions-main').endsWith('some backward-compatibility testing bottom'));
}},
testElementWrap: function() {with(this) {
var element = $('wrap'), parent = document.createElement('div');
element.wrap('div');
assert(getInnerHTML('wrap-container').startsWith('<div><p'));
element.wrap(parent);
assert(getInnerHTML('wrap-container').startsWith('<div><div><p'));
assert(typeof parent.setStyle == 'function');
element.wrap();
assert(getInnerHTML('wrap-container').startsWith('<div><div><div><p'));
}},
testElementVisible: function(){with(this) {
@ -414,18 +554,31 @@
assertMatch(/^<tr>\s*<td>boo!<\/td><\/tr>$/,$('table').innerHTML.toLowerCase());
}},
testElementUpdateInSelect: function() {with(this) {
var select = $('select_for_update');
select.update('<option value="3">option 3</option><option selected="selected">option 4</option>');
assertEqual('option 4', select.getValue());
}},
testElementReplace: function() {with(this) {
$('testdiv-replace-1').replace('hello from div!');
assertEqual('hello from div!', $('testdiv-replace-container-1').innerHTML);
$('testdiv-replace-2').replace(123);
assertEqual('123', $('testdiv-replace-container-2').innerHTML)
assertEqual('123', $('testdiv-replace-container-2').innerHTML);
$('testdiv-replace-3').replace();
assertEqual('', $('testdiv-replace-container-3').innerHTML)
assertEqual('', $('testdiv-replace-container-3').innerHTML);
$('testinput-replace').replace('<p>hello world</p>');
assertEqual('<p>hello world</p>',
$('testform-replace').innerHTML.gsub('\r\n', '').toLowerCase());
$('testform-replace').replace('<form></form>');
assertEqual('<p>some text</p><form></form><p>some text</p>',
$('testform-replace-container').innerHTML.gsub('\r\n', '').toLowerCase());
}},
testElementReplaceWithScript: function() {with(this) {
$('testdiv-replace-4').replace('hello from div!<script>testVarReplace="hello!"</'+'script>');
assertEqual('hello from div!', $('testdiv-replace-container-4').innerHTML);
@ -441,7 +594,7 @@
});
});
}},
testElementSelectorMethod: function() {with(this) {
var testSelector = $('container').getElementsBySelector('p.test');
assertEqual(testSelector.length, 4);
@ -835,6 +988,118 @@
assertEnumEqual(['2', null], elements.invoke('readAttribute', 'bar'));
}},
testElementWriteAttribute: function() {with(this) {
var element = Element.extend(document.body.appendChild(document.createElement('p')));
assertRespondsTo('writeAttribute', element);
assertEqual(element, element.writeAttribute('id', 'write_attribute_test'));
assertEqual('write_attribute_test', element.id);
assertEqual('http://prototypejs.org/', $('write_attribute_link').
writeAttribute({href: 'http://prototypejs.org/', title: 'Home of Prototype'}).href);
assertEqual('Home of Prototype', $('write_attribute_link').title);
var element2 = Element.extend(document.createElement('p'));
element2.writeAttribute('id', 'write_attribute_without_hash');
assertEqual('write_attribute_without_hash', element2.id);
element2.writeAttribute('animal', 'cat');
assertEqual('cat', element2.readAttribute('animal'));
}},
testElementWriteAttributeWithBooleans: function() {with(this) {
var input = $('write_attribute_input'),
select = $('write_attribute_select'),
checkbox = $('write_attribute_checkbox'),
checkedCheckbox = $('write_attribute_checked_checkbox');
assert( input. writeAttribute('readonly'). hasAttribute('readonly'));
assert(!input. writeAttribute('readonly', false). hasAttribute('readonly'));
assert( input. writeAttribute('readonly', true). hasAttribute('readonly'));
assert(!input. writeAttribute('readonly', null). hasAttribute('readonly'));
assert( input. writeAttribute('readonly', 'readonly').hasAttribute('readonly'));
assert( select. writeAttribute('multiple'). hasAttribute('multiple'));
assert( input. writeAttribute('disabled'). hasAttribute('disabled'));
assert( checkbox. writeAttribute('checked'). checked);
assert(!checkedCheckbox.writeAttribute('checked', false). checked);
}},
testElementWriteAttributeWithIssues: function() {with(this) {
var input = $('write_attribute_input').writeAttribute({maxlength: 90, tabindex: 10}),
td = $('write_attribute_td').writeAttribute({valign: 'bottom', colspan: 2, rowspan: 2});
assertEqual(90, input.readAttribute('maxlength'));
assertEqual(10, input.readAttribute('tabindex'));
assertEqual(2, td.readAttribute('colspan'));
assertEqual(2, td.readAttribute('rowspan'));
assertEqual('bottom', td.readAttribute('valign'));
var p = $('write_attribute_para'), label = $('write_attribute_label');
assertEqual('some-class', p. writeAttribute({'class': 'some-class'}). readAttribute('class'));
assertEqual('some-className', p. writeAttribute({className: 'some-className'}).readAttribute('class'));
assertEqual('some-id', label.writeAttribute({'for': 'some-id'}). readAttribute('for'));
assertEqual('some-other-id', label.writeAttribute({htmlFor: 'some-other-id'}). readAttribute('for'));
assert(p.writeAttribute({style: 'width: 5px;'}).readAttribute('style').toLowerCase().include('width'));
}},
testElementWriteAttributeWithCustom: function() {with(this) {
var p = $('write_attribute_para').writeAttribute({name: 'martin', location: 'stockholm', age: 26});
assertEqual('martin', p.readAttribute('name'));
assertEqual('stockholm', p.readAttribute('location'));
assertEqual('26', p.readAttribute('age'));
}},
testNewElement: function() {with(this) {
assert(new Element('h1'));
var XHTML_TAGS = $w(
'a abbr acronym address area '+
'b bdo big blockquote br button caption '+
'cite code col colgroup dd del dfn div dl dt '+
'em fieldset form h1 h2 h3 h4 h5 h6 hr '+
'i iframe img input ins kbd label legend li '+
'map object ol optgroup option p param pre q samp '+
'script select small span strong style sub sup '+
'table tbody td textarea tfoot th thead tr tt ul var');
XHTML_TAGS.each(function(tag, index) {
var id = tag + '_' + index, element = document.body.appendChild(new Element(tag, {id: id}));
assertEqual(tag, element.tagName.toLowerCase());
assertEqual(element, document.body.lastChild);
assertEqual(id, element.id);
});
assertRespondsTo('update', new Element('div'));
Element.addMethods({
cheeseCake: function(){
return 'Cheese cake';
}
});
assertRespondsTo('cheeseCake', new Element('div'));
/* window.ElementOld = function(tagName, attributes) {
if (Prototype.Browser.IE && attributes && attributes.name) {
tagName = '<' + tagName + ' name="' + attributes.name + '">';
delete attributes.name;
}
return Element.extend(document.createElement(tagName)).writeAttribute(attributes || {});
};
benchmark(function(){
XHTML_TAGS.each(function(tagName){new Element(tagName)});
}, 5);
benchmark(function(){
XHTML_TAGS.each(function(tagName){new ElementOld(tagName)});
}, 5); */
assertEqual('foobar', new Element('a', {custom: 'foobar'}).readAttribute('custom'));
var input = document.body.appendChild(new Element('input',
{id: 'my_input_field_id', name: 'my_input_field'}));
assertEqual(input, document.body.lastChild);
assertEqual('my_input_field', $(document.body.lastChild).name);
if (Prototype.Browser.IE)
assertMatch(/name=["']?my_input_field["']?/, $('my_input_field').outerHTML);
}},
testElementGetHeight: function() {with(this) {
assertIdentical(100, $('dimensions-visible').getHeight());
assertIdentical(100, $('dimensions-display-none').getHeight());
@ -991,9 +1256,38 @@
});
$(element).update("<script>var blah='"+'\\'.times(10000)+"'</scr"+"ipt>");
assertEqual('', element.innerHTML);
}},
testPositionedOffset: function() {with(this) {
assertEnumEqual([10,10],
$('body_absolute').positionedOffset());
assertEnumEqual([10,10],
$('absolute_absolute').positionedOffset());
assertEnumEqual([10,10],
$('absolute_relative').positionedOffset());
assertEnumEqual([0,10],
$('absolute_relative_undefined').positionedOffset());
}},
testViewportOffset: function() {with(this) {
assertEnumEqual([10,10],
$('body_absolute').viewportOffset());
assertEnumEqual([20,20],
$('absolute_absolute').viewportOffset());
assertEnumEqual([20,20],
$('absolute_relative').viewportOffset());
assertEnumEqual([20,30],
$('absolute_relative_undefined').viewportOffset());
}},
testOffsetParent: function() {with(this) {
assertEqual('body_absolute', $('absolute_absolute').getOffsetParent().id);
assertEqual('body_absolute', $('absolute_relative').getOffsetParent().id);
assertEqual('absolute_relative', $('inline').getOffsetParent().id);
assertEqual('absolute_relative', $('absolute_relative_undefined').getOffsetParent().id);
}}
}, 'testlog');
// ]]>
</script>
</body>

View File

@ -63,35 +63,6 @@
assertEqual(30, Position.deltaY);
}},
testPositionedOffset: function() {with(this) {
assertEnumEqual([10,10],
Position.positionedOffset($('body_absolute')));
assertEnumEqual([10,10],
Position.positionedOffset($('absolute_absolute')));
assertEnumEqual([10,10],
Position.positionedOffset($('absolute_relative')));
assertEnumEqual([0,10],
Position.positionedOffset($('absolute_relative_undefined')));
}},
testPage: function() {with(this) {
assertEnumEqual([10,10],
Position.page($('body_absolute')));
assertEnumEqual([20,20],
Position.page($('absolute_absolute')));
assertEnumEqual([20,20],
Position.page($('absolute_relative')));
assertEnumEqual([20,30],
Position.page($('absolute_relative_undefined')));
}},
testOffsetParent: function() {with(this) {
assertEqual('body_absolute', Position.offsetParent($('absolute_absolute')).id);
assertEqual('body_absolute', Position.offsetParent($('absolute_relative')).id);
assertEqual('absolute_relative', Position.offsetParent($('inline')).id);
assertEqual('absolute_relative', Position.offsetParent($('absolute_relative_undefined')).id);
}},
testWithin: function() {with(this) {
[true, false].each(function(withScrollOffsets) {
Position.includeScrollOffsets = withScrollOffsets;
@ -115,4 +86,4 @@
// ]]>
</script>
</body>
</html>
</html>