From: Eugene Crosser Date: Wed, 23 Dec 2009 19:58:35 +0000 (+0000) Subject: Refresh version of mootools, now slideshow works with IE8 X-Git-Tag: 2.01~1 X-Git-Url: http://www.average.org/gitweb/?p=mkgallery.git;a=commitdiff_plain;h=b39075695e95b6668e5d3c149bb179dbe9a65f3e Refresh version of mootools, now slideshow works with IE8 --- diff --git a/include/mootools.js b/include/mootools.js index ebc3984..3ad6d9f 100644 --- a/include/mootools.js +++ b/include/mootools.js @@ -1,38 +1,41 @@ /* -Script: Core.js - MooTools - My Object Oriented JavaScript Tools. +--- -License: - MIT-style license. +script: Core.js -Copyright: - Copyright (c) 2006-2007 [Valerio Proietti](http://mad4milk.net/). +description: The core of MooTools, contains all the base functions and the Native and Hash implementations. Required by all the other scripts. -Code & Documentation: - [The MooTools production team](http://mootools.net/developers/). +license: MIT-style license. -Inspiration: - - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) - - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) +copyright: Copyright (c) 2006-2008 [Valerio Proietti](http://mad4milk.net/). + +authors: The MooTools production team (http://mootools.net/developers/) + +inspiration: +- Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) +- Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) + +provides: [Mootools, Native, Hash.base, Array.each, $util] + +... */ var MooTools = { - 'version': '1.2.0', - 'build': '' + 'version': '1.2.4', + 'build': '0d9113241a90b9cd5643b926795852a2026710d4' }; - + var Native = function(options){ options = options || {}; - - var afterImplement = options.afterImplement || function(){}; - var generics = options.generics; - generics = (generics !== false); + var name = options.name; var legacy = options.legacy; - var initialize = options.initialize; var protect = options.protect; - var name = options.name; - + var methods = options.implement; + var generics = options.generics; + var initialize = options.initialize; + var afterImplement = options.afterImplement || function(){}; var object = initialize || legacy; + generics = generics !== false; object.constructor = Native; object.$family = {name: 'native'}; @@ -51,28 +54,25 @@ var Native = function(options){ afterImplement.call(obj, name, method); return obj; }; - - object.implement = function(a1, a2, a3){ - if (typeof a1 == 'string') return add(this, a1, a2, a3); - for (var p in a1) add(this, p, a1[p], a2); - return this; - }; - + object.alias = function(a1, a2, a3){ if (typeof a1 == 'string'){ - a1 = this.prototype[a1]; - if (a1) add(this, a2, a1, a3); - } else { - for (var a in a1) this.alias(a, a1[a], a2); + var pa1 = this.prototype[a1]; + if ((a1 = pa1)) return add(this, a2, a1, a3); } + for (var a in a1) this.alias(a, a1[a], a2); return this; }; - return object; -}; + object.implement = function(a1, a2, a3){ + if (typeof a1 == 'string') return add(this, a1, a2, a3); + for (var p in a1) add(this, p, a1[p], a2); + return this; + }; -Native.implement = function(objects, properties){ - for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties); + if (methods) object.implement(methods); + + return object; }; Native.genericize = function(object, property, check){ @@ -82,30 +82,96 @@ Native.genericize = function(object, property, check){ }; }; +Native.implement = function(objects, properties){ + for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties); +}; + Native.typize = function(object, family){ if (!object.type) object.type = function(item){ return ($type(item) === family); }; }; -Native.alias = function(objects, a1, a2, a3){ - for (var i = 0, j = objects.length; i < j; i++) objects[i].alias(a1, a2, a3); -}; +(function(){ + var natives = {'Array': Array, 'Date': Date, 'Function': Function, 'Number': Number, 'RegExp': RegExp, 'String': String}; + for (var n in natives) new Native({name: n, initialize: natives[n], protect: true}); + + var types = {'boolean': Boolean, 'native': Native, 'object': Object}; + for (var t in types) Native.typize(types[t], t); + + var generics = { + 'Array': ["concat", "indexOf", "join", "lastIndexOf", "pop", "push", "reverse", "shift", "slice", "sort", "splice", "toString", "unshift", "valueOf"], + 'String': ["charAt", "charCodeAt", "concat", "indexOf", "lastIndexOf", "match", "replace", "search", "slice", "split", "substr", "substring", "toLowerCase", "toUpperCase", "valueOf"] + }; + for (var g in generics){ + for (var i = generics[g].length; i--;) Native.genericize(natives[g], generics[g][i], true); + } +})(); + +var Hash = new Native({ + + name: 'Hash', + + initialize: function(object){ + if ($type(object) == 'hash') object = $unlink(object.getClean()); + for (var key in object) this[key] = object[key]; + return this; + } + +}); + +Hash.implement({ + + forEach: function(fn, bind){ + for (var key in this){ + if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this); + } + }, + + getClean: function(){ + var clean = {}; + for (var key in this){ + if (this.hasOwnProperty(key)) clean[key] = this[key]; + } + return clean; + }, + + getLength: function(){ + var length = 0; + for (var key in this){ + if (this.hasOwnProperty(key)) length++; + } + return length; + } + +}); + +Hash.alias('forEach', 'each'); + +Array.implement({ -(function(objects){ - for (var name in objects) Native.typize(objects[name], name); -})({'boolean': Boolean, 'native': Native, 'object': Object}); + forEach: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this); + } + +}); + +Array.alias('forEach', 'each'); -(function(objects){ - for (var name in objects) new Native({name: name, initialize: objects[name], protect: true}); -})({'String': String, 'Function': Function, 'Number': Number, 'Array': Array, 'RegExp': RegExp, 'Date': Date}); +function $A(iterable){ + if (iterable.item){ + var l = iterable.length, array = new Array(l); + while (l--) array[l] = iterable[l]; + return array; + } + return Array.prototype.slice.call(iterable); +}; -(function(object, methods){ - for (var i = methods.length; i--; i) Native.genericize(object, methods[i], true); - return arguments.callee; -}) -(Array, ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 'toString', 'valueOf', 'indexOf', 'lastIndexOf']) -(String, ['charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'replace', 'search', 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase', 'valueOf']); +function $arguments(i){ + return function(){ + return arguments[i]; + }; +}; function $chk(obj){ return !!(obj || obj === 0); @@ -121,54 +187,41 @@ function $defined(obj){ return (obj != undefined); }; -function $empty(){}; - -function $arguments(i){ - return function(){ - return arguments[i]; - }; +function $each(iterable, fn, bind){ + var type = $type(iterable); + ((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind); }; -function $lambda(value){ - return (typeof value == 'function') ? value : function(){ - return value; - }; -}; +function $empty(){}; function $extend(original, extended){ for (var key in (extended || {})) original[key] = extended[key]; return original; }; -function $unlink(object){ - var unlinked; - - switch ($type(object)){ - case 'object': - unlinked = {}; - for (var p in object) unlinked[p] = $unlink(object[p]); - break; - case 'hash': - unlinked = $unlink(object.getClean()); - break; - case 'array': - unlinked = []; - for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]); - break; - default: return object; - } - - return unlinked; +function $H(object){ + return new Hash(object); +}; + +function $lambda(value){ + return ($type(value) == 'function') ? value : function(){ + return value; + }; }; function $merge(){ - var mix = {}; - for (var i = 0, l = arguments.length; i < l; i++){ + var args = Array.slice(arguments); + args.unshift({}); + return $mixin.apply(null, args); +}; + +function $mixin(mix){ + for (var i = 1, l = arguments.length; i < l; i++){ var object = arguments[i]; if ($type(object) != 'object') continue; for (var key in object){ var op = object[key], mp = mix[key]; - mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $merge(mp, op) : $unlink(op); + mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $mixin(mp, op) : $unlink(op); } } return mix; @@ -191,7 +244,7 @@ function $splat(obj){ }; var $time = Date.now || function(){ - return new Date().getTime(); + return +new Date; }; function $try(){ @@ -218,105 +271,102 @@ function $type(obj){ return typeof obj; }; -var Hash = new Native({ +function $unlink(object){ + var unlinked; + switch ($type(object)){ + case 'object': + unlinked = {}; + for (var p in object) unlinked[p] = $unlink(object[p]); + break; + case 'hash': + unlinked = new Hash(object); + break; + case 'array': + unlinked = []; + for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]); + break; + default: return object; + } + return unlinked; +}; - name: 'Hash', - initialize: function(object){ - if ($type(object) == 'hash') object = $unlink(object.getClean()); - for (var key in object) this[key] = object[key]; - return this; - } +/* +--- -}); +script: Browser.js -Hash.implement({ - - getLength: function(){ - var length = 0; - for (var key in this){ - if (this.hasOwnProperty(key)) length++; - } - return length; - }, +description: The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash. - forEach: function(fn, bind){ - for (var key in this){ - if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this); - } - }, - - getClean: function(){ - var clean = {}; - for (var key in this){ - if (this.hasOwnProperty(key)) clean[key] = this[key]; - } - return clean; - } +license: MIT-style license. -}); +requires: +- /Native +- /$util -Hash.alias('forEach', 'each'); +provides: [Browser, Window, Document, $exec] -function $H(object){ - return new Hash(object); -}; +... +*/ -Array.implement({ +var Browser = $merge({ - forEach: function(fn, bind){ - for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this); - } + Engine: {name: 'unknown', version: 0}, -}); + Platform: {name: (window.orientation != undefined) ? 'ipod' : (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()}, -Array.alias('forEach', 'each'); + Features: {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)}, -function $A(iterable){ - if (iterable.item){ - var array = []; - for (var i = 0, l = iterable.length; i < l; i++) array[i] = iterable[i]; - return array; - } - return Array.prototype.slice.call(iterable); -}; + Plugins: {}, -function $each(iterable, fn, bind){ - var type = $type(iterable); - ((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind); -}; + Engines: { + presto: function(){ + return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); + }, -/* -Script: Browser.js - The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash. + trident: function(){ + return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); + }, -License: - MIT-style license. -*/ + webkit: function(){ + return (navigator.taintEnabled) ? false : ((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) : 419); + }, -var Browser = new Hash({ - Engine: {name: 'unknown', version: ''}, - Platform: {name: (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()}, - Features: {xpath: !!(document.evaluate), air: !!(window.runtime)}, - Plugins: {} -}); + gecko: function(){ + return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18); + } -if (window.opera) Browser.Engine = {name: 'presto', version: (document.getElementsByClassName) ? 950 : 925}; -else if (window.ActiveXObject) Browser.Engine = {name: 'trident', version: (window.XMLHttpRequest) ? 5 : 4}; -else if (!navigator.taintEnabled) Browser.Engine = {name: 'webkit', version: (Browser.Features.xpath) ? 420 : 419}; -else if (document.getBoxObjectFor != null) Browser.Engine = {name: 'gecko', version: (document.getElementsByClassName) ? 19 : 18}; -Browser.Engine[Browser.Engine.name] = Browser.Engine[Browser.Engine.name + Browser.Engine.version] = true; + } -if (window.orientation != undefined) Browser.Platform.name = 'ipod'; +}, Browser || {}); Browser.Platform[Browser.Platform.name] = true; +Browser.detect = function(){ + + for (var engine in this.Engines){ + var version = this.Engines[engine](); + if (version){ + this.Engine = {name: engine, version: version}; + this.Engine[engine] = this.Engine[engine + version] = true; + break; + } + } + + return {name: engine, version: version}; + +}; + +Browser.detect(); + Browser.Request = function(){ return $try(function(){ return new XMLHttpRequest(); }, function(){ return new ActiveXObject('MSXML2.XMLHTTP'); + }, function(){ + return new ActiveXObject('Microsoft.XMLHTTP'); }); }; @@ -328,7 +378,7 @@ Browser.Plugins.Flash = (function(){ }, function(){ return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); }) || '0 r0').match(/\d+/g); - return {version: parseInt(version[0] || 0 + '.' + version[1] || 0), build: parseInt(version[2] || 0)}; + return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0}; })(); function $exec(text){ @@ -338,7 +388,7 @@ function $exec(text){ } else { var script = document.createElement('script'); script.setAttribute('type', 'text/javascript'); - script.text = text; + script[(Browser.Engine.webkit && Browser.Engine.version < 420) ? 'innerText' : 'text'] = text; document.head.appendChild(script); document.head.removeChild(script); } @@ -366,6 +416,7 @@ var Window = new Native({ if (Browser.Engine.webkit) win.document.createElement("iframe"); //fixes safari 2 win.Element.prototype = (Browser.Engine.webkit) ? window["[[DOMElement.prototype]]"] : {}; } + win.document.window = win; return $extend(win, Window.Prototype); }, @@ -389,10 +440,13 @@ var Document = new Native({ $uid(doc); doc.head = doc.getElementsByTagName('head')[0]; doc.html = doc.getElementsByTagName('html')[0]; - doc.window = doc.defaultView || doc.parentWindow; - if (Browser.Engine.trident4) $try(function(){ + if (Browser.Engine.trident && Browser.Engine.version <= 4) $try(function(){ doc.execCommand("BackgroundImageCache", false, true); }); + if (Browser.Engine.trident) doc.window.attachEvent('onunload', function(){ + doc.window.detachEvent('onunload', arguments.callee); + doc.head = doc.html = doc.window = null; + }); return $extend(doc, Document.Prototype); }, @@ -406,12 +460,23 @@ Document.Prototype = {$family: {name: 'document'}}; new Document(document); + /* -Script: Array.js - Contains Array Prototypes like copy, each, contains, and remove. +--- + +script: Array.js -License: - MIT-style license. +description: Contains Array Prototypes like each, contains, and erase. + +license: MIT-style license. + +requires: +- /$util +- /Array.each + +provides: [Array] + +... */ Array.implement({ @@ -430,8 +495,8 @@ Array.implement({ } return results; }, - - clean: function() { + + clean: function(){ return this.filter($defined); }, @@ -484,7 +549,7 @@ Array.implement({ for (var i = 0, j = array.length; i < j; i++) this.push(array[i]); return this; }, - + getLast: function(){ return (this.length) ? this[this.length - 1] : null; }, @@ -547,83 +612,105 @@ Array.implement({ }); -/* -Script: Function.js - Contains Function Prototypes like create, bind, pass, and delay. - -License: - MIT-style license. -*/ - -Function.implement({ - - extend: function(properties){ - for (var property in properties) this[property] = properties[property]; - return this; - }, - - create: function(options){ - var self = this; - options = options || {}; - return function(event){ - var args = options.arguments; - args = (args != undefined) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0); - if (options.event) args = [event || window.event].extend(args); - var returns = function(){ - return self.apply(options.bind || null, args); - }; - if (options.delay) return setTimeout(returns, options.delay); - if (options.periodical) return setInterval(returns, options.periodical); - if (options.attempt) return $try(returns); - return returns(); - }; - }, - - pass: function(args, bind){ - return this.create({arguments: args, bind: bind}); - }, - - attempt: function(args, bind){ - return this.create({arguments: args, bind: bind, attempt: true})(); - }, - - bind: function(bind, args){ - return this.create({bind: bind, arguments: args}); - }, - - bindWithEvent: function(bind, args){ - return this.create({bind: bind, event: true, arguments: args}); - }, - - delay: function(delay, bind, args){ - return this.create({delay: delay, bind: bind, arguments: args})(); - }, - - periodical: function(interval, bind, args){ - return this.create({periodical: interval, bind: bind, arguments: args})(); - }, - - run: function(args, bind){ - return this.apply(bind, $splat(args)); - } - -}); /* -Script: Number.js - Contains Number Prototypes like limit, round, times, and ceil. +--- -License: - MIT-style license. -*/ +script: Function.js -Number.implement({ +description: Contains Function Prototypes like create, bind, pass, and delay. - limit: function(min, max){ - return Math.min(max, Math.max(min, this)); - }, +license: MIT-style license. - round: function(precision){ +requires: +- /Native +- /$util + +provides: [Function] + +... +*/ + +Function.implement({ + + extend: function(properties){ + for (var property in properties) this[property] = properties[property]; + return this; + }, + + create: function(options){ + var self = this; + options = options || {}; + return function(event){ + var args = options.arguments; + args = (args != undefined) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0); + if (options.event) args = [event || window.event].extend(args); + var returns = function(){ + return self.apply(options.bind || null, args); + }; + if (options.delay) return setTimeout(returns, options.delay); + if (options.periodical) return setInterval(returns, options.periodical); + if (options.attempt) return $try(returns); + return returns(); + }; + }, + + run: function(args, bind){ + return this.apply(bind, $splat(args)); + }, + + pass: function(args, bind){ + return this.create({bind: bind, arguments: args}); + }, + + bind: function(bind, args){ + return this.create({bind: bind, arguments: args}); + }, + + bindWithEvent: function(bind, args){ + return this.create({bind: bind, arguments: args, event: true}); + }, + + attempt: function(args, bind){ + return this.create({bind: bind, arguments: args, attempt: true})(); + }, + + delay: function(delay, bind, args){ + return this.create({bind: bind, arguments: args, delay: delay})(); + }, + + periodical: function(periodical, bind, args){ + return this.create({bind: bind, arguments: args, periodical: periodical})(); + } + +}); + + +/* +--- + +script: Number.js + +description: Contains Number Prototypes like limit, round, times, and ceil. + +license: MIT-style license. + +requires: +- /Native +- /$util + +provides: [Number] + +... +*/ + +Number.implement({ + + limit: function(min, max){ + return Math.min(max, Math.max(min, this)); + }, + + round: function(precision){ precision = Math.pow(10, precision || 0); return Math.round(this * precision) / precision; }, @@ -654,12 +741,22 @@ Number.alias('times', 'each'); Number.implement(methods); })(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); + /* -Script: String.js - Contains String Prototypes like camelCase, capitalize, test, and toInt. +--- -License: - MIT-style license. +script: String.js + +description: Contains String Prototypes like camelCase, capitalize, test, and toInt. + +license: MIT-style license. + +requires: +- /Native + +provides: [String] + +... */ String.implement({ @@ -732,7 +829,7 @@ String.implement({ }, substitute: function(object, regexp){ - return this.replace(regexp || (/\\?\{([^}]+)\}/g), function(match, name){ + return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ if (match.charAt(0) == '\\') return match.slice(1); return (object[name] != undefined) ? object[name] : ''; }); @@ -740,12 +837,22 @@ String.implement({ }); + /* -Script: Hash.js - Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects. +--- + +script: Hash.js + +description: Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects. -License: - MIT-style license. +license: MIT-style license. + +requires: +- /Hash.base + +provides: [Hash] + +... */ Hash.implement({ @@ -764,14 +871,14 @@ Hash.implement({ }, extend: function(properties){ - Hash.each(properties, function(value, key){ + Hash.each(properties || {}, function(value, key){ Hash.set(this, key, value); }, this); return this; }, combine: function(properties){ - Hash.each(properties, function(value, key){ + Hash.each(properties || {}, function(value, key){ Hash.include(this, key, value); }, this); return this; @@ -799,8 +906,7 @@ Hash.implement({ }, include: function(key, value){ - var k = this[key]; - if (k == undefined) this[key] = value; + if (this[key] == undefined) this[key] = value; return this; }, @@ -849,7 +955,7 @@ Hash.implement({ }); return values; }, - + toQueryString: function(base){ var queryString = []; Hash.each(this, function(value, key){ @@ -868,7 +974,7 @@ Hash.implement({ } if (value != undefined) queryString.push(result); }); - + return queryString.join('&'); } @@ -876,12 +982,27 @@ Hash.implement({ Hash.alias({keyOf: 'indexOf', hasValue: 'contains'}); + /* -Script: Event.js - Contains the Event Native, to make the event object completely crossbrowser. +--- -License: - MIT-style license. +script: Event.js + +description: Contains the Event Class, to make the event object cross-browser. + +license: MIT-style license. + +requires: +- /Window +- /Document +- /Hash +- /Array +- /Function +- /String + +provides: [Event] + +... */ var Event = new Native({ @@ -897,7 +1018,7 @@ var Event = new Native({ var type = event.type; var target = event.target || event.srcElement; while (target && target.nodeType == 3) target = target.parentNode; - + if (type.test(/key/)){ var code = event.which || event.keyCode; var key = Event.Keys.keyOf(code); @@ -936,19 +1057,19 @@ var Event = new Native({ return $extend(this, { event: event, type: type, - + page: page, client: client, rightClick: rightClick, - + wheel: wheel, - + relatedTarget: related, target: target, - + code: code, key: key, - + shift: event.shiftKey, control: event.ctrlKey, alt: event.altKey, @@ -991,126 +1112,208 @@ Event.implement({ }); + /* -Script: Class.js - Contains the Class Function for easily creating, extending, and implementing reusable Classes. +--- + +script: Class.js + +description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. -License: - MIT-style license. +license: MIT-style license. + +requires: +- /$util +- /Native +- /Array +- /String +- /Function +- /Number +- /Hash + +provides: [Class] + +... */ -var Class = new Native({ +function Class(params){ + + if (params instanceof Function) params = {initialize: params}; + + var newClass = function(){ + Object.reset(this); + if (newClass._prototyping) return this; + this._current = $empty; + var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; + delete this._current; delete this.caller; + return value; + }.extend(this); + + newClass.implement(params); + + newClass.constructor = Class; + newClass.prototype.constructor = newClass; - name: 'Class', + return newClass; - initialize: function(properties){ - properties = properties || {}; - var klass = function(empty){ - for (var key in this) this[key] = $unlink(this[key]); - for (var mutator in Class.Mutators){ - if (!this[mutator]) continue; - Class.Mutators[mutator](this, this[mutator]); - delete this[mutator]; - } +}; - this.constructor = klass; - if (empty === $empty) return this; - - var self = (this.initialize) ? this.initialize.apply(this, arguments) : this; - if (this.options && this.options.initialize) this.options.initialize.call(this); - return self; - }; +Function.prototype.protect = function(){ + this._protected = true; + return this; +}; - $extend(klass, this); - klass.constructor = Class; - klass.prototype = properties; - return klass; +Object.reset = function(object, key){ + + if (key == null){ + for (var p in object) Object.reset(object, p); + return object; + } + + delete object[key]; + + switch ($type(object[key])){ + case 'object': + var F = function(){}; + F.prototype = object[key]; + var i = new F; + object[key] = Object.reset(i); + break; + case 'array': object[key] = $unlink(object[key]); break; } + + return object; + +}; + +new Native({name: 'Class', initialize: Class}).extend({ + + instantiate: function(F){ + F._prototyping = true; + var proto = new F; + delete F._prototyping; + return proto; + }, + + wrap: function(self, key, method){ + if (method._origin) method = method._origin; + + return function(){ + if (method._protected && this._current == null) throw new Error('The method "' + key + '" cannot be called.'); + var caller = this.caller, current = this._current; + this.caller = current; this._current = arguments.callee; + var result = method.apply(this, arguments); + this._current = current; this.caller = caller; + return result; + }.extend({_owner: self, _origin: method, _name: key}); + } + }); Class.implement({ + + implement: function(key, value){ + + if ($type(key) == 'object'){ + for (var p in key) this.implement(p, key[p]); + return this; + } + + var mutator = Class.Mutators[key]; + + if (mutator){ + value = mutator.call(this, value); + if (value == null) return this; + } + + var proto = this.prototype; + + switch ($type(value)){ + + case 'function': + if (value._hidden) return this; + proto[key] = Class.wrap(this, key, value); + break; + + case 'object': + var previous = proto[key]; + if ($type(previous) == 'object') $mixin(previous, value); + else proto[key] = $unlink(value); + break; + + case 'array': + proto[key] = $unlink(value); + break; + + default: proto[key] = value; - implement: function(){ - Class.Mutators.Implements(this.prototype, Array.slice(arguments)); + } + return this; - } + } + }); Class.Mutators = { - - Implements: function(self, klasses){ - $splat(klasses).each(function(klass){ - $extend(self, ($type(klass) == 'class') ? new klass($empty) : klass); - }); - }, - - Extends: function(self, klass){ - var instance = new klass($empty); - delete instance.parent; - delete instance.parentOf; - - for (var key in instance){ - var current = self[key], previous = instance[key]; - if (current == undefined){ - self[key] = previous; - continue; - } - - var ctype = $type(current), ptype = $type(previous); - if (ctype != ptype) continue; - - switch (ctype){ - case 'function': - // this code will be only executed if the current browser does not support function.caller (currently only opera). - // we replace the function code with brute force. Not pretty, but it will only be executed if function.caller is not supported. - - if (!arguments.callee.caller) self[key] = eval('(' + String(current).replace(/\bthis\.parent\(\s*(\))?/g, function(full, close){ - return 'arguments.callee._parent_.call(this' + (close || ', '); - }) + ')'); - - // end "opera" code - self[key]._parent_ = previous; - break; - case 'object': self[key] = $merge(previous, current); - } - - } - - self.parent = function(){ - return arguments.callee.caller._parent_.apply(this, arguments); - }; - - self.parentOf = function(descendant){ - return descendant._parent_.apply(this, Array.slice(arguments, 1)); - }; - } - + + Extends: function(parent){ + + this.parent = parent; + this.prototype = Class.instantiate(parent); + + this.implement('parent', function(){ + var name = this.caller._name, previous = this.caller._owner.parent.prototype[name]; + if (!previous) throw new Error('The method "' + name + '" has no parent.'); + return previous.apply(this, arguments); + }.protect()); + + }, + + Implements: function(items){ + $splat(items).each(function(item){ + if (item instanceof Function) item = Class.instantiate(item); + this.implement(item); + }, this); + + } + }; /* -Script: Class.Extras.js - Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. +--- + +script: Class.Extras.js + +description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. -License: - MIT-style license. +license: MIT-style license. + +requires: +- /Class + +provides: [Chain, Events, Options] + +... */ var Chain = new Class({ + $chain: [], + chain: function(){ - this.$chain = (this.$chain || []).extend(arguments); + this.$chain.extend(Array.flatten(arguments)); return this; }, callChain: function(){ - return (this.$chain && this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; + return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; }, clearChain: function(){ - if (this.$chain) this.$chain.empty(); + this.$chain.empty(); return this; } @@ -1118,10 +1321,11 @@ var Chain = new Class({ var Events = new Class({ + $events: {}, + addEvent: function(type, fn, internal){ type = Events.removeOn(type); if (fn != $empty){ - this.$events = this.$events || {}; this.$events[type] = this.$events[type] || []; this.$events[type].include(fn); if (internal) fn.internal = true; @@ -1145,16 +1349,22 @@ var Events = new Class({ removeEvent: function(type, fn){ type = Events.removeOn(type); - if (!this.$events || !this.$events[type]) return this; + if (!this.$events[type]) return this; if (!fn.internal) this.$events[type].erase(fn); return this; }, - removeEvents: function(type){ - for (var e in this.$events){ - if (type && type != e) continue; - var fns = this.$events[e]; - for (var i = fns.length; i--; i) this.removeEvent(e, fns[i]); + removeEvents: function(events){ + var type; + if ($type(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + if (events) events = Events.removeOn(events); + for (type in this.$events){ + if (events && events != type) continue; + var fns = this.$events[type]; + for (var i = fns.length; i--; i) this.removeEvent(type, fns[i]); } return this; } @@ -1162,7 +1372,7 @@ var Events = new Class({ }); Events.removeOn = function(string){ - return string.replace(/^on([A-Z])/, function(full, first) { + return string.replace(/^on([A-Z])/, function(full, first){ return first.toLowerCase(); }); }; @@ -1182,47 +1392,29 @@ var Options = new Class({ }); -/* -Script: Element.js - 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. -*/ -Document.implement({ +/* +--- - newElement: function(tag, props){ - if (Browser.Engine.trident && props){ - ['name', 'type', 'checked'].each(function(attribute){ - if (!props[attribute]) return; - tag += ' ' + attribute + '="' + props[attribute] + '"'; - if (attribute != 'checked') delete props[attribute]; - }); - tag = '<' + tag + '>'; - } - return $.element(this.createElement(tag)).set(props); - }, +script: Element.js - newTextNode: function(text){ - return this.createTextNode(text); - }, +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. - getDocument: function(){ - return this; - }, +license: MIT-style license. - getWindow: function(){ - return this.defaultView || this.parentWindow; - }, +requires: +- /Window +- /Document +- /Array +- /String +- /Function +- /Number +- /Hash - purge: function(){ - var elements = this.getElementsByTagName('*'); - for (var i = 0, l = elements.length; i < l; i++) Browser.freeMem(elements[i]); - } +provides: [Element, Elements, $, $$, Iframe] -}); +... +*/ var Element = new Native({ @@ -1234,12 +1426,21 @@ var Element = new Native({ var konstructor = Element.Constructors.get(tag); if (konstructor) return konstructor(props); if (typeof tag == 'string') return document.newElement(tag, props); - return $(tag).set(props); + return document.id(tag).set(props); }, afterImplement: function(key, value){ - if (!Array[key]) Elements.implement(key, Elements.multi(key)); Element.Prototype[key] = value; + if (Array[key]) return; + Elements.implement(key, function(){ + var items = [], elements = true; + for (var i = 0, j = this.length; i < j; i++){ + var returns = this[i][key].apply(this[i], arguments); + items.push(returns); + if (elements) elements = ($type(returns) == 'element'); + } + return (elements) ? new Elements(items) : items; + }); } }); @@ -1257,23 +1458,26 @@ var IFrame = new Native({ initialize: function(){ var params = Array.link(arguments, {properties: Object.type, iframe: $defined}); var props = params.properties || {}; - var iframe = $(params.iframe) || false; + var iframe = document.id(params.iframe); var onload = props.onload || $empty; delete props.onload; - props.id = props.name = $pick(props.id, props.name, iframe.id, iframe.name, 'IFrame_' + $time()); + props.id = props.name = $pick(props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + $time()); iframe = new Element(iframe || 'iframe', props); var onFrameLoad = function(){ var host = $try(function(){ return iframe.contentWindow.location.host; }); - if (host && host == window.location.host){ + if (!host || host == window.location.host){ var win = new Window(iframe.contentWindow); - var doc = new Document(iframe.contentWindow.document); + new Document(iframe.contentWindow.document); $extend(win.Element.prototype, Element.Prototype); } onload.call(iframe.contentWindow, iframe.contentWindow.document); }; - (!window.frames[props.id]) ? iframe.addListener('load', onFrameLoad) : onFrameLoad(); + var contentWindow = $try(function(){ + return iframe.contentWindow; + }); + ((contentWindow && contentWindow.document.body) || window.frames[props.id]) ? onFrameLoad() : iframe.addListener('load', onFrameLoad); return iframe; } @@ -1287,12 +1491,12 @@ var Elements = new Native({ if (options.ddup || options.cash){ var uniques = {}, returned = []; for (var i = 0, l = elements.length; i < l; i++){ - var el = $.element(elements[i], !options.cash); + var el = document.id(elements[i], !options.cash); if (options.ddup){ if (uniques[el.uid]) continue; uniques[el.uid] = true; } - returned.push(el); + if (el) returned.push(el); } elements = returned; } @@ -1312,26 +1516,76 @@ Elements.implement({ }); -Elements.multi = function(property){ - return function(){ - var items = []; - var elements = true; - for (var i = 0, j = this.length; i < j; i++){ - var returns = this[i][property].apply(this[i], arguments); - items.push(returns); - if (elements) elements = ($type(returns) == 'element'); +Document.implement({ + + newElement: function(tag, props){ + if (Browser.Engine.trident && props){ + ['name', 'type', 'checked'].each(function(attribute){ + if (!props[attribute]) return; + tag += ' ' + attribute + '="' + props[attribute] + '"'; + if (attribute != 'checked') delete props[attribute]; + }); + tag = '<' + tag + '>'; } - return (elements) ? new Elements(items) : items; - }; -}; + return document.id(this.createElement(tag)).set(props); + }, -Window.implement({ + newTextNode: function(text){ + return this.createTextNode(text); + }, + + getDocument: function(){ + return this; + }, - $: function(el, nocash){ - if (el && el.$family && el.uid) return el; - var type = $type(el); - return ($[type]) ? $[type](el, nocash, this.document) : null; + getWindow: function(){ + return this.window; }, + + id: (function(){ + + var types = { + + string: function(id, nocash, doc){ + id = doc.getElementById(id); + return (id) ? types.element(id, nocash) : null; + }, + + element: function(el, nocash){ + $uid(el); + if (!nocash && !el.$family && !(/^object|embed$/i).test(el.tagName)){ + var proto = Element.Prototype; + for (var p in proto) el[p] = proto[p]; + }; + return el; + }, + + object: function(obj, nocash, doc){ + if (obj.toElement) return types.element(obj.toElement(doc), nocash); + return null; + } + + }; + + types.textnode = types.whitespace = types.window = types.document = $arguments(0); + + return function(el, nocash, doc){ + if (el && el.$family && el.uid) return el; + var type = $type(el); + return (types[type]) ? types[type](el, nocash, doc || document) : null; + }; + + })() + +}); + +if (window.$ == null) Window.implement({ + $: function(el, nc){ + return document.id(el, nc, this.document); + } +}); + +Window.implement({ $$: function(selector){ if (arguments.length == 1 && typeof selector == 'string') return this.document.getElements(selector); @@ -1340,11 +1594,9 @@ Window.implement({ for (var i = 0, l = args.length; i < l; i++){ var item = args[i]; switch ($type(item)){ - case 'element': item = [item]; break; - case 'string': item = this.document.getElements(item, true); break; - default: item = false; + case 'element': elements.push(item); break; + case 'string': elements.extend(this.document.getElements(item, true)); } - if (item) elements.extend(item); } return new Elements(elements); }, @@ -1359,31 +1611,10 @@ Window.implement({ }); -$.string = function(id, nocash, doc){ - id = doc.getElementById(id); - return (id) ? $.element(id, nocash) : null; -}; - -$.element = function(el, nocash){ - $uid(el); - if (!nocash && !el.$family && !(/^object|embed$/i).test(el.tagName)){ - var proto = Element.Prototype; - for (var p in proto) el[p] = proto[p]; - }; - return el; -}; - -$.object = function(obj, nocash, doc){ - if (obj.toElement) return $.element(obj.toElement(doc), nocash); - return null; -}; - -$.textnode = $.whitespace = $.window = $.document = $arguments(0); - Native.implement([Element, Document], { getElement: function(selector, nocash){ - return $(this.getElements(selector, true)[0] || null, nocash); + return document.id(this.getElements(selector, true)[0] || null, nocash); }, getElements: function(tags, nocash){ @@ -1399,50 +1630,108 @@ Native.implement([Element, Document], { }); -Element.Storage = { +(function(){ - get: function(uid){ - return (this[uid] || (this[uid] = {})); - } +var collected = {}, storage = {}; +var props = {input: 'checked', option: 'selected', textarea: (Browser.Engine.webkit && Browser.Engine.version < 420) ? 'innerHTML' : 'value'}; +var get = function(uid){ + return (storage[uid] || (storage[uid] = {})); }; -Element.Inserters = new Hash({ - - before: function(context, element){ - if (element.parentNode) element.parentNode.insertBefore(context, element); - }, +var clean = function(item, retain){ + if (!item) return; + var uid = item.uid; + if (Browser.Engine.trident){ + if (item.clearAttributes){ + var clone = retain && item.cloneNode(false); + item.clearAttributes(); + if (clone) item.mergeAttributes(clone); + } else if (item.removeEvents){ + item.removeEvents(); + } + if ((/object/i).test(item.tagName)){ + for (var p in item){ + if (typeof item[p] == 'function') item[p] = $empty; + } + Element.dispose(item); + } + } + if (!uid) return; + collected[uid] = storage[uid] = null; +}; - after: function(context, element){ - if (!element.parentNode) return; - var next = element.nextSibling; - (next) ? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context); - }, +var purge = function(){ + Hash.each(collected, clean); + if (Browser.Engine.trident) $A(document.getElementsByTagName('object')).each(clean); + if (window.CollectGarbage) CollectGarbage(); + collected = storage = null; +}; - bottom: function(context, element){ - element.appendChild(context); - }, +var walk = function(element, walk, start, match, all, nocash){ + var el = element[start || walk]; + var elements = []; + while (el){ + if (el.nodeType == 1 && (!match || Element.match(el, match))){ + if (!all) return document.id(el, nocash); + elements.push(el); + } + el = el[walk]; + } + return (all) ? new Elements(elements, {ddup: false, cash: !nocash}) : null; +}; + +var attributes = { + 'html': 'innerHTML', + 'class': 'className', + 'for': 'htmlFor', + 'defaultValue': 'defaultValue', + 'text': (Browser.Engine.trident || (Browser.Engine.webkit && Browser.Engine.version < 420)) ? 'innerText' : 'textContent' +}; +var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readonly', 'multiple', 'selected', 'noresize', 'defer']; +var camels = ['value', 'type', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap']; + +bools = bools.associate(bools); + +Hash.extend(attributes, bools); +Hash.extend(attributes, camels.associate(camels.map(String.toLowerCase))); + +var inserters = { + + before: function(context, element){ + if (element.parentNode) element.parentNode.insertBefore(context, element); + }, + + after: function(context, element){ + if (!element.parentNode) return; + var next = element.nextSibling; + (next) ? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context); + }, + + bottom: function(context, element){ + element.appendChild(context); + }, top: function(context, element){ var first = element.firstChild; (first) ? element.insertBefore(context, first) : element.appendChild(context); } -}); +}; -Element.Inserters.inside = Element.Inserters.bottom; +inserters.inside = inserters.bottom; -Element.Inserters.each(function(value, key){ +Hash.each(inserters, function(inserter, where){ - var Key = key.capitalize(); + where = where.capitalize(); - Element.implement('inject' + Key, function(el){ - value(this, $(el, true)); + Element.implement('inject' + where, function(el){ + inserter(this, document.id(el, true)); return this; }); - Element.implement('grab' + Key, function(el){ - value($(el, true), this); + Element.implement('grab' + where, function(el){ + inserter(document.id(el, true), this); return this; }); @@ -1450,23 +1739,6 @@ Element.Inserters.each(function(value, key){ Element.implement({ - getDocument: function(){ - return this.ownerDocument; - }, - - getWindow: function(){ - return this.ownerDocument.getWindow(); - }, - - getElementById: function(id, nocash){ - var el = this.ownerDocument.getElementById(id); - if (!el) return null; - for (var parent = el.parentNode; parent != this; parent = parent.parentNode){ - if (!parent) return null; - } - return $.element(el, nocash); - }, - set: function(prop, value){ switch ($type(prop)){ case 'object': @@ -1486,72 +1758,42 @@ Element.implement({ erase: function(prop){ var property = Element.Properties.get(prop); - (property && property.erase) ? property.erase.apply(this, Array.slice(arguments, 1)) : this.removeProperty(prop); + (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); return this; }, - match: function(tag){ - return (!tag || Element.get(this, 'tag') == tag); - }, - - inject: function(el, where){ - Element.Inserters.get(where || 'bottom')(this, $(el, true)); + setProperty: function(attribute, value){ + var key = attributes[attribute]; + if (value == undefined) return this.removeProperty(attribute); + if (key && bools[attribute]) value = !!value; + (key) ? this[key] = value : this.setAttribute(attribute, '' + value); return this; }, - wraps: function(el, where){ - el = $(el, true); - return this.replaces(el).grab(el, where); - }, - - grab: function(el, where){ - Element.Inserters.get(where || 'bottom')($(el, true), this); + setProperties: function(attributes){ + for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); return this; }, - appendText: function(text, where){ - return this.grab(this.getDocument().newTextNode(text), where); - }, - - adopt: function(){ - Array.flatten(arguments).each(function(element){ - element = $(element, true); - if (element) this.appendChild(element); - }, this); - return this; + getProperty: function(attribute){ + var key = attributes[attribute]; + var value = (key) ? this[key] : this.getAttribute(attribute, 2); + return (bools[attribute]) ? !!value : (key) ? value : value || null; }, - dispose: function(){ - return (this.parentNode) ? this.parentNode.removeChild(this) : this; + getProperties: function(){ + var args = $A(arguments); + return args.map(this.getProperty, this).associate(args); }, - clone: function(contents, keepid){ - switch ($type(this)){ - case 'element': - var attributes = {}; - for (var j = 0, l = this.attributes.length; j < l; j++){ - var attribute = this.attributes[j], key = attribute.nodeName.toLowerCase(); - if (Browser.Engine.trident && (/input/i).test(this.tagName) && (/width|height/).test(key)) continue; - var value = (key == 'style' && this.style) ? this.style.cssText : attribute.nodeValue; - if (!$chk(value) || key == 'uid' || (key == 'id' && !keepid)) continue; - if (value != 'inherit' && ['string', 'number'].contains($type(value))) attributes[key] = value; - } - var element = new Element(this.nodeName.toLowerCase(), attributes); - if (contents !== false){ - for (var i = 0, k = this.childNodes.length; i < k; i++){ - var child = Element.clone(this.childNodes[i], true, keepid); - if (child) element.grab(child); - } - } - return element; - case 'textnode': return document.newTextNode(this.nodeValue); - } - return null; + removeProperty: function(attribute){ + var key = attributes[attribute]; + (key) ? this[key] = (key && bools[attribute]) ? false : '' : this.removeAttribute(attribute); + return this; }, - replaces: function(el){ - el = $(el, true); - el.parentNode.replaceChild(this, el); + removeProperties: function(){ + Array.each(arguments, this.removeProperty, this); return this; }, @@ -1565,7 +1807,7 @@ Element.implement({ }, removeClass: function(className){ - this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean(); + this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1'); return this; }, @@ -1573,101 +1815,38 @@ Element.implement({ return this.hasClass(className) ? this.removeClass(className) : this.addClass(className); }, - getComputedStyle: function(property){ - if (this.currentStyle) return this.currentStyle[property.camelCase()]; - var computed = this.getWindow().getComputedStyle(this, null); - return (computed) ? computed.getPropertyValue([property.hyphenate()]) : null; - }, - - empty: function(){ - $A(this.childNodes).each(function(node){ - Browser.freeMem(node); - Element.empty(node); - Element.dispose(node); + adopt: function(){ + Array.flatten(arguments).each(function(element){ + element = document.id(element, true); + if (element) this.appendChild(element); }, this); return this; }, - destroy: function(){ - Browser.freeMem(this.empty().dispose()); - return null; - }, - - getSelected: function(){ - return new Elements($A(this.options).filter(function(option){ - return option.selected; - })); - }, - - toQueryString: function(){ - var queryString = []; - this.getElements('input, select, textarea').each(function(el){ - if (!el.name || el.disabled) return; - var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map(function(opt){ - return opt.value; - }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value; - $splat(value).each(function(val){ - if (val) queryString.push(el.name + '=' + encodeURIComponent(val)); - }); - }); - return queryString.join('&'); - }, - - getProperty: function(attribute){ - var EA = Element.Attributes, key = EA.Props[attribute]; - var value = (key) ? this[key] : this.getAttribute(attribute, 2); - return (EA.Bools[attribute]) ? !!value : (key) ? value : value || null; - }, - - getProperties: function(){ - var args = $A(arguments); - return args.map(function(attr){ - return this.getProperty(attr); - }, this).associate(args); + appendText: function(text, where){ + return this.grab(this.getDocument().newTextNode(text), where); }, - setProperty: function(attribute, value){ - var EA = Element.Attributes, key = EA.Props[attribute], hasValue = $defined(value); - if (key && EA.Bools[attribute]) value = (value || !hasValue) ? true : false; - else if (!hasValue) return this.removeProperty(attribute); - (key) ? this[key] = value : this.setAttribute(attribute, value); + grab: function(el, where){ + inserters[where || 'bottom'](document.id(el, true), this); return this; }, - setProperties: function(attributes){ - for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); + inject: function(el, where){ + inserters[where || 'bottom'](this, document.id(el, true)); return this; }, - removeProperty: function(attribute){ - var EA = Element.Attributes, key = EA.Props[attribute], isBool = (key && EA.Bools[attribute]); - (key) ? this[key] = (isBool) ? false : '' : this.removeAttribute(attribute); + replaces: function(el){ + el = document.id(el, true); + el.parentNode.replaceChild(this, el); return this; }, - removeProperties: function(){ - Array.each(arguments, this.removeProperty, this); - return this; - } - -}); - -(function(){ - -var walk = function(element, walk, start, match, all, nocash){ - var el = element[start || walk]; - var elements = []; - while (el){ - if (el.nodeType == 1 && (!match || Element.match(el, match))){ - elements.push(el); - if (!all) break; - } - el = el[walk]; - } - return (all) ? new Elements(elements, {ddup: false, cash: !nocash}) : $(elements[0], nocash); -}; - -Element.implement({ + wraps: function(el, where){ + el = document.id(el, true); + return this.replaces(el).grab(el, where); + }, getPrevious: function(match, nocash){ return walk(this, 'previousSibling', null, match, false, nocash); @@ -1700,53 +1879,128 @@ Element.implement({ getParents: function(match, nocash){ return walk(this, 'parentNode', null, match, true, nocash); }, + + getSiblings: function(match, nocash){ + return this.getParent().getChildren(match, nocash).erase(this); + }, getChildren: function(match, nocash){ return walk(this, 'nextSibling', 'firstChild', match, true, nocash); }, - hasChild: function(el){ - el = $(el, true); - return (!!el && $A(this.getElementsByTagName(el.tagName)).contains(el)); - } + getWindow: function(){ + return this.ownerDocument.window; + }, -}); + getDocument: function(){ + return this.ownerDocument; + }, -})(); + getElementById: function(id, nocash){ + var el = this.ownerDocument.getElementById(id); + if (!el) return null; + for (var parent = el.parentNode; parent != this; parent = parent.parentNode){ + if (!parent) return null; + } + return document.id(el, nocash); + }, -Element.Properties = new Hash; + getSelected: function(){ + return new Elements($A(this.options).filter(function(option){ + return option.selected; + })); + }, -Element.Properties.style = { + getComputedStyle: function(property){ + if (this.currentStyle) return this.currentStyle[property.camelCase()]; + var computed = this.getDocument().defaultView.getComputedStyle(this, null); + return (computed) ? computed.getPropertyValue([property.hyphenate()]) : null; + }, - set: function(style){ - this.style.cssText = style; + toQueryString: function(){ + var queryString = []; + this.getElements('input, select, textarea', true).each(function(el){ + if (!el.name || el.disabled || el.type == 'submit' || el.type == 'reset' || el.type == 'file') return; + var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map(function(opt){ + return opt.value; + }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value; + $splat(value).each(function(val){ + if (typeof val != 'undefined') queryString.push(el.name + '=' + encodeURIComponent(val)); + }); + }); + return queryString.join('&'); }, - get: function(){ - return this.style.cssText; + clone: function(contents, keepid){ + contents = contents !== false; + var clone = this.cloneNode(contents); + var clean = function(node, element){ + if (!keepid) node.removeAttribute('id'); + if (Browser.Engine.trident){ + 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; + } + } + var prop = props[element.tagName.toLowerCase()]; + if (prop && element[prop]) node[prop] = element[prop]; + }; + + if (contents){ + var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*'); + for (var i = ce.length; i--;) clean(ce[i], te[i]); + } + + clean(clone, this); + return document.id(clone); }, - erase: function(){ - this.style.cssText = ''; - } + destroy: function(){ + Element.empty(this); + Element.dispose(this); + clean(this, true); + return null; + }, -}; + empty: function(){ + $A(this.childNodes).each(function(node){ + Element.destroy(node); + }); + return this; + }, -Element.Properties.tag = {get: function(){ - return this.tagName.toLowerCase(); -}}; + dispose: function(){ + return (this.parentNode) ? this.parentNode.removeChild(this) : this; + }, -Element.Properties.href = {get: function(){ - return (!this.href) ? null : this.href.replace(new RegExp('^' + document.location.protocol + '\/\/' + document.location.host), ''); -}}; + hasChild: function(el){ + el = document.id(el, true); + if (!el) return false; + if (Browser.Engine.webkit && Browser.Engine.version < 420) return $A(this.getElementsByTagName(el.tagName)).contains(el); + return (this.contains) ? (this != el && this.contains(el)) : !!(this.compareDocumentPosition(el) & 16); + }, -Element.Properties.html = {set: function(){ - return this.innerHTML = Array.flatten(arguments).join(''); -}}; + match: function(tag){ + return (!tag || (tag == this) || (Element.get(this, 'tag') == tag)); + } + +}); Native.implement([Element, Window, Document], { addListener: function(type, fn){ + if (type == 'unload'){ + var old = fn, self = this; + fn = function(){ + self.removeListener('unload', fn); + old(); + }; + } else { + collected[this.uid] = this; + } if (this.addEventListener) this.addEventListener(type, fn, false); else this.attachEvent('on' + type, fn); return this; @@ -1759,214 +2013,276 @@ Native.implement([Element, Window, Document], { }, retrieve: function(property, dflt){ - var storage = Element.Storage.get(this.uid); - var prop = storage[property]; - if ($defined(dflt) && !$defined(prop)) prop = storage[property] = dflt; + var storage = get(this.uid), prop = storage[property]; + if (dflt != undefined && prop == undefined) prop = storage[property] = dflt; return $pick(prop); }, store: function(property, value){ - var storage = Element.Storage.get(this.uid); + var storage = get(this.uid); storage[property] = value; return this; }, eliminate: function(property){ - var storage = Element.Storage.get(this.uid); + var storage = get(this.uid); delete storage[property]; return this; } }); -Element.Attributes = new Hash({ - Props: {'html': 'innerHTML', 'class': 'className', 'for': 'htmlFor', 'text': (Browser.Engine.trident) ? 'innerText' : 'textContent'}, - Bools: ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readonly', 'multiple', 'selected', 'noresize', 'defer'], - Camels: ['value', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap'] -}); +window.addListener('unload', purge); -Browser.freeMem = function(item){ - if (!item) return; - if (Browser.Engine.trident && (/object/i).test(item.tagName)){ - for (var p in item){ - if (typeof item[p] == 'function') item[p] = $empty; - } - Element.dispose(item); - } - if (item.uid && item.removeEvents) item.removeEvents(); -}; +})(); -(function(EA){ +Element.Properties = new Hash; - var EAB = EA.Bools, EAC = EA.Camels; - EA.Bools = EAB = EAB.associate(EAB); - Hash.extend(Hash.combine(EA.Props, EAB), EAC.associate(EAC.map(function(v){ - return v.toLowerCase(); - }))); - EA.erase('Camels'); +Element.Properties.style = { -})(Element.Attributes); + set: function(style){ + this.style.cssText = style; + }, -window.addListener('unload', function(){ - window.removeListener('unload', arguments.callee); - document.purge(); - if (Browser.Engine.trident) CollectGarbage(); -}); + get: function(){ + return this.style.cssText; + }, -/* -Script: Element.Event.js - Contains Element methods for dealing with events, and custom Events. - -License: - MIT-style license. -*/ - -Element.Properties.events = {set: function(events){ - this.addEvents(events); -}}; - -Native.implement([Element, Window, Document], { - - addEvent: function(type, fn){ - var events = this.retrieve('events', {}); - events[type] = events[type] || {'keys': [], 'values': []}; - if (events[type].keys.contains(fn)) return this; - events[type].keys.push(fn); - var realType = type, custom = Element.Events.get(type), condition = fn, self = this; - if (custom){ - if (custom.onAdd) custom.onAdd.call(this, fn); - if (custom.condition){ - condition = function(event){ - if (custom.condition.call(this, event)) return fn.call(this, event); - return false; - }; - } - realType = custom.base || realType; - } - var defn = function(){ - return fn.call(self); - }; - var nativeEvent = Element.NativeEvents[realType] || 0; - if (nativeEvent){ - if (nativeEvent == 2){ - defn = function(event){ - event = new Event(event, self.getWindow()); - if (condition.call(self, event) === false) event.stop(); - }; - } - this.addListener(realType, defn); - } - events[type].values.push(defn); - return this; - }, - - removeEvent: function(type, fn){ - var events = this.retrieve('events'); - if (!events || !events[type]) return this; - var pos = events[type].keys.indexOf(fn); - if (pos == -1) return this; - var key = events[type].keys.splice(pos, 1)[0]; - var value = events[type].values.splice(pos, 1)[0]; - var custom = Element.Events.get(type); - if (custom){ - if (custom.onRemove) custom.onRemove.call(this, fn); - type = custom.base || type; - } - return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this; - }, - - addEvents: function(events){ - for (var event in events) this.addEvent(event, events[event]); - return this; - }, - - removeEvents: function(type){ - var events = this.retrieve('events'); - if (!events) return this; - if (!type){ - for (var evType in events) this.removeEvents(evType); - events = null; - } else if (events[type]){ - while (events[type].keys[0]) this.removeEvent(type, events[type].keys[0]); - events[type] = null; - } - return this; - }, - - fireEvent: function(type, args, delay){ - var events = this.retrieve('events'); - if (!events || !events[type]) return this; - events[type].keys.each(function(fn){ - fn.create({'bind': this, 'delay': delay, 'arguments': args})(); - }, this); - return this; - }, - - cloneEvents: function(from, type){ - from = $(from); - var fevents = from.retrieve('events'); - if (!fevents) return this; - if (!type){ - for (var evType in fevents) this.cloneEvents(from, evType); - } else if (fevents[type]){ - fevents[type].keys.each(function(fn){ - this.addEvent(type, fn); - }, this); - } - return this; - } - -}); - -Element.NativeEvents = { - click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons - mousewheel: 2, DOMMouseScroll: 2, //mouse wheel - mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement - keydown: 2, keypress: 2, keyup: 2, //keyboard - focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements - load: 1, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window - error: 1, abort: 1, scroll: 1 //misc -}; - -(function(){ - -var $check = function(event){ - var related = event.relatedTarget; - if (related == undefined) return true; - if (related === false) return false; - return ($type(this) != 'document' && related != this && related.prefix != 'xul' && !this.hasChild(related)); -}; - -Element.Events = new Hash({ - - mouseenter: { - base: 'mouseover', - condition: $check - }, - - mouseleave: { - base: 'mouseout', - condition: $check - }, - - mousewheel: { - base: (Browser.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel' - } - -}); - -})(); + erase: function(){ + this.style.cssText = ''; + } -/* -Script: Element.Style.js - Contains methods for interacting with the styles of Elements in a fashionable way. +}; -License: - MIT-style license. -*/ +Element.Properties.tag = { -Element.Properties.styles = {set: function(styles){ - this.setStyles(styles); + get: function(){ + return this.tagName.toLowerCase(); + } + +}; + +Element.Properties.html = (function(){ + var wrapper = document.createElement('div'); + + var translations = { + table: [1, '', '
'], + select: [1, ''], + tbody: [2, '', '
'], + tr: [3, '', '
'] + }; + translations.thead = translations.tfoot = translations.tbody; + + var html = { + set: function(){ + var html = Array.flatten(arguments).join(''); + var wrap = Browser.Engine.trident && translations[this.get('tag')]; + 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); + } else { + this.innerHTML = html; + } + } + }; + + html.erase = html.set; + + return html; +})(); + +if (Browser.Engine.webkit && Browser.Engine.version < 420) Element.Properties.text = { + get: function(){ + if (this.innerText) return this.innerText; + var temp = this.ownerDocument.newElement('div', {html: this.innerHTML}).inject(this.ownerDocument.body); + var text = temp.innerText; + temp.destroy(); + return text; + } +}; + + +/* +--- + +script: Element.Event.js + +description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events. + +license: MIT-style license. + +requires: +- /Element +- /Event + +provides: [Element.Event] + +... +*/ + +Element.Properties.events = {set: function(events){ + this.addEvents(events); +}}; + +Native.implement([Element, Window, Document], { + + addEvent: function(type, fn){ + var events = this.retrieve('events', {}); + events[type] = events[type] || {'keys': [], 'values': []}; + if (events[type].keys.contains(fn)) return this; + events[type].keys.push(fn); + var realType = type, custom = Element.Events.get(type), condition = fn, self = this; + if (custom){ + if (custom.onAdd) custom.onAdd.call(this, fn); + if (custom.condition){ + condition = function(event){ + if (custom.condition.call(this, event)) return fn.call(this, event); + return true; + }; + } + realType = custom.base || realType; + } + 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()); + if (condition.call(self, event) === false) event.stop(); + }; + } + this.addListener(realType, defn); + } + events[type].values.push(defn); + return this; + }, + + removeEvent: function(type, fn){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + var pos = events[type].keys.indexOf(fn); + if (pos == -1) return this; + events[type].keys.splice(pos, 1); + var value = events[type].values.splice(pos, 1)[0]; + var custom = Element.Events.get(type); + if (custom){ + if (custom.onRemove) custom.onRemove.call(this, fn); + type = custom.base || type; + } + return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this; + }, + + addEvents: function(events){ + for (var event in events) this.addEvent(event, events[event]); + return this; + }, + + removeEvents: function(events){ + var type; + if ($type(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + var attached = this.retrieve('events'); + if (!attached) return this; + if (!events){ + for (type in attached) this.removeEvents(type); + this.eliminate('events'); + } else if (attached[events]){ + while (attached[events].keys[0]) this.removeEvent(events, attached[events].keys[0]); + attached[events] = null; + } + return this; + }, + + fireEvent: function(type, args, delay){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + events[type].keys.each(function(fn){ + fn.create({'bind': this, 'delay': delay, 'arguments': args})(); + }, this); + return this; + }, + + cloneEvents: function(from, type){ + from = document.id(from); + var fevents = from.retrieve('events'); + if (!fevents) return this; + if (!type){ + for (var evType in fevents) this.cloneEvents(from, evType); + } else if (fevents[type]){ + fevents[type].keys.each(function(fn){ + this.addEvent(type, fn); + }, this); + } + return this; + } + +}); + +Element.NativeEvents = { + click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons + mousewheel: 2, DOMMouseScroll: 2, //mouse wheel + mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement + keydown: 2, keypress: 2, keyup: 2, //keyboard + focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements + load: 1, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window + error: 1, abort: 1, scroll: 1 //misc +}; + +(function(){ + +var $check = function(event){ + var related = event.relatedTarget; + if (related == undefined) return true; + if (related === false) return false; + return ($type(this) != 'document' && related != this && related.prefix != 'xul' && !this.hasChild(related)); +}; + +Element.Events = new Hash({ + + mouseenter: { + base: 'mouseover', + condition: $check + }, + + mouseleave: { + base: 'mouseout', + condition: $check + }, + + mousewheel: { + base: (Browser.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel' + } + +}); + +})(); + + +/* +--- + +script: Element.Style.js + +description: Contains methods for interacting with the styles of Elements in a fashionable way. + +license: MIT-style license. + +requires: +- /Element + +provides: [Element.Style] + +... +*/ + +Element.Properties.styles = {set: function(styles){ + this.setStyles(styles); }}; Element.Properties.opacity = { @@ -1992,11 +2308,11 @@ Element.Properties.opacity = { }; Element.implement({ - + setOpacity: function(value){ return this.set('opacity', value, true); }, - + getOpacity: function(){ return this.get('opacity'); }, @@ -2041,7 +2357,7 @@ Element.implement({ var color = result.match(/rgba?\([\d\s,]+\)/); if (color) result = result.replace(color[0], color[0].rgbToHex()); } - if (Browser.Engine.presto || (Browser.Engine.trident && !$chk(parseInt(result)))){ + if (Browser.Engine.presto || (Browser.Engine.trident && !$chk(parseInt(result, 10)))){ if (property.test(/^(height|width)$/)){ var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; values.each(function(value){ @@ -2049,7 +2365,7 @@ Element.implement({ }, this); return this['offset' + property.capitalize()] - size + 'px'; } - if (Browser.Engine.presto && String(result).test('px')) return result; + if ((Browser.Engine.presto) && String(result).test('px')) return result; if (property.test(/(border(.+)Width|margin|padding)/)) return '0px'; } return result; @@ -2062,7 +2378,7 @@ Element.implement({ getStyles: function(){ var result = {}; - Array.each(arguments, function(key){ + Array.flatten(arguments).each(function(key){ result[key] = this.getStyle(key); }, this); return result; @@ -2100,15 +2416,24 @@ Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, bor /* -Script: Element.Dimensions.js - Contains methods to work with size, scroll, or positioning of Elements and the window object. +--- + +script: Element.Dimensions.js + +description: Contains methods to work with size, scroll, or positioning of Elements and the window object. + +license: MIT-style license. -License: - MIT-style license. +credits: +- Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). +- Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). -Credits: - - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). - - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). +requires: +- /Element + +provides: [Element.Dimensions] + +... */ (function(){ @@ -2149,18 +2474,32 @@ Element.implement({ } return position; }, - + getOffsetParent: function(){ var element = this; - if (isBody(element)) return null; + if (isBody(element)) return null; if (!Browser.Engine.trident) return element.offsetParent; - while ((element = element.parentNode) && !isBody(element)){ + while ((element = element.parentNode) && !isBody(element)){ if (styleString(element, 'position') != 'static') return element; - } + } return null; }, getOffsets: function(){ + if (this.getBoundingClientRect){ + var bound = this.getBoundingClientRect(), + html = document.id(this.getDocument().documentElement), + htmlScroll = html.getScroll(), + elemScrolls = this.getScrolls(), + elemScroll = this.getScroll(), + isFixed = (styleString(this, 'position') == 'fixed'); + + return { + x: bound.left.toInt() + elemScrolls.x - elemScroll.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft, + y: bound.top.toInt() + elemScrolls.y - elemScroll.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop + }; + } + var element = this, position = {x: 0, y: 0}; if (isBody(this)) return position; @@ -2178,15 +2517,12 @@ Element.implement({ position.x += leftBorder(parent); position.y += topBorder(parent); } - } else if (element != this && (Browser.Engine.trident || Browser.Engine.webkit)){ + } else if (element != this && Browser.Engine.webkit){ position.x += leftBorder(element); position.y += topBorder(element); } element = element.offsetParent; - if (Browser.Engine.trident){ - while (element && !element.currentStyle.hasLayout) element = element.offsetParent; - } } if (Browser.Engine.gecko && !borderBox(this)){ position.x -= leftBorder(this); @@ -2197,49 +2533,63 @@ Element.implement({ 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}; - var relativePosition = (relative && (relative = $(relative))) ? relative.getPosition() : {x: 0, y: 0}; + var offset = this.getOffsets(), + scroll = this.getScrolls(); + var position = { + x: offset.x - scroll.x, + y: offset.y - scroll.y + }; + var relativePosition = (relative && (relative = document.id(relative))) ? relative.getPosition() : {x: 0, y: 0}; return {x: position.x - relativePosition.x, y: position.y - relativePosition.y}; }, getCoordinates: function(element){ if (isBody(this)) return this.getWindow().getCoordinates(); - var position = this.getPosition(element), size = this.getSize(); - var obj = {left: position.x, top: position.y, width: size.x, height: size.y}; + var position = this.getPosition(element), + size = this.getSize(); + var obj = { + left: position.x, + top: position.y, + width: size.x, + height: size.y + }; obj.right = obj.left + obj.width; obj.bottom = obj.top + obj.height; return obj; }, computePosition: function(obj){ - return {left: obj.x - styleNumber(this, 'margin-left'), top: obj.y - styleNumber(this, 'margin-top')}; + return { + left: obj.x - styleNumber(this, 'margin-left'), + top: obj.y - styleNumber(this, 'margin-top') + }; }, - position: function(obj){ + setPosition: function(obj){ return this.setStyles(this.computePosition(obj)); } }); + Native.implement([Document, Window], { getSize: function(){ - var win = this.getWindow(); - if (Browser.Engine.presto || Browser.Engine.webkit) return {x: win.innerWidth, y: win.innerHeight}; + if (Browser.Engine.presto || Browser.Engine.webkit){ + var win = this.getWindow(); + return {x: win.innerWidth, y: win.innerHeight}; + } var doc = getCompatElement(this); return {x: doc.clientWidth, y: doc.clientHeight}; }, getScroll: function(){ - var win = this.getWindow(); - var doc = getCompatElement(this); + var win = this.getWindow(), doc = getCompatElement(this); return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; }, getScrollSize: function(){ - var doc = getCompatElement(this); - var min = this.getSize(); + var doc = getCompatElement(this), min = this.getSize(); return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)}; }, @@ -2286,6 +2636,7 @@ function getCompatElement(element){ })(); //aliases +Element.alias('setPosition', 'position'); //compatability Native.implement([Window, Document, Element], { @@ -2323,16 +2674,26 @@ Native.implement([Window, Document, Element], { }); + /* -Script: Selectors.js - Adds advanced CSS Querying capabilities for targeting elements. Also includes pseudoselectors support. +--- + +script: Selectors.js + +description: Adds advanced CSS-style querying capabilities for targeting HTML Elements. Includes pseudo selectors. -License: - MIT-style license. +license: MIT-style license. + +requires: +- /Element + +provides: [Selectors] + +... */ Native.implement([Document, Element], { - + getElements: function(expression, nocash){ expression = expression.split(','); var items, local = {}; @@ -2343,20 +2704,20 @@ Native.implement([Document, Element], { } return new Elements(items, {ddup: (expression.length > 1), cash: !nocash}); } - + }); Element.implement({ - + match: function(selector){ - if (!selector) return true; + if (!selector || (selector == this)) return true; var tagid = Selectors.Utils.parseTagAndID(selector); var tag = tagid[0], id = tagid[1]; if (!Selectors.Filters.byID(this, id) || !Selectors.Filters.byTag(this, tag)) return false; var parsed = Selectors.Utils.parseSelector(selector); return (parsed) ? Selectors.Utils.filter(this, parsed, {}) : true; } - + }); var Selectors = {Cache: {nth: {}, parsed: {}}}; @@ -2366,26 +2727,26 @@ Selectors.RegExps = { tag: (/^(\w+|\*)/), quick: (/^(\w+|\*)$/), splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g), - combined: (/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g) + combined: (/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)(["']?)([^\4]*?)\4)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g) }; Selectors.Utils = { - + chk: function(item, uniques){ if (!uniques) return true; var uid = $uid(item); if (!uniques[uid]) return uniques[uid] = true; return false; }, - + parseNthArgument: function(argument){ if (Selectors.Cache.nth[argument]) return Selectors.Cache.nth[argument]; var parsed = argument.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/); if (!parsed) return false; - var inta = parseInt(parsed[1]); + var inta = parseInt(parsed[1], 10); var a = (inta || inta === 0) ? inta : 1; var special = parsed[2] || false; - var b = parseInt(parsed[3]) || 0; + var b = parseInt(parsed[3], 10) || 0; if (a != 0){ b--; while (b < 1) b += a; @@ -2397,21 +2758,21 @@ Selectors.Utils = { switch (special){ case 'n': parsed = {a: a, b: b, special: 'n'}; break; case 'odd': parsed = {a: 2, b: 0, special: 'n'}; break; - case 'even': parsed = {a: 2, b: 1, special: 'n'}; break; + case 'even': parsed = {a: 2, b: 1, special: 'n'}; break; case 'first': parsed = {a: 0, special: 'index'}; break; case 'last': parsed = {special: 'last-child'}; break; case 'only': parsed = {special: 'only-child'}; break; default: parsed = {a: (a - 1), special: 'index'}; } - + return Selectors.Cache.nth[argument] = parsed; }, - + parseSelector: function(selector){ if (Selectors.Cache.parsed[selector]) return Selectors.Cache.parsed[selector]; var m, parsed = {classes: [], pseudos: [], attributes: []}; while ((m = Selectors.RegExps.combined.exec(selector))){ - var cn = m[1], an = m[2], ao = m[3], av = m[4], pn = m[5], pa = m[6]; + var cn = m[1], an = m[2], ao = m[3], av = m[5], pn = m[6], pa = m[7]; if (cn){ parsed.classes.push(cn); } else if (pn){ @@ -2428,13 +2789,13 @@ Selectors.Utils = { if (!parsed.classes && !parsed.attributes && !parsed.pseudos) parsed = null; return Selectors.Cache.parsed[selector] = parsed; }, - + parseTagAndID: function(selector){ var tag = selector.match(Selectors.RegExps.tag); var id = selector.match(Selectors.RegExps.id); return [(tag) ? tag[1] : '*', (id) ? id[1] : false]; }, - + filter: function(item, parsed, local){ var i; if (parsed.classes){ @@ -2457,7 +2818,7 @@ Selectors.Utils = { } return true; }, - + getByTagAndID: function(ctx, tag, id){ if (id){ var item = (ctx.getElementById) ? ctx.getElementById(id, true) : Element.getElementById(ctx, id, true); @@ -2466,28 +2827,28 @@ Selectors.Utils = { return ctx.getElementsByTagName(tag); } }, - + search: function(self, expression, local){ var splitters = []; - + var selectors = expression.trim().replace(Selectors.RegExps.splitter, function(m0, m1, m2){ splitters.push(m1); return ':)' + m2; }).split(':)'); - - var items, match, filtered, item; - + + var items, filtered, item; + for (var i = 0, l = selectors.length; i < l; i++){ - + var selector = selectors[i]; - + if (i == 0 && Selectors.RegExps.quick.test(selector)){ items = self.getElementsByTagName(selector); continue; } - + var splitter = splitters[i - 1]; - + var tagid = Selectors.Utils.parseTagAndID(selector); var tag = tagid[0], id = tagid[1]; @@ -2498,9 +2859,9 @@ Selectors.Utils = { for (var j = 0, k = items.length; j < k; j++) found = Selectors.Getters[splitter](found, items[j], tag, id, uniques); items = found; } - + var parsed = Selectors.Utils.parseSelector(selector); - + if (parsed){ filtered = []; for (var m = 0, n = items.length; m < n; m++){ @@ -2509,17 +2870,17 @@ Selectors.Utils = { } items = filtered; } - + } - + return items; - + } - + }; Selectors.Getters = { - + ' ': function(found, self, tag, id, uniques){ var items = Selectors.Utils.getByTagAndID(self, tag, id); for (var i = 0, l = items.length; i < l; i++){ @@ -2528,7 +2889,7 @@ Selectors.Getters = { } return found; }, - + '>': function(found, self, tag, id, uniques){ var children = Selectors.Utils.getByTagAndID(self, tag, id); for (var i = 0, l = children.length; i < l; i++){ @@ -2537,7 +2898,7 @@ Selectors.Getters = { } return found; }, - + '+': function(found, self, tag, id, uniques){ while ((self = self.nextSibling)){ if (self.nodeType == 1){ @@ -2547,41 +2908,40 @@ Selectors.Getters = { } return found; }, - + '~': function(found, self, tag, id, uniques){ - while ((self = self.nextSibling)){ if (self.nodeType == 1){ if (!Selectors.Utils.chk(self, uniques)) break; if (Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self); - } + } } return found; } - + }; Selectors.Filters = { - + byTag: function(self, tag){ return (tag == '*' || (self.tagName && self.tagName.toLowerCase() == tag)); }, - + byID: function(self, id){ return (!id || (self.id && self.id == id)); }, - + byClass: function(self, klass){ - return (self.className && self.className.contains(klass, ' ')); + return (self.className && self.className.contains && self.className.contains(klass, ' ')); }, - + byPseudo: function(self, parser, argument, local){ return parser.call(self, argument, local); }, - + byAttribute: function(self, name, operator, value){ var result = Element.prototype.getProperty.call(self, name); - if (!result) return false; + if (!result) return (operator == '!='); if (!operator || value == undefined) return true; switch (operator){ case '=': return (result == value); @@ -2594,29 +2954,33 @@ Selectors.Filters = { } return false; } - + }; Selectors.Pseudo = new Hash({ - + // w3c pseudo selectors + + checked: function(){ + return this.checked; + }, empty: function(){ return !(this.innerText || this.textContent || '').length; }, - + not: function(selector){ return !Element.match(this, selector); }, - + contains: function(text){ return (this.innerText || this.textContent || '').contains(text); }, - + 'first-child': function(){ return Selectors.Pseudo.index.call(this, 0); }, - + 'last-child': function(){ var element = this; while ((element = element.nextSibling)){ @@ -2624,7 +2988,7 @@ Selectors.Pseudo = new Hash({ } return true; }, - + 'only-child': function(){ var prev = this; while ((prev = prev.previousSibling)){ @@ -2636,7 +3000,7 @@ Selectors.Pseudo = new Hash({ } return true; }, - + 'nth-child': function(argument, local){ argument = (argument == undefined) ? 'n' : argument; var parsed = Selectors.Utils.parseNthArgument(argument); @@ -2659,9 +3023,9 @@ Selectors.Pseudo = new Hash({ } return (local.positions[uid] % parsed.a == parsed.b); }, - + // custom pseudo selectors - + index: function(index){ var element = this, count = 0; while ((element = element.previousSibling)){ @@ -2669,23 +3033,41 @@ Selectors.Pseudo = new Hash({ } return (count == index); }, - + even: function(argument, local){ return Selectors.Pseudo['nth-child'].call(this, '2n+1', local); }, odd: function(argument, local){ return Selectors.Pseudo['nth-child'].call(this, '2n', local); - } + }, + + selected: function(){ + return this.selected; + }, + enabled: function(){ + return (this.disabled === false); + } + }); + /* -Script: Domready.js - Contains the domready custom event. +--- + +script: DomReady.js + +description: Contains the custom event domready. -License: - MIT-style license. +license: MIT-style license. + +requires: +- /Element.Event + +provides: [DomReady] + +... */ Element.Events.domready = { @@ -2697,7 +3079,7 @@ Element.Events.domready = { }; (function(){ - + var domready = function(){ if (Browser.loaded) return; Browser.loaded = true; @@ -2705,49 +3087,67 @@ Element.Events.domready = { document.fireEvent('domready'); }; - switch (Browser.Engine.name){ - - case 'webkit': (function(){ + window.addEvent('load', domready); + + if (Browser.Engine.trident){ + var temp = document.createElement('div'); + (function(){ + ($try(function(){ + temp.doScroll(); // Technique by Diego Perini + return document.id(temp).inject(document.body).set('html', 'temp').dispose(); + })) ? domready() : arguments.callee.delay(50); + })(); + } else if (Browser.Engine.webkit && Browser.Engine.version < 525){ + (function(){ (['loaded', 'complete'].contains(document.readyState)) ? domready() : arguments.callee.delay(50); - })(); break; - - case 'trident': - var temp = document.createElement('div'); - (function(){ - ($try(function(){ - temp.doScroll('left'); - return $(temp).inject(document.body).set('html', 'temp').dispose(); - })) ? domready() : arguments.callee.delay(50); - })(); - break; - - default: - window.addEvent('load', domready); - document.addEvent('DOMContentLoaded', domready); - + })(); + } else { + document.addEvent('DOMContentLoaded', domready); } - + })(); + /* -Script: JSON.js - JSON encoder and decoder. +--- + +script: JSON.js + +description: JSON encoder and decoder. + +license: MIT-style license. -License: - MIT-style license. +See Also: -See Also: - +requires: +- /Array +- /String +- /Number +- /Function +- /Hash + +provides: [JSON] + +... */ -var JSON = new Hash({ +var JSON = new Hash(this.JSON && { + stringify: JSON.stringify, + parse: JSON.parse +}).extend({ + + $specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}, + + $replaceChars: function(chr){ + return JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16); + }, encode: function(obj){ switch ($type(obj)){ case 'string': return '"' + obj.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"'; case 'array': - return '[' + String(obj.map(JSON.encode).filter($defined)) + ']'; + return '[' + String(obj.map(JSON.encode).clean()) + ']'; case 'object': case 'hash': var string = []; Hash.each(obj, function(value, key){ @@ -2761,12 +3161,6 @@ var JSON = new Hash({ return null; }, - $specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}, - - $replaceChars: function(chr){ - return JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16); - }, - decode: function(string, secure){ if ($type(string) != 'string' || !string.length) return null; if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null; @@ -2785,14 +3179,23 @@ Native.implement([Hash, Array, String, Number], { /* -Script: Cookie.js - Class for creating, loading, and saving browser Cookies. +--- + +script: Cookie.js + +description: Class for creating, reading, and deleting browser Cookies. + +license: MIT-style license. + +credits: +- Based on the functions by Peter-Paul Koch (http://quirksmode.org). + +requires: +- /Options -License: - MIT-style license. +provides: [Cookie] -Credits: - Based on the functions by Peter-Paul Koch (http://quirksmode.org). +... */ var Cookie = new Class({ @@ -2850,15 +3253,26 @@ Cookie.dispose = function(key, options){ return new Cookie(key, options).dispose(); }; + /* -Script: Swiff.js - Wrapper for embedding SWF movies. Supports (and fixes) External Interface Communication. +--- + +script: Swiff.js + +description: Wrapper for embedding SWF movies. Supports External Interface Communication. + +license: MIT-style license. -License: - MIT-style license. +credits: +- Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. -Credits: - Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. +requires: +- /Options +- /$util + +provides: [Swiff] + +... */ var Swiff = new Class({ @@ -2891,7 +3305,7 @@ var Swiff = new Class({ this.setOptions(options); options = this.options; var id = this.id = options.id || this.instance; - var container = $(options.container); + var container = document.id(options.container); Swiff.CallBacks[this.instance] = {}; @@ -2924,17 +3338,17 @@ var Swiff = new Class({ if (params[param]) build += ''; } build += ''; - this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild; + this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild; }, replaces: function(element){ - element = $(element, true); + element = document.id(element, true); element.parentNode.replaceChild(this.toElement(), element); return this; }, inject: function(element){ - $(element, true).appendChild(this.toElement()); + document.id(element, true).appendChild(this.toElement()); return this; }, @@ -2951,141 +3365,167 @@ Swiff.remote = function(obj, fn){ return eval(rs); }; -/* -Script: Fx.js - Contains the basic animation logic to be extended by all other Fx Classes. - -License: - MIT-style license. -*/ - -var Fx = new Class({ - - Implements: [Chain, Events, Options], - - options: { - /* - onStart: $empty, - onCancel: $empty, - onComplete: $empty, - */ - fps: 50, - unit: false, - duration: 500, - link: 'ignore', - transition: function(p){ - return -(Math.cos(Math.PI * p) - 1) / 2; - } - }, - - initialize: function(options){ - this.subject = this.subject || this; - this.setOptions(options); - this.options.duration = Fx.Durations[this.options.duration] || this.options.duration.toInt(); - var wait = this.options.wait; - if (wait === false) this.options.link = 'cancel'; - }, - - step: function(){ - var time = $time(); - if (time < this.time + this.options.duration){ - var delta = this.options.transition((time - this.time) / this.options.duration); - this.set(this.compute(this.from, this.to, delta)); - } else { - this.set(this.compute(this.from, this.to, 1)); - this.complete(); - } - }, - - set: function(now){ - return now; - }, - - compute: function(from, to, delta){ - return Fx.compute(from, to, delta); - }, - - check: function(caller){ - if (!this.timer) return true; - switch (this.options.link){ - case 'cancel': this.cancel(); return true; - case 'chain': this.chain(caller.bind(this, Array.slice(arguments, 1))); return false; - } - return false; - }, - - start: function(from, to){ - if (!this.check(arguments.callee, from, to)) return this; - this.from = from; - this.to = to; - this.time = 0; - this.startTimer(); - this.onStart(); - return this; - }, - - complete: function(){ - if (this.stopTimer()) this.onComplete(); - return this; - }, - - cancel: function(){ - if (this.stopTimer()) this.onCancel(); - return this; - }, - - onStart: function(){ - this.fireEvent('start', this.subject); - }, - - onComplete: function(){ - this.fireEvent('complete', this.subject); - if (!this.callChain()) this.fireEvent('chainComplete', this.subject); - }, - - onCancel: function(){ - this.fireEvent('cancel', this.subject).clearChain(); - }, - - pause: function(){ - this.stopTimer(); - return this; - }, - - resume: function(){ - this.startTimer(); - return this; - }, - - stopTimer: function(){ - if (!this.timer) return false; - this.time = $time() - this.time; - this.timer = $clear(this.timer); - return true; - }, - - startTimer: function(){ - if (this.timer) return false; - this.time = $time() - this.time; - this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this); - return true; - } - -}); - -Fx.compute = function(from, to, delta){ - return (to - from) * delta + from; -}; - -Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; + +/* +--- + +script: Fx.js + +description: Contains the basic animation logic to be extended by all other Fx Classes. + +license: MIT-style license. + +requires: +- /Chain +- /Events +- /Options + +provides: [Fx] + +... +*/ + +var Fx = new Class({ + + Implements: [Chain, Events, Options], + + options: { + /* + onStart: $empty, + onCancel: $empty, + onComplete: $empty, + */ + fps: 50, + unit: false, + duration: 500, + link: 'ignore' + }, + + initialize: function(options){ + this.subject = this.subject || this; + this.setOptions(options); + this.options.duration = Fx.Durations[this.options.duration] || this.options.duration.toInt(); + var wait = this.options.wait; + if (wait === false) this.options.link = 'cancel'; + }, + + getTransition: function(){ + return function(p){ + return -(Math.cos(Math.PI * p) - 1) / 2; + }; + }, + + step: function(){ + var time = $time(); + if (time < this.time + this.options.duration){ + var delta = this.transition((time - this.time) / this.options.duration); + this.set(this.compute(this.from, this.to, delta)); + } else { + this.set(this.compute(this.from, this.to, 1)); + this.complete(); + } + }, + + set: function(now){ + return now; + }, + + compute: function(from, to, delta){ + return Fx.compute(from, to, delta); + }, + + check: function(){ + if (!this.timer) return true; + switch (this.options.link){ + case 'cancel': this.cancel(); return true; + case 'chain': this.chain(this.caller.bind(this, arguments)); return false; + } + return false; + }, + + start: function(from, to){ + if (!this.check(from, to)) return this; + this.from = from; + this.to = to; + this.time = 0; + this.transition = this.getTransition(); + this.startTimer(); + this.onStart(); + return this; + }, + + complete: function(){ + if (this.stopTimer()) this.onComplete(); + return this; + }, + + cancel: function(){ + if (this.stopTimer()) this.onCancel(); + return this; + }, + + onStart: function(){ + this.fireEvent('start', this.subject); + }, + + onComplete: function(){ + this.fireEvent('complete', this.subject); + if (!this.callChain()) this.fireEvent('chainComplete', this.subject); + }, + + onCancel: function(){ + this.fireEvent('cancel', this.subject).clearChain(); + }, + + pause: function(){ + this.stopTimer(); + return this; + }, + + resume: function(){ + this.startTimer(); + return this; + }, + + stopTimer: function(){ + if (!this.timer) return false; + this.time = $time() - this.time; + this.timer = $clear(this.timer); + return true; + }, + + startTimer: function(){ + if (this.timer) return false; + this.time = $time() - this.time; + this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this); + return true; + } + +}); + +Fx.compute = function(from, to, delta){ + return (to - from) * delta + from; +}; + +Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; /* -Script: Fx.CSS.js - Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. +--- + +script: Fx.CSS.js + +description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. -License: - MIT-style license. +license: MIT-style license. + +requires: +- /Fx +- /Element.Style + +provides: [Fx.CSS] + +... */ Fx.CSS = new Class({ @@ -3215,11 +3655,20 @@ Fx.CSS.Parsers = new Hash({ /* -Script: Fx.Tween.js - Formerly Fx.Style, effect to transition any CSS property for an element. +--- + +script: Fx.Tween.js + +description: Formerly Fx.Style, effect to transition any CSS property for an element. + +license: MIT-style license. + +requires: +- /Fx.CSS -License: - MIT-style license. +provides: [Fx.Tween, Element.fade, Element.highlight] + +... */ Fx.Tween = new Class({ @@ -3227,7 +3676,7 @@ Fx.Tween = new Class({ Extends: Fx.CSS, initialize: function(element, options){ - this.element = this.subject = $(element); + this.element = this.subject = document.id(element); this.parent(options); }, @@ -3241,7 +3690,7 @@ Fx.Tween = new Class({ }, start: function(property, from, to){ - if (!this.check(arguments.callee, property, from, to)) return this; + if (!this.check(property, from, to)) return this; var args = Array.flatten(arguments); this.property = this.options.property || args.shift(); var parsed = this.prepare(this.element, this.property, args); @@ -3312,11 +3761,20 @@ Element.implement({ /* -Script: Fx.Morph.js - Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. +--- + +script: Fx.Morph.js + +description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. + +license: MIT-style license. -License: - MIT-style license. +requires: +- /Fx.CSS + +provides: [Fx.Morph] + +... */ Fx.Morph = new Class({ @@ -3324,7 +3782,7 @@ Fx.Morph = new Class({ Extends: Fx.CSS, initialize: function(element, options){ - this.element = this.subject = $(element); + this.element = this.subject = document.id(element); this.parent(options); }, @@ -3341,7 +3799,7 @@ Fx.Morph = new Class({ }, start: function(properties){ - if (!this.check(arguments.callee, properties)) return this; + if (!this.check(properties)) return this; if (typeof properties == 'string') properties = this.search(properties); var from = {}, to = {}; for (var p in properties){ @@ -3381,33 +3839,41 @@ Element.implement({ }); + /* -Script: Fx.Transitions.js - Contains a set of advanced transitions to be used with any of the Fx Classes. +--- -License: - MIT-style license. +script: Fx.Transitions.js -Credits: - Easing Equations by Robert Penner, , modified and optimized to be used with MooTools. -*/ +description: Contains a set of advanced transitions to be used with any of the Fx Classes. -(function(){ +license: MIT-style license. + +credits: +- Easing Equations by Robert Penner, , modified and optimized to be used with MooTools. - var old = Fx.prototype.initialize; +requires: +- /Fx - Fx.prototype.initialize = function(options){ - old.call(this, options); - var trans = this.options.transition; - if (typeof trans == 'string' && (trans = trans.split(':'))){ - var base = Fx.Transitions; - base = base[trans[0]] || base[trans[0].capitalize()]; - if (trans[1]) base = base['ease' + trans[1].capitalize() + (trans[2] ? trans[2].capitalize() : '')]; - this.options.transition = base; +provides: [Fx.Transitions] + +... +*/ + +Fx.implement({ + + getTransition: function(){ + var trans = this.options.transition || Fx.Transitions.Sine.easeInOut; + if (typeof trans == 'string'){ + var data = trans.split(':'); + trans = Fx.Transitions; + trans = trans[data[0]] || trans[data[0].capitalize()]; + if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]; } - }; + return trans; + } -})(); +}); Fx.Transition = function(transition, params){ params = $splat(params); @@ -3461,7 +3927,7 @@ Fx.Transitions.extend({ var value; for (var a = 0, b = 1; 1; a += b, b /= 2){ if (p >= (7 - 4 * a) / 11){ - value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b; + value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); break; } } @@ -3482,19 +3948,34 @@ Fx.Transitions.extend({ /* -Script: Request.js - Powerful all purpose Request Class. Uses XMLHTTPRequest. +--- + +script: Request.js + +description: Powerful all purpose Request Class. Uses XMLHTTPRequest. + +license: MIT-style license. + +requires: +- /Element +- /Chain +- /Events +- /Options +- /Browser + +provides: [Request] -License: - MIT-style license. +... */ var Request = new Class({ Implements: [Chain, Events, Options], - options: { - /*onRequest: $empty, + options: {/* + onRequest: $empty, + onComplete: $empty, + onCancel: $empty, onSuccess: $empty, onFailure: $empty, onException: $empty,*/ @@ -3513,7 +3994,8 @@ var Request = new Class({ urlEncoded: true, encoding: 'utf-8', evalScripts: false, - evalResponse: false + evalResponse: false, + noCache: false }, initialize: function(options){ @@ -3530,6 +4012,7 @@ var Request = new Class({ $try(function(){ this.status = this.xhr.status; }.bind(this)); + this.xhr.onreadystatechange = $empty; if (this.options.isSuccess.call(this, this.status)){ this.response = {text: this.xhr.responseText, xml: this.xhr.responseXML}; this.success(this.response.text, this.response.xml); @@ -3537,7 +4020,6 @@ var Request = new Class({ this.response = {text: null, xml: null}; this.failure(); } - this.xhr.onreadystatechange = $empty; }, isSuccess: function(){ @@ -3552,11 +4034,11 @@ var Request = new Class({ success: function(text, xml){ this.onSuccess(this.processScripts(text), xml); }, - + onSuccess: function(){ this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); }, - + failure: function(){ this.onFailure(); }, @@ -3576,17 +4058,17 @@ var Request = new Class({ }.bind(this)); }, - check: function(caller){ + check: function(){ if (!this.running) return true; switch (this.options.link){ case 'cancel': this.cancel(); return true; - case 'chain': this.chain(caller.bind(this, Array.slice(arguments, 1))); return false; + case 'chain': this.chain(this.caller.bind(this, arguments)); return false; } return false; }, send: function(options){ - if (!this.check(arguments.callee, options)) return this; + if (!this.check(options)) return this; this.running = true; var type = $type(options); @@ -3594,10 +4076,10 @@ var Request = new Class({ var old = this.options; options = $extend({data: old.data, url: old.url, method: old.method}, options); - var data = options.data, url = options.url, method = options.method; + var data = options.data, url = String(options.url), method = options.method.toLowerCase(); switch ($type(data)){ - case 'element': data = $(data).toQueryString(); break; + case 'element': data = document.id(data).toQueryString(); break; case 'object': case 'hash': data = Hash.toQueryString(data); } @@ -3606,7 +4088,7 @@ var Request = new Class({ data = (data) ? format + '&' + data : format; } - if (this.options.emulation && ['put', 'delete'].contains(method)){ + if (this.options.emulation && !['get', 'post'].contains(method)){ var _method = '_method=' + method; data = (data) ? _method + '&' + data : _method; method = 'post'; @@ -3617,6 +4099,14 @@ var Request = new Class({ this.headers.set('Content-type', 'application/x-www-form-urlencoded' + encoding); } + if (this.options.noCache){ + var noCache = 'noCache=' + new Date().getTime(); + data = (data) ? noCache + '&' + data : noCache; + } + + var trimPosition = url.lastIndexOf('/'); + if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition); + if (data && method == 'get'){ url = url + (url.contains('?') ? '&' : '?') + data; data = null; @@ -3627,10 +4117,11 @@ var Request = new Class({ this.xhr.onreadystatechange = this.onStateChange.bind(this); this.headers.each(function(value, key){ - if (!$try(function(){ + try { this.xhr.setRequestHeader(key, value); - return true; - }.bind(this))) this.fireEvent('exception', [key, value]); + } catch (e){ + this.fireEvent('exception', [key, value]); + } }, this); this.fireEvent('request'); @@ -3657,7 +4148,7 @@ var methods = {}; ['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ methods[method] = function(){ var params = Array.link(arguments, {url: String.type, data: $defined}); - return this.send($extend(params, {method: method.toLowerCase()})); + return this.send($extend(params, {method: method})); }; }); @@ -3666,7 +4157,7 @@ Request.implement(methods); })(); Element.Properties.send = { - + set: function(options){ var send = this.retrieve('send'); if (send) send.cancel(); @@ -3697,11 +4188,21 @@ Element.implement({ /* -Script: Request.HTML.js - Extends the basic Request Class with additional methods for interacting with HTML responses. +--- -License: - MIT-style license. +script: Request.HTML.js + +description: Extends the basic Request Class with additional methods for interacting with HTML responses. + +license: MIT-style license. + +requires: +- /Request +- /Element + +provides: [Request.HTML] + +... */ Request.HTML = new Class({ @@ -3710,6 +4211,7 @@ Request.HTML = new Class({ options: { update: false, + append: false, evalScripts: true, filter: false }, @@ -3717,9 +4219,9 @@ Request.HTML = new Class({ processHTML: function(text){ var match = text.match(/]*>([\s\S]*?)<\/body>/i); text = (match) ? match[1] : text; - + var container = new Element('div'); - + return $try(function(){ var root = '' + text + '', doc; if (Browser.Engine.trident){ @@ -3730,6 +4232,7 @@ Request.HTML = new Class({ doc = new DOMParser().parseFromString(root, 'text/xml'); } root = doc.getElementsByTagName('root')[0]; + if (!root) return null; for (var i = 0, k = root.childNodes.length; i < k; i++){ var child = Element.clone(root.childNodes[i], true, true); if (child) container.grab(child); @@ -3740,30 +4243,31 @@ Request.HTML = new Class({ success: function(text){ var options = this.options, response = this.response; - + response.html = text.stripScripts(function(script){ response.javascript = script; }); - + var temp = this.processHTML(response.html); - + response.tree = temp.childNodes; response.elements = temp.getElements('*'); - + if (options.filter) response.tree = response.elements.filter(options.filter); - if (options.update) $(options.update).empty().adopt(response.tree); + 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.evalScripts) $exec(response.javascript); - + this.onSuccess(response.tree, response.elements, response.html, response.javascript); } }); Element.Properties.load = { - + set: function(options){ var load = this.retrieve('load'); - if (load) send.cancel(); + if (load) load.cancel(); return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options)); }, @@ -3778,7 +4282,7 @@ Element.Properties.load = { }; Element.implement({ - + load: function(){ this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type})); return this; @@ -3788,11 +4292,20 @@ Element.implement({ /* -Script: Request.JSON.js - Extends the basic Request Class with additional methods for sending and receiving JSON data. +--- + +script: Request.JSON.js + +description: Extends the basic Request Class with additional methods for sending and receiving JSON data. + +license: MIT-style license. -License: - MIT-style license. +requires: +- /Request JSON + +provides: [Request.HTML] + +... */ Request.JSON = new Class({ @@ -3814,243 +4327,54 @@ Request.JSON = new Class({ } }); -//MooTools More, . Copyright (c) 2006-2008 Valerio Proietti, , MIT Style License. - -/* -Script: Fx.Slide.js - Effect to slide an element in and out of view. - -License: - MIT-style license. -*/ - -Fx.Slide = new Class({ - - Extends: Fx, - - options: { - mode: 'vertical' - }, - - initialize: function(element, options){ - this.addEvent('complete', function(){ - this.open = (this.wrapper['offset' + this.layout.capitalize()] != 0); - if (this.open && Browser.Engine.webkit419) this.element.dispose().inject(this.wrapper); - }, true); - this.element = this.subject = $(element); - this.parent(options); - var wrapper = this.element.retrieve('wrapper'); - this.wrapper = wrapper || new Element('div', { - styles: $extend(this.element.getStyles('margin', 'position'), {'overflow': 'hidden'}) - }).wraps(this.element); - this.element.store('wrapper', this.wrapper).setStyle('margin', 0); - this.now = []; - this.open = true; - }, - - vertical: function(){ - this.margin = 'margin-top'; - this.layout = 'height'; - this.offset = this.element.offsetHeight; - }, - - horizontal: function(){ - this.margin = 'margin-left'; - this.layout = 'width'; - this.offset = this.element.offsetWidth; - }, - - set: function(now){ - this.element.setStyle(this.margin, now[0]); - this.wrapper.setStyle(this.layout, now[1]); - return this; - }, - - compute: function(from, to, delta){ - var now = []; - var x = 2; - x.times(function(i){ - now[i] = Fx.compute(from[i], to[i], delta); - }); - return now; - }, - - start: function(how, mode){ - if (!this.check(arguments.callee, how, mode)) return this; - this[mode || this.options.mode](); - var margin = this.element.getStyle(this.margin).toInt(); - var layout = this.wrapper.getStyle(this.layout).toInt(); - var caseIn = [[margin, layout], [0, this.offset]]; - var caseOut = [[margin, layout], [-this.offset, 0]]; - var start; - switch (how){ - case 'in': start = caseIn; break; - case 'out': start = caseOut; break; - case 'toggle': start = (this.wrapper['offset' + this.layout.capitalize()] == 0) ? caseIn : caseOut; - } - return this.parent(start[0], start[1]); - }, - - slideIn: function(mode){ - return this.start('in', mode); - }, - - slideOut: function(mode){ - return this.start('out', mode); - }, - - hide: function(mode){ - this[mode || this.options.mode](); - this.open = false; - return this.set([-this.offset, 0]); - }, - - show: function(mode){ - this[mode || this.options.mode](); - this.open = true; - return this.set([0, this.offset]); - }, - - toggle: function(mode){ - return this.start('toggle', mode); - } - -}); - -Element.Properties.slide = { - - set: function(options){ - var slide = this.retrieve('slide'); - if (slide) slide.cancel(); - return this.eliminate('slide').store('slide:options', $extend({link: 'cancel'}, options)); - }, - - get: function(options){ - if (options || !this.retrieve('slide')){ - if (options || !this.retrieve('slide:options')) this.set('slide', options); - this.store('slide', new Fx.Slide(this, this.retrieve('slide:options'))); - } - return this.retrieve('slide'); - } - -}; - -Element.implement({ - - slide: function(how, mode){ - how = how || 'toggle'; - var slide = this.get('slide'), toggle; - switch (how){ - case 'hide': slide.hide(mode); break; - case 'show': slide.show(mode); break; - case 'toggle': - var flag = this.retrieve('slide:flag', slide.open); - slide[(flag) ? 'slideOut' : 'slideIn'](mode); - this.store('slide:flag', !flag); - toggle = true; - break; - default: slide.start(how, mode); - } - if (!toggle) this.eliminate('slide:flag'); - return this; - } - -}); - +//MooTools More, . Copyright (c) 2006-2009 Aaron Newton , Valerio Proietti & the MooTools team , MIT Style License. /* -Script: Fx.Scroll.js - Effect to smoothly scroll any element, including the window. - -License: - MIT-style license. -*/ - -Fx.Scroll = new Class({ - - Extends: Fx, - - options: { - offset: {'x': 0, 'y': 0}, - wheelStops: true - }, +--- - initialize: function(element, options){ - this.element = this.subject = $(element); - this.parent(options); - var cancel = this.cancel.bind(this, false); +script: More.js - if ($type(this.element) != 'element') this.element = $(this.element.getDocument().body); +description: MooTools More - var stopper = this.element; +license: MIT-style license - if (this.options.wheelStops){ - this.addEvent('start', function(){ - stopper.addEvent('mousewheel', cancel); - }, true); - this.addEvent('complete', function(){ - stopper.removeEvent('mousewheel', cancel); - }, true); - } - }, +authors: +- Guillermo Rauch +- Thomas Aylott +- Scott Kyle - set: function(){ - var now = Array.flatten(arguments); - this.element.scrollTo(now[0], now[1]); - }, +requires: +- core:1.2.4/MooTools - compute: function(from, to, delta){ - var now = []; - var x = 2; - x.times(function(i){ - now.push(Fx.compute(from[i], to[i], delta)); - }); - return now; - }, +provides: [MooTools.More] - start: function(x, y){ - if (!this.check(arguments.callee, x, y)) return this; - var offsetSize = this.element.getSize(), scrollSize = this.element.getScrollSize(); - var scroll = this.element.getScroll(), values = {x: x, y: y}; - for (var z in values){ - var max = scrollSize[z] - offsetSize[z]; - if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z].limit(0, max) : max; - else values[z] = scroll[z]; - values[z] += this.options.offset[z]; - } - return this.parent([scroll.x, scroll.y], [values.x, values.y]); - }, +... +*/ - toTop: function(){ - return this.start(false, 0); - }, +MooTools.More = { + 'version': '1.2.4.2', + 'build': 'bd5a93c0913cce25917c48cbdacde568e15e02ef' +}; - toLeft: function(){ - return this.start(0, false); - }, +/* +--- - toRight: function(){ - return this.start('right', false); - }, +script: Fx.Elements.js - toBottom: function(){ - return this.start(false, 'bottom'); - }, +description: Effect to change any number of CSS properties of any number of Elements. - toElement: function(el){ - var position = $(el).getPosition(this.element); - return this.start(position.x, position.y); - } +license: MIT-style license -}); +authors: +- Valerio Proietti +requires: +- core:1.2.4/Fx.CSS +- /MooTools.More -/* -Script: Fx.Elements.js - Effect to change any number of CSS properties of any number of Elements. +provides: [Fx.Elements] -License: - MIT-style license. +... */ Fx.Elements = new Class({ @@ -4080,7 +4404,7 @@ Fx.Elements = new Class({ }, start: function(obj){ - if (!this.check(arguments.callee, obj)) return this; + if (!this.check(obj)) return this; var from = {}, to = {}; for (var i in obj){ var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {}; @@ -4096,491 +4420,182 @@ Fx.Elements = new Class({ }); /* -Script: Drag.js - The base Drag Class. Can be used to drag and resize Elements using mouse events. - -License: - MIT-style license. -*/ - -var Drag = new Class({ - - Implements: [Events, Options], - - options: {/* - onBeforeStart: $empty, - onStart: $empty, - onDrag: $empty, - onCancel: $empty, - onComplete: $empty,*/ - snap: 6, - unit: 'px', - grid: false, - style: true, - limit: false, - handle: false, - invert: false, - preventDefault: false, - modifiers: {x: 'left', y: 'top'} - }, +--- - initialize: function(){ - var params = Array.link(arguments, {'options': Object.type, 'element': $defined}); - this.element = $(params.element); - this.document = this.element.getDocument(); - this.setOptions(params.options || {}); - var htype = $type(this.options.handle); - this.handles = (htype == 'array' || htype == 'collection') ? $$(this.options.handle) : $(this.options.handle) || this.element; - this.mouse = {'now': {}, 'pos': {}}; - this.value = {'start': {}, 'now': {}}; - - this.selection = (Browser.Engine.trident) ? 'selectstart' : 'mousedown'; - - this.bound = { - start: this.start.bind(this), - check: this.check.bind(this), - drag: this.drag.bind(this), - stop: this.stop.bind(this), - cancel: this.cancel.bind(this), - eventStop: $lambda(false) - }; - this.attach(); - }, - - attach: function(){ - this.handles.addEvent('mousedown', this.bound.start); - return this; - }, - - detach: function(){ - this.handles.removeEvent('mousedown', this.bound.start); - return this; - }, - - start: function(event){ - if (this.options.preventDefault) event.preventDefault(); - this.fireEvent('beforeStart', this.element); - this.mouse.start = event.page; - var limit = this.options.limit; - this.limit = {'x': [], 'y': []}; - for (var z in this.options.modifiers){ - if (!this.options.modifiers[z]) continue; - if (this.options.style) this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt(); - else this.value.now[z] = this.element[this.options.modifiers[z]]; - if (this.options.invert) this.value.now[z] *= -1; - this.mouse.pos[z] = event.page[z] - this.value.now[z]; - if (limit && limit[z]){ - for (var i = 2; i--; i){ - if ($chk(limit[z][i])) this.limit[z][i] = $lambda(limit[z][i])(); - } - } - } - if ($type(this.options.grid) == 'number') this.options.grid = {'x': this.options.grid, 'y': this.options.grid}; - this.document.addEvents({mousemove: this.bound.check, mouseup: this.bound.cancel}); - this.document.addEvent(this.selection, this.bound.eventStop); - }, - - check: function(event){ - if (this.options.preventDefault) event.preventDefault(); - var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2))); - if (distance > this.options.snap){ - this.cancel(); - this.document.addEvents({ - mousemove: this.bound.drag, - mouseup: this.bound.stop - }); - this.fireEvent('start', this.element).fireEvent('snap', this.element); - } - }, +script: Fx.Slide.js - drag: function(event){ - if (this.options.preventDefault) event.preventDefault(); - this.mouse.now = event.page; - for (var z in this.options.modifiers){ - if (!this.options.modifiers[z]) continue; - this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z]; - if (this.options.invert) this.value.now[z] *= -1; - if (this.options.limit && this.limit[z]){ - if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){ - this.value.now[z] = this.limit[z][1]; - } else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){ - this.value.now[z] = this.limit[z][0]; - } - } - if (this.options.grid[z]) this.value.now[z] -= (this.value.now[z] % this.options.grid[z]); - if (this.options.style) this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit); - else this.element[this.options.modifiers[z]] = this.value.now[z]; - } - this.fireEvent('drag', this.element); - }, +description: Effect to slide an element in and out of view. - cancel: function(event){ - this.document.removeEvent('mousemove', this.bound.check); - this.document.removeEvent('mouseup', this.bound.cancel); - if (event){ - this.document.removeEvent(this.selection, this.bound.eventStop); - this.fireEvent('cancel', this.element); - } - }, - - stop: function(event){ - this.document.removeEvent(this.selection, this.bound.eventStop); - this.document.removeEvent('mousemove', this.bound.drag); - this.document.removeEvent('mouseup', this.bound.stop); - if (event) this.fireEvent('complete', this.element); - } +license: MIT-style license -}); - -Element.implement({ - - makeResizable: function(options){ - return new Drag(this, $merge({modifiers: {'x': 'width', 'y': 'height'}}, options)); - } +authors: +- Valerio Proietti -}); +requires: +- core:1.2.4/Fx Element.Style +- /MooTools.More -/* -Script: Drag.Move.js - A Drag extension that provides support for the constraining of draggables to containers and droppables. +provides: [Fx.Slide] -License: - MIT-style license. +... */ -Drag.Move = new Class({ +Fx.Slide = new Class({ - Extends: Drag, + Extends: Fx, options: { - droppables: [], - container: false + mode: 'vertical', + hideOverflow: true }, initialize: function(element, options){ - this.parent(element, options); - this.droppables = $$(this.options.droppables); - this.container = $(this.options.container); - if (this.container && $type(this.container) != 'element') this.container = $(this.container.getDocument().body); - element = this.element; - - var current = element.getStyle('position'); - var position = (current != 'static') ? current : 'absolute'; - if (element.getStyle('left') == 'auto' || element.getStyle('top') == 'auto') element.position(element.getPosition(element.offsetParent)); - - element.setStyle('position', position); - - this.addEvent('start', function(){ - this.checkDroppables(); + this.addEvent('complete', function(){ + this.open = (this.wrapper['offset' + this.layout.capitalize()] != 0); + if (this.open && Browser.Engine.webkit419) this.element.dispose().inject(this.wrapper); }, true); + this.element = this.subject = document.id(element); + this.parent(options); + var wrapper = this.element.retrieve('wrapper'); + var styles = this.element.getStyles('margin', 'position', 'overflow'); + if (this.options.hideOverflow) styles = $extend(styles, {overflow: 'hidden'}); + this.wrapper = wrapper || new Element('div', { + styles: styles + }).wraps(this.element); + this.element.store('wrapper', this.wrapper).setStyle('margin', 0); + this.now = []; + this.open = true; }, - start: function(event){ - if (this.container){ - var el = this.element, cont = this.container, ccoo = cont.getCoordinates(el.offsetParent), cps = {}, ems = {}; - - ['top', 'right', 'bottom', 'left'].each(function(pad){ - cps[pad] = cont.getStyle('padding-' + pad).toInt(); - ems[pad] = el.getStyle('margin-' + pad).toInt(); - }, this); - - var width = el.offsetWidth + ems.left + ems.right, height = el.offsetHeight + ems.top + ems.bottom; - var x = [ccoo.left + cps.left, ccoo.right - cps.right - width]; - var y = [ccoo.top + cps.top, ccoo.bottom - cps.bottom - height]; - - this.options.limit = {x: x, y: y}; - } - this.parent(event); + vertical: function(){ + this.margin = 'margin-top'; + this.layout = 'height'; + this.offset = this.element.offsetHeight; }, - checkAgainst: function(el){ - el = el.getCoordinates(); - var now = this.mouse.now; - return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top); + horizontal: function(){ + this.margin = 'margin-left'; + this.layout = 'width'; + this.offset = this.element.offsetWidth; }, - checkDroppables: function(){ - var overed = this.droppables.filter(this.checkAgainst, this).getLast(); - if (this.overed != overed){ - if (this.overed) this.fireEvent('leave', [this.element, this.overed]); - if (overed){ - this.overed = overed; - this.fireEvent('enter', [this.element, overed]); - } else { - this.overed = null; - } - } + set: function(now){ + this.element.setStyle(this.margin, now[0]); + this.wrapper.setStyle(this.layout, now[1]); + return this; }, - drag: function(event){ - this.parent(event); - if (this.droppables.length) this.checkDroppables(); + compute: function(from, to, delta){ + return [0, 1].map(function(i){ + return Fx.compute(from[i], to[i], delta); + }); }, - stop: function(event){ - this.checkDroppables(); - this.fireEvent('drop', [this.element, this.overed]); - this.overed = null; - return this.parent(event); - } - -}); - -Element.implement({ - - makeDraggable: function(options){ - return new Drag.Move(this, options); - } - -}); - - -/* -Script: Hash.Cookie.js - Class for creating, reading, and deleting Cookies in JSON format. - -License: - MIT-style license. -*/ - -Hash.Cookie = new Class({ - - Extends: Cookie, - - options: { - autoSave: true - }, - - initialize: function(name, options){ - this.parent(name, options); - this.load(); - }, - - save: function(){ - var value = JSON.encode(this.hash); - if (!value || value.length > 4096) return false; //cookie would be truncated! - if (value == '{}') this.dispose(); - else this.write(value); - return true; - }, - - load: function(){ - this.hash = new Hash(JSON.decode(this.read(), true)); - return this; - } - -}); - -Hash.Cookie.implement((function(){ - - var methods = {}; - - Hash.each(Hash.prototype, function(method, name){ - methods[name] = function(){ - var value = method.apply(this.hash, arguments); - if (this.options.autoSave) this.save(); - return value; - }; - }); - - return methods; - -})()); - -/* -Script: Color.js - Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa. - -License: - MIT-style license. -*/ - -var Color = new Native({ - - initialize: function(color, type){ - if (arguments.length >= 3){ - type = "rgb"; color = Array.slice(arguments, 0, 3); - } else if (typeof color == 'string'){ - if (color.match(/rgb/)) color = color.rgbToHex().hexToRgb(true); - else if (color.match(/hsb/)) color = color.hsbToRgb(); - else color = color.hexToRgb(true); - } - type = type || 'rgb'; - switch (type){ - case 'hsb': - var old = color; - color = color.hsbToRgb(); - color.hsb = old; - break; - case 'hex': color = color.hexToRgb(true); break; + start: function(how, mode){ + if (!this.check(how, mode)) return this; + this[mode || this.options.mode](); + var margin = this.element.getStyle(this.margin).toInt(); + var layout = this.wrapper.getStyle(this.layout).toInt(); + var caseIn = [[margin, layout], [0, this.offset]]; + var caseOut = [[margin, layout], [-this.offset, 0]]; + var start; + switch (how){ + case 'in': start = caseIn; break; + case 'out': start = caseOut; break; + case 'toggle': start = (layout == 0) ? caseIn : caseOut; } - color.rgb = color.slice(0, 3); - color.hsb = color.hsb || color.rgbToHsb(); - color.hex = color.rgbToHex(); - return $extend(color, this); - } - -}); - -Color.implement({ + return this.parent(start[0], start[1]); + }, - mix: function(){ - var colors = Array.slice(arguments); - var alpha = ($type(colors.getLast()) == 'number') ? colors.pop() : 50; - var rgb = this.slice(); - colors.each(function(color){ - color = new Color(color); - for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha)); - }); - return new Color(rgb, 'rgb'); + slideIn: function(mode){ + return this.start('in', mode); }, - invert: function(){ - return new Color(this.map(function(value){ - return 255 - value; - })); + slideOut: function(mode){ + return this.start('out', mode); }, - setHue: function(value){ - return new Color([value, this.hsb[1], this.hsb[2]], 'hsb'); + hide: function(mode){ + this[mode || this.options.mode](); + this.open = false; + return this.set([-this.offset, 0]); }, - setSaturation: function(percent){ - return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb'); + show: function(mode){ + this[mode || this.options.mode](); + this.open = true; + return this.set([0, this.offset]); }, - setBrightness: function(percent){ - return new Color([this.hsb[0], this.hsb[1], percent], 'hsb'); + toggle: function(mode){ + return this.start('toggle', mode); } }); -function $RGB(r, g, b){ - return new Color([r, g, b], 'rgb'); -}; - -function $HSB(h, s, b){ - return new Color([h, s, b], 'hsb'); -}; - -function $HEX(hex){ - return new Color(hex, 'hex'); -}; - -Array.implement({ +Element.Properties.slide = { - rgbToHsb: function(){ - var red = this[0], green = this[1], blue = this[2]; - var hue, saturation, brightness; - var max = Math.max(red, green, blue), min = Math.min(red, green, blue); - var delta = max - min; - brightness = max / 255; - saturation = (max != 0) ? delta / max : 0; - if (saturation == 0){ - hue = 0; - } else { - var rr = (max - red) / delta; - var gr = (max - green) / delta; - var br = (max - blue) / delta; - if (red == max) hue = br - gr; - else if (green == max) hue = 2 + rr - br; - else hue = 4 + gr - rr; - hue /= 6; - if (hue < 0) hue++; - } - return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)]; + set: function(options){ + var slide = this.retrieve('slide'); + if (slide) slide.cancel(); + return this.eliminate('slide').store('slide:options', $extend({link: 'cancel'}, options)); }, - hsbToRgb: function(){ - var br = Math.round(this[2] / 100 * 255); - if (this[1] == 0){ - return [br, br, br]; - } else { - var hue = this[0] % 360; - var f = hue % 60; - var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255); - var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255); - var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255); - switch (Math.floor(hue / 60)){ - case 0: return [br, t, p]; - case 1: return [q, br, p]; - case 2: return [p, br, t]; - case 3: return [p, q, br]; - case 4: return [t, p, br]; - case 5: return [br, p, q]; - } + get: function(options){ + if (options || !this.retrieve('slide')){ + if (options || !this.retrieve('slide:options')) this.set('slide', options); + this.store('slide', new Fx.Slide(this, this.retrieve('slide:options'))); } - return false; + return this.retrieve('slide'); } -}); +}; -String.implement({ +Element.implement({ - rgbToHsb: function(){ - var rgb = this.match(/\d{1,3}/g); - return (rgb) ? hsb.rgbToHsb() : null; - }, - - hsbToRgb: function(){ - var hsb = this.match(/\d{1,3}/g); - return (hsb) ? hsb.hsbToRgb() : null; + slide: function(how, mode){ + how = how || 'toggle'; + var slide = this.get('slide'), toggle; + switch (how){ + case 'hide': slide.hide(mode); break; + case 'show': slide.show(mode); break; + case 'toggle': + var flag = this.retrieve('slide:flag', slide.open); + slide[flag ? 'slideOut' : 'slideIn'](mode); + this.store('slide:flag', !flag); + toggle = true; + break; + default: slide.start(how, mode); + } + if (!toggle) this.eliminate('slide:flag'); + return this; } }); /* -Script: Group.js - Class for monitoring collections of events - -License: - MIT-style license. -*/ +--- -var Group = new Class({ +script: Assets.js - initialize: function(){ - this.instances = Array.flatten(arguments); - this.events = {}; - this.checker = {}; - }, +description: Provides methods to dynamically load JavaScript, CSS, and Image files into the document. - addEvent: function(type, fn){ - this.checker[type] = this.checker[type] || {}; - this.events[type] = this.events[type] || []; - if (this.events[type].contains(fn)) return false; - else this.events[type].push(fn); - this.instances.each(function(instance, i){ - instance.addEvent(type, this.check.bind(this, [type, instance, i])); - }, this); - return this; - }, +license: MIT-style license - check: function(type, instance, i){ - this.checker[type][i] = true; - var every = this.instances.every(function(current, j){ - return this.checker[type][j] || false; - }, this); - if (!every) return; - this.checker[type] = {}; - this.events[type].each(function(event){ - event.call(this, this.instances, instance); - }, this); - } - -}); +authors: +- Valerio Proietti +requires: +- core:1.2.4/Element.Event +- /MooTools.More -/* -Script: Assets.js - Provides methods to dynamically load JavaScript, CSS, and Image files into the document. +provides: [Assets] -License: - MIT-style license. +... */ -var Asset = new Hash({ +var Asset = { javascript: function(source, properties){ properties = $extend({ @@ -4588,43 +4603,49 @@ var Asset = new Hash({ document: document, check: $lambda(true) }, properties); - - var script = new Element('script', {'src': source, 'type': 'text/javascript'}); - - var load = properties.onload.bind(script), check = properties.check, doc = properties.document; - delete properties.onload; delete properties.check; delete properties.document; - + + var script = new Element('script', {src: source, type: 'text/javascript'}); + + var load = properties.onload.bind(script), + check = properties.check, + doc = properties.document; + delete properties.onload; + delete properties.check; + delete properties.document; + script.addEvents({ load: load, readystatechange: function(){ if (['loaded', 'complete'].contains(this.readyState)) load(); } - }).setProperties(properties); - - + }).set(properties); + if (Browser.Engine.webkit419) var checker = (function(){ if (!$try(check)) return; $clear(checker); load(); }).periodical(50); - + return script.inject(doc.head); }, css: function(source, properties){ return new Element('link', $merge({ - 'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source + rel: 'stylesheet', + media: 'screen', + type: 'text/css', + href: source }, properties)).inject(document.head); }, image: function(source, properties){ properties = $merge({ - 'onload': $empty, - 'onabort': $empty, - 'onerror': $empty + onload: $empty, + onabort: $empty, + onerror: $empty }, properties); var image = new Image(); - var element = $(image) || new Element('img'); + var element = document.id(image) || new Element('img'); ['load', 'abort', 'error'].each(function(name){ var type = 'on' + name; var event = properties[type]; @@ -4642,666 +4663,33 @@ var Asset = new Hash({ }); image.src = element.src = source; if (image && image.complete) image.onload.delay(1); - return element.setProperties(properties); + return element.set(properties); }, images: function(sources, options){ options = $merge({ onComplete: $empty, - onProgress: $empty + onProgress: $empty, + onError: $empty, + properties: {} }, options); - if (!sources.push) sources = [sources]; + sources = $splat(sources); var images = []; var counter = 0; - sources.each(function(source){ - var img = new Asset.image(source, { - 'onload': function(){ + return new Elements(sources.map(function(source){ + return Asset.image(source, $extend(options.properties, { + onload: function(){ options.onProgress.call(this, counter, sources.indexOf(source)); counter++; if (counter == sources.length) options.onComplete(); + }, + onerror: function(){ + options.onError.call(this, counter, sources.indexOf(source)); + counter++; + if (counter == sources.length) options.onComplete(); } - }); - images.push(img); - }); - return new Elements(images); - } - -}); - -/* -Script: Sortables.js - Class for creating a drag and drop sorting interface for lists of items. - -License: - MIT-style license. -*/ - -var Sortables = new Class({ - - Implements: [Events, Options], - - options: {/* - onSort: $empty, - onStart: $empty, - onComplete: $empty,*/ - snap: 4, - opacity: 1, - clone: false, - revert: false, - handle: false, - constrain: false - }, - - initialize: function(lists, options){ - this.setOptions(options); - this.elements = []; - this.lists = []; - this.idle = true; - - this.addLists($$($(lists) || lists)); - if (!this.options.clone) this.options.revert = false; - if (this.options.revert) this.effect = new Fx.Morph(null, $merge({duration: 250, link: 'cancel'}, this.options.revert)); - }, - - attach: function(){ - this.addLists(this.lists); - return this; - }, - - detach: function(){ - this.lists = this.removeLists(this.lists); - return this; - }, - - addItems: function(){ - Array.flatten(arguments).each(function(element){ - this.elements.push(element); - var start = element.retrieve('sortables:start', this.start.bindWithEvent(this, element)); - (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start); - }, this); - return this; - }, - - addLists: function(){ - Array.flatten(arguments).each(function(list){ - this.lists.push(list); - this.addItems(list.getChildren()); - }, this); - return this; - }, - - removeItems: function(){ - var elements = []; - Array.flatten(arguments).each(function(element){ - elements.push(element); - this.elements.erase(element); - var start = element.retrieve('sortables:start'); - (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start); - }, this); - return $$(elements); - }, - - removeLists: function(){ - var lists = []; - Array.flatten(arguments).each(function(list){ - lists.push(list); - this.lists.erase(list); - this.removeItems(list.getChildren()); - }, this); - return $$(lists); - }, - - getClone: function(event, element){ - if (!this.options.clone) return new Element('div').inject(document.body); - if ($type(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list); - return element.clone(true).setStyles({ - 'margin': '0px', - 'position': 'absolute', - 'visibility': 'hidden', - 'width': element.getStyle('width') - }).inject(this.list).position(element.getPosition(element.getOffsetParent())); - }, - - getDroppables: function(){ - var droppables = this.list.getChildren(); - if (!this.options.constrain) droppables = this.lists.concat(droppables).erase(this.list); - return droppables.erase(this.clone).erase(this.element); - }, - - insert: function(dragging, element){ - var where = 'inside'; - if (this.lists.contains(element)){ - this.list = element; - this.drag.droppables = this.getDroppables(); - } else { - where = this.element.getAllPrevious().contains(element) ? 'before' : 'after'; - } - this.element.inject(element, where); - this.fireEvent('sort', [this.element, this.clone]); - }, - - start: function(event, element){ - if (!this.idle) return; - this.idle = false; - this.element = element; - this.opacity = element.get('opacity'); - this.list = element.getParent(); - this.clone = this.getClone(event, element); - - this.drag = new Drag.Move(this.clone, { - snap: this.options.snap, - container: this.options.constrain && this.element.getParent(), - droppables: this.getDroppables(), - onSnap: function(){ - event.stop(); - this.clone.setStyle('visibility', 'visible'); - this.element.set('opacity', this.options.opacity || 0); - this.fireEvent('start', [this.element, this.clone]); - }.bind(this), - onEnter: this.insert.bind(this), - onCancel: this.reset.bind(this), - onComplete: this.end.bind(this) - }); - - this.clone.inject(this.element, 'before'); - this.drag.start(event); - }, - - end: function(){ - this.drag.detach(); - this.element.set('opacity', this.opacity); - if (this.effect){ - var dim = this.element.getStyles('width', 'height'); - var pos = this.clone.computePosition(this.element.getPosition(this.clone.offsetParent)); - this.effect.element = this.clone; - this.effect.start({ - top: pos.top, - left: pos.left, - width: dim.width, - height: dim.height, - opacity: 0.25 - }).chain(this.reset.bind(this)); - } else { - this.reset(); - } - }, - - reset: function(){ - this.idle = true; - this.clone.destroy(); - this.fireEvent('complete', this.element); - }, - - serialize: function(){ - var params = Array.link(arguments, {modifier: Function.type, index: $defined}); - var serial = this.lists.map(function(list){ - return list.getChildren().map(params.modifier || function(element){ - return element.get('id'); - }, this); - }, this); - - var index = params.index; - if (this.lists.length == 1) index = 0; - return $chk(index) && index >= 0 && index < this.lists.length ? serial[index] : serial; - } - -}); - -/* -Script: Tips.js - Class for creating nice tips that follow the mouse cursor when hovering an element. - -License: - MIT-style license. -*/ - -var Tips = new Class({ - - Implements: [Events, Options], - - options: { - onShow: function(tip){ - tip.setStyle('visibility', 'visible'); - }, - onHide: function(tip){ - tip.setStyle('visibility', 'hidden'); - }, - showDelay: 100, - hideDelay: 100, - className: null, - offsets: {x: 16, y: 16}, - fixed: false - }, - - initialize: function(){ - var params = Array.link(arguments, {options: Object.type, elements: $defined}); - this.setOptions(params.options || null); - - this.tip = new Element('div').inject(document.body); - - if (this.options.className) this.tip.addClass(this.options.className); - - var top = new Element('div', {'class': 'tip-top'}).inject(this.tip); - this.container = new Element('div', {'class': 'tip'}).inject(this.tip); - var bottom = new Element('div', {'class': 'tip-bottom'}).inject(this.tip); - - this.tip.setStyles({position: 'absolute', top: 0, left: 0, visibility: 'hidden'}); - - if (params.elements) this.attach(params.elements); - }, - - attach: function(elements){ - $$(elements).each(function(element){ - var title = element.retrieve('tip:title', element.get('title')); - var text = element.retrieve('tip:text', element.get('rel') || element.get('href')); - var enter = element.retrieve('tip:enter', this.elementEnter.bindWithEvent(this, element)); - var leave = element.retrieve('tip:leave', this.elementLeave.bindWithEvent(this, element)); - element.addEvents({mouseenter: enter, mouseleave: leave}); - if (!this.options.fixed){ - var move = element.retrieve('tip:move', this.elementMove.bindWithEvent(this, element)); - element.addEvent('mousemove', move); - } - element.store('tip:native', element.get('title')); - element.erase('title'); - }, this); - return this; - }, - - detach: function(elements){ - $$(elements).each(function(element){ - element.removeEvent('mouseenter', element.retrieve('tip:enter') || $empty); - element.removeEvent('mouseleave', element.retrieve('tip:leave') || $empty); - element.removeEvent('mousemove', element.retrieve('tip:move') || $empty); - element.eliminate('tip:enter').eliminate('tip:leave').eliminate('tip:move'); - var original = element.retrieve('tip:native'); - if (original) element.set('title', original); - }); - return this; - }, - - elementEnter: function(event, element){ - - $A(this.container.childNodes).each(Element.dispose); - - var title = element.retrieve('tip:title'); - - if (title){ - this.titleElement = new Element('div', {'class': 'tip-title'}).inject(this.container); - this.fill(this.titleElement, title); - } - - var text = element.retrieve('tip:text'); - if (text){ - this.textElement = new Element('div', {'class': 'tip-text'}).inject(this.container); - this.fill(this.textElement, text); - } - - this.timer = $clear(this.timer); - this.timer = this.show.delay(this.options.showDelay, this); - - this.position((!this.options.fixed) ? event : {page: element.getPosition()}); - }, - - elementLeave: function(event){ - $clear(this.timer); - this.timer = this.hide.delay(this.options.hideDelay, this); - }, - - elementMove: function(event){ - this.position(event); - }, - - position: function(event){ - var size = window.getSize(), scroll = window.getScroll(); - var tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight}; - var props = {x: 'left', y: 'top'}; - for (var z in props){ - var pos = event.page[z] + this.options.offsets[z]; - if ((pos + tip[z] - scroll[z]) > size[z]) pos = event.page[z] - this.options.offsets[z] - tip[z]; - this.tip.setStyle(props[z], pos); - } - }, - - fill: function(element, contents){ - (typeof contents == 'string') ? element.set('html', contents) : element.adopt(contents); - }, - - show: function(){ - this.fireEvent('show', this.tip); - }, - - hide: function(){ - this.fireEvent('hide', this.tip); - } - -}); - -/* -Script: SmoothScroll.js - Class for creating a smooth scrolling effect to all internal links on the page. - -License: - MIT-style license. -*/ - -var SmoothScroll = new Class({ - - Extends: Fx.Scroll, - - initialize: function(options, context){ - context = context || document; - var doc = context.getDocument(), win = context.getWindow(); - this.parent(doc, options); - this.links = (this.options.links) ? $$(this.options.links) : $$(doc.links); - var location = win.location.href.match(/^[^#]*/)[0] + '#'; - this.links.each(function(link){ - if (link.href.indexOf(location) != 0) return; - var anchor = link.href.substr(location.length); - if (anchor && $(anchor)) this.useLink(link, anchor); - }, this); - if (!Browser.Engine.webkit419) this.addEvent('complete', function(){ - win.location.hash = this.anchor; - }, true); - }, - - useLink: function(link, anchor){ - link.addEvent('click', function(event){ - this.anchor = anchor; - this.toElement(anchor); - event.stop(); - }.bind(this)); - } - -}); - -/* -Script: Slider.js - Class for creating horizontal and vertical slider controls. - -License: - MIT-style license. -*/ - -var Slider = new Class({ - - Implements: [Events, Options], - - options: {/* - onChange: $empty, - onComplete: $empty,*/ - onTick: function(position){ - if(this.options.snap) position = this.toPosition(this.step); - this.knob.setStyle(this.property, position); - }, - snap: false, - offset: 0, - range: false, - wheel: false, - steps: 100, - mode: 'horizontal' - }, - - initialize: function(element, knob, options){ - this.setOptions(options); - this.element = $(element); - this.knob = $(knob); - this.previousChange = this.previousEnd = this.step = -1; - this.element.addEvent('mousedown', this.clickedElement.bind(this)); - if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement.bindWithEvent(this)); - var offset, limit = {}, modifiers = {'x': false, 'y': false}; - switch (this.options.mode){ - case 'vertical': - this.axis = 'y'; - this.property = 'top'; - offset = 'offsetHeight'; - break; - case 'horizontal': - this.axis = 'x'; - this.property = 'left'; - offset = 'offsetWidth'; - } - this.half = this.knob[offset] / 2; - this.full = this.element[offset] - this.knob[offset] + (this.options.offset * 2); - this.min = $chk(this.options.range[0]) ? this.options.range[0] : 0; - this.max = $chk(this.options.range[1]) ? this.options.range[1] : this.options.steps; - this.range = this.max - this.min; - this.steps = this.options.steps || this.full; - this.stepSize = Math.abs(this.range) / this.steps; - this.stepWidth = this.stepSize * this.full / Math.abs(this.range) ; - - this.knob.setStyle('position', 'relative').setStyle(this.property, - this.options.offset); - modifiers[this.axis] = this.property; - limit[this.axis] = [- this.options.offset, this.full - this.options.offset]; - this.drag = new Drag(this.knob, { - snap: 0, - limit: limit, - modifiers: modifiers, - onDrag: this.draggedKnob.bind(this), - onStart: this.draggedKnob.bind(this), - onComplete: function(){ - this.draggedKnob(); - this.end(); - }.bind(this) - }); - if (this.options.snap) { - this.drag.options.grid = Math.ceil(this.stepWidth); - this.drag.options.limit[this.axis][1] = this.full; - } - }, - - set: function(step){ - if (!((this.range > 0) ^ (step < this.min))) step = this.min; - if (!((this.range > 0) ^ (step > this.max))) step = this.max; - - this.step = Math.round(step); - this.checkStep(); - this.end(); - this.fireEvent('tick', this.toPosition(this.step)); - return this; - }, - - clickedElement: function(event){ - var dir = this.range < 0 ? -1 : 1; - var position = event.page[this.axis] - this.element.getPosition()[this.axis] - this.half; - position = position.limit(-this.options.offset, this.full -this.options.offset); - - this.step = Math.round(this.min + dir * this.toStep(position)); - this.checkStep(); - this.end(); - this.fireEvent('tick', position); - }, - - scrolledElement: function(event){ - var mode = (this.options.mode == 'horizontal') ? (event.wheel < 0) : (event.wheel > 0); - this.set(mode ? this.step - this.stepSize : this.step + this.stepSize); - event.stop(); - }, - - draggedKnob: function(){ - var dir = this.range < 0 ? -1 : 1; - var position = this.drag.value.now[this.axis]; - position = position.limit(-this.options.offset, this.full -this.options.offset); - this.step = Math.round(this.min + dir * this.toStep(position)); - this.checkStep(); - }, - - checkStep: function(){ - if (this.previousChange != this.step){ - this.previousChange = this.step; - this.fireEvent('change', this.step); - } - }, - - end: function(){ - if (this.previousEnd !== this.step){ - this.previousEnd = this.step; - this.fireEvent('complete', this.step + ''); - } - }, - - toStep: function(position){ - var step = (position + this.options.offset) * this.stepSize / this.full * this.steps; - return this.options.steps ? Math.round(step -= step % this.stepSize) : step; - }, - - toPosition: function(step){ - return (this.full * Math.abs(this.min - step)) / (this.steps * this.stepSize) - this.options.offset; - } - -}); - -/* -Script: Scroller.js - Class which scrolls the contents of any Element (including the window) when the mouse reaches the Element's boundaries. - -License: - MIT-style license. -*/ - -var Scroller = new Class({ - - Implements: [Events, Options], - - options: { - area: 20, - velocity: 1, - onChange: function(x, y){ - this.element.scrollTo(x, y); - } - }, - - initialize: function(element, options){ - this.setOptions(options); - this.element = $(element); - this.listener = ($type(this.element) != 'element') ? $(this.element.getDocument().body) : this.element; - this.timer = null; - this.coord = this.getCoords.bind(this); - }, - - start: function(){ - this.listener.addEvent('mousemove', this.coord); - }, - - stop: function(){ - this.listener.removeEvent('mousemove', this.coord); - this.timer = $clear(this.timer); - }, - - getCoords: function(event){ - this.page = (this.listener.get('tag') == 'body') ? event.client : event.page; - if (!this.timer) this.timer = this.scroll.periodical(50, this); - }, - - scroll: function(){ - var size = this.element.getSize(), scroll = this.element.getScroll(), pos = this.element.getPosition(), change = {'x': 0, 'y': 0}; - for (var z in this.page){ - if (this.page[z] < (this.options.area + pos[z]) && scroll[z] != 0) - change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity; - else if (this.page[z] + this.options.area > (size[z] + pos[z]) && size[z] + size[z] != scroll[z]) - change[z] = (this.page[z] - size[z] + this.options.area - pos[z]) * this.options.velocity; - } - if (change.y || change.x) this.fireEvent('change', [scroll.x + change.x, scroll.y + change.y]); + })); + })); } -}); - -/* -Script: Accordion.js - An Fx.Elements extension which allows you to easily create accordion type controls. - -License: - MIT-style license. -*/ - -var Accordion = new Class({ - - Extends: Fx.Elements, - - options: {/* - onActive: $empty, - onBackground: $empty,*/ - display: 0, - show: false, - height: true, - width: false, - opacity: true, - fixedHeight: false, - fixedWidth: false, - wait: false, - alwaysHide: false - }, - - initialize: function(){ - var params = Array.link(arguments, {'container': Element.type, 'options': Object.type, 'togglers': $defined, 'elements': $defined}); - this.parent(params.elements, params.options); - this.togglers = $$(params.togglers); - this.container = $(params.container); - this.previous = -1; - if (this.options.alwaysHide) this.options.wait = true; - if ($chk(this.options.show)){ - this.options.display = false; - this.previous = this.options.show; - } - if (this.options.start){ - this.options.display = false; - this.options.show = false; - } - this.effects = {}; - if (this.options.opacity) this.effects.opacity = 'fullOpacity'; - if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth'; - if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight'; - for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]); - this.elements.each(function(el, i){ - if (this.options.show === i){ - this.fireEvent('active', [this.togglers[i], el]); - } else { - for (var fx in this.effects) el.setStyle(fx, 0); - } - }, this); - if ($chk(this.options.display)) this.display(this.options.display); - }, - - addSection: function(toggler, element, pos){ - toggler = $(toggler); - element = $(element); - var test = this.togglers.contains(toggler); - var len = this.togglers.length; - this.togglers.include(toggler); - this.elements.include(element); - if (len && (!test || pos)){ - pos = $pick(pos, len - 1); - toggler.inject(this.togglers[pos], 'before'); - element.inject(toggler, 'after'); - } else if (this.container && !test){ - toggler.inject(this.container); - element.inject(this.container); - } - var idx = this.togglers.indexOf(toggler); - toggler.addEvent('click', this.display.bind(this, idx)); - if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'}); - if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'}); - element.fullOpacity = 1; - if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth; - if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight; - element.setStyle('overflow', 'hidden'); - if (!test){ - for (var fx in this.effects) element.setStyle(fx, 0); - } - return this; - }, - - display: function(index){ - index = ($type(index) == 'element') ? this.elements.indexOf(index) : index; - if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this; - this.previous = index; - var obj = {}; - this.elements.each(function(el, i){ - obj[i] = {}; - var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0)); - this.fireEvent(hide ? 'background' : 'active', [this.togglers[i], el]); - for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]]; - }, this); - return this.start(obj); - } - -}); +}; \ No newline at end of file