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:
parent
67a4d00588
commit
83b4b337e1
14
CHANGELOG
14
CHANGELOG
|
@ -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]
|
||||
|
|
14
src/ajax.js
14
src/ajax.js
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
590
src/dom.js
590
src/dom.js
|
@ -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();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead');
|
||||
var $break = {};
|
||||
|
||||
var Enumerable = {
|
||||
each: function(iterator) {
|
||||
|
|
225
src/position.js
225
src/position.js
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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();
|
||||
|
|
|
@ -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 }) :
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue