vendor/assets/javascripts/mootools.js in mootools-rails-0.4 vs vendor/assets/javascripts/mootools.js in mootools-rails-1.0.0

- old
+ new

@@ -1,14 +1,14 @@ /* --- MooTools: the javascript framework web build: - - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7 + - http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0 packager build: - - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff /* --- name: Core @@ -31,12 +31,12 @@ */ (function(){ this.MooTools = { - version: '1.3.2', - build: 'c9f1ff10e9e7facb65e9481049ed1b450959d587' + version: '1.4.1', + build: 'd1fb25710e3c5482a219ab9dc675a4e0ad2176b6' }; // typeOf, instanceOf var typeOf = this.typeOf = function(item){ @@ -201,11 +201,11 @@ for (var i = 0; i < hooks.length; i++){ var hook = hooks[i]; if (typeOf(hook) == 'type') implement.call(hook, name, method); else hook.call(this, name, method); } - + var previous = this.prototype[name]; if (previous == null || !previous.$protected) this.prototype[name] = method; if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ return method.apply(item, slice.call(arguments, 1)); @@ -263,11 +263,11 @@ return force; }; force('String', String, [ 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', - 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase' + 'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase' ])('Array', Array, [ 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' ])('Number', Number, [ 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' @@ -419,42 +419,42 @@ Array.implement({ /*<!ES5>*/ every: function(fn, bind){ - for (var i = 0, l = this.length; i < l; i++){ + for (var i = 0, l = this.length >>> 0; i < l; i++){ if ((i in this) && !fn.call(bind, this[i], i, this)) return false; } return true; }, filter: function(fn, bind){ var results = []; - for (var i = 0, l = this.length; i < l; i++){ + for (var i = 0, l = this.length >>> 0; i < l; i++){ if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]); } return results; }, indexOf: function(item, from){ - var len = this.length; - for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){ + var length = this.length >>> 0; + for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){ if (this[i] === item) return i; } return -1; }, map: function(fn, bind){ - var results = []; - for (var i = 0, l = this.length; i < l; i++){ + var length = this.length >>> 0, results = Array(length); + for (var i = 0; i < length; i++){ if (i in this) results[i] = fn.call(bind, this[i], i, this); } return results; }, some: function(fn, bind){ - for (var i = 0, l = this.length; i < l; i++){ + for (var i = 0, l = this.length >>> 0; i < l; i++){ if ((i in this) && fn.call(bind, this[i], i, this)) return true; } return false; }, /*</!ES5>*/ @@ -594,41 +594,41 @@ test: function(regex, params){ return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); }, contains: function(string, separator){ - return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1; + return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : String(this).indexOf(string) > -1; }, trim: function(){ - return this.replace(/^\s+|\s+$/g, ''); + return String(this).replace(/^\s+|\s+$/g, ''); }, clean: function(){ - return this.replace(/\s+/g, ' ').trim(); + return String(this).replace(/\s+/g, ' ').trim(); }, camelCase: function(){ - return this.replace(/-\D/g, function(match){ + return String(this).replace(/-\D/g, function(match){ return match.charAt(1).toUpperCase(); }); }, hyphenate: function(){ - return this.replace(/[A-Z]/g, function(match){ + return String(this).replace(/[A-Z]/g, function(match){ return ('-' + match.charAt(0).toLowerCase()); }); }, capitalize: function(){ - return this.replace(/\b[a-z]/g, function(match){ + return String(this).replace(/\b[a-z]/g, function(match){ return match.toUpperCase(); }); }, escapeRegExp: function(){ - return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); + return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); }, toInt: function(base){ return parseInt(this, base || 10); }, @@ -636,21 +636,21 @@ toFloat: function(){ return parseFloat(this); }, hexToRgb: function(array){ - var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); + var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); return (hex) ? hex.slice(1).hexToRgb(array) : null; }, rgbToHex: function(array){ - var rgb = this.match(/\d{1,3}/g); + var rgb = String(this).match(/\d{1,3}/g); return (rgb) ? rgb.rgbToHex(array) : null; }, substitute: function(object, regexp){ - return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ + return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ if (match.charAt(0) == '\\') return match.slice(1); return (object[name] != null) ? object[name] : ''; }); } @@ -744,26 +744,34 @@ attempt: function(args, bind){ try { return this.apply(bind, Array.from(args)); } catch (e){} - + return null; }, - /*<!ES5>*/ - bind: function(bind){ + /*<!ES5-bind>*/ + bind: function(that){ var self = this, - args = (arguments.length > 1) ? Array.slice(arguments, 1) : null; - - return function(){ - if (!args && !arguments.length) return self.call(bind); - if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments))); - return self.apply(bind, args || arguments); + args = arguments.length > 1 ? Array.slice(arguments, 1) : null, + F = function(){}; + + var bound = function(){ + var context = that, length = arguments.length; + if (this instanceof bound){ + F.prototype = self.prototype; + context = new F; + } + var result = (!args && !length) + ? self.call(context) + : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments); + return context == that ? result : context; }; + return bound; }, - /*</!ES5>*/ + /*</!ES5-bind>*/ pass: function(args, bind){ var self = this; if (args != null) args = Array.from(args); return function(){ @@ -1116,121 +1124,89 @@ /* --- name: Event -description: Contains the Event Class, to make the event object cross-browser. +description: Contains the Event Type, to make the event object cross-browser. license: MIT-style license. requires: [Window, Document, Array, Function, String, Object] provides: Event ... */ -var Event = new Type('Event', function(event, win){ +(function() { + +var _keys = {}; + +var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){ if (!win) win = window; - var doc = win.document; event = event || win.event; if (event.$extended) return event; + this.event = event; this.$extended = true; - var type = event.type, - target = event.target || event.srcElement, - page = {}, - client = {}, - related = null, - rightClick, wheel, code, key; + this.shift = event.shiftKey; + this.control = event.ctrlKey; + this.alt = event.altKey; + this.meta = event.metaKey; + var type = this.type = event.type; + var target = event.target || event.srcElement; while (target && target.nodeType == 3) target = target.parentNode; + this.target = document.id(target); - if (type.indexOf('key') != -1){ - code = event.which || event.keyCode; - key = Object.keyOf(Event.Keys, code); + if (type.indexOf('key') == 0){ + var code = this.code = (event.which || event.keyCode); + this.key = _keys[code]; if (type == 'keydown'){ - var fKey = code - 111; - if (fKey > 0 && fKey < 13) key = 'f' + fKey; + if (code > 111 && code < 124) this.key = 'f' + (code - 111); + else if (code > 95 && code < 106) this.key = code - 96; } - if (!key) key = String.fromCharCode(code).toLowerCase(); - } else if ((/click|mouse|menu/i).test(type)){ + if (this.key == null) this.key = String.fromCharCode(code).toLowerCase(); + } else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){ + var doc = win.document; doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; - page = { + this.page = { x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft, y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop }; - client = { + this.client = { x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX, y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY }; - if ((/DOMMouseScroll|mousewheel/).test(type)){ - wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; + if (type == 'DOMMouseScroll' || type == 'mousewheel') + this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; + + this.rightClick = (event.which == 3 || event.button == 2); + if (type == 'mouseover' || type == 'mouseout'){ + var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; + while (related && related.nodeType == 3) related = related.parentNode; + this.relatedTarget = document.id(related); } - rightClick = (event.which == 3) || (event.button == 2); - if ((/over|out/).test(type)){ - related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; - var testRelated = function(){ - while (related && related.nodeType == 3) related = related.parentNode; - return true; - }; - var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated(); - related = (hasRelated) ? related : null; - } - } else if ((/gesture|touch/i).test(type)){ + } else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){ this.rotation = event.rotation; this.scale = event.scale; this.targetTouches = event.targetTouches; this.changedTouches = event.changedTouches; var touches = this.touches = event.touches; if (touches && touches[0]){ var touch = touches[0]; - page = {x: touch.pageX, y: touch.pageY}; - client = {x: touch.clientX, y: touch.clientY}; + this.page = {x: touch.pageX, y: touch.pageY}; + this.client = {x: touch.clientX, y: touch.clientY}; } } - return Object.append(this, { - event: event, - type: type, - - page: page, - client: client, - rightClick: rightClick, - - wheel: wheel, - - relatedTarget: document.id(related), - target: document.id(target), - - code: code, - key: key, - - shift: event.shiftKey, - control: event.ctrlKey, - alt: event.altKey, - meta: event.metaKey - }); + if (!this.client) this.client = {}; + if (!this.page) this.page = {}; }); -Event.Keys = { - 'enter': 13, - 'up': 38, - 'down': 40, - 'left': 37, - 'right': 39, - 'esc': 27, - 'space': 32, - 'backspace': 8, - 'tab': 9, - 'delete': 46 -}; +DOMEvent.implement({ - - -Event.implement({ - stop: function(){ - return this.stopPropagation().preventDefault(); + return this.preventDefault().stopPropagation(); }, stopPropagation: function(){ if (this.event.stopPropagation) this.event.stopPropagation(); else this.event.cancelBubble = true; @@ -1243,11 +1219,30 @@ return this; } }); +DOMEvent.defineKey = function(code, key){ + _keys[code] = key; + return this; +}; +DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true); + +DOMEvent.defineKeys({ + '38': 'up', '40': 'down', '37': 'left', '39': 'right', + '27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab', + '46': 'delete', '13': 'enter' +}); + +})(); + + + + + + /* --- name: Class @@ -1435,11 +1430,11 @@ if (delay) fn.delay(delay, this, args); else fn.apply(this, args); }, this); return this; }, - + removeEvent: function(type, fn){ type = removeOn(type); var events = this.$events[type]; if (events && !fn.internal){ var index = events.indexOf(fn); @@ -1790,11 +1785,11 @@ brokenSecondClassNameGEBCN, cachedGetElementsByClassName, brokenFormAttributeGetter; var selected, id = 'slick_uniqueid'; var testNode = document.createElement('div'); - + var testRoot = document.body || document.getElementsByTagName('body')[0] || root; testRoot.appendChild(testNode); // on non-HTML documents innerHTML and getElementsById doesnt work properly try { @@ -1841,11 +1836,11 @@ brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2); } catch(e){}; features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN; } - + if (testNode.querySelectorAll){ // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents try { testNode.innerHTML = 'foo</foo>'; selected = testNode.querySelectorAll('*'); @@ -1967,11 +1962,11 @@ qsaFailExpCache = {}; local.search = function(context, expression, append, first){ var found = this.found = (first) ? null : (append || []); - + if (!context) return found; else if (context.navigator) context = context.document; // Convert the node from a window to a document else if (!context.nodeType) return found; // setup @@ -2273,16 +2268,16 @@ if (this.isHTMLDocument && this.nativeMatchesSelector){ try { return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); } catch(matchError) {} } - + var parsed = this.Slick.parse(selector); if (!parsed) return true; // simple (single) selectors - var expressions = parsed.expressions, reversedExpressions, simpleExpCounter = 0, i; + var expressions = parsed.expressions, simpleExpCounter = 0, i; for (i = 0; (currentExpression = expressions[i]); i++){ if (currentExpression.length == 1){ var exp = currentExpression[0]; if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true; simpleExpCounter++; @@ -2352,11 +2347,11 @@ var idNode = item.getAttributeNode('id'); if (idNode && idNode.nodeValue == id){ this.push(item, tag, null, classes, attributes, pseudos); break; } - } + } return; } if (!item){ // if the context is in the dom we return, else we will try GEBTN, breaking the getById label if (this.contains(this.root, node)) return; @@ -2561,11 +2556,11 @@ }, 'root': function(node){ return (node === this.root); }, - + 'selected': function(node){ return node.selected; } /*</pseudo-selectors>*/ @@ -2573,11 +2568,11 @@ for (var p in pseudos) local['pseudo:' + p] = pseudos[p]; // attributes methods -local.attributeGetters = { +var attributeGetters = local.attributeGetters = { 'class': function(){ return this.getAttribute('class') || this.className; }, @@ -2590,27 +2585,34 @@ }, 'style': function(){ return (this.style) ? this.style.cssText : this.getAttribute('style'); }, - + 'tabindex': function(){ var attributeNode = this.getAttributeNode('tabindex'); return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; }, 'type': function(){ return this.getAttribute('type'); + }, + + 'maxlength': function(){ + var attributeNode = this.getAttributeNode('maxLength'); + return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; } }; +attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength; + // Slick var Slick = local.Slick = (this.Slick || {}); -Slick.version = '1.1.5'; +Slick.version = '1.1.6'; // Slick finder Slick.search = function(context, expression, append){ return local.search(context, expression, append); @@ -2628,13 +2630,19 @@ }; // Slick attribute getter Slick.getAttribute = function(node, name){ + local.setDocument(node); return local.getAttribute(node, name); }; +Slick.hasAttribute = function(node, name){ + local.setDocument(node); + return local.hasAttribute(node, name); +}; + // Slick matcher Slick.match = function(node, selector){ if (!(node && selector)) return false; if (!selector || selector === node) return true; @@ -2695,11 +2703,11 @@ description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. license: MIT-style license. -requires: [Window, Document, Array, String, Function, Number, Slick.Parser, Slick.Finder] +requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder] provides: [Element, Elements, $, $$, Iframe, Selectors] ... */ @@ -2715,12 +2723,12 @@ var parsed = Slick.parse(tag).expressions[0][0]; tag = (parsed.tag == '*') ? 'div' : parsed.tag; if (parsed.id && props.id == null) props.id = parsed.id; var attributes = parsed.attributes; - if (attributes) for (var i = 0, l = attributes.length; i < l; i++){ - var attr = attributes[i]; + if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){ + attr = attributes[i]; if (props[attr.key] != null) continue; if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value; else if (!attr.value && !attr.operator) props[attr.key] = true; } @@ -2860,13 +2868,13 @@ var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2}; splice.call(object, 1, 1); if (object[1] == 1) Elements.implement('splice', function(){ var length = this.length; - splice.apply(this, arguments); + var result = splice.apply(this, arguments); while (length >= this.length) delete this[length--]; - return this; + return result; }.protect()); Elements.implement(Array.prototype); Array.mirror(Elements); @@ -2982,65 +2990,97 @@ return document.id(Slick.find(this, expression)); } }); +var contains = {contains: function(element){ + return Slick.contains(this, element); +}}; +if (!document.contains) Document.implement(contains); +if (!document.createElement('div').contains) Element.implement(contains); + + +// tree walking + +var injectCombinator = function(expression, combinator){ + if (!expression) return combinator; + + expression = Object.clone(Slick.parse(expression)); + + var expressions = expression.expressions; + for (var i = expressions.length; i--;) + expressions[i][0].combinator = combinator; + + return expression; +}; + +Object.forEach({ + getNext: '~', + getPrevious: '!~', + getParent: '!' +}, function(combinator, method){ + Element.implement(method, function(expression){ + return this.getElement(injectCombinator(expression, combinator)); + }); +}); + +Object.forEach({ + getAllNext: '~', + getAllPrevious: '!~', + getSiblings: '~~', + getChildren: '>', + getParents: '!' +}, function(combinator, method){ + Element.implement(method, function(expression){ + return this.getElements(injectCombinator(expression, combinator)); + }); +}); + +Element.implement({ + + getFirst: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); + }, + + getLast: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); + }, + + getWindow: function(){ + return this.ownerDocument.window; + }, + + getDocument: function(){ + return this.ownerDocument; + }, + + getElementById: function(id){ + return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); + }, + + match: function(expression){ + return !expression || Slick.match(this, expression); + } + +}); + + + if (window.$$ == null) Window.implement('$$', function(selector){ if (arguments.length == 1){ if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements); else if (Type.isEnumerable(selector)) return new Elements(selector); } return new Elements(arguments); }); (function(){ -var collected = {}, storage = {}; -var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; +// Inserters -var get = function(uid){ - return (storage[uid] || (storage[uid] = {})); -}; - -var clean = function(item){ - var uid = item.uid; - if (item.removeEvents) item.removeEvents(); - if (item.clearAttributes) item.clearAttributes(); - if (uid != null){ - delete collected[uid]; - delete storage[uid]; - } - return item; -}; - -var camels = ['defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', - 'rowSpan', 'tabIndex', 'useMap' -]; -var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected', - 'noresize', 'defer', 'defaultChecked' -]; - var attributes = { - 'html': 'innerHTML', - 'class': 'className', - 'for': 'htmlFor', - 'text': (function(){ - var temp = document.createElement('div'); - return (temp.textContent == null) ? 'innerText' : 'textContent'; - })() -}; -var readOnly = ['type']; -var expandos = ['value', 'defaultValue']; -var uriAttrs = /^(?:href|src|usemap)$/i; - -bools = bools.associate(bools); -camels = camels.associate(camels.map(String.toLowerCase)); -readOnly = readOnly.associate(readOnly); - -Object.append(attributes, expandos.associate(expandos)); - var inserters = { before: function(context, element){ var parent = element.parentNode; if (parent) parent.insertBefore(context, element); @@ -3063,81 +3103,141 @@ inserters.inside = inserters.bottom; -var injectCombinator = function(expression, combinator){ - if (!expression) return combinator; +// getProperty / setProperty - expression = Object.clone(Slick.parse(expression)); +var propertyGetters = {}, propertySetters = {}; - var expressions = expression.expressions; - for (var i = expressions.length; i--;) - expressions[i][0].combinator = combinator; +// properties - return expression; -}; +var properties = {}; +Array.forEach([ + 'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', + 'frameBorder', 'readOnly', 'rowSpan', 'tabIndex', 'useMap' +], function(property){ + properties[property.toLowerCase()] = property; +}); -Element.implement({ +Object.append(properties, { + 'html': 'innerHTML', + 'text': (function(){ + var temp = document.createElement('div'); + return (temp.textContent == null) ? 'innerText': 'textContent'; + })() +}); - set: function(prop, value){ - var property = Element.Properties[prop]; - (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); - }.overloadSetter(), +Object.forEach(properties, function(real, key){ + propertySetters[key] = function(node, value){ + node[real] = value; + }; + propertyGetters[key] = function(node){ + return node[real]; + }; +}); - get: function(prop){ - var property = Element.Properties[prop]; - return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); - }.overloadGetter(), +// Booleans - erase: function(prop){ - var property = Element.Properties[prop]; - (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); - return this; +var bools = [ + 'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', + 'disabled', 'readOnly', 'multiple', 'selected', 'noresize', + 'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay', + 'loop' +]; + +var booleans = {}; +Array.forEach(bools, function(bool){ + var lower = bool.toLowerCase(); + booleans[lower] = bool; + propertySetters[lower] = function(node, value){ + node[bool] = !!value; + }; + propertyGetters[lower] = function(node){ + return !!node[bool]; + }; +}); + +// Special cases + +Object.append(propertySetters, { + + 'class': function(node, value){ + ('className' in node) ? node.className = value : node.setAttribute('class', value); }, - setProperty: function(attribute, value){ - attribute = camels[attribute] || attribute; - if (value == null) return this.removeProperty(attribute); - var key = attributes[attribute]; - (key) ? this[key] = value : - (bools[attribute]) ? this[attribute] = !!value : this.setAttribute(attribute, '' + value); + 'for': function(node, value){ + ('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value); + }, + + 'style': function(node, value){ + (node.style) ? node.style.cssText = value : node.setAttribute('style', value); + } + +}); + +/* getProperty, setProperty */ + +Element.implement({ + + setProperty: function(name, value){ + var lower = name.toLowerCase(); + if (value == null){ + if (!booleans[lower]){ + this.removeAttribute(name); + return this; + } + value = false; + } + var setter = propertySetters[lower]; + if (setter) setter(this, value); + else this.setAttribute(name, value); return this; }, setProperties: function(attributes){ for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); return this; }, - getProperty: function(attribute){ - attribute = camels[attribute] || attribute; - var key = attributes[attribute] || readOnly[attribute]; - return (key) ? this[key] : - (bools[attribute]) ? !!this[attribute] : - (uriAttrs.test(attribute) ? this.getAttribute(attribute, 2) : - (key = this.getAttributeNode(attribute)) ? key.nodeValue : null) || null; + getProperty: function(name){ + var getter = propertyGetters[name.toLowerCase()]; + if (getter) return getter(this); + var result = Slick.getAttribute(this, name); + return (!result && !Slick.hasAttribute(this, name)) ? null : result; }, getProperties: function(){ var args = Array.from(arguments); return args.map(this.getProperty, this).associate(args); }, - removeProperty: function(attribute){ - attribute = camels[attribute] || attribute; - var key = attributes[attribute]; - (key) ? this[key] = '' : - (bools[attribute]) ? this[attribute] = false : this.removeAttribute(attribute); - return this; + removeProperty: function(name){ + return this.setProperty(name, null); }, removeProperties: function(){ Array.each(arguments, this.removeProperty, this); return this; }, + set: function(prop, value){ + var property = Element.Properties[prop]; + (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); + }.overloadSetter(), + + get: function(prop){ + var property = Element.Properties[prop]; + return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); + }.overloadGetter(), + + erase: function(prop){ + var property = Element.Properties[prop]; + (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); + return this; + }, + hasClass: function(className){ return this.className.clean().contains(className, ' '); }, addClass: function(className){ @@ -3192,62 +3292,10 @@ wraps: function(el, where){ el = document.id(el, true); return this.replaces(el).grab(el, where); }, - getPrevious: function(expression){ - return document.id(Slick.find(this, injectCombinator(expression, '!~'))); - }, - - getAllPrevious: function(expression){ - return Slick.search(this, injectCombinator(expression, '!~'), new Elements); - }, - - getNext: function(expression){ - return document.id(Slick.find(this, injectCombinator(expression, '~'))); - }, - - getAllNext: function(expression){ - return Slick.search(this, injectCombinator(expression, '~'), new Elements); - }, - - getFirst: function(expression){ - return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); - }, - - getLast: function(expression){ - return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); - }, - - getParent: function(expression){ - return document.id(Slick.find(this, injectCombinator(expression, '!'))); - }, - - getParents: function(expression){ - return Slick.search(this, injectCombinator(expression, '!'), new Elements); - }, - - getSiblings: function(expression){ - return Slick.search(this, injectCombinator(expression, '~~'), new Elements); - }, - - getChildren: function(expression){ - return Slick.search(this, injectCombinator(expression, '>'), new Elements); - }, - - getWindow: function(){ - return this.ownerDocument.window; - }, - - getDocument: function(){ - return this.ownerDocument; - }, - - getElementById: function(id){ - return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); - }, - getSelected: function(){ this.selectedIndex; // Safari 3.2.1 return new Elements(Array.from(this.options).filter(function(option){ return option.selected; })); @@ -3267,12 +3315,35 @@ Array.from(value).each(function(val){ if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val)); }); }); return queryString.join('&'); - }, + } +}); + +var collected = {}, storage = {}; + +var get = function(uid){ + return (storage[uid] || (storage[uid] = {})); +}; + +var clean = function(item){ + var uid = item.uid; + if (item.removeEvents) item.removeEvents(); + if (item.clearAttributes) item.clearAttributes(); + if (uid != null){ + delete collected[uid]; + delete storage[uid]; + } + return item; +}; + +var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; + +Element.implement({ + destroy: function(){ var children = clean(this).getElementsByTagName('*'); Array.each(children, clean); Element.dispose(this); return null; @@ -3285,59 +3356,48 @@ dispose: function(){ return (this.parentNode) ? this.parentNode.removeChild(this) : this; }, - match: function(expression){ - return !expression || Slick.match(this, expression); - } + clone: function(contents, keepid){ + contents = contents !== false; + var clone = this.cloneNode(contents), ce = [clone], te = [this], i; -}); + if (contents){ + ce.append(Array.from(clone.getElementsByTagName('*'))); + te.append(Array.from(this.getElementsByTagName('*'))); + } -var cleanClone = function(node, element, keepid){ - if (!keepid) node.setAttributeNode(document.createAttribute('id')); - if (node.clearAttributes){ - node.clearAttributes(); - node.mergeAttributes(element); - node.removeAttribute('uid'); - if (node.options){ - var no = node.options, eo = element.options; - for (var i = no.length; i--;) no[i].selected = eo[i].selected; + for (i = ce.length; i--;){ + var node = ce[i], element = te[i]; + if (!keepid) node.removeAttribute('id'); + /*<ltIE9>*/ + if (node.clearAttributes){ + node.clearAttributes(); + node.mergeAttributes(element); + node.removeAttribute('uid'); + if (node.options){ + var no = node.options, eo = element.options; + for (var j = no.length; j--;) no[j].selected = eo[j].selected; + } + } + /*</ltIE9>*/ + var prop = formProps[element.tagName.toLowerCase()]; + if (prop && element[prop]) node[prop] = element[prop]; } - } - var prop = formProps[element.tagName.toLowerCase()]; - if (prop && element[prop]) node[prop] = element[prop]; -}; - -Element.implement('clone', function(contents, keepid){ - contents = contents !== false; - var clone = this.cloneNode(contents), i; - - if (contents){ - var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*'); - for (i = ce.length; i--;) cleanClone(ce[i], te[i], keepid); + /*<ltIE9>*/ + if (Browser.ie){ + var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); + for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; + } + /*</ltIE9>*/ + return document.id(clone); } - cleanClone(clone, this, keepid); - - if (Browser.ie){ - var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); - for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; - } - return document.id(clone); }); -var contains = {contains: function(element){ - return Slick.contains(this, element); -}}; - -if (!document.contains) Document.implement(contains); -if (!document.createElement('div').contains) Element.implement(contains); - - - [Element, Window, Document].invoke('implement', { addListener: function(type, fn){ if (type == 'unload'){ var old = fn, self = this; @@ -3384,12 +3444,10 @@ Object.each(collected, clean); if (window.CollectGarbage) CollectGarbage(); }); /*</ltIE9>*/ -})(); - Element.Properties = {}; Element.Properties.style = { @@ -3414,21 +3472,10 @@ return this.tagName.toLowerCase(); } }; -/*<ltIE9>*/ -(function(maxLength){ - if (maxLength != null) Element.Properties.maxlength = Element.Properties.maxLength = { - get: function(){ - var maxlength = this.getAttribute('maxLength'); - return maxlength == maxLength ? null : maxlength; - } - }; -})(document.createElement('input').getAttribute('maxLength')); -/*</ltIE9>*/ - /*<!webkit>*/ Element.Properties.html = (function(){ var tableTest = Function.attempt(function(){ var table = document.createElement('table'); @@ -3443,14 +3490,30 @@ tbody: [2, '<table><tbody>', '</tbody></table>'], tr: [3, '<table><tbody><tr>', '</tr></tbody></table>'] }; translations.thead = translations.tfoot = translations.tbody; + /*<ltIE9>*/ + // technique by jdbarlett - http://jdbartlett.com/innershiv/ + wrapper.innerHTML = '<nav></nav>'; + var HTML5Test = wrapper.childNodes.length == 1; + if (!HTML5Test){ + var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '), + fragment = document.createDocumentFragment(), l = tags.length; + while (l--) fragment.createElement(tags[l]); + fragment.appendChild(wrapper); + } + /*</ltIE9>*/ + var html = { - set: function(){ - var html = Array.flatten(arguments).join(''); + set: function(html){ + if (typeOf(html) == 'array') html = html.join(''); + var wrap = (!tableTest && translations[this.get('tag')]); + /*<ltIE9>*/ + if (!wrap && !HTML5Test) wrap = [0, '', '']; + /*</ltIE9>*/ if (wrap){ var first = wrapper; first.innerHTML = wrap[1] + html + wrap[2]; for (var i = wrap[0]; i--;) first = first.firstChild; this.empty().adopt(first.childNodes); @@ -3464,11 +3527,45 @@ return html; })(); /*</!webkit>*/ +/*<ltIE9>*/ +var testForm = document.createElement('form'); +testForm.innerHTML = '<select><option>s</option></select>'; +if (testForm.firstChild.value != 's') Element.Properties.value = { + + set: function(value){ + var tag = this.get('tag'); + if (tag != 'select') return this.setProperty('value', value); + var options = this.getElements('option'); + for (var i = 0; i < options.length; i++){ + var option = options[i], + attr = option.getAttributeNode('value'), + optionValue = (attr && attr.specified) ? option.value : option.get('text'); + if (optionValue == value) return option.selected = true; + } + }, + + get: function(){ + var option = this, tag = option.get('tag'); + + if (tag != 'select' && tag != 'option') return this.getProperty('value'); + + if (tag == 'select' && !(option = option.getSelected()[0])) return ''; + + var attr = option.getAttributeNode('value'); + return (attr && attr.specified) ? option.value : option.get('text'); + } + +}; +/*</ltIE9>*/ + +})(); + + /* --- name: Element.Style @@ -3489,46 +3586,43 @@ Element.Properties.styles = {set: function(styles){ this.setStyles(styles); }}; -var hasOpacity = (html.style.opacity != null); -var reAlpha = /alpha\(opacity=([\d.]+)\)/i; +var hasOpacity = (html.style.opacity != null), + hasFilter = (html.style.filter != null), + reAlpha = /alpha\(opacity=([\d.]+)\)/i; -var setOpacity = function(element, opacity){ - if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1; - if (hasOpacity){ - element.style.opacity = opacity; - } else { - opacity = (opacity * 100).limit(0, 100).round(); - opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')'; - var filter = element.style.filter || element.getComputedStyle('filter') || ''; - element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity; - } +var setVisibility = function(element, opacity){ + element.store('$opacity', opacity); + element.style.visibility = opacity > 0 ? 'visible' : 'hidden'; }; -Element.Properties.opacity = { +var setOpacity = (hasOpacity ? function(element, opacity){ + element.style.opacity = opacity; +} : (hasFilter ? function(element, opacity){ + if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1; + opacity = (opacity * 100).limit(0, 100).round(); + opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')'; + var filter = element.style.filter || element.getComputedStyle('filter') || ''; + element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity; +} : setVisibility)); - set: function(opacity){ - var visibility = this.style.visibility; - if (opacity == 0 && visibility != 'hidden') this.style.visibility = 'hidden'; - else if (opacity != 0 && visibility != 'visible') this.style.visibility = 'visible'; +var getOpacity = (hasOpacity ? function(element){ + var opacity = element.style.opacity || element.getComputedStyle('opacity'); + return (opacity == '') ? 1 : opacity.toFloat(); +} : (hasFilter ? function(element){ + var filter = (element.style.filter || element.getComputedStyle('filter')), + opacity; + if (filter) opacity = filter.match(reAlpha); + return (opacity == null || filter == null) ? 1 : (opacity[1] / 100); +} : function(element){ + var opacity = element.retrieve('$opacity'); + if (opacity == null) opacity = (element.style.visibility == 'hidden' ? 0 : 1); + return opacity; +})); - setOpacity(this, opacity); - }, - - get: (hasOpacity) ? function(){ - var opacity = this.style.opacity || this.getComputedStyle('opacity'); - return (opacity == '') ? 1 : opacity; - } : function(){ - var opacity, filter = (this.style.filter || this.getComputedStyle('filter')); - if (filter) opacity = filter.match(reAlpha); - return (opacity == null || filter == null) ? 1 : (opacity[1] / 100); - } - -}; - var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat'; Element.implement({ getComputedStyle: function(property){ @@ -3536,25 +3630,16 @@ var defaultView = Element.getDocument(this).defaultView, computed = defaultView ? defaultView.getComputedStyle(this, null) : null; return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null; }, - setOpacity: function(value){ - setOpacity(this, value); - return this; - }, - - getOpacity: function(){ - return this.get('opacity'); - }, - setStyle: function(property, value){ - switch (property){ - case 'opacity': return this.set('opacity', parseFloat(value)); - case 'float': property = floatName; + if (property == 'opacity'){ + setOpacity(this, parseFloat(value)); + return this; } - property = property.camelCase(); + property = (property == 'float' ? floatName : property).camelCase(); if (typeOf(value) != 'string'){ var map = (Element.Styles[property] || '@').split(' '); value = Array.from(value).map(function(val, i){ if (!map[i]) return ''; return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; @@ -3565,15 +3650,12 @@ this.style[property] = value; return this; }, getStyle: function(property){ - switch (property){ - case 'opacity': return this.get('opacity'); - case 'float': property = floatName; - } - property = property.camelCase(); + if (property == 'opacity') return getOpacity(this); + property = (property == 'float' ? floatName : property).camelCase(); var result = this.style[property]; if (!result || property == 'zIndex'){ result = []; for (var style in Element.ShortStyles){ if (property != style) continue; @@ -3626,10 +3708,12 @@ zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' }; + + Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; ['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ var Short = Element.ShortStyles; var All = Element.Styles; @@ -3681,27 +3765,27 @@ var realType = type, custom = Element.Events[type], condition = fn, self = this; if (custom){ - if (custom.onAdd) custom.onAdd.call(this, fn); + if (custom.onAdd) custom.onAdd.call(this, fn, type); if (custom.condition){ condition = function(event){ - if (custom.condition.call(this, event)) return fn.call(this, event); + if (custom.condition.call(this, event, type)) return fn.call(this, event); return true; }; } - realType = custom.base || realType; + if (custom.base) realType = Function.from(custom.base).call(this, type); } var defn = function(){ return fn.call(self); }; var nativeEvent = Element.NativeEvents[realType]; if (nativeEvent){ if (nativeEvent == 2){ defn = function(event){ - event = new Event(event, self.getWindow()); + event = new DOMEvent(event, self.getWindow()); if (condition.call(self, event) === false) event.stop(); }; } this.addListener(realType, defn, arguments[2]); } @@ -3718,12 +3802,12 @@ var value = list.values[index]; delete list.keys[index]; delete list.values[index]; var custom = Element.Events[type]; if (custom){ - if (custom.onRemove) custom.onRemove.call(this, fn); - type = custom.base || type; + if (custom.onRemove) custom.onRemove.call(this, fn, type); + if (custom.base) type = Function.from(custom.base).call(this, type); } return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this; }, addEvents: function(events){ @@ -3785,11 +3869,11 @@ mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement keydown: 2, keypress: 2, keyup: 2, //keyboard orientationchange: 2, // mobile touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture - focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements + focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, input: 2, //form elements load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window error: 1, abort: 1, scroll: 1 //misc }; var check = function(event){ @@ -3815,18 +3899,234 @@ base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel' } }; +/*<ltIE9>*/ +if (!window.addEventListener){ + Element.NativeEvents.propertychange = 2; + Element.Events.change = { + base: function(){ + var type = this.type; + return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change' + }, + condition: function(event){ + return !!(this.type != 'radio' || this.checked); + } + } +} +/*</ltIE9>*/ + })(); /* --- +name: Element.Delegation + +description: Extends the Element native object to include the delegate method for more efficient event management. + +license: MIT-style license. + +requires: [Element.Event] + +provides: [Element.Delegation] + +... +*/ + +(function(){ + +var eventListenerSupport = !!window.addEventListener; + +Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2; + +var bubbleUp = function(self, match, fn, event, target){ + while (target && target != self){ + if (match(target, event)) return fn.call(target, event, target); + target = document.id(target.parentNode); + } +}; + +var map = { + mouseenter: { + base: 'mouseover' + }, + mouseleave: { + base: 'mouseout' + }, + focus: { + base: 'focus' + (eventListenerSupport ? '' : 'in'), + capture: true + }, + blur: { + base: eventListenerSupport ? 'blur' : 'focusout', + capture: true + } +}; + +/*<ltIE9>*/ +var _key = '$delegation:'; +var formObserver = function(type){ + + return { + + base: 'focusin', + + remove: function(self, uid){ + var list = self.retrieve(_key + type + 'listeners', {})[uid]; + if (list && list.forms) for (var i = list.forms.length; i--;){ + list.forms[i].removeEvent(type, list.fns[i]); + } + }, + + listen: function(self, match, fn, event, target, uid){ + var form = (target.get('tag') == 'form') ? target : event.target.getParent('form'); + if (!form) return; + + var listeners = self.retrieve(_key + type + 'listeners', {}), + listener = listeners[uid] || {forms: [], fns: []}, + forms = listener.forms, fns = listener.fns; + + if (forms.indexOf(form) != -1) return; + forms.push(form); + + var _fn = function(event){ + bubbleUp(self, match, fn, event, target); + }; + form.addEvent(type, _fn); + fns.push(_fn); + + listeners[uid] = listener; + self.store(_key + type + 'listeners', listeners); + } + }; +}; + +var inputObserver = function(type){ + return { + base: 'focusin', + listen: function(self, match, fn, event, target){ + var events = {blur: function(){ + this.removeEvents(events); + }}; + events[type] = function(event){ + bubbleUp(self, match, fn, event, target); + }; + event.target.addEvents(events); + } + }; +}; + +if (!eventListenerSupport) Object.append(map, { + submit: formObserver('submit'), + reset: formObserver('reset'), + change: inputObserver('change'), + select: inputObserver('select') +}); +/*</ltIE9>*/ + +var proto = Element.prototype, + addEvent = proto.addEvent, + removeEvent = proto.removeEvent; + +var relay = function(old, method){ + return function(type, fn, useCapture){ + if (type.indexOf(':relay') == -1) return old.call(this, type, fn, useCapture); + var parsed = Slick.parse(type).expressions[0][0]; + if (parsed.pseudos[0].key != 'relay') return old.call(this, type, fn, useCapture); + var newType = parsed.tag; + parsed.pseudos.slice(1).each(function(pseudo){ + newType += ':' + pseudo.key + (pseudo.value ? '(' + pseudo.value + ')' : ''); + }); + old.call(this, type, fn); + return method.call(this, newType, parsed.pseudos[0].value, fn); + }; +}; + +var delegation = { + + addEvent: function(type, match, fn){ + var storage = this.retrieve('$delegates', {}), stored = storage[type]; + if (stored) for (var _uid in stored){ + if (stored[_uid].fn == fn && stored[_uid].match == match) return this; + } + + var _type = type, _match = match, _fn = fn, _map = map[type] || {}; + type = _map.base || _type; + + match = function(target){ + return Slick.match(target, _match); + }; + + var elementEvent = Element.Events[_type]; + if (elementEvent && elementEvent.condition){ + var __match = match, condition = elementEvent.condition; + match = function(target, event){ + return __match(target, event) && condition.call(target, event, type); + }; + } + + var self = this, uid = String.uniqueID(); + var delegator = _map.listen ? function(event, target){ + if (!target && event && event.target) target = event.target; + if (target) _map.listen(self, match, fn, event, target, uid); + } : function(event, target){ + if (!target && event && event.target) target = event.target; + if (target) bubbleUp(self, match, fn, event, target); + }; + + if (!stored) stored = {}; + stored[uid] = { + match: _match, + fn: _fn, + delegator: delegator + }; + storage[_type] = stored; + return addEvent.call(this, type, delegator, _map.capture); + }, + + removeEvent: function(type, match, fn, _uid){ + var storage = this.retrieve('$delegates', {}), stored = storage[type]; + if (!stored) return this; + + if (_uid){ + var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {}; + type = _map.base || _type; + if (_map.remove) _map.remove(this, _uid); + delete stored[_uid]; + storage[_type] = stored; + return removeEvent.call(this, type, delegator); + } + + var __uid, s; + if (fn) for (__uid in stored){ + s = stored[__uid]; + if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid); + } else for (__uid in stored){ + s = stored[__uid]; + if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid); + } + return this; + } + +}; + +[Element, Window, Document].invoke('implement', { + addEvent: relay(addEvent, delegation.addEvent), + removeEvent: relay(removeEvent, delegation.removeEvent) +}); + +})(); + + +/* +--- + name: Element.Dimensions description: Contains methods to work with size, scroll, or positioning of Elements and the window object. license: MIT-style license. @@ -3959,18 +4259,17 @@ } return position; }, getPosition: function(relative){ - if (isBody(this)) return {x: 0, y: 0}; var offset = this.getOffsets(), scroll = this.getScrolls(); var position = { x: offset.x - scroll.x, y: offset.y - scroll.y }; - + if (relative && (relative = document.id(relative))){ var relativePosition = relative.getPosition(); return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)}; } return position; @@ -4160,11 +4459,11 @@ this.time = now; this.frame += frames; } else { this.frame++; } - + if (this.frame < this.frames){ var delta = this.transition(this.frame / this.frames); this.set(this.compute(this.from, this.to, delta)); } else { this.frame = this.frames; @@ -4203,11 +4502,11 @@ this.frames = frames || Math.round(this.duration / this.frameInterval); this.fireEvent('start', this.subject); pushInstance.call(this, fps); return this; }, - + stop: function(){ if (this.isRunning()){ this.time = null; pullInstance.call(this, this.options.fps); if (this.frames == this.frame){ @@ -4217,34 +4516,34 @@ this.fireEvent('stop', this.subject); } } return this; }, - + cancel: function(){ if (this.isRunning()){ this.time = null; pullInstance.call(this, this.options.fps); this.frame = this.frames; this.fireEvent('cancel', this.subject).clearChain(); } return this; }, - + pause: function(){ if (this.isRunning()){ this.time = null; pullInstance.call(this, this.options.fps); } return this; }, - + resume: function(){ if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps); return this; }, - + isRunning: function(){ var list = instances[this.options.fps]; return list && list.contains(this); } @@ -4498,31 +4797,37 @@ }; Element.implement({ tween: function(property, from, to){ - this.get('tween').start(arguments); + this.get('tween').start(property, from, to); return this; }, fade: function(how){ - var fade = this.get('tween'), o = 'opacity', toggle; - how = [how, 'toggle'].pick(); + var fade = this.get('tween'), method, to, toggle; + if (how == null) how = 'toggle'; switch (how){ - case 'in': fade.start(o, 1); break; - case 'out': fade.start(o, 0); break; - case 'show': fade.set(o, 1); break; - case 'hide': fade.set(o, 0); break; + case 'in': method = 'start'; to = 1; break; + case 'out': method = 'start'; to = 0; break; + case 'show': method = 'set'; to = 1; break; + case 'hide': method = 'set'; to = 0; break; case 'toggle': - var flag = this.retrieve('fade:flag', this.get('opacity') == 1); - fade.start(o, (flag) ? 0 : 1); + var flag = this.retrieve('fade:flag', this.getStyle('opacity') == 1); + method = 'start'; + to = flag ? 0 : 1; this.store('fade:flag', !flag); toggle = true; break; - default: fade.start(o, arguments); + default: method = 'start'; to = how; } if (!toggle) this.eliminate('fade:flag'); + fade[method]('opacity', to); + if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible'); + else fade.chain(function(){ + this.element.setStyle('visibility', 'hidden'); + }); return this; }, highlight: function(start, end){ if (!end){ @@ -4803,11 +5108,11 @@ this.status = (status == 1223) ? 204 : status; }.bind(this)); xhr.onreadystatechange = empty; if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; clearTimeout(this.timer); - + this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML}; if (this.options.isSuccess.call(this, this.status)) this.success(this.response.text, this.response.xml); else this.failure(); @@ -4840,19 +5145,19 @@ }, onFailure: function(){ this.fireEvent('complete').fireEvent('failure', this.xhr); }, - + loadstart: function(event){ this.fireEvent('loadstart', [event, this.xhr]); }, - + progress: function(event){ this.fireEvent('progress', [event, this.xhr]); }, - + timeout: function(){ this.fireEvent('timeout', this.xhr); }, setHeader: function(name, value){ @@ -4872,11 +5177,11 @@ case 'cancel': this.cancel(); return true; case 'chain': this.chain(this.caller.pass(arguments, this)); return false; } return false; }, - + send: function(options){ if (!this.check(options)) return this; this.options.isSuccess = this.options.isSuccess || this.isSuccess; this.running = true; @@ -4908,11 +5213,11 @@ var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding; } if (!url) url = document.location.pathname; - + var trimPosition = url.lastIndexOf('/'); if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition); if (this.options.noCache) url += (url.contains('?') ? '&' : '?') + String.uniqueID(); @@ -4928,11 +5233,11 @@ xhr.onprogress = this.progress.bind(this); } xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password); if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true; - + xhr.onreadystatechange = this.onStateChange.bind(this); Object.each(this.headers, function(value, key){ try { xhr.setRequestHeader(key, value); @@ -5049,15 +5354,22 @@ var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i); if (match) response.html = match[1]; var temp = new Element('div').set('html', response.html); response.tree = temp.childNodes; - response.elements = temp.getElements('*'); + response.elements = temp.getElements(options.filter || '*'); - if (options.filter) response.tree = response.elements.filter(options.filter); - if (options.update) document.id(options.update).empty().set('html', response.html); - else if (options.append) document.id(options.append).adopt(temp.getChildren()); + if (options.filter) response.tree = response.elements; + if (options.update){ + var update = document.id(options.update).empty(); + if (options.filter) update.adopt(response.elements); + else update.set('html', response.html); + } else if (options.append){ + var append = document.id(options.append); + if (options.filter) response.elements.reverse().inject(append); + else append.adopt(temp.getChildren()); + } if (options.evalScripts) Browser.exec(response.javascript); this.onSuccess(response.tree, response.elements, response.html, response.javascript); } @@ -5099,11 +5411,11 @@ description: JSON encoder and decoder. license: MIT-style license. -See Also: <http://www.json.org/> +SeeAlso: <http://www.json.org/> requires: [Array, String, Number, Function] provides: JSON @@ -5320,11 +5632,11 @@ var domready = function(){ clearTimeout(timer); if (ready) return; Browser.loaded = ready = true; document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check); - + document.fireEvent('domready'); window.fireEvent('domready'); }; var check = function(){ @@ -5349,10 +5661,10 @@ try { testElement.doScroll(); return true; } catch (e){} return false; -} +}; // If doScroll works already, it can't be used to determine domready // e.g. in an iframe if (testElement.doScroll && !doScrollWorks()){ checks.push(doScrollWorks); shouldPoll = true;