0
@@ -287,7 +287,6 @@ Element.Methods = {
0
if (t.names[name]) name = t.names[name];
0
if (Prototype.Browser.IE) {
0
- var t = Element._attributeTranslations.read;
0
// If we're reading from a form, avoid a conflict between an attribute
0
if (element.tagName.toUpperCase() == 'FORM' &&
0
@@ -296,7 +295,6 @@ Element.Methods = {
0
element = $(element.cloneNode(false));
0
if (t.values[name]) return t.values[name](element, name);
0
- if (t.names[name]) name = t.names[name];
0
if (name.include(':')) {
0
return (!element.attributes || !element.attributes[name]) ? null :
0
element.attributes[name].value;
0
@@ -447,25 +445,29 @@ Element.Methods = {
0
getDimensions: function(element) {
0
- var display = element.getStyle('display');
0
- if (display != 'none' && display != null) // Safari bug
0
- return {width: element.offsetWidth, height: element.offsetHeight};
0
+ var display = element.getStyle('display'),
0
+ dimensions = { width: element.clientWidth, height: element.clientHeight };
0
- // All *Width and *Height properties give 0 on elements with display
none,
0
+ // All *Width and *Height properties give 0 on elements with display
: none,
0
// so enable the element temporarily
0
- var els = element.style;
0
- var originalVisibility = els.visibility;
0
- var originalPosition = els.position;
0
- var originalDisplay = els.display;
0
- els.visibility = 'hidden';
0
- els.position = 'absolute';
0
- els.display = 'block';
0
- var originalWidth = element.clientWidth;
0
- var originalHeight = element.clientHeight;
0
- els.display = originalDisplay;
0
- els.position = originalPosition;
0
- els.visibility = originalVisibility;
0
- return {width: originalWidth, height: originalHeight};
0
+ if (display === "none" || display === null) {
0
+ var els = element.style,
0
+ originalVisibility = els.visibility,
0
+ originalPosition = els.position,
0
+ originalDisplay = els.display;
0
+ els.visibility = 'hidden';
0
+ els.position = 'absolute';
0
+ els.display = 'block';
0
+ dimensions = { width: element.clientWidth, height: element.clientHeight };
0
+ els.display = originalDisplay;
0
+ els.position = originalPosition;
0
+ els.visibility = originalVisibility;
0
makePositioned: function(element) {
0
@@ -574,128 +576,215 @@ Element.Methods = {
0
relativize: function(element) {
0
if (element.getStyle('position') == 'relative') return element;
0
- // Position.prepare(); // To be done manually by Scripty when it needs it.
0
- if
(!element._originalTop){
0
+ if
(!element._originalTop){
0
/* fix bizarre IE position issue with empty elements */
0
var isBuggy = element.outerHTML && element.innerHTML.blank();
0
- if
(isBuggy) element.innerHTML = '\x00';
0
+ if
(isBuggy) element.innerHTML = '\x00';
0
Object.extend(element, {
0
- _originalTop: element.offsetTop,
0
- _originalLeft: element.offsetLeft,
0
- _originalWidth: element.clientWidth + 'px',
0
- _originalHeight: element.clientHeight + 'px'
0
+ _originalTop: element.offsetTop,
0
+ _originalLeft: element.offsetLeft,
0
+ _originalWidth: Element.getStyle(element, 'width'),
0
+ _originalHeight: Element.getStyle(element, 'height'),
0
+ _originalMarginTop: Element.getStyle(element, 'marginTop'),
0
+ _originalMarginLeft: Element.getStyle(element, 'marginLeft')
0
- if
(isBuggy) element.innerHTML = '';
0
+ if
(isBuggy) element.innerHTML = '';
0
- element.style.position = 'relative';
0
+ Element.setStyle(element, {
0
+ width: element._originalWidth,
0
+ height: element._originalHeight,
0
+ marginTop: element._originalMarginTop,
0
+ marginLeft: element._originalMarginLeft
0
var offsets = element.positionedOffset(),
0
- top = element._originalTop - offsets.top,
0
- left = element._originalLeft - offsets.left;
0
+ top = element._originalTop - offsets.top,
0
+ left = element._originalLeft - offsets.left;
0
var isAuto = /^(auto|)$/;
0
- if(!isAuto.test(element.style.top)) top += element._originalTop;
0
- if(!isAuto.test(element.style.left)) left+= element._originalLeft;
0
+ if (!isAuto.test(element.style.top)) top += element._originalTop;
0
+ if (!isAuto.test(element.style.left)) left += element._originalLeft;
0
- element.style.top = top + 'px';
0
- element.style.left = left + 'px';
0
- element.style.height = element._originalHeight;
0
- element.style.width = element._originalWidth;
0
- cumulativeScrollOffset: function(element) {
0
- var valueT = 0, valueL = 0,
0
- endElement = (Prototype.Browser.Opera && opera.version() < 9.5) ? document.documentElement : document;
0
- valueT += element.scrollTop || 0;
0
- valueL += element.scrollLeft || 0;
0
- } while ((element = element.parentNode) && element != endElement);
0
+ Element.setStyle(element, {
0
- return
Element._returnOffset(valueL, valueT);
0
getOffsetParent: function(element) {
0
- var op = element.offsetParent;
0
- if (op && op != document.documentElement) return $(op);
0
+ var op = element.offsetParent, docElement = document.documentElement;
0
+ if (op && op != docElement) return $(op);
0
- while ((element = element.parentNode) && element.tagName.toUpperCase() != 'HTML')
0
+ while ((element = element.parentNode) && element !== docElement &&
0
+ element !== document) {
0
if (Element.getStyle(element, 'position') != 'static')
0
return $(document.body);
0
- viewportOffset: function(forElement) {
0
- forElement = $(forElement);
0
+Object.extend(Element.Methods, (function() {
0
+ function getNumericStyle(element, style) {
0
+ return parseFloat(Element.getStyle(element, style)) || 0;
0
- var element = forElement, valueT = 0, valueL = 0,
0
- endElement = (Prototype.Browser.Opera && opera.version() < 9.5) ? document.documentElement : document;
0
- valueT += element.offsetTop || 0;
0
- valueL += element.offsetLeft || 0;
0
- } while ((element = element.getOffsetParent()) != document.body);
0
+ function getStyleDiff(element, source, style) {
0
+ return getNumericStyle(source, style) - getNumericStyle(element, style);
0
+ function cloneDimension(element, source, dimension) {
0
+ var d = Element.getDimensions(source), style = { };
0
+ style[dimension] = d[dimension] + 'px';
0
- if (Element.getStyle(element, 'position') != 'fixed') {
0
- while ((element = element.parentNode) && element != endElement) {
0
- if (Element.getStyle(element, 'position') == 'fixed') break;
0
- valueT -= element.scrollTop || 0;
0
- valueL -= element.scrollLeft || 0;
0
+ var styles = $w('margin padding');
0
+ var sides = (dimension === 'height') ? $w('top bottom') :
0
+ for (var i = 0; i < 2; i++) {
0
+ for (var j = 0; j < 2; j++) {
0
+ property = styles[i] + sides[j].capitalize();
0
+ style[property] = (getNumericStyle(element, property) +
0
+ getStyleDiff(element, source, property)) + 'px';
0
- return Element._returnOffset(valueL, valueT);
0
+ Element.setStyle(element, style);
0
+ cumulativeScrollOffset: function(element) {
0
+ var valueT = 0, valueL = 0, endElement = document;
0
+ var B = Prototype.Browser;
0
- clonePosition: function(element, source) {
0
- var options = Object.extend({
0
- }, arguments[2] || { });
0
- // find page position of source
0
- var p = source.viewportOffset();
0
- // find coordinate system to use
0
- // delta [0,0] will do fine with position: fixed elements,
0
- // position:absolute needs offsetParent deltas
0
- if (Element.getStyle(element, 'position') == 'absolute') {
0
- parent = element.getOffsetParent();
0
- delta = parent.viewportOffset();
0
+ // Safari and Opera need to stop at document.body or else they'll
0
+ // report inaccurate values.
0
+ if (B.WebKit || B.Opera && opera.version() < 9.5) {
0
+ if ([document, document.body, document.documentElement].include(element))
0
+ return Element._returnOffset(0, 0);
0
- // correct by body offsets (fixes Safari)
0
- if (parent == document.body) {
0
- delta[0] -= document.body.offsetLeft;
0
- delta[1] -= document.body.offsetTop;
0
+ endElement = document.body;
0
- if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
0
- if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
0
- if (options.setWidth) element.style.width = source.offsetWidth + 'px';
0
- if (options.setHeight) element.style.height = source.offsetHeight + 'px';
0
+ if (Element.getStyle(element, 'position') !== 'fixed') {
0
+ while ((element = element.parentNode) && element !== endElement) {
0
+ if (Element.getStyle(element, 'position') === 'fixed') break;
0
+ valueT += element.scrollTop || 0;
0
+ valueL += element.scrollLeft || 0;
0
+ return Element._returnOffset(valueL, valueT);
0
+ cumulativeOffset: function(element) {
0
+ var valueT = 0, valueL = 0;
0
+ valueT += (element.offsetTop || 0);
0
+ valueL += (element.offsetLeft || 0);
0
+ } while ((element = Element.getOffsetParent(element)) != document.body);
0
+ return Element._returnOffset(valueL, valueT);
0
+ positionedOffset: function(element) {
0
+ var valueT = 0, valueL = 0;
0
+ valueT += (element.offsetTop || 0);
0
+ valueL += (element.offsetLeft || 0);
0
+ element = Element.getOffsetParent(element);
0
+ } while (element != document.body &&
0
+ Element.getStyle(element, 'position') == 'static');
0
+ return Element._returnOffset(valueL, valueT);
0
+ viewportOffset: function(forElement) {
0
+ forElement = $(forElement);
0
+ var op, element = forElement, valueT = 0, valueL = 0;
0
+ valueT += (element.offsetTop || 0);
0
+ valueL += (element.offsetLeft || 0);
0
+ op = Element.getOffsetParent(element);
0
+ if (op == document.body && Element.getStyle(element,
0
+ 'position') == 'absolute') break;
0
+ } while ((element = op) != document.body);
0
+ var scrollOffset = Element.cumulativeScrollOffset(forElement);
0
+ valueT -= scrollOffset.top;
0
+ valueL -= scrollOffset.left;
0
+ return Element._returnOffset(valueL, valueT);
0
+ clonePosition: function(element, source) {
0
+ var options = Object.extend({
0
+ }, arguments[2] || { });
0
+ // find coordinate system to use
0
+ // delta [0,0] will do fine with position: fixed elements;
0
+ // position: absolute needs offsetParent deltas
0
+ var parent, delta = [0, 0];
0
+ if (Element.getStyle(element, 'position') == 'absolute') {
0
+ parent = Element.getOffsetParent(element);
0
+ delta = Element.viewportOffset(parent);
0
+ // correct by body offsets (fixes Safari)
0
+ if (parent == document.body) {
0
+ delta[0] -= document.body.offsetLeft;
0
+ delta[1] -= document.body.offsetTop;
0
+ if (options.setWidth) cloneDimension(element, source, 'width');
0
+ if (options.setHeight) cloneDimension(element, source, 'height');
0
+ // find page position of source
0
+ var p = Element.viewportOffset(source),
0
+ borderOffset = ['borderLeftWidth', 'borderTopWidth'].map(
0
+ function(style) { return getStyleDiff(element, source, style); });
0
+ if (options.setLeft) {
0
+ var left = p[0] - delta[0] + borderOffset[0];
0
+ if (options.offsetLeft)
0
+ left += options.offsetLeft + getNumericStyle(element, 'paddingLeft');
0
+ element.style.left = left + 'px';
0
+ var top = p[1] - delta[1] + borderOffset[1];
0
+ if (options.offsetTop)
0
+ top += options.offsetTop + getNumericStyle(element, 'paddingTop');
0
+ element.style.top = top + 'px';
0
Element.Methods.identify.counter = 1;
0
@@ -782,11 +871,13 @@ else if (Prototype.Browser.IE) {
0
function(proceed, element) {
0
// IE throws an error if element is not in document
0
- try { element.offsetParent }
0
- catch(e) { return $(document.body) }
0
+ try { element.offsetParent; }
0
+ catch(e) { return $(document.body); }
0
var position = element.getStyle('position');
0
if (position !== 'static') return proceed(element);
0
element.setStyle({ position: 'relative' });
0
var value = proceed(element);
0
element.setStyle({ position: position });
0
@@ -797,30 +888,25 @@ else if (Prototype.Browser.IE) {
0
Element.Methods[method] = Element.Methods[method].wrap(
0
function(proceed, element) {
0
- try { element.offsetParent }
0
- catch(e) { return Element._returnOffset(0,0) }
0
- var position = element.getStyle('position');
0
+ var position = Element.getStyle(element, 'position');
0
if (position !== 'static') return proceed(element);
0
// Trigger hasLayout on the offset parent so that IE6 reports
0
// accurate offsetTop and offsetLeft values for position: fixed.
0
- var offsetParent = element.getOffsetParent();
0
- if (offsetParent && offsetParent.getStyle('position') === 'fixed')
0
- offsetParent.setStyle({ zoom: 1 });
0
- element.setStyle({ position: 'relative' });
0
+ var offsetParent = Element.getOffsetParent(element),
0
+ style = { position: 'relative' };
0
+ if (Element.getOffsetParent(offsetParent, 'position') === 'fixed')
0
+ Element.setStyle(element, style);
0
var value = proceed(element);
0
-
element.setStyle({ position: position });
0
+
Element.setStyle(element, { position: position});
0
- Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
0
- function(proceed, element) {
0
- try { $(element).offsetParent }
0
- catch(e) { return Element._returnOffset(0,0) }
0
- return proceed(element);
0
Element.Methods.getStyle = function(element, style) {
0
@@ -1048,9 +1134,12 @@ if ('outerHTML' in document.createElement('div')) {
0
content = Object.toHTML(content);
0
var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
0
- if (Element._insertionTranslations.tags[tagName]) {
0
+ // Avoid outerHTML in IE because it incorrectly removes the replaced
0
+ // elements' child nodes.
0
+ if (Element._insertionTranslations.tags[tagName] || Prototype.Browser.IE) {
0
var nextSibling = element.next();
0
- var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
0
+ var fragments = Element._getContentFromAnonymousElement(tagName,
0
+ content.stripScripts());
0
parent.removeChild(element);
0
fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
0
@@ -1111,9 +1200,11 @@ Element._insertionTranslations = {
0
}).call(Element._insertionTranslations);
0
Element.Methods.Simulated = {
0
+ // No use of $ in this function in order to keep things fast.
0
+ // Used by the Selector class.
0
hasAttribute: function(element, attribute) {
0
attribute = Element._attributeTranslations.has[attribute] || attribute;
0
- var node =
$(element).getAttributeNode(attribute);
0
+ var node =
element.getAttributeNode(attribute);
0
return !!(node && node.specified);
0
@@ -1138,6 +1229,9 @@ Element.extend = (function() {
0
var extend = Object.extend(function(element) {
0
if (!element || element._extendedByPrototype ||
0
element.nodeType != 1 || element == window) return element;
0
+ // Filter out XML nodes in IE.
0
+ if (!(element.ownerDocument || element).body) return element;
0
var methods = Object.clone(Methods),
0
tagName = element.tagName.toUpperCase(), property, value;
0
@@ -1168,8 +1262,11 @@ Element.extend = (function() {
0
+// No use of $ in this function in order to keep things fast.
0
+// Used by the Selector class.
0
Element.hasAttribute = function(element, attribute) {
0
- if (
(element = $(element)).hasAttribute) return element.hasAttribute(attribute);
0
+ if (
element.hasAttribute) return element.hasAttribute(attribute);
0
return Element.Methods.Simulated.hasAttribute(element, attribute);
er…. This absolutely needs to be broken down into separate, tested commits.
Woah, yeah… I’d love to see these in separate commits in the future :) Right now it’s just a huge mob of craziness.
Yeah, sorry; these über-commits were kludges so I could keep up with future fixes from JDD. That was a dumb idea on my part.