[fusion-commits] r2124 - sandbox/jxlib-3.0/lib
svn_fusion at osgeo.org
svn_fusion at osgeo.org
Wed Mar 31 15:17:23 EDT 2010
Author: madair
Date: 2010-03-31 15:17:23 -0400 (Wed, 31 Mar 2010)
New Revision: 2124
Modified:
sandbox/jxlib-3.0/lib/jxlib.uncompressed.js
Log:
update to most recent JxLib
Modified: sandbox/jxlib-3.0/lib/jxlib.uncompressed.js
===================================================================
--- sandbox/jxlib-3.0/lib/jxlib.uncompressed.js 2010-03-31 19:07:52 UTC (rev 2123)
+++ sandbox/jxlib-3.0/lib/jxlib.uncompressed.js 2010-03-31 19:17:23 UTC (rev 2124)
@@ -6,7 +6,7 @@
* reset.css - Copyright (c) 2006, Yahoo! Inc. All rights reserved.
* Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt
******************************************************************************
- * Jx UI Library, 2.0.1
+ * Jx UI Library, 3.0alpha
* Copyright (c) 2006-2008, DM Solutions Group Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -27,13822 +27,14557 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
-/*
----
-
-script: Core.js
-
-description: The core of MooTools, contains all the base functions and the Native and Hash implementations. Required by all the other scripts.
-
-license: MIT-style license.
-
-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.4',
- 'build': '0d9113241a90b9cd5643b926795852a2026710d4'
-};
-
-var Native = function(options){
- options = options || {};
- var name = options.name;
- var legacy = options.legacy;
- var protect = options.protect;
- 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'};
- if (legacy && initialize) object.prototype = legacy.prototype;
- object.prototype.constructor = object;
-
- if (name){
- var family = name.toLowerCase();
- object.prototype.$family = {name: family};
- Native.typize(object, family);
- }
-
- var add = function(obj, name, method, force){
- if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method;
- if (generics) Native.genericize(obj, name, protect);
- afterImplement.call(obj, name, method);
- return obj;
- };
-
- object.alias = function(a1, a2, a3){
- if (typeof a1 == 'string'){
- 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;
- };
-
- 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;
- };
-
- if (methods) object.implement(methods);
-
- return object;
-};
-
-Native.genericize = function(object, property, check){
- if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){
- var args = Array.prototype.slice.call(arguments);
- return object.prototype[property].apply(args.shift(), args);
- };
-};
-
-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);
- };
-};
-
-(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({
-
- 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 $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 $arguments(i){
- return function(){
- return arguments[i];
- };
-};
-
-function $chk(obj){
- return !!(obj || obj === 0);
-};
-
-function $clear(timer){
- clearTimeout(timer);
- clearInterval(timer);
- return null;
-};
-
-function $defined(obj){
- return (obj != undefined);
-};
-
-function $each(iterable, fn, bind){
- var type = $type(iterable);
- ((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind);
-};
-
-function $empty(){};
-
-function $extend(original, extended){
- for (var key in (extended || {})) original[key] = extended[key];
- return original;
-};
-
-function $H(object){
- return new Hash(object);
-};
-
-function $lambda(value){
- return ($type(value) == 'function') ? value : function(){
- return value;
- };
-};
-
-function $merge(){
- 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') ? $mixin(mp, op) : $unlink(op);
- }
- }
- return mix;
-};
-
-function $pick(){
- for (var i = 0, l = arguments.length; i < l; i++){
- if (arguments[i] != undefined) return arguments[i];
- }
- return null;
-};
-
-function $random(min, max){
- return Math.floor(Math.random() * (max - min + 1) + min);
-};
-
-function $splat(obj){
- var type = $type(obj);
- return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : [];
-};
-
-var $time = Date.now || function(){
- return +new Date;
-};
-
-function $try(){
- for (var i = 0, l = arguments.length; i < l; i++){
- try {
- return arguments[i]();
- } catch(e){}
- }
- return null;
-};
-
-function $type(obj){
- if (obj == undefined) return false;
- if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name;
- if (obj.nodeName){
- switch (obj.nodeType){
- case 1: return 'element';
- case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
- }
- } else if (typeof obj.length == 'number'){
- if (obj.callee) return 'arguments';
- else if (obj.item) return 'collection';
- }
- return typeof obj;
-};
-
-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;
-};
-/*
----
-
-script: Browser.js
-
-description: The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash.
-
-license: MIT-style license.
-
-requires:
-- /Native
-- /$util
-
-provides: [Browser, Window, Document, $exec]
-
-...
-*/
-
-var Browser = $merge({
-
- Engine: {name: 'unknown', version: 0},
-
- Platform: {name: (window.orientation != undefined) ? 'ipod' : (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()},
-
- Features: {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)},
-
- Plugins: {},
-
- Engines: {
-
- presto: function(){
- return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925));
- },
-
- trident: function(){
- return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4);
- },
-
- webkit: function(){
- return (navigator.taintEnabled) ? false : ((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) : 419);
- },
-
- gecko: function(){
- return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18);
- }
-
- }
-
-}, 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');
- });
-};
-
-Browser.Features.xhr = !!(Browser.Request());
-
-Browser.Plugins.Flash = (function(){
- var version = ($try(function(){
- return navigator.plugins['Shockwave Flash'].description;
- }, function(){
- return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
- }) || '0 r0').match(/\d+/g);
- return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
-})();
-
-function $exec(text){
- if (!text) return text;
- if (window.execScript){
- window.execScript(text);
- } else {
- var script = document.createElement('script');
- script.setAttribute('type', 'text/javascript');
- script[(Browser.Engine.webkit && Browser.Engine.version < 420) ? 'innerText' : 'text'] = text;
- document.head.appendChild(script);
- document.head.removeChild(script);
- }
- return text;
-};
-
-Native.UID = 1;
-
-var $uid = (Browser.Engine.trident) ? function(item){
- return (item.uid || (item.uid = [Native.UID++]))[0];
-} : function(item){
- return item.uid || (item.uid = Native.UID++);
-};
-
-var Window = new Native({
-
- name: 'Window',
-
- legacy: (Browser.Engine.trident) ? null: window.Window,
-
- initialize: function(win){
- $uid(win);
- if (!win.Element){
- win.Element = $empty;
- 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);
- },
-
- afterImplement: function(property, value){
- window[property] = Window.Prototype[property] = value;
- }
-
-});
-
-Window.Prototype = {$family: {name: 'window'}};
-
-new Window(window);
-
-var Document = new Native({
-
- name: 'Document',
-
- legacy: (Browser.Engine.trident) ? null: window.Document,
-
- initialize: function(doc){
- $uid(doc);
- doc.head = doc.getElementsByTagName('head')[0];
- doc.html = doc.getElementsByTagName('html')[0];
- 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);
- },
-
- afterImplement: function(property, value){
- document[property] = Document.Prototype[property] = value;
- }
-
-});
-
-Document.Prototype = {$family: {name: 'document'}};
-
-new Document(document);
-/*
----
-
-script: Array.js
-
-description: Contains Array Prototypes like each, contains, and erase.
-
-license: MIT-style license.
-
-requires:
-- /$util
-- /Array.each
-
-provides: [Array]
-
-...
-*/
-
-Array.implement({
-
- every: function(fn, bind){
- for (var i = 0, l = this.length; i < l; i++){
- if (!fn.call(bind, this[i], i, this)) return false;
- }
- return true;
- },
-
- filter: function(fn, bind){
- var results = [];
- for (var i = 0, l = this.length; i < l; i++){
- if (fn.call(bind, this[i], i, this)) results.push(this[i]);
- }
- return results;
- },
-
- clean: function(){
- return this.filter($defined);
- },
-
- indexOf: function(item, from){
- var len = this.length;
- for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
- if (this[i] === item) return i;
- }
- return -1;
- },
-
- map: function(fn, bind){
- var results = [];
- for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this);
- return results;
- },
-
- some: function(fn, bind){
- for (var i = 0, l = this.length; i < l; i++){
- if (fn.call(bind, this[i], i, this)) return true;
- }
- return false;
- },
-
- associate: function(keys){
- var obj = {}, length = Math.min(this.length, keys.length);
- for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
- return obj;
- },
-
- link: function(object){
- var result = {};
- for (var i = 0, l = this.length; i < l; i++){
- for (var key in object){
- if (object[key](this[i])){
- result[key] = this[i];
- delete object[key];
- break;
- }
- }
- }
- return result;
- },
-
- contains: function(item, from){
- return this.indexOf(item, from) != -1;
- },
-
- extend: function(array){
- 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;
- },
-
- getRandom: function(){
- return (this.length) ? this[$random(0, this.length - 1)] : null;
- },
-
- include: function(item){
- if (!this.contains(item)) this.push(item);
- return this;
- },
-
- combine: function(array){
- for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
- return this;
- },
-
- erase: function(item){
- for (var i = this.length; i--; i){
- if (this[i] === item) this.splice(i, 1);
- }
- return this;
- },
-
- empty: function(){
- this.length = 0;
- return this;
- },
-
- flatten: function(){
- var array = [];
- for (var i = 0, l = this.length; i < l; i++){
- var type = $type(this[i]);
- if (!type) continue;
- array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? Array.flatten(this[i]) : this[i]);
- }
- return array;
- },
-
- hexToRgb: function(array){
- if (this.length != 3) return null;
- var rgb = this.map(function(value){
- if (value.length == 1) value += value;
- return value.toInt(16);
- });
- return (array) ? rgb : 'rgb(' + rgb + ')';
- },
-
- rgbToHex: function(array){
- if (this.length < 3) return null;
- if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
- var hex = [];
- for (var i = 0; i < 3; i++){
- var bit = (this[i] - 0).toString(16);
- hex.push((bit.length == 1) ? '0' + bit : bit);
- }
- return (array) ? hex : '#' + hex.join('');
- }
-
-});
-/*
----
-
-script: Function.js
-
-description: Contains Function Prototypes like create, bind, pass, and delay.
-
-license: MIT-style license.
-
-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;
- },
-
- times: function(fn, bind){
- for (var i = 0; i < this; i++) fn.call(bind, i, this);
- },
-
- toFloat: function(){
- return parseFloat(this);
- },
-
- toInt: function(base){
- return parseInt(this, base || 10);
- }
-
-});
-
-Number.alias('times', 'each');
-
-(function(math){
- var methods = {};
- math.each(function(name){
- if (!Number[name]) methods[name] = function(){
- return Math[name].apply(null, [this].concat($A(arguments)));
- };
- });
- Number.implement(methods);
-})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
-/*
----
-
-script: String.js
-
-description: Contains String Prototypes like camelCase, capitalize, test, and toInt.
-
-license: MIT-style license.
-
-requires:
-- /Native
-
-provides: [String]
-
-...
-*/
-
-String.implement({
-
- test: function(regex, params){
- return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this);
- },
-
- contains: function(string, separator){
- return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
- },
-
- trim: function(){
- return this.replace(/^\s+|\s+$/g, '');
- },
-
- clean: function(){
- return this.replace(/\s+/g, ' ').trim();
- },
-
- camelCase: function(){
- return this.replace(/-\D/g, function(match){
- return match.charAt(1).toUpperCase();
- });
- },
-
- hyphenate: function(){
- return this.replace(/[A-Z]/g, function(match){
- return ('-' + match.charAt(0).toLowerCase());
- });
- },
-
- capitalize: function(){
- return this.replace(/\b[a-z]/g, function(match){
- return match.toUpperCase();
- });
- },
-
- escapeRegExp: function(){
- return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
- },
-
- toInt: function(base){
- return parseInt(this, base || 10);
- },
-
- toFloat: function(){
- return parseFloat(this);
- },
-
- hexToRgb: function(array){
- var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
- return (hex) ? hex.slice(1).hexToRgb(array) : null;
- },
-
- rgbToHex: function(array){
- var rgb = this.match(/\d{1,3}/g);
- return (rgb) ? rgb.rgbToHex(array) : null;
- },
-
- stripScripts: function(option){
- var scripts = '';
- var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
- scripts += arguments[1] + '\n';
- return '';
- });
- if (option === true) $exec(scripts);
- else if ($type(option) == 'function') option(scripts, text);
- return text;
- },
-
- substitute: function(object, regexp){
- return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
- if (match.charAt(0) == '\\') return match.slice(1);
- return (object[name] != undefined) ? object[name] : '';
- });
- }
-
-});
-/*
----
-
-script: Hash.js
-
-description: Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.
-
-license: MIT-style license.
-
-requires:
-- /Hash.base
-
-provides: [Hash]
-
-...
-*/
-
-Hash.implement({
-
- has: Object.prototype.hasOwnProperty,
-
- keyOf: function(value){
- for (var key in this){
- if (this.hasOwnProperty(key) && this[key] === value) return key;
- }
- return null;
- },
-
- hasValue: function(value){
- return (Hash.keyOf(this, value) !== null);
- },
-
- extend: function(properties){
- Hash.each(properties || {}, function(value, key){
- Hash.set(this, key, value);
- }, this);
- return this;
- },
-
- combine: function(properties){
- Hash.each(properties || {}, function(value, key){
- Hash.include(this, key, value);
- }, this);
- return this;
- },
-
- erase: function(key){
- if (this.hasOwnProperty(key)) delete this[key];
- return this;
- },
-
- get: function(key){
- return (this.hasOwnProperty(key)) ? this[key] : null;
- },
-
- set: function(key, value){
- if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
- return this;
- },
-
- empty: function(){
- Hash.each(this, function(value, key){
- delete this[key];
- }, this);
- return this;
- },
-
- include: function(key, value){
- if (this[key] == undefined) this[key] = value;
- return this;
- },
-
- map: function(fn, bind){
- var results = new Hash;
- Hash.each(this, function(value, key){
- results.set(key, fn.call(bind, value, key, this));
- }, this);
- return results;
- },
-
- filter: function(fn, bind){
- var results = new Hash;
- Hash.each(this, function(value, key){
- if (fn.call(bind, value, key, this)) results.set(key, value);
- }, this);
- return results;
- },
-
- every: function(fn, bind){
- for (var key in this){
- if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
- }
- return true;
- },
-
- some: function(fn, bind){
- for (var key in this){
- if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
- }
- return false;
- },
-
- getKeys: function(){
- var keys = [];
- Hash.each(this, function(value, key){
- keys.push(key);
- });
- return keys;
- },
-
- getValues: function(){
- var values = [];
- Hash.each(this, function(value){
- values.push(value);
- });
- return values;
- },
-
- toQueryString: function(base){
- var queryString = [];
- Hash.each(this, function(value, key){
- if (base) key = base + '[' + key + ']';
- var result;
- switch ($type(value)){
- case 'object': result = Hash.toQueryString(value, key); break;
- case 'array':
- var qs = {};
- value.each(function(val, i){
- qs[i] = val;
- });
- result = Hash.toQueryString(qs, key);
- break;
- default: result = key + '=' + encodeURIComponent(value);
- }
- if (value != undefined) queryString.push(result);
- });
-
- return queryString.join('&');
- }
-
-});
-
-Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});
-/*
----
-
-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({
-
- name: 'Event',
-
- initialize: function(event, win){
- win = win || window;
- var doc = win.document;
- event = event || win.event;
- if (event.$extended) return event;
- this.$extended = true;
- 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);
- if (type == 'keydown'){
- var fKey = code - 111;
- if (fKey > 0 && fKey < 13) key = 'f' + fKey;
- }
- key = key || String.fromCharCode(code).toLowerCase();
- } else if (type.match(/(click|mouse|menu)/i)){
- doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
- var page = {
- x: event.pageX || event.clientX + doc.scrollLeft,
- y: event.pageY || event.clientY + doc.scrollTop
- };
- var client = {
- x: (event.pageX) ? event.pageX - win.pageXOffset : event.clientX,
- y: (event.pageY) ? event.pageY - win.pageYOffset : event.clientY
- };
- if (type.match(/DOMMouseScroll|mousewheel/)){
- var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
- }
- var rightClick = (event.which == 3) || (event.button == 2);
- var related = null;
- if (type.match(/over|out/)){
- switch (type){
- case 'mouseover': related = event.relatedTarget || event.fromElement; break;
- case 'mouseout': related = event.relatedTarget || event.toElement;
- }
- if (!(function(){
- while (related && related.nodeType == 3) related = related.parentNode;
- return true;
- }).create({attempt: Browser.Engine.gecko})()) related = false;
- }
- }
-
- 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,
- meta: event.metaKey
- });
- }
-
-});
-
-Event.Keys = new Hash({
- 'enter': 13,
- 'up': 38,
- 'down': 40,
- 'left': 37,
- 'right': 39,
- 'esc': 27,
- 'space': 32,
- 'backspace': 8,
- 'tab': 9,
- 'delete': 46
-});
-
-Event.implement({
-
- stop: function(){
- return this.stopPropagation().preventDefault();
- },
-
- stopPropagation: function(){
- if (this.event.stopPropagation) this.event.stopPropagation();
- else this.event.cancelBubble = true;
- return this;
- },
-
- preventDefault: function(){
- if (this.event.preventDefault) this.event.preventDefault();
- else this.event.returnValue = false;
- return this;
- }
-
-});
-/*
----
-
-script: Class.js
-
-description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
-
-license: MIT-style license.
-
-requires:
-- /$util
-- /Native
-- /Array
-- /String
-- /Function
-- /Number
-- /Hash
-
-provides: [Class]
-
-...
-*/
-
-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;
-
- return newClass;
-
-};
-
-Function.prototype.protect = function(){
- this._protected = true;
- return this;
-};
-
-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;
-
- }
-
- return this;
-
- }
-
-});
-
-Class.Mutators = {
-
- 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
-
-description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
-
-license: MIT-style license.
-
-requires:
-- /Class
-
-provides: [Chain, Events, Options]
-
-...
-*/
-
-var Chain = new Class({
-
- $chain: [],
-
- chain: function(){
- this.$chain.extend(Array.flatten(arguments));
- return this;
- },
-
- callChain: function(){
- return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
- },
-
- clearChain: function(){
- this.$chain.empty();
- return this;
- }
-
-});
-
-var Events = new Class({
-
- $events: {},
-
- addEvent: function(type, fn, internal){
- type = Events.removeOn(type);
- if (fn != $empty){
- this.$events[type] = this.$events[type] || [];
- this.$events[type].include(fn);
- if (internal) fn.internal = true;
- }
- return this;
- },
-
- addEvents: function(events){
- for (var type in events) this.addEvent(type, events[type]);
- return this;
- },
-
- fireEvent: function(type, args, delay){
- type = Events.removeOn(type);
- if (!this.$events || !this.$events[type]) return this;
- this.$events[type].each(function(fn){
- fn.create({'bind': this, 'delay': delay, 'arguments': args})();
- }, this);
- return this;
- },
-
- removeEvent: function(type, fn){
- type = Events.removeOn(type);
- if (!this.$events[type]) return this;
- if (!fn.internal) this.$events[type].erase(fn);
- return this;
- },
-
- 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;
- }
-
-});
-
-Events.removeOn = function(string){
- return string.replace(/^on([A-Z])/, function(full, first){
- return first.toLowerCase();
- });
-};
-
-var Options = new Class({
-
- setOptions: function(){
- this.options = $merge.run([this.options].extend(arguments));
- if (!this.addEvent) return this;
- for (var option in this.options){
- if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
- this.addEvent(option, this.options[option]);
- delete this.options[option];
- }
- return this;
- }
-
-});
-/*
----
-
-script: Element.js
-
-description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements.
-
-license: MIT-style license.
-
-requires:
-- /Window
-- /Document
-- /Array
-- /String
-- /Function
-- /Number
-- /Hash
-
-provides: [Element, Elements, $, $$, Iframe]
-
-...
-*/
-
-var Element = new Native({
-
- name: 'Element',
-
- legacy: window.Element,
-
- initialize: function(tag, props){
- var konstructor = Element.Constructors.get(tag);
- if (konstructor) return konstructor(props);
- if (typeof tag == 'string') return document.newElement(tag, props);
- return document.id(tag).set(props);
- },
-
- afterImplement: function(key, value){
- 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;
- });
- }
-
-});
-
-Element.Prototype = {$family: {name: 'element'}};
-
-Element.Constructors = new Hash;
-
-var IFrame = new Native({
-
- name: 'IFrame',
-
- generics: false,
-
- initialize: function(){
- var params = Array.link(arguments, {properties: Object.type, iframe: $defined});
- var props = params.properties || {};
- var iframe = document.id(params.iframe);
- var onload = props.onload || $empty;
- delete props.onload;
- 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){
- var win = new Window(iframe.contentWindow);
- new Document(iframe.contentWindow.document);
- $extend(win.Element.prototype, Element.Prototype);
- }
- onload.call(iframe.contentWindow, iframe.contentWindow.document);
- };
- var contentWindow = $try(function(){
- return iframe.contentWindow;
- });
- ((contentWindow && contentWindow.document.body) || window.frames[props.id]) ? onFrameLoad() : iframe.addListener('load', onFrameLoad);
- return iframe;
- }
-
-});
-
-var Elements = new Native({
-
- initialize: function(elements, options){
- options = $extend({ddup: true, cash: true}, options);
- elements = elements || [];
- if (options.ddup || options.cash){
- var uniques = {}, returned = [];
- for (var i = 0, l = elements.length; i < l; i++){
- var el = document.id(elements[i], !options.cash);
- if (options.ddup){
- if (uniques[el.uid]) continue;
- uniques[el.uid] = true;
- }
- if (el) returned.push(el);
- }
- elements = returned;
- }
- return (options.cash) ? $extend(elements, this) : elements;
- }
-
-});
-
-Elements.implement({
-
- filter: function(filter, bind){
- if (!filter) return this;
- return new Elements(Array.filter(this, (typeof filter == 'string') ? function(item){
- return item.match(filter);
- } : filter, bind));
- }
-
-});
-
-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 document.id(this.createElement(tag)).set(props);
- },
-
- newTextNode: function(text){
- return this.createTextNode(text);
- },
-
- getDocument: function(){
- return this;
- },
-
- 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);
- var elements = [];
- var args = Array.flatten(arguments);
- for (var i = 0, l = args.length; i < l; i++){
- var item = args[i];
- switch ($type(item)){
- case 'element': elements.push(item); break;
- case 'string': elements.extend(this.document.getElements(item, true));
- }
- }
- return new Elements(elements);
- },
-
- getDocument: function(){
- return this.document;
- },
-
- getWindow: function(){
- return this;
- }
-
-});
-
-Native.implement([Element, Document], {
-
- getElement: function(selector, nocash){
- return document.id(this.getElements(selector, true)[0] || null, nocash);
- },
-
- getElements: function(tags, nocash){
- tags = tags.split(',');
- var elements = [];
- var ddup = (tags.length > 1);
- tags.each(function(tag){
- var partial = this.getElementsByTagName(tag.trim());
- (ddup) ? elements.extend(partial) : elements = partial;
- }, this);
- return new Elements(elements, {ddup: ddup, cash: !nocash});
- }
-
-});
-
-(function(){
-
-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] = {}));
-};
-
-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;
-};
-
-var purge = function(){
- Hash.each(collected, clean);
- if (Browser.Engine.trident) $A(document.getElementsByTagName('object')).each(clean);
- if (window.CollectGarbage) CollectGarbage();
- collected = storage = null;
-};
-
-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);
- }
-
-};
-
-inserters.inside = inserters.bottom;
-
-Hash.each(inserters, function(inserter, where){
-
- where = where.capitalize();
-
- Element.implement('inject' + where, function(el){
- inserter(this, document.id(el, true));
- return this;
- });
-
- Element.implement('grab' + where, function(el){
- inserter(document.id(el, true), this);
- return this;
- });
-
-});
-
-Element.implement({
-
- set: function(prop, value){
- switch ($type(prop)){
- case 'object':
- for (var p in prop) this.set(p, prop[p]);
- break;
- case 'string':
- var property = Element.Properties.get(prop);
- (property && property.set) ? property.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(prop, value);
- }
- return this;
- },
-
- get: function(prop){
- var property = Element.Properties.get(prop);
- return (property && property.get) ? property.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(prop);
- },
-
- erase: function(prop){
- var property = Element.Properties.get(prop);
- (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
- return this;
- },
-
- 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;
- },
-
- setProperties: function(attributes){
- for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
- 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;
- },
-
- getProperties: function(){
- var args = $A(arguments);
- return args.map(this.getProperty, this).associate(args);
- },
-
- removeProperty: function(attribute){
- var key = attributes[attribute];
- (key) ? this[key] = (key && bools[attribute]) ? false : '' : this.removeAttribute(attribute);
- return this;
- },
-
- removeProperties: function(){
- Array.each(arguments, this.removeProperty, this);
- return this;
- },
-
- hasClass: function(className){
- return this.className.contains(className, ' ');
- },
-
- addClass: function(className){
- if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
- return this;
- },
-
- removeClass: function(className){
- this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
- return this;
- },
-
- toggleClass: function(className){
- return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
- },
-
- adopt: function(){
- Array.flatten(arguments).each(function(element){
- element = document.id(element, true);
- if (element) this.appendChild(element);
- }, this);
- return this;
- },
-
- appendText: function(text, where){
- return this.grab(this.getDocument().newTextNode(text), where);
- },
-
- grab: function(el, where){
- inserters[where || 'bottom'](document.id(el, true), this);
- return this;
- },
-
- inject: function(el, where){
- inserters[where || 'bottom'](this, document.id(el, true));
- return this;
- },
-
- replaces: function(el){
- el = document.id(el, true);
- el.parentNode.replaceChild(this, el);
- return this;
- },
-
- 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);
- },
-
- getAllPrevious: function(match, nocash){
- return walk(this, 'previousSibling', null, match, true, nocash);
- },
-
- getNext: function(match, nocash){
- return walk(this, 'nextSibling', null, match, false, nocash);
- },
-
- getAllNext: function(match, nocash){
- return walk(this, 'nextSibling', null, match, true, nocash);
- },
-
- getFirst: function(match, nocash){
- return walk(this, 'nextSibling', 'firstChild', match, false, nocash);
- },
-
- getLast: function(match, nocash){
- return walk(this, 'previousSibling', 'lastChild', match, false, nocash);
- },
-
- getParent: function(match, nocash){
- return walk(this, 'parentNode', null, match, false, nocash);
- },
-
- 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);
- },
-
- 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);
- },
-
- getSelected: function(){
- return new Elements($A(this.options).filter(function(option){
- return option.selected;
- }));
- },
-
- 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;
- },
-
- 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('&');
- },
-
- 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);
- },
-
- 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;
- },
-
- dispose: function(){
- return (this.parentNode) ? this.parentNode.removeChild(this) : this;
- },
-
- 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);
- },
-
- 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;
- },
-
- removeListener: function(type, fn){
- if (this.removeEventListener) this.removeEventListener(type, fn, false);
- else this.detachEvent('on' + type, fn);
- return this;
- },
-
- retrieve: function(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 = get(this.uid);
- storage[property] = value;
- return this;
- },
-
- eliminate: function(property){
- var storage = get(this.uid);
- delete storage[property];
- return this;
- }
-
-});
-
-window.addListener('unload', purge);
-
-})();
-
-Element.Properties = new Hash;
-
-Element.Properties.style = {
-
- set: function(style){
- this.style.cssText = style;
- },
-
- get: function(){
- return this.style.cssText;
- },
-
- erase: function(){
- this.style.cssText = '';
- }
-
-};
-
-Element.Properties.tag = {
-
- get: function(){
- return this.tagName.toLowerCase();
- }
-
-};
-
-Element.Properties.html = (function(){
- var wrapper = document.createElement('div');
-
- var translations = {
- table: [1, '<table>', '</table>'],
- select: [1, '<select>', '</select>'],
- tbody: [2, '<table><tbody>', '</tbody></table>'],
- tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
- };
- 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 = {
-
- set: function(opacity, novisibility){
- if (!novisibility){
- if (opacity == 0){
- if (this.style.visibility != 'hidden') this.style.visibility = 'hidden';
- } else {
- if (this.style.visibility != 'visible') this.style.visibility = 'visible';
- }
- }
- if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
- if (Browser.Engine.trident) this.style.filter = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')';
- this.style.opacity = opacity;
- this.store('opacity', opacity);
- },
-
- get: function(){
- return this.retrieve('opacity', 1);
- }
-
-};
-
-Element.implement({
-
- setOpacity: function(value){
- return this.set('opacity', value, true);
- },
-
- getOpacity: function(){
- return this.get('opacity');
- },
-
- setStyle: function(property, value){
- switch (property){
- case 'opacity': return this.set('opacity', parseFloat(value));
- case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
- }
- property = property.camelCase();
- if ($type(value) != 'string'){
- var map = (Element.Styles.get(property) || '@').split(' ');
- value = $splat(value).map(function(val, i){
- if (!map[i]) return '';
- return ($type(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
- }).join(' ');
- } else if (value == String(Number(value))){
- value = Math.round(value);
- }
- this.style[property] = value;
- return this;
- },
-
- getStyle: function(property){
- switch (property){
- case 'opacity': return this.get('opacity');
- case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
- }
- property = property.camelCase();
- var result = this.style[property];
- if (!$chk(result)){
- result = [];
- for (var style in Element.ShortStyles){
- if (property != style) continue;
- for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
- return result.join(' ');
- }
- result = this.getComputedStyle(property);
- }
- if (result){
- result = String(result);
- 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, 10)))){
- if (property.test(/^(height|width)$/)){
- var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
- values.each(function(value){
- size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
- }, this);
- return this['offset' + property.capitalize()] - size + 'px';
- }
- if ((Browser.Engine.presto) && String(result).test('px')) return result;
- if (property.test(/(border(.+)Width|margin|padding)/)) return '0px';
- }
- return result;
- },
-
- setStyles: function(styles){
- for (var style in styles) this.setStyle(style, styles[style]);
- return this;
- },
-
- getStyles: function(){
- var result = {};
- Array.flatten(arguments).each(function(key){
- result[key] = this.getStyle(key);
- }, this);
- return result;
- }
-
-});
-
-Element.Styles = new Hash({
- left: '@px', top: '@px', bottom: '@px', right: '@px',
- width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
- backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
- fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
- margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
- borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
- zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
-});
-
-Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};
-
-['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
- var Short = Element.ShortStyles;
- var All = Element.Styles;
- ['margin', 'padding'].each(function(style){
- var sd = style + direction;
- Short[style][sd] = All[sd] = '@px';
- });
- var bd = 'border' + direction;
- Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
- var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
- Short[bd] = {};
- Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
- Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
- Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
-});
-/*
----
-
-script: Element.Dimensions.js
-
-description: Contains methods to work with size, scroll, or positioning of Elements and the window object.
-
-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).
-
-requires:
-- /Element
-
-provides: [Element.Dimensions]
-
-...
-*/
-
-(function(){
-
-Element.implement({
-
- scrollTo: function(x, y){
- if (isBody(this)){
- this.getWindow().scrollTo(x, y);
- } else {
- this.scrollLeft = x;
- this.scrollTop = y;
- }
- return this;
- },
-
- getSize: function(){
- if (isBody(this)) return this.getWindow().getSize();
- return {x: this.offsetWidth, y: this.offsetHeight};
- },
-
- getScrollSize: function(){
- if (isBody(this)) return this.getWindow().getScrollSize();
- return {x: this.scrollWidth, y: this.scrollHeight};
- },
-
- getScroll: function(){
- if (isBody(this)) return this.getWindow().getScroll();
- return {x: this.scrollLeft, y: this.scrollTop};
- },
-
- getScrolls: function(){
- var element = this, position = {x: 0, y: 0};
- while (element && !isBody(element)){
- position.x += element.scrollLeft;
- position.y += element.scrollTop;
- element = element.parentNode;
- }
- return position;
- },
-
- getOffsetParent: function(){
- var element = this;
- if (isBody(element)) return null;
- if (!Browser.Engine.trident) return element.offsetParent;
- 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;
-
- while (element && !isBody(element)){
- position.x += element.offsetLeft;
- position.y += element.offsetTop;
-
- if (Browser.Engine.gecko){
- if (!borderBox(element)){
- position.x += leftBorder(element);
- position.y += topBorder(element);
- }
- var parent = element.parentNode;
- if (parent && styleString(parent, 'overflow') != 'visible'){
- position.x += leftBorder(parent);
- position.y += topBorder(parent);
- }
- } else if (element != this && Browser.Engine.webkit){
- position.x += leftBorder(element);
- position.y += topBorder(element);
- }
-
- element = element.offsetParent;
- }
- if (Browser.Engine.gecko && !borderBox(this)){
- position.x -= leftBorder(this);
- position.y -= topBorder(this);
- }
- return position;
- },
-
- getPosition: function(relative){
- if (isBody(this)) return {x: 0, y: 0};
- var offset = this.getOffsets(),
- scroll = this.getScrolls();
- var position = {
- x: offset.x - scroll.x,
- y: offset.y - scroll.y
- };
- 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
- };
- 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')
- };
- },
-
- setPosition: function(obj){
- return this.setStyles(this.computePosition(obj));
- }
-
-});
-
-
-Native.implement([Document, Window], {
-
- getSize: function(){
- 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(), doc = getCompatElement(this);
- return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
- },
-
- getScrollSize: function(){
- var doc = getCompatElement(this), min = this.getSize();
- return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)};
- },
-
- getPosition: function(){
- return {x: 0, y: 0};
- },
-
- getCoordinates: function(){
- var size = this.getSize();
- return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
- }
-
-});
-
-// private methods
-
-var styleString = Element.getComputedStyle;
-
-function styleNumber(element, style){
- return styleString(element, style).toInt() || 0;
-};
-
-function borderBox(element){
- return styleString(element, '-moz-box-sizing') == 'border-box';
-};
-
-function topBorder(element){
- return styleNumber(element, 'border-top-width');
-};
-
-function leftBorder(element){
- return styleNumber(element, 'border-left-width');
-};
-
-function isBody(element){
- return (/^(?:body|html)$/i).test(element.tagName);
-};
-
-function getCompatElement(element){
- var doc = element.getDocument();
- return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
-};
-
-})();
-
-//aliases
-Element.alias('setPosition', 'position'); //compatability
-
-Native.implement([Window, Document, Element], {
-
- getHeight: function(){
- return this.getSize().y;
- },
-
- getWidth: function(){
- return this.getSize().x;
- },
-
- getScrollTop: function(){
- return this.getScroll().y;
- },
-
- getScrollLeft: function(){
- return this.getScroll().x;
- },
-
- getScrollHeight: function(){
- return this.getScrollSize().y;
- },
-
- getScrollWidth: function(){
- return this.getScrollSize().x;
- },
-
- getTop: function(){
- return this.getPosition().y;
- },
-
- getLeft: function(){
- return this.getPosition().x;
- }
-
-});
-/*
----
-
-script: Selectors.js
-
-description: Adds advanced CSS-style querying capabilities for targeting HTML Elements. Includes pseudo selectors.
-
-license: MIT-style license.
-
-requires:
-- /Element
-
-provides: [Selectors]
-
-...
-*/
-
-Native.implement([Document, Element], {
-
- getElements: function(expression, nocash){
- expression = expression.split(',');
- var items, local = {};
- for (var i = 0, l = expression.length; i < l; i++){
- var selector = expression[i], elements = Selectors.Utils.search(this, selector, local);
- if (i != 0 && elements.item) elements = $A(elements);
- items = (i == 0) ? elements : (items.item) ? $A(items).concat(elements) : items.concat(elements);
- }
- return new Elements(items, {ddup: (expression.length > 1), cash: !nocash});
- }
-
-});
-
-Element.implement({
-
- match: function(selector){
- 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: {}}};
-
-Selectors.RegExps = {
- id: (/#([\w-]+)/),
- tag: (/^(\w+|\*)/),
- quick: (/^(\w+|\*)$/),
- splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/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], 10);
- var a = (inta || inta === 0) ? inta : 1;
- var special = parsed[2] || false;
- var b = parseInt(parsed[3], 10) || 0;
- if (a != 0){
- b--;
- while (b < 1) b += a;
- while (b >= a) b -= a;
- } else {
- a = b;
- special = 'index';
- }
- 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 '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[5], pn = m[6], pa = m[7];
- if (cn){
- parsed.classes.push(cn);
- } else if (pn){
- var parser = Selectors.Pseudo.get(pn);
- if (parser) parsed.pseudos.push({parser: parser, argument: pa});
- else parsed.attributes.push({name: pn, operator: '=', value: pa});
- } else if (an){
- parsed.attributes.push({name: an, operator: ao, value: av});
- }
- }
- if (!parsed.classes.length) delete parsed.classes;
- if (!parsed.attributes.length) delete parsed.attributes;
- if (!parsed.pseudos.length) delete parsed.pseudos;
- 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){
- for (i = parsed.classes.length; i--; i){
- var cn = parsed.classes[i];
- if (!Selectors.Filters.byClass(item, cn)) return false;
- }
- }
- if (parsed.attributes){
- for (i = parsed.attributes.length; i--; i){
- var att = parsed.attributes[i];
- if (!Selectors.Filters.byAttribute(item, att.name, att.operator, att.value)) return false;
- }
- }
- if (parsed.pseudos){
- for (i = parsed.pseudos.length; i--; i){
- var psd = parsed.pseudos[i];
- if (!Selectors.Filters.byPseudo(item, psd.parser, psd.argument, local)) return false;
- }
- }
- return true;
- },
-
- getByTagAndID: function(ctx, tag, id){
- if (id){
- var item = (ctx.getElementById) ? ctx.getElementById(id, true) : Element.getElementById(ctx, id, true);
- return (item && Selectors.Filters.byTag(item, tag)) ? [item] : [];
- } else {
- 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, 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];
-
- if (i == 0){
- items = Selectors.Utils.getByTagAndID(self, tag, id);
- } else {
- var uniques = {}, found = [];
- 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++){
- item = items[m];
- if (Selectors.Utils.filter(item, parsed, local)) filtered.push(item);
- }
- 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++){
- var item = items[i];
- if (Selectors.Utils.chk(item, uniques)) found.push(item);
- }
- 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++){
- var child = children[i];
- if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child);
- }
- return found;
- },
-
- '+': function(found, self, tag, id, uniques){
- while ((self = self.nextSibling)){
- if (self.nodeType == 1){
- if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
- break;
- }
- }
- 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 && 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 (operator == '!=');
- if (!operator || value == undefined) return true;
- switch (operator){
- case '=': return (result == value);
- case '*=': return (result.contains(value));
- case '^=': return (result.substr(0, value.length) == value);
- case '$=': return (result.substr(result.length - value.length) == value);
- case '!=': return (result != value);
- case '~=': return result.contains(value, ' ');
- case '|=': return result.contains(value, '-');
- }
- 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)){
- if (element.nodeType == 1) return false;
- }
- return true;
- },
-
- 'only-child': function(){
- var prev = this;
- while ((prev = prev.previousSibling)){
- if (prev.nodeType == 1) return false;
- }
- var next = this;
- while ((next = next.nextSibling)){
- if (next.nodeType == 1) return false;
- }
- return true;
- },
-
- 'nth-child': function(argument, local){
- argument = (argument == undefined) ? 'n' : argument;
- var parsed = Selectors.Utils.parseNthArgument(argument);
- if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local);
- var count = 0;
- local.positions = local.positions || {};
- var uid = $uid(this);
- if (!local.positions[uid]){
- var self = this;
- while ((self = self.previousSibling)){
- if (self.nodeType != 1) continue;
- count ++;
- var position = local.positions[$uid(self)];
- if (position != undefined){
- count = position + count;
- break;
- }
- }
- local.positions[uid] = count;
- }
- return (local.positions[uid] % parsed.a == parsed.b);
- },
-
- // custom pseudo selectors
-
- index: function(index){
- var element = this, count = 0;
- while ((element = element.previousSibling)){
- if (element.nodeType == 1 && ++count > index) return false;
- }
- 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
-
-description: Contains the custom event domready.
-
-license: MIT-style license.
-
-requires:
-- /Element.Event
-
-provides: [DomReady]
-
-...
-*/
-
-Element.Events.domready = {
-
- onAdd: function(fn){
- if (Browser.loaded) fn.call(this);
- }
-
-};
-
-(function(){
-
- var domready = function(){
- if (Browser.loaded) return;
- Browser.loaded = true;
- window.fireEvent('domready');
- document.fireEvent('domready');
- };
-
- 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);
- })();
- } else {
- document.addEvent('DOMContentLoaded', domready);
- }
-
-})();
-/*
----
-
-script: JSON.js
-
-description: JSON encoder and decoder.
-
-license: MIT-style license.
-
-See Also: <http://www.json.org/>
-
-requires:
-- /Array
-- /String
-- /Number
-- /Function
-- /Hash
-
-provides: [JSON]
-
-...
-*/
-
-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).clean()) + ']';
- case 'object': case 'hash':
- var string = [];
- Hash.each(obj, function(value, key){
- var json = JSON.encode(value);
- if (json) string.push(JSON.encode(key) + ':' + json);
- });
- return '{' + string + '}';
- case 'number': case 'boolean': return String(obj);
- case false: return 'null';
- }
- return null;
- },
-
- 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;
- return eval('(' + string + ')');
- }
-
-});
-
-Native.implement([Hash, Array, String, Number], {
-
- toJSON: function(){
- return JSON.encode(this);
- }
-
-});
-/*
----
-
-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
-
-provides: [Cookie]
-
-...
-*/
-
-var Cookie = new Class({
-
- Implements: Options,
-
- options: {
- path: false,
- domain: false,
- duration: false,
- secure: false,
- document: document
- },
-
- initialize: function(key, options){
- this.key = key;
- this.setOptions(options);
- },
-
- write: function(value){
- value = encodeURIComponent(value);
- if (this.options.domain) value += '; domain=' + this.options.domain;
- if (this.options.path) value += '; path=' + this.options.path;
- if (this.options.duration){
- var date = new Date();
- date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
- value += '; expires=' + date.toGMTString();
- }
- if (this.options.secure) value += '; secure';
- this.options.document.cookie = this.key + '=' + value;
- return this;
- },
-
- read: function(){
- var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
- return (value) ? decodeURIComponent(value[1]) : null;
- },
-
- dispose: function(){
- new Cookie(this.key, $merge(this.options, {duration: -1})).write('');
- return this;
- }
-
-});
-
-Cookie.write = function(key, value, options){
- return new Cookie(key, options).write(value);
-};
-
-Cookie.read = function(key){
- return new Cookie(key).read();
-};
-
-Cookie.dispose = function(key, options){
- return new Cookie(key, options).dispose();
-};
-/*
----
-
-script: Swiff.js
-
-description: Wrapper for embedding SWF movies. Supports External Interface Communication.
-
-license: MIT-style license.
-
-credits:
-- Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject.
-
-requires:
-- /Options
-- /$util
-
-provides: [Swiff]
-
-...
-*/
-
-var Swiff = new Class({
-
- Implements: [Options],
-
- options: {
- id: null,
- height: 1,
- width: 1,
- container: null,
- properties: {},
- params: {
- quality: 'high',
- allowScriptAccess: 'always',
- wMode: 'transparent',
- swLiveConnect: true
- },
- callBacks: {},
- vars: {}
- },
-
- toElement: function(){
- return this.object;
- },
-
- initialize: function(path, options){
- this.instance = 'Swiff_' + $time();
-
- this.setOptions(options);
- options = this.options;
- var id = this.id = options.id || this.instance;
- var container = document.id(options.container);
-
- Swiff.CallBacks[this.instance] = {};
-
- var params = options.params, vars = options.vars, callBacks = options.callBacks;
- var properties = $extend({height: options.height, width: options.width}, options.properties);
-
- var self = this;
-
- for (var callBack in callBacks){
- Swiff.CallBacks[this.instance][callBack] = (function(option){
- return function(){
- return option.apply(self.object, arguments);
- };
- })(callBacks[callBack]);
- vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;
- }
-
- params.flashVars = Hash.toQueryString(vars);
- if (Browser.Engine.trident){
- properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
- params.movie = path;
- } else {
- properties.type = 'application/x-shockwave-flash';
- properties.data = path;
- }
- var build = '<object id="' + id + '"';
- for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
- build += '>';
- for (var param in params){
- if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';
- }
- build += '</object>';
- this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;
- },
-
- replaces: function(element){
- element = document.id(element, true);
- element.parentNode.replaceChild(this.toElement(), element);
- return this;
- },
-
- inject: function(element){
- document.id(element, true).appendChild(this.toElement());
- return this;
- },
-
- remote: function(){
- return Swiff.remote.apply(Swiff, [this.toElement()].extend(arguments));
- }
-
-});
-
-Swiff.CallBacks = {};
-
-Swiff.remote = function(obj, fn){
- var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
- return eval(rs);
-};
-/*
----
-
-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
-
-description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.
-
-license: MIT-style license.
-
-requires:
-- /Fx
-- /Element.Style
-
-provides: [Fx.CSS]
-
-...
-*/
-
-Fx.CSS = new Class({
-
- Extends: Fx,
-
- //prepares the base from/to object
-
- prepare: function(element, property, values){
- values = $splat(values);
- var values1 = values[1];
- if (!$chk(values1)){
- values[1] = values[0];
- values[0] = element.getStyle(property);
- }
- var parsed = values.map(this.parse);
- return {from: parsed[0], to: parsed[1]};
- },
-
- //parses a value into an array
-
- parse: function(value){
- value = $lambda(value)();
- value = (typeof value == 'string') ? value.split(' ') : $splat(value);
- return value.map(function(val){
- val = String(val);
- var found = false;
- Fx.CSS.Parsers.each(function(parser, key){
- if (found) return;
- var parsed = parser.parse(val);
- if ($chk(parsed)) found = {value: parsed, parser: parser};
- });
- found = found || {value: val, parser: Fx.CSS.Parsers.String};
- return found;
- });
- },
-
- //computes by a from and to prepared objects, using their parsers.
-
- compute: function(from, to, delta){
- var computed = [];
- (Math.min(from.length, to.length)).times(function(i){
- computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
- });
- computed.$family = {name: 'fx:css:value'};
- return computed;
- },
-
- //serves the value as settable
-
- serve: function(value, unit){
- if ($type(value) != 'fx:css:value') value = this.parse(value);
- var returned = [];
- value.each(function(bit){
- returned = returned.concat(bit.parser.serve(bit.value, unit));
- });
- return returned;
- },
-
- //renders the change to an element
-
- render: function(element, property, value, unit){
- element.setStyle(property, this.serve(value, unit));
- },
-
- //searches inside the page css to find the values for a selector
-
- search: function(selector){
- if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
- var to = {};
- Array.each(document.styleSheets, function(sheet, j){
- var href = sheet.href;
- if (href && href.contains('://') && !href.contains(document.domain)) return;
- var rules = sheet.rules || sheet.cssRules;
- Array.each(rules, function(rule, i){
- if (!rule.style) return;
- var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
- return m.toLowerCase();
- }) : null;
- if (!selectorText || !selectorText.test('^' + selector + '$')) return;
- Element.Styles.each(function(value, style){
- if (!rule.style[style] || Element.ShortStyles[style]) return;
- value = String(rule.style[style]);
- to[style] = (value.test(/^rgb/)) ? value.rgbToHex() : value;
- });
- });
- });
- return Fx.CSS.Cache[selector] = to;
- }
-
-});
-
-Fx.CSS.Cache = {};
-
-Fx.CSS.Parsers = new Hash({
-
- Color: {
- parse: function(value){
- if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
- return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
- },
- compute: function(from, to, delta){
- return from.map(function(value, i){
- return Math.round(Fx.compute(from[i], to[i], delta));
- });
- },
- serve: function(value){
- return value.map(Number);
- }
- },
-
- Number: {
- parse: parseFloat,
- compute: Fx.compute,
- serve: function(value, unit){
- return (unit) ? value + unit : value;
- }
- },
-
- String: {
- parse: $lambda(false),
- compute: $arguments(1),
- serve: $arguments(0)
- }
-
-});
-/*
----
-
-script: Fx.Tween.js
-
-description: Formerly Fx.Style, effect to transition any CSS property for an element.
-
-license: MIT-style license.
-
-requires:
-- /Fx.CSS
-
-provides: [Fx.Tween, Element.fade, Element.highlight]
-
-...
-*/
-
-Fx.Tween = new Class({
-
- Extends: Fx.CSS,
-
- initialize: function(element, options){
- this.element = this.subject = document.id(element);
- this.parent(options);
- },
-
- set: function(property, now){
- if (arguments.length == 1){
- now = property;
- property = this.property || this.options.property;
- }
- this.render(this.element, property, now, this.options.unit);
- return this;
- },
-
- start: function(property, from, to){
- 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);
- return this.parent(parsed.from, parsed.to);
- }
-
-});
-
-Element.Properties.tween = {
-
- set: function(options){
- var tween = this.retrieve('tween');
- if (tween) tween.cancel();
- return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options));
- },
-
- get: function(options){
- if (options || !this.retrieve('tween')){
- if (options || !this.retrieve('tween:options')) this.set('tween', options);
- this.store('tween', new Fx.Tween(this, this.retrieve('tween:options')));
- }
- return this.retrieve('tween');
- }
-
-};
-
-Element.implement({
-
- tween: function(property, from, to){
- this.get('tween').start(arguments);
- return this;
- },
-
- fade: function(how){
- var fade = this.get('tween'), o = 'opacity', toggle;
- how = $pick(how, 'toggle');
- switch (how){
- case 'in': fade.start(o, 1); break;
- case 'out': fade.start(o, 0); break;
- case 'show': fade.set(o, 1); break;
- case 'hide': fade.set(o, 0); break;
- case 'toggle':
- var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
- fade.start(o, (flag) ? 0 : 1);
- this.store('fade:flag', !flag);
- toggle = true;
- break;
- default: fade.start(o, arguments);
- }
- if (!toggle) this.eliminate('fade:flag');
- return this;
- },
-
- highlight: function(start, end){
- if (!end){
- end = this.retrieve('highlight:original', this.getStyle('background-color'));
- end = (end == 'transparent') ? '#fff' : end;
- }
- var tween = this.get('tween');
- tween.start('background-color', start || '#ffff88', end).chain(function(){
- this.setStyle('background-color', this.retrieve('highlight:original'));
- tween.callChain();
- }.bind(this));
- return this;
- }
-
-});
-/*
----
-
-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.
-
-requires:
-- /Fx.CSS
-
-provides: [Fx.Morph]
-
-...
-*/
-
-Fx.Morph = new Class({
-
- Extends: Fx.CSS,
-
- initialize: function(element, options){
- this.element = this.subject = document.id(element);
- this.parent(options);
- },
-
- set: function(now){
- if (typeof now == 'string') now = this.search(now);
- for (var p in now) this.render(this.element, p, now[p], this.options.unit);
- return this;
- },
-
- compute: function(from, to, delta){
- var now = {};
- for (var p in from) now[p] = this.parent(from[p], to[p], delta);
- return now;
- },
-
- start: function(properties){
- if (!this.check(properties)) return this;
- if (typeof properties == 'string') properties = this.search(properties);
- var from = {}, to = {};
- for (var p in properties){
- var parsed = this.prepare(this.element, p, properties[p]);
- from[p] = parsed.from;
- to[p] = parsed.to;
- }
- return this.parent(from, to);
- }
-
-});
-
-Element.Properties.morph = {
-
- set: function(options){
- var morph = this.retrieve('morph');
- if (morph) morph.cancel();
- return this.eliminate('morph').store('morph:options', $extend({link: 'cancel'}, options));
- },
-
- get: function(options){
- if (options || !this.retrieve('morph')){
- if (options || !this.retrieve('morph:options')) this.set('morph', options);
- this.store('morph', new Fx.Morph(this, this.retrieve('morph:options')));
- }
- return this.retrieve('morph');
- }
-
-};
-
-Element.implement({
-
- morph: function(props){
- this.get('morph').start(props);
- return this;
- }
-
-});
-/*
----
-
-script: Fx.Transitions.js
-
-description: Contains a set of advanced transitions to be used with any of the Fx Classes.
-
-license: MIT-style license.
-
-credits:
-- Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.
-
-requires:
-- /Fx
-
-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);
- return $extend(transition, {
- easeIn: function(pos){
- return transition(pos, params);
- },
- easeOut: function(pos){
- return 1 - transition(1 - pos, params);
- },
- easeInOut: function(pos){
- return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2;
- }
- });
-};
-
-Fx.Transitions = new Hash({
-
- linear: $arguments(0)
-
-});
-
-Fx.Transitions.extend = function(transitions){
- for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
-};
-
-Fx.Transitions.extend({
-
- Pow: function(p, x){
- return Math.pow(p, x[0] || 6);
- },
-
- Expo: function(p){
- return Math.pow(2, 8 * (p - 1));
- },
-
- Circ: function(p){
- return 1 - Math.sin(Math.acos(p));
- },
-
- Sine: function(p){
- return 1 - Math.sin((1 - p) * Math.PI / 2);
- },
-
- Back: function(p, x){
- x = x[0] || 1.618;
- return Math.pow(p, 2) * ((x + 1) * p - x);
- },
-
- Bounce: function(p){
- var value;
- for (var a = 0, b = 1; 1; a += b, b /= 2){
- if (p >= (7 - 4 * a) / 11){
- value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
- break;
- }
- }
- return value;
- },
-
- Elastic: function(p, x){
- return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3);
- }
-
-});
-
-['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
- Fx.Transitions[transition] = new Fx.Transition(function(p){
- return Math.pow(p, [i + 2]);
- });
-});
-/*
----
-
-script: Request.js
-
-description: Powerful all purpose Request Class. Uses XMLHTTPRequest.
-
-license: MIT-style license.
-
-requires:
-- /Element
-- /Chain
-- /Events
-- /Options
-- /Browser
-
-provides: [Request]
-
-...
-*/
-
-var Request = new Class({
-
- Implements: [Chain, Events, Options],
-
- options: {/*
- onRequest: $empty,
- onComplete: $empty,
- onCancel: $empty,
- onSuccess: $empty,
- onFailure: $empty,
- onException: $empty,*/
- url: '',
- data: '',
- headers: {
- 'X-Requested-With': 'XMLHttpRequest',
- 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
- },
- async: true,
- format: false,
- method: 'post',
- link: 'ignore',
- isSuccess: null,
- emulation: true,
- urlEncoded: true,
- encoding: 'utf-8',
- evalScripts: false,
- evalResponse: false,
- noCache: false
- },
-
- initialize: function(options){
- this.xhr = new Browser.Request();
- this.setOptions(options);
- this.options.isSuccess = this.options.isSuccess || this.isSuccess;
- this.headers = new Hash(this.options.headers);
- },
-
- onStateChange: function(){
- if (this.xhr.readyState != 4 || !this.running) return;
- this.running = false;
- this.status = 0;
- $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);
- } else {
- this.response = {text: null, xml: null};
- this.failure();
- }
- },
-
- isSuccess: function(){
- return ((this.status >= 200) && (this.status < 300));
- },
-
- processScripts: function(text){
- if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return $exec(text);
- return text.stripScripts(this.options.evalScripts);
- },
-
- success: function(text, xml){
- this.onSuccess(this.processScripts(text), xml);
- },
-
- onSuccess: function(){
- this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
- },
-
- failure: function(){
- this.onFailure();
- },
-
- onFailure: function(){
- this.fireEvent('complete').fireEvent('failure', this.xhr);
- },
-
- setHeader: function(name, value){
- this.headers.set(name, value);
- return this;
- },
-
- getHeader: function(name){
- return $try(function(){
- return this.xhr.getResponseHeader(name);
- }.bind(this));
- },
-
- check: function(){
- if (!this.running) 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;
- },
-
- send: function(options){
- if (!this.check(options)) return this;
- this.running = true;
-
- var type = $type(options);
- if (type == 'string' || type == 'element') options = {data: options};
-
- var old = this.options;
- options = $extend({data: old.data, url: old.url, method: old.method}, options);
- var data = options.data, url = String(options.url), method = options.method.toLowerCase();
-
- switch ($type(data)){
- case 'element': data = document.id(data).toQueryString(); break;
- case 'object': case 'hash': data = Hash.toQueryString(data);
- }
-
- if (this.options.format){
- var format = 'format=' + this.options.format;
- data = (data) ? format + '&' + data : format;
- }
-
- if (this.options.emulation && !['get', 'post'].contains(method)){
- var _method = '_method=' + method;
- data = (data) ? _method + '&' + data : _method;
- method = 'post';
- }
-
- if (this.options.urlEncoded && method == 'post'){
- var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
- 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;
- }
-
- this.xhr.open(method.toUpperCase(), url, this.options.async);
-
- this.xhr.onreadystatechange = this.onStateChange.bind(this);
-
- this.headers.each(function(value, key){
- try {
- this.xhr.setRequestHeader(key, value);
- } catch (e){
- this.fireEvent('exception', [key, value]);
- }
- }, this);
-
- this.fireEvent('request');
- this.xhr.send(data);
- if (!this.options.async) this.onStateChange();
- return this;
- },
-
- cancel: function(){
- if (!this.running) return this;
- this.running = false;
- this.xhr.abort();
- this.xhr.onreadystatechange = $empty;
- this.xhr = new Browser.Request();
- this.fireEvent('cancel');
- return this;
- }
-
-});
-
-(function(){
-
-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}));
- };
-});
-
-Request.implement(methods);
-
-})();
-
-Element.Properties.send = {
-
- set: function(options){
- var send = this.retrieve('send');
- if (send) send.cancel();
- return this.eliminate('send').store('send:options', $extend({
- data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
- }, options));
- },
-
- get: function(options){
- if (options || !this.retrieve('send')){
- if (options || !this.retrieve('send:options')) this.set('send', options);
- this.store('send', new Request(this.retrieve('send:options')));
- }
- return this.retrieve('send');
- }
-
-};
-
-Element.implement({
-
- send: function(url){
- var sender = this.get('send');
- sender.send({data: this, url: url || sender.options.url});
- return this;
- }
-
-});
-/*
----
-
-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({
-
- Extends: Request,
-
- options: {
- update: false,
- append: false,
- evalScripts: true,
- filter: false
- },
-
- processHTML: function(text){
- var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
- text = (match) ? match[1] : text;
-
- var container = new Element('div');
-
- return $try(function(){
- var root = '<root>' + text + '</root>', doc;
- if (Browser.Engine.trident){
- doc = new ActiveXObject('Microsoft.XMLDOM');
- doc.async = false;
- doc.loadXML(root);
- } else {
- 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);
- }
- return container;
- }) || container.set('html', text);
- },
-
- 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) 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) load.cancel();
- return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options));
- },
-
- get: function(options){
- if (options || ! this.retrieve('load')){
- if (options || !this.retrieve('load:options')) this.set('load', options);
- this.store('load', new Request.HTML(this.retrieve('load:options')));
- }
- return this.retrieve('load');
- }
-
-};
-
-Element.implement({
-
- load: function(){
- this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type}));
- return this;
- }
-
-});
-/*
----
-
-script: Request.JSON.js
-
-description: Extends the basic Request Class with additional methods for sending and receiving JSON data.
-
-license: MIT-style license.
-
-requires:
-- /Request JSON
-
-provides: [Request.HTML]
-
-...
-*/
-
-Request.JSON = new Class({
-
- Extends: Request,
-
- options: {
- secure: true
- },
-
- initialize: function(options){
- this.parent(options);
- this.headers.extend({'Accept': 'application/json', 'X-Request': 'JSON'});
- },
-
- success: function(text){
- this.response.json = JSON.decode(text, this.options.secure);
- this.onSuccess(this.response.json, text);
- }
-
-});
-/*
----
-
-script: More.js
-
-description: MooTools More
-
-license: MIT-style license
-
-authors:
-- Guillermo Rauch
-- Thomas Aylott
-- Scott Kyle
-
-requires:
-- core:1.2.4/MooTools
-
-provides: [MooTools.More]
-
-...
-*/
-
-MooTools.More = {
- 'version': '1.2.4.1'
-};/*
----
-
-script: Log.js
-
-description: Provides basic logging functionality for plugins to implement.
-
-license: MIT-style license
-
-authors:
-- Guillermo Rauch
-- Thomas Aylott
-- Scott Kyle
-
-requires:
-- core:1.2.4/Class
-- /MooTools.More
-
-provides: [Log]
-
-...
-*/
-
-(function(){
-
-var global = this;
-
-var log = function(){
- if (global.console && console.log){
- try {
- console.log.apply(console, arguments);
- } catch(e) {
- console.log(Array.slice(arguments));
- }
- } else {
- Log.logged.push(arguments);
- }
- return this;
-};
-
-var disabled = function(){
- this.logged.push(arguments);
- return this;
-};
-
-this.Log = new Class({
-
- logged: [],
-
- log: disabled,
-
- resetLog: function(){
- this.logged.empty();
- return this;
- },
-
- enableLog: function(){
- this.log = log;
- this.logged.each(function(args){
- this.log.apply(this, args);
- }, this);
- return this.resetLog();
- },
-
- disableLog: function(){
- this.log = disabled;
- return this;
- }
-
-});
-
-Log.extend(new Log).enableLog();
-
-// legacy
-Log.logger = function(){
- return this.log.apply(this, arguments);
-};
-
-})();/*
----
-
-script: Depender.js
-
-description: A stand alone dependency loader for the MooTools library.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element.Events
-- core:1.2.4/Request.JSON
-- /MooTools.More
-- /Log
-
-provides: Depender
-
-...
-*/
-
-var Depender = {
-
- options: {
- /*
- onRequire: $empty(options),
- onRequirementLoaded: $empty([scripts, options]),
- onScriptLoaded: $empty({
- script: script,
- totalLoaded: percentOfTotalLoaded,
- loaded: scriptsState
- }),
- serial: false,
- target: null,
- noCache: false,
- log: false,*/
- loadedSources: [],
- loadedScripts: ['Core', 'Browser', 'Array', 'String', 'Function', 'Number', 'Hash', 'Element', 'Event', 'Element.Event', 'Class', 'DomReady', 'Class.Extras', 'Request', 'JSON', 'Request.JSON', 'More', 'Depender', 'Log'],
- useScriptInjection: true
- },
-
- loaded: [],
-
- sources: {},
-
- libs: {},
-
- include: function(libs){
- this.log('include: ', libs);
- this.mapLoaded = false;
- var loader = function(data){
- this.libs = $merge(this.libs, data);
- $each(this.libs, function(data, lib){
- if (data.scripts) this.loadSource(lib, data.scripts);
- }, this);
- }.bind(this);
- if ($type(libs) == 'string'){
- this.log('fetching libs ', libs);
- this.request(libs, loader);
- } else {
- loader(libs);
- }
- return this;
- },
-
- required: [],
-
- require: function(options){
- var loaded = function(){
- var scripts = this.calculateDependencies(options.scripts);
- if (options.sources){
- options.sources.each(function(source){
- scripts.combine(this.libs[source].files);
- }, this);
- }
- if (options.serial) scripts.combine(this.getLoadedScripts());
- options.scripts = scripts;
- this.required.push(options);
- this.fireEvent('require', options);
- this.loadScripts(options.scripts);
- };
- if (this.mapLoaded){
- loaded.call(this);
- } else {
- this.addEvent('mapLoaded', function(){
- loaded.call(this);
- this.removeEvent('mapLoaded', arguments.callee);
- });
- }
- return this;
- },
-
- cleanDoubleSlash: function(str){
- if (!str) return str;
- var prefix = '';
- if (str.test(/^http:\/\//)){
- prefix = 'http://';
- str = str.substring(7, str.length);
- }
- str = str.replace(/\/\//g, '/');
- return prefix + str;
- },
-
- request: function(url, callback){
- new Request.JSON({
- url: url,
- secure: false,
- onSuccess: callback
- }).send();
- },
-
- loadSource: function(lib, source){
- if (this.libs[lib].files){
- this.dataLoaded();
- return;
- }
- this.log('loading source: ', source);
- this.request(this.cleanDoubleSlash(source + '/scripts.json'), function(result){
- this.log('loaded source: ', source);
- this.libs[lib].files = result;
- this.dataLoaded();
- }.bind(this));
- },
-
- dataLoaded: function(){
- var loaded = true;
- $each(this.libs, function(v, k){
- if (!this.libs[k].files) loaded = false;
- }, this);
- if (loaded){
- this.mapTree();
- this.mapLoaded = true;
- this.calculateLoaded();
- this.lastLoaded = this.getLoadedScripts().getLength();
- this.fireEvent('mapLoaded');
- }
- },
-
- calculateLoaded: function(){
- var set = function(script){
- this.scriptsState[script] = true;
- }.bind(this);
- if (this.options.loadedScripts) this.options.loadedScripts.each(set);
- if (this.options.loadedSources){
- this.options.loadedSources.each(function(lib){
- $each(this.libs[lib].files, function(dir){
- $each(dir, function(data, file){
- set(file);
- }, this);
- }, this);
- }, this);
- }
- },
-
- deps: {},
-
- pathMap: {},
-
- mapTree: function(){
- $each(this.libs, function(data, source){
- $each(data.files, function(scripts, folder){
- $each(scripts, function(details, script){
- var path = source + ':' + folder + ':' + script;
- if (this.deps[path]) return;
- this.deps[path] = details.deps;
- this.pathMap[script] = path;
- }, this);
- }, this);
- }, this);
- },
-
- getDepsForScript: function(script){
- return this.deps[this.pathMap[script]] || [];
- },
-
- calculateDependencies: function(scripts){
- var reqs = [];
- $splat(scripts).each(function(script){
- if (script == 'None' || !script) return;
- var deps = this.getDepsForScript(script);
- if (!deps){
- if (window.console && console.warn) console.warn('dependencies not mapped: script: %o, map: %o, :deps: %o', script, this.pathMap, this.deps);
- } else {
- deps.each(function(scr){
- if (scr == script || scr == 'None' || !scr) return;
- if (!reqs.contains(scr)) reqs.combine(this.calculateDependencies(scr));
- reqs.include(scr);
- }, this);
- }
- reqs.include(script);
- }, this);
- return reqs;
- },
-
- getPath: function(script){
- try {
- var chunks = this.pathMap[script].split(':');
- var lib = this.libs[chunks[0]];
- var dir = (lib.path || lib.scripts) + '/';
- chunks.shift();
- return this.cleanDoubleSlash(dir + chunks.join('/') + '.js');
- } catch(e){
- return script;
- }
- },
-
- loadScripts: function(scripts){
- scripts = scripts.filter(function(s){
- if (!this.scriptsState[s] && s != 'None'){
- this.scriptsState[s] = false;
- return true;
- }
- }, this);
- if (scripts.length){
- scripts.each(function(scr){
- this.loadScript(scr);
- }, this);
- } else {
- this.check();
- }
- },
-
- toLoad: [],
-
- loadScript: function(script){
- if (this.scriptsState[script] && this.toLoad.length){
- this.loadScript(this.toLoad.shift());
- return;
- } else if (this.loading){
- this.toLoad.push(script);
- return;
- }
- var finish = function(){
- this.loading = false;
- this.scriptLoaded(script);
- if (this.toLoad.length) this.loadScript(this.toLoad.shift());
- }.bind(this);
- var error = function(){
- this.log('could not load: ', scriptPath);
- }.bind(this);
- this.loading = true;
- var scriptPath = this.getPath(script);
- if (this.options.useScriptInjection){
- this.log('injecting script: ', scriptPath);
- var loaded = function(){
- this.log('loaded script: ', scriptPath);
- finish();
- }.bind(this);
- new Element('script', {
- src: scriptPath + (this.options.noCache ? '?noCache=' + new Date().getTime() : ''),
- events: {
- load: loaded,
- readystatechange: function(){
- if (['loaded', 'complete'].contains(this.readyState)) loaded();
- },
- error: error
- }
- }).inject(this.options.target || document.head);
- } else {
- this.log('requesting script: ', scriptPath);
- new Request({
- url: scriptPath,
- noCache: this.options.noCache,
- onComplete: function(js){
- this.log('loaded script: ', scriptPath);
- $exec(js);
- finish();
- }.bind(this),
- onFailure: error,
- onException: error
- }).send();
- }
- },
-
- scriptsState: $H(),
-
- getLoadedScripts: function(){
- return this.scriptsState.filter(function(state){
- return state;
- });
- },
-
- scriptLoaded: function(script){
- this.log('loaded script: ', script);
- this.scriptsState[script] = true;
- this.check();
- var loaded = this.getLoadedScripts();
- var loadedLength = loaded.getLength();
- var toLoad = this.scriptsState.getLength();
- this.fireEvent('scriptLoaded', {
- script: script,
- totalLoaded: (loadedLength / toLoad * 100).round(),
- currentLoaded: ((loadedLength - this.lastLoaded) / (toLoad - this.lastLoaded) * 100).round(),
- loaded: loaded
- });
- if (loadedLength == toLoad) this.lastLoaded = loadedLength;
- },
-
- lastLoaded: 0,
-
- check: function(){
- var incomplete = [];
- this.required.each(function(required){
- var loaded = [];
- required.scripts.each(function(script){
- if (this.scriptsState[script]) loaded.push(script);
- }, this);
- if (required.onStep){
- required.onStep({
- percent: loaded.length / required.scripts.length * 100,
- scripts: loaded
- });
- };
- if (required.scripts.length != loaded.length) return;
- required.callback();
- this.required.erase(required);
- this.fireEvent('requirementLoaded', [loaded, required]);
- }, this);
- }
-
-};
-
-$extend(Depender, new Events);
-$extend(Depender, new Options);
-$extend(Depender, new Log);
-
-Depender._setOptions = Depender.setOptions;
-Depender.setOptions = function(){
- Depender._setOptions.apply(Depender, arguments);
- if (this.options.log) Depender.enableLog();
- return this;
-};
-/*
----
-
-script: MooTools.Lang.js
-
-description: Provides methods for localization.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Events
-- /MooTools.More
-
-provides: [MooTools.Lang]
-
-...
-*/
-
-(function(){
-
- var data = {
- language: 'en-US',
- languages: {
- 'en-US': {}
- },
- cascades: ['en-US']
- };
-
- var cascaded;
-
- MooTools.lang = new Events();
-
- $extend(MooTools.lang, {
-
- setLanguage: function(lang){
- if (!data.languages[lang]) return this;
- data.language = lang;
- this.load();
- this.fireEvent('langChange', lang);
- return this;
- },
-
- load: function() {
- var langs = this.cascade(this.getCurrentLanguage());
- cascaded = {};
- $each(langs, function(set, setName){
- cascaded[setName] = this.lambda(set);
- }, this);
- },
-
- getCurrentLanguage: function(){
- return data.language;
- },
-
- addLanguage: function(lang){
- data.languages[lang] = data.languages[lang] || {};
- return this;
- },
-
- cascade: function(lang){
- var cascades = (data.languages[lang] || {}).cascades || [];
- cascades.combine(data.cascades);
- cascades.erase(lang).push(lang);
- var langs = cascades.map(function(lng){
- return data.languages[lng];
- }, this);
- return $merge.apply(this, langs);
- },
-
- lambda: function(set) {
- (set || {}).get = function(key, args){
- return $lambda(set[key]).apply(this, $splat(args));
- };
- return set;
- },
-
- get: function(set, key, args){
- if (cascaded && cascaded[set]) return (key ? cascaded[set].get(key, args) : cascaded[set]);
- },
-
- set: function(lang, set, members){
- this.addLanguage(lang);
- langData = data.languages[lang];
- if (!langData[set]) langData[set] = {};
- $extend(langData[set], members);
- if (lang == this.getCurrentLanguage()){
- this.load();
- this.fireEvent('langChange', lang);
- }
- return this;
- },
-
- list: function(){
- return Hash.getKeys(data.languages);
- }
-
- });
-
-})();/*
----
-
-script: Class.Refactor.js
-
-description: Extends a class onto itself with new property, preserving any items attached to the class's namespace.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Class
-- /MooTools.More
-
-provides: [Class.refactor]
-
-...
-*/
-
-Class.refactor = function(original, refactors){
-
- $each(refactors, function(item, name){
- var origin = original.prototype[name];
- if (origin && (origin = origin._origin) && typeof item == 'function') original.implement(name, function(){
- var old = this.previous;
- this.previous = origin;
- var value = item.apply(this, arguments);
- this.previous = old;
- return value;
- }); else original.implement(name, item);
- });
-
- return original;
-
-};/*
----
-
-script: Class.Binds.js
-
-description: Automagically binds specified methods in a class to the instance of the class.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Class
-- /MooTools.More
-
-provides: [Class.Binds]
-
-...
-*/
-
-Class.Mutators.Binds = function(binds){
- return binds;
-};
-
-Class.Mutators.initialize = function(initialize){
- return function(){
- $splat(this.Binds).each(function(name){
- var original = this[name];
- if (original) this[name] = original.bind(this);
- }, this);
- return initialize.apply(this, arguments);
- };
-};
-/*
----
-
-script: Class.Occlude.js
-
-description: Prevents a class from being applied to a DOM element twice.
-
-license: MIT-style license.
-
-authors:
-- Aaron Newton
-
-requires:
-- core/1.2.4/Class
-- core:1.2.4/Element
-- /MooTools.More
-
-provides: [Class.Occlude]
-
-...
-*/
-
-Class.Occlude = new Class({
-
- occlude: function(property, element){
- element = document.id(element || this.element);
- var instance = element.retrieve(property || this.property);
- if (instance && !$defined(this.occluded))
- return this.occluded = instance;
-
- this.occluded = false;
- element.store(property || this.property, this);
- return this.occluded;
- }
-
-});/*
----
-
-script: Chain.Wait.js
-
-description: value, Adds a method to inject pauses between chained events.
-
-license: MIT-style license.
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Chain
-- core:1.2.4/Element
-- core:1.2.4/Fx
-- /MooTools.More
-
-provides: [Chain.Wait]
-
-...
-*/
-
-(function(){
-
- var wait = {
- wait: function(duration){
- return this.chain(function(){
- this.callChain.delay($pick(duration, 500), this);
- }.bind(this));
- }
- };
-
- Chain.implement(wait);
-
- if (window.Fx){
- Fx.implement(wait);
- ['Css', 'Tween', 'Elements'].each(function(cls){
- if (Fx[cls]) Fx[cls].implement(wait);
- });
- }
-
- Element.implement({
- chains: function(effects){
- $splat($pick(effects, ['tween', 'morph', 'reveal'])).each(function(effect){
- effect = this.get(effect);
- if (!effect) return;
- effect.setOptions({
- link:'chain'
- });
- }, this);
- return this;
- },
- pauseFx: function(duration, effect){
- this.chains(effect).get($pick(effect, 'tween')).wait(duration);
- return this;
- }
- });
-
-})();/*
----
-
-script: Array.Extras.js
-
-description: Extends the Array native object to include useful methods to work with arrays.
-
-license: MIT-style license
-
-authors:
-- Christoph Pojer
-
-requires:
-- core:1.2.4/Array
-
-provides: [Array.Extras]
-
-...
-*/
-Array.implement({
-
- min: function(){
- return Math.min.apply(null, this);
- },
-
- max: function(){
- return Math.max.apply(null, this);
- },
-
- average: function(){
- return this.length ? this.sum() / this.length : 0;
- },
-
- sum: function(){
- var result = 0, l = this.length;
- if (l){
- do {
- result += this[--l];
- } while (l);
- }
- return result;
- },
-
- unique: function(){
- return [].combine(this);
- }
-
-});/*
----
-
-script: Date.English.US.js
-
-description: Date messages for US English.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.English.US]
-
-...
-*/
-
-MooTools.lang.set('en-US', 'Date', {
-
- months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
- days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
- //culture's date order: MM/DD/YYYY
- dateOrder: ['month', 'date', 'year'],
- shortDate: '%m/%d/%Y',
- shortTime: '%I:%M%p',
- AM: 'AM',
- PM: 'PM',
-
- /* Date.Extras */
- ordinal: function(dayOfMonth){
- //1st, 2nd, 3rd, etc.
- return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)];
- },
-
- lessThanMinuteAgo: 'less than a minute ago',
- minuteAgo: 'about a minute ago',
- minutesAgo: '{delta} minutes ago',
- hourAgo: 'about an hour ago',
- hoursAgo: 'about {delta} hours ago',
- dayAgo: '1 day ago',
- daysAgo: '{delta} days ago',
- weekAgo: '1 week ago',
- weeksAgo: '{delta} weeks ago',
- monthAgo: '1 month ago',
- monthsAgo: '{delta} months ago',
- yearAgo: '1 year ago',
- yearsAgo: '{delta} years ago',
- lessThanMinuteUntil: 'less than a minute from now',
- minuteUntil: 'about a minute from now',
- minutesUntil: '{delta} minutes from now',
- hourUntil: 'about an hour from now',
- hoursUntil: 'about {delta} hours from now',
- dayUntil: '1 day from now',
- daysUntil: '{delta} days from now',
- weekUntil: '1 week from now',
- weeksUntil: '{delta} weeks from now',
- monthUntil: '1 month from now',
- monthsUntil: '{delta} months from now',
- yearUntil: '1 year from now',
- yearsUntil: '{delta} years from now'
-
-});
-/*
----
-
-script: Date.js
-
-description: Extends the Date native object to include methods useful in managing dates.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-- Nicholas Barthelemy - https://svn.nbarthelemy.com/date-js/
-- Harald Kirshner - mail [at] digitarald.de; http://digitarald.de
-- Scott Kyle - scott [at] appden.com; http://appden.com
-
-requires:
-- core:1.2.4/Array
-- core:1.2.4/String
-- core:1.2.4/Number
-- core:1.2.4/Lang
-- core:1.2.4/Date.English.US
-- /MooTools.More
-
-provides: [Date]
-
-...
-*/
-
-(function(){
-
-var Date = this.Date;
-
-if (!Date.now) Date.now = $time;
-
-Date.Methods = {
- ms: 'Milliseconds',
- year: 'FullYear',
- min: 'Minutes',
- mo: 'Month',
- sec: 'Seconds',
- hr: 'Hours'
-};
-
-['Date', 'Day', 'FullYear', 'Hours', 'Milliseconds', 'Minutes', 'Month', 'Seconds', 'Time', 'TimezoneOffset',
- 'Week', 'Timezone', 'GMTOffset', 'DayOfYear', 'LastMonth', 'LastDayOfMonth', 'UTCDate', 'UTCDay', 'UTCFullYear',
- 'AMPM', 'Ordinal', 'UTCHours', 'UTCMilliseconds', 'UTCMinutes', 'UTCMonth', 'UTCSeconds'].each(function(method){
- Date.Methods[method.toLowerCase()] = method;
-});
-
-var pad = function(what, length){
- return new Array(length - String(what).length + 1).join('0') + what;
-};
-
-Date.implement({
-
- set: function(prop, value){
- switch ($type(prop)){
- case 'object':
- for (var p in prop) this.set(p, prop[p]);
- break;
- case 'string':
- prop = prop.toLowerCase();
- var m = Date.Methods;
- if (m[prop]) this['set' + m[prop]](value);
- }
- return this;
- },
-
- get: function(prop){
- prop = prop.toLowerCase();
- var m = Date.Methods;
- if (m[prop]) return this['get' + m[prop]]();
- return null;
- },
-
- clone: function(){
- return new Date(this.get('time'));
- },
-
- increment: function(interval, times){
- interval = interval || 'day';
- times = $pick(times, 1);
-
- switch (interval){
- case 'year':
- return this.increment('month', times * 12);
- case 'month':
- var d = this.get('date');
- this.set('date', 1).set('mo', this.get('mo') + times);
- return this.set('date', d.min(this.get('lastdayofmonth')));
- case 'week':
- return this.increment('day', times * 7);
- case 'day':
- return this.set('date', this.get('date') + times);
- }
-
- if (!Date.units[interval]) throw new Error(interval + ' is not a supported interval');
-
- return this.set('time', this.get('time') + times * Date.units[interval]());
- },
-
- decrement: function(interval, times){
- return this.increment(interval, -1 * $pick(times, 1));
- },
-
- isLeapYear: function(){
- return Date.isLeapYear(this.get('year'));
- },
-
- clearTime: function(){
- return this.set({hr: 0, min: 0, sec: 0, ms: 0});
- },
-
- diff: function(date, resolution){
- if ($type(date) == 'string') date = Date.parse(date);
-
- return ((date - this) / Date.units[resolution || 'day'](3, 3)).toInt(); // non-leap year, 30-day month
- },
-
- getLastDayOfMonth: function(){
- return Date.daysInMonth(this.get('mo'), this.get('year'));
- },
-
- getDayOfYear: function(){
- return (Date.UTC(this.get('year'), this.get('mo'), this.get('date') + 1)
- - Date.UTC(this.get('year'), 0, 1)) / Date.units.day();
- },
-
- getWeek: function(){
- return (this.get('dayofyear') / 7).ceil();
- },
-
- getOrdinal: function(day){
- return Date.getMsg('ordinal', day || this.get('date'));
- },
-
- getTimezone: function(){
- return this.toString()
- .replace(/^.*? ([A-Z]{3}).[0-9]{4}.*$/, '$1')
- .replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, '$1$2$3');
- },
-
- getGMTOffset: function(){
- var off = this.get('timezoneOffset');
- return ((off > 0) ? '-' : '+') + pad((off.abs() / 60).floor(), 2) + pad(off % 60, 2);
- },
-
- setAMPM: function(ampm){
- ampm = ampm.toUpperCase();
- var hr = this.get('hr');
- if (hr > 11 && ampm == 'AM') return this.decrement('hour', 12);
- else if (hr < 12 && ampm == 'PM') return this.increment('hour', 12);
- return this;
- },
-
- getAMPM: function(){
- return (this.get('hr') < 12) ? 'AM' : 'PM';
- },
-
- parse: function(str){
- this.set('time', Date.parse(str));
- return this;
- },
-
- isValid: function(date) {
- return !!(date || this).valueOf();
- },
-
- format: function(f){
- if (!this.isValid()) return 'invalid date';
- f = f || '%x %X';
- f = formats[f.toLowerCase()] || f; // replace short-hand with actual format
- var d = this;
- return f.replace(/%([a-z%])/gi,
- function($0, $1){
- switch ($1){
- case 'a': return Date.getMsg('days')[d.get('day')].substr(0, 3);
- case 'A': return Date.getMsg('days')[d.get('day')];
- case 'b': return Date.getMsg('months')[d.get('month')].substr(0, 3);
- case 'B': return Date.getMsg('months')[d.get('month')];
- case 'c': return d.toString();
- case 'd': return pad(d.get('date'), 2);
- case 'H': return pad(d.get('hr'), 2);
- case 'I': return ((d.get('hr') % 12) || 12);
- case 'j': return pad(d.get('dayofyear'), 3);
- case 'm': return pad((d.get('mo') + 1), 2);
- case 'M': return pad(d.get('min'), 2);
- case 'o': return d.get('ordinal');
- case 'p': return Date.getMsg(d.get('ampm'));
- case 'S': return pad(d.get('seconds'), 2);
- case 'U': return pad(d.get('week'), 2);
- case 'w': return d.get('day');
- case 'x': return d.format(Date.getMsg('shortDate'));
- case 'X': return d.format(Date.getMsg('shortTime'));
- case 'y': return d.get('year').toString().substr(2);
- case 'Y': return d.get('year');
- case 'T': return d.get('GMTOffset');
- case 'Z': return d.get('Timezone');
- }
- return $1;
- }
- );
- },
-
- toISOString: function(){
- return this.format('iso8601');
- }
-
-});
-
-Date.alias('toISOString', 'toJSON');
-Date.alias('diff', 'compare');
-Date.alias('format', 'strftime');
-
-var formats = {
- db: '%Y-%m-%d %H:%M:%S',
- compact: '%Y%m%dT%H%M%S',
- iso8601: '%Y-%m-%dT%H:%M:%S%T',
- rfc822: '%a, %d %b %Y %H:%M:%S %Z',
- 'short': '%d %b %H:%M',
- 'long': '%B %d, %Y %H:%M'
-};
-
-var parsePatterns = [];
-var nativeParse = Date.parse;
-
-var parseWord = function(type, word, num){
- var ret = -1;
- var translated = Date.getMsg(type + 's');
-
- switch ($type(word)){
- case 'object':
- ret = translated[word.get(type)];
- break;
- case 'number':
- ret = translated[month - 1];
- if (!ret) throw new Error('Invalid ' + type + ' index: ' + index);
- break;
- case 'string':
- var match = translated.filter(function(name){
- return this.test(name);
- }, new RegExp('^' + word, 'i'));
- if (!match.length) throw new Error('Invalid ' + type + ' string');
- if (match.length > 1) throw new Error('Ambiguous ' + type);
- ret = match[0];
- }
-
- return (num) ? translated.indexOf(ret) : ret;
-};
-
-Date.extend({
-
- getMsg: function(key, args) {
- return MooTools.lang.get('Date', key, args);
- },
-
- units: {
- ms: $lambda(1),
- second: $lambda(1000),
- minute: $lambda(60000),
- hour: $lambda(3600000),
- day: $lambda(86400000),
- week: $lambda(608400000),
- month: function(month, year){
- var d = new Date;
- return Date.daysInMonth($pick(month, d.get('mo')), $pick(year, d.get('year'))) * 86400000;
- },
- year: function(year){
- year = year || new Date().get('year');
- return Date.isLeapYear(year) ? 31622400000 : 31536000000;
- }
- },
-
- daysInMonth: function(month, year){
- return [31, Date.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
- },
-
- isLeapYear: function(year){
- return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
- },
-
- parse: function(from){
- var t = $type(from);
- if (t == 'number') return new Date(from);
- if (t != 'string') return from;
- from = from.clean();
- if (!from.length) return null;
-
- var parsed;
- parsePatterns.some(function(pattern){
- var bits = pattern.re.exec(from);
- return (bits) ? (parsed = pattern.handler(bits)) : false;
- });
-
- return parsed || new Date(nativeParse(from));
- },
-
- parseDay: function(day, num){
- return parseWord('day', day, num);
- },
-
- parseMonth: function(month, num){
- return parseWord('month', month, num);
- },
-
- parseUTC: function(value){
- var localDate = new Date(value);
- var utcSeconds = Date.UTC(
- localDate.get('year'),
- localDate.get('mo'),
- localDate.get('date'),
- localDate.get('hr'),
- localDate.get('min'),
- localDate.get('sec')
- );
- return new Date(utcSeconds);
- },
-
- orderIndex: function(unit){
- return Date.getMsg('dateOrder').indexOf(unit) + 1;
- },
-
- defineFormat: function(name, format){
- formats[name] = format;
- },
-
- defineFormats: function(formats){
- for (var name in formats) Date.defineFormat(name, formats[name]);
- },
-
- parsePatterns: parsePatterns, // this is deprecated
-
- defineParser: function(pattern){
- parsePatterns.push((pattern.re && pattern.handler) ? pattern : build(pattern));
- },
-
- defineParsers: function(){
- Array.flatten(arguments).each(Date.defineParser);
- },
-
- define2DigitYearStart: function(year){
- startYear = year % 100;
- startCentury = year - startYear;
- }
-
-});
-
-var startCentury = 1900;
-var startYear = 70;
-
-var regexOf = function(type){
- return new RegExp('(?:' + Date.getMsg(type).map(function(name){
- return name.substr(0, 3);
- }).join('|') + ')[a-z]*');
-};
-
-var replacers = function(key){
- switch(key){
- case 'x': // iso8601 covers yyyy-mm-dd, so just check if month is first
- return ((Date.orderIndex('month') == 1) ? '%m[.-/]%d' : '%d[.-/]%m') + '([.-/]%y)?';
- case 'X':
- return '%H([.:]%M)?([.:]%S([.:]%s)?)? ?%p? ?%T?';
- }
- return null;
-};
-
-var keys = {
- d: /[0-2]?[0-9]|3[01]/,
- H: /[01]?[0-9]|2[0-3]/,
- I: /0?[1-9]|1[0-2]/,
- M: /[0-5]?\d/,
- s: /\d+/,
- o: /[a-z]*/,
- p: /[ap]\.?m\.?/,
- y: /\d{2}|\d{4}/,
- Y: /\d{4}/,
- T: /Z|[+-]\d{2}(?::?\d{2})?/
-};
-
-keys.m = keys.I;
-keys.S = keys.M;
-
-var currentLanguage;
-
-var recompile = function(language){
- currentLanguage = language;
-
- keys.a = keys.A = regexOf('days');
- keys.b = keys.B = regexOf('months');
-
- parsePatterns.each(function(pattern, i){
- if (pattern.format) parsePatterns[i] = build(pattern.format);
- });
-};
-
-var build = function(format){
- if (!currentLanguage) return {format: format};
-
- var parsed = [];
- var re = (format.source || format) // allow format to be regex
- .replace(/%([a-z])/gi,
- function($0, $1){
- return replacers($1) || $0;
- }
- ).replace(/\((?!\?)/g, '(?:') // make all groups non-capturing
- .replace(/ (?!\?|\*)/g, ',? ') // be forgiving with spaces and commas
- .replace(/%([a-z%])/gi,
- function($0, $1){
- var p = keys[$1];
- if (!p) return $1;
- parsed.push($1);
- return '(' + p.source + ')';
- }
- ).replace(/\[a-z\]/gi, '[a-z\\u00c0-\\uffff]'); // handle unicode words
-
- return {
- format: format,
- re: new RegExp('^' + re + '$', 'i'),
- handler: function(bits){
- bits = bits.slice(1).associate(parsed);
- var date = new Date().clearTime();
- if ('d' in bits) handle.call(date, 'd', 1);
- if ('m' in bits) handle.call(date, 'm', 1);
- for (var key in bits) handle.call(date, key, bits[key]);
- return date;
- }
- };
-};
-
-var handle = function(key, value){
- if (!value) return this;
-
- switch(key){
- case 'a': case 'A': return this.set('day', Date.parseDay(value, true));
- case 'b': case 'B': return this.set('mo', Date.parseMonth(value, true));
- case 'd': return this.set('date', value);
- case 'H': case 'I': return this.set('hr', value);
- case 'm': return this.set('mo', value - 1);
- case 'M': return this.set('min', value);
- case 'p': return this.set('ampm', value.replace(/\./g, ''));
- case 'S': return this.set('sec', value);
- case 's': return this.set('ms', ('0.' + value) * 1000);
- case 'w': return this.set('day', value);
- case 'Y': return this.set('year', value);
- case 'y':
- value = +value;
- if (value < 100) value += startCentury + (value < startYear ? 100 : 0);
- return this.set('year', value);
- case 'T':
- if (value == 'Z') value = '+00';
- var offset = value.match(/([+-])(\d{2}):?(\d{2})?/);
- offset = (offset[1] + '1') * (offset[2] * 60 + (+offset[3] || 0)) + this.getTimezoneOffset();
- return this.set('time', this - offset * 60000);
- }
-
- return this;
-};
-
-Date.defineParsers(
- '%Y([-./]%m([-./]%d((T| )%X)?)?)?', // "1999-12-31", "1999-12-31 11:59pm", "1999-12-31 23:59:59", ISO8601
- '%Y%m%d(T%H(%M%S?)?)?', // "19991231", "19991231T1159", compact
- '%x( %X)?', // "12/31", "12.31.99", "12-31-1999", "12/31/2008 11:59 PM"
- '%d%o( %b( %Y)?)?( %X)?', // "31st", "31st December", "31 Dec 1999", "31 Dec 1999 11:59pm"
- '%b( %d%o)?( %Y)?( %X)?', // Same as above with month and day switched
- '%Y %b( %d%o( %X)?)?' // Same as above with year coming first
-);
-
-MooTools.lang.addEvent('langChange', function(language){
- if (MooTools.lang.get('Date')) recompile(language);
-}).fireEvent('langChange', MooTools.lang.getCurrentLanguage());
-
-})();/*
----
-
-script: Date.Extras.js
-
-description: Extends the Date native object to include extra methods (on top of those in Date.js).
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-- Scott Kyle
-
-requires:
-- /Date
-
-provides: [Date.Extras]
-
-...
-*/
-
-Date.implement({
-
- timeDiffInWords: function(relative_to){
- return Date.distanceOfTimeInWords(this, relative_to || new Date);
- },
-
- timeDiff: function(to, joiner){
- if (to == null) to = new Date;
- var delta = ((to - this) / 1000).toInt();
- if (!delta) return '0s';
-
- var durations = {s: 60, m: 60, h: 24, d: 365, y: 0};
- var duration, vals = [];
-
- for (var step in durations){
- if (!delta) break;
- if ((duration = durations[step])){
- vals.unshift((delta % duration) + step);
- delta = (delta / duration).toInt();
- } else {
- vals.unshift(delta + step);
- }
- }
-
- return vals.join(joiner || ':');
- }
-
-});
-
-Date.alias('timeDiffInWords', 'timeAgoInWords');
-
-Date.extend({
-
- distanceOfTimeInWords: function(from, to){
- return Date.getTimePhrase(((to - from) / 1000).toInt());
- },
-
- getTimePhrase: function(delta){
- var suffix = (delta < 0) ? 'Until' : 'Ago';
- if (delta < 0) delta *= -1;
-
- var units = {
- minute: 60,
- hour: 60,
- day: 24,
- week: 7,
- month: 52 / 12,
- year: 12,
- eon: Infinity
- };
-
- var msg = 'lessThanMinute';
-
- for (var unit in units){
- var interval = units[unit];
- if (delta < 1.5 * interval){
- if (delta > 0.75 * interval) msg = unit;
- break;
- }
- delta /= interval;
- msg = unit + 's';
- }
-
- return Date.getMsg(msg + suffix).substitute({delta: delta.round()});
- }
-
-});
-
-
-Date.defineParsers(
-
- {
- // "today", "tomorrow", "yesterday"
- re: /^(?:tod|tom|yes)/i,
- handler: function(bits){
- var d = new Date().clearTime();
- switch(bits[0]){
- case 'tom': return d.increment();
- case 'yes': return d.decrement();
- default: return d;
- }
- }
- },
-
- {
- // "next Wednesday", "last Thursday"
- re: /^(next|last) ([a-z]+)$/i,
- handler: function(bits){
- var d = new Date().clearTime();
- var day = d.getDay();
- var newDay = Date.parseDay(bits[2], true);
- var addDays = newDay - day;
- if (newDay <= day) addDays += 7;
- if (bits[1] == 'last') addDays -= 7;
- return d.set('date', d.getDate() + addDays);
- }
- }
-
-);
-/*
----
-
-script: Hash.Extras.js
-
-description: Extends the Hash native object to include getFromPath which allows a path notation to child elements.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Hash.base
-- /MooTools.More
-
-provides: [Hash.Extras]
-
-...
-*/
-
-Hash.implement({
-
- getFromPath: function(notation){
- var source = this.getClean();
- notation.replace(/\[([^\]]+)\]|\.([^.[]+)|[^[.]+/g, function(match){
- if (!source) return null;
- var prop = arguments[2] || arguments[1] || arguments[0];
- source = (prop in source) ? source[prop] : null;
- return match;
- });
- return source;
- },
-
- cleanValues: function(method){
- method = method || $defined;
- this.each(function(v, k){
- if (!method(v)) this.erase(k);
- }, this);
- return this;
- },
-
- run: function(){
- var args = arguments;
- this.each(function(v, k){
- if ($type(v) == 'function') v.run(args);
- });
- }
-
-});/*
----
-
-script: String.Extras.js
-
-description: Extends the String native object to include methods useful in managing various kinds of strings (query strings, urls, html, etc).
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-- Guillermo Rauch
-
-requires:
-- core:1.2.4/String
-- core:1.2.4/$util
-- core:1.2.4/Array
-
-provides: [String.Extras]
-
-...
-*/
-
-(function(){
-
-var special = ['Ã','à ','Ã','á','Ã','â','Ã','ã','Ã','ä','Ã
','Ã¥','Ä','Ä','Ä','Ä
','Ä','Ä','Ä','Ä','Ã','ç', 'Ä','Ä','Ä','Ä', 'Ã','è','Ã','é','Ã','ê','Ã','ë','Ä','Ä','Ä','Ä', 'Ä','Ä','Ã','ì','Ã','Ã','Ã','î','Ã','ï', 'Ĺ','ĺ','Ľ','ľ','Å','Å', 'Ã','ñ','Å','Å','Å','Å','Ã','ò','Ã','ó','Ã','ô','Ã','õ','Ã','ö','Ã','ø','Å','Å','Å','Å','Å','Å ','Å¡','Å','Å','Å','Å', 'Ť','Å¥','Ť','Å¥','Å¢','Å£','Ã','ù','Ã','ú','Ã','û','Ã','ü','Å®','ů', 'Ÿ','ÿ','ý','Ã','Ž','ž','Ź','ź','Å»','ż', 'Ã','þ','Ã','ð','Ã','Å','Å','Ã','æ','µ'];
-
-var standard = ['A','a','A','a','A','a','A','a','Ae','ae','A','a','A','a','A','a','C','c','C','c','C','c','D','d','D','d', 'E','e','E','e','E','e','E','e','E','e','E','e','G','g','I','i','I','i','I','i','I','i','L','l','L','l','L','l', 'N','n','N','n','N','n', 'O','o','O','o','O','o','O','o','Oe','oe','O','o','o', 'R','r','R','r', 'S','s','S','s','S','s','T','t','T','t','T','t', 'U','u','U','u','U','u','Ue','ue','U','u','Y','y','Y','y','Z','z','Z','z','Z','z','TH','th','DH','dh','ss','OE','oe','AE','ae','u'];
-
-var tidymap = {
- "[\xa0\u2002\u2003\u2009]": " ",
- "\xb7": "*",
- "[\u2018\u2019]": "'",
- "[\u201c\u201d]": '"',
- "\u2026": "...",
- "\u2013": "-",
- "\u2014": "--",
- "\uFFFD": "»"
-};
-
-var getRegForTag = function(tag, contents) {
- tag = tag || '';
- var regstr = contents ? "<" + tag + "[^>]*>([\\s\\S]*?)<\/" + tag + ">" : "<\/?" + tag + "([^>]+)?>";
- reg = new RegExp(regstr, "gi");
- return reg;
-};
-
-String.implement({
-
- standardize: function(){
- var text = this;
- special.each(function(ch, i){
- text = text.replace(new RegExp(ch, 'g'), standard[i]);
- });
- return text;
- },
-
- repeat: function(times){
- return new Array(times + 1).join(this);
- },
-
- pad: function(length, str, dir){
- if (this.length >= length) return this;
- var pad = (str == null ? ' ' : '' + str).repeat(length - this.length).substr(0, length - this.length);
- if (!dir || dir == 'right') return this + pad;
- if (dir == 'left') return pad + this;
- return pad.substr(0, (pad.length / 2).floor()) + this + pad.substr(0, (pad.length / 2).ceil());
- },
-
- getTags: function(tag, contents){
- return this.match(getRegForTag(tag, contents)) || [];
- },
-
- stripTags: function(tag, contents){
- return this.replace(getRegForTag(tag, contents), '');
- },
-
- tidy: function(){
- var txt = this.toString();
- $each(tidymap, function(value, key){
- txt = txt.replace(new RegExp(key, 'g'), value);
- });
- return txt;
- }
-
-});
-
-})();/*
----
-
-script: String.QueryString.js
-
-description: Methods for dealing with URI query strings.
-
-license: MIT-style license
-
-authors:
-- Sebastian Markbåge, Aaron Newton, Lennart Pilon, Valerio Proietti
-
-requires:
-- core:1.2.4/Array
-- core:1.2.4/String
-- /MooTools.More
-
-provides: [String.QueryString]
-
-...
-*/
-
-String.implement({
-
- parseQueryString: function(){
- var vars = this.split(/[&;]/), res = {};
- if (vars.length) vars.each(function(val){
- var index = val.indexOf('='),
- keys = index < 0 ? [''] : val.substr(0, index).match(/[^\]\[]+/g),
- value = decodeURIComponent(val.substr(index + 1)),
- obj = res;
- keys.each(function(key, i){
- var current = obj[key];
- if(i < keys.length - 1)
- obj = obj[key] = current || {};
- else if($type(current) == 'array')
- current.push(value);
- else
- obj[key] = $defined(current) ? [current, value] : value;
- });
- });
- return res;
- },
-
- cleanQueryString: function(method){
- return this.split('&').filter(function(val){
- var index = val.indexOf('='),
- key = index < 0 ? '' : val.substr(0, index),
- value = val.substr(index + 1);
- return method ? method.run([key, value]) : $chk(value);
- }).join('&');
- }
-
-});/*
----
-
-script: URI.js
-
-description: Provides methods useful in managing the window location and uris.
-
-license: MIT-style license
-
-authors:
-- Sebastian Markbåge
-- Aaron Newton
-
-requires:
-- core:1.2.4/Selectors
-- /String.QueryString
-
-provides: URI
-
-...
-*/
-
-var URI = new Class({
-
- Implements: Options,
-
- options: {
- /*base: false*/
- },
-
- regex: /^(?:(\w+):)?(?:\/\/(?:(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)?(\.\.?$|(?:[^?#\/]*\/)*)([^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
- parts: ['scheme', 'user', 'password', 'host', 'port', 'directory', 'file', 'query', 'fragment'],
- schemes: {http: 80, https: 443, ftp: 21, rtsp: 554, mms: 1755, file: 0},
-
- initialize: function(uri, options){
- this.setOptions(options);
- var base = this.options.base || URI.base;
- if(!uri) uri = base;
-
- if (uri && uri.parsed) this.parsed = $unlink(uri.parsed);
- else this.set('value', uri.href || uri.toString(), base ? new URI(base) : false);
- },
-
- parse: function(value, base){
- var bits = value.match(this.regex);
- if (!bits) return false;
- bits.shift();
- return this.merge(bits.associate(this.parts), base);
- },
-
- merge: function(bits, base){
- if ((!bits || !bits.scheme) && (!base || !base.scheme)) return false;
- if (base){
- this.parts.every(function(part){
- if (bits[part]) return false;
- bits[part] = base[part] || '';
- return true;
- });
- }
- bits.port = bits.port || this.schemes[bits.scheme.toLowerCase()];
- bits.directory = bits.directory ? this.parseDirectory(bits.directory, base ? base.directory : '') : '/';
- return bits;
- },
-
- parseDirectory: function(directory, baseDirectory) {
- directory = (directory.substr(0, 1) == '/' ? '' : (baseDirectory || '/')) + directory;
- if (!directory.test(URI.regs.directoryDot)) return directory;
- var result = [];
- directory.replace(URI.regs.endSlash, '').split('/').each(function(dir){
- if (dir == '..' && result.length > 0) result.pop();
- else if (dir != '.') result.push(dir);
- });
- return result.join('/') + '/';
- },
-
- combine: function(bits){
- return bits.value || bits.scheme + '://' +
- (bits.user ? bits.user + (bits.password ? ':' + bits.password : '') + '@' : '') +
- (bits.host || '') + (bits.port && bits.port != this.schemes[bits.scheme] ? ':' + bits.port : '') +
- (bits.directory || '/') + (bits.file || '') +
- (bits.query ? '?' + bits.query : '') +
- (bits.fragment ? '#' + bits.fragment : '');
- },
-
- set: function(part, value, base){
- if (part == 'value'){
- var scheme = value.match(URI.regs.scheme);
- if (scheme) scheme = scheme[1];
- if (scheme && !$defined(this.schemes[scheme.toLowerCase()])) this.parsed = { scheme: scheme, value: value };
- else this.parsed = this.parse(value, (base || this).parsed) || (scheme ? { scheme: scheme, value: value } : { value: value });
- } else if (part == 'data') {
- this.setData(value);
- } else {
- this.parsed[part] = value;
- }
- return this;
- },
-
- get: function(part, base){
- switch(part){
- case 'value': return this.combine(this.parsed, base ? base.parsed : false);
- case 'data' : return this.getData();
- }
- return this.parsed[part] || '';
- },
-
- go: function(){
- document.location.href = this.toString();
- },
-
- toURI: function(){
- return this;
- },
-
- getData: function(key, part){
- var qs = this.get(part || 'query');
- if (!$chk(qs)) return key ? null : {};
- var obj = qs.parseQueryString();
- return key ? obj[key] : obj;
- },
-
- setData: function(values, merge, part){
- if (typeof values == 'string'){
- values = this.getData();
- values[arguments[0]] = arguments[1];
- } else if (merge) {
- values = $merge(this.getData(), values);
- }
- return this.set(part || 'query', Hash.toQueryString(values));
- },
-
- clearData: function(part){
- return this.set(part || 'query', '');
- }
-
-});
-
-URI.prototype.toString = URI.prototype.valueOf = function(){
- return this.get('value');
-};
-
-URI.regs = {
- endSlash: /\/$/,
- scheme: /^(\w+):/,
- directoryDot: /\.\/|\.$/
-};
-
-URI.base = new URI(document.getElements('base[href]', true).getLast(), {base: document.location});
-
-String.implement({
-
- toURI: function(options){
- return new URI(this, options);
- }
-
-});/*
----
-
-script: URI.Relative.js
-
-description: Extends the URI class to add methods for computing relative and absolute urls.
-
-license: MIT-style license
-
-authors:
-- Sebastian Markbåge
-
-
-requires:
-- /Class.refactor
-- /URI
-
-provides: [URI.Relative]
-
-...
-*/
-
-URI = Class.refactor(URI, {
-
- combine: function(bits, base){
- if (!base || bits.scheme != base.scheme || bits.host != base.host || bits.port != base.port)
- return this.previous.apply(this, arguments);
- var end = bits.file + (bits.query ? '?' + bits.query : '') + (bits.fragment ? '#' + bits.fragment : '');
-
- if (!base.directory) return (bits.directory || (bits.file ? '' : './')) + end;
-
- var baseDir = base.directory.split('/'),
- relDir = bits.directory.split('/'),
- path = '',
- offset;
-
- var i = 0;
- for(offset = 0; offset < baseDir.length && offset < relDir.length && baseDir[offset] == relDir[offset]; offset++);
- for(i = 0; i < baseDir.length - offset - 1; i++) path += '../';
- for(i = offset; i < relDir.length - 1; i++) path += relDir[i] + '/';
-
- return (path || (bits.file ? '' : './')) + end;
- },
-
- toAbsolute: function(base){
- base = new URI(base);
- if (base) base.set('directory', '').set('file', '');
- return this.toRelative(base);
- },
-
- toRelative: function(base){
- return this.get('value', new URI(base));
- }
-
-});/*
----
-
-script: Element.Forms.js
-
-description: Extends the Element native object to include methods useful in managing inputs.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element
-- /MooTools.More
-
-provides: [Element.Forms]
-
-...
-*/
-
-Element.implement({
-
- tidy: function(){
- this.set('value', this.get('value').tidy());
- },
-
- getTextInRange: function(start, end){
- return this.get('value').substring(start, end);
- },
-
- getSelectedText: function(){
- if (this.setSelectionRange) return this.getTextInRange(this.getSelectionStart(), this.getSelectionEnd());
- return document.selection.createRange().text;
- },
-
- getSelectedRange: function() {
- if ($defined(this.selectionStart)) return {start: this.selectionStart, end: this.selectionEnd};
- var pos = {start: 0, end: 0};
- var range = this.getDocument().selection.createRange();
- if (!range || range.parentElement() != this) return pos;
- var dup = range.duplicate();
- if (this.type == 'text') {
- pos.start = 0 - dup.moveStart('character', -100000);
- pos.end = pos.start + range.text.length;
- } else {
- var value = this.get('value');
- var offset = value.length;
- dup.moveToElementText(this);
- dup.setEndPoint('StartToEnd', range);
- if(dup.text.length) offset -= value.match(/[\n\r]*$/)[0].length;
- pos.end = offset - dup.text.length;
- dup.setEndPoint('StartToStart', range);
- pos.start = offset - dup.text.length;
- }
- return pos;
- },
-
- getSelectionStart: function(){
- return this.getSelectedRange().start;
- },
-
- getSelectionEnd: function(){
- return this.getSelectedRange().end;
- },
-
- setCaretPosition: function(pos){
- if (pos == 'end') pos = this.get('value').length;
- this.selectRange(pos, pos);
- return this;
- },
-
- getCaretPosition: function(){
- return this.getSelectedRange().start;
- },
-
- selectRange: function(start, end){
- if (this.setSelectionRange) {
- this.focus();
- this.setSelectionRange(start, end);
- } else {
- var value = this.get('value');
- var diff = value.substr(start, end - start).replace(/\r/g, '').length;
- start = value.substr(0, start).replace(/\r/g, '').length;
- var range = this.createTextRange();
- range.collapse(true);
- range.moveEnd('character', start + diff);
- range.moveStart('character', start);
- range.select();
- }
- return this;
- },
-
- insertAtCursor: function(value, select){
- var pos = this.getSelectedRange();
- var text = this.get('value');
- this.set('value', text.substring(0, pos.start) + value + text.substring(pos.end, text.length));
- if ($pick(select, true)) this.selectRange(pos.start, pos.start + value.length);
- else this.setCaretPosition(pos.start + value.length);
- return this;
- },
-
- insertAroundCursor: function(options, select){
- options = $extend({
- before: '',
- defaultMiddle: '',
- after: ''
- }, options);
- var value = this.getSelectedText() || options.defaultMiddle;
- var pos = this.getSelectedRange();
- var text = this.get('value');
- if (pos.start == pos.end){
- this.set('value', text.substring(0, pos.start) + options.before + value + options.after + text.substring(pos.end, text.length));
- this.selectRange(pos.start + options.before.length, pos.end + options.before.length + value.length);
- } else {
- var current = text.substring(pos.start, pos.end);
- this.set('value', text.substring(0, pos.start) + options.before + current + options.after + text.substring(pos.end, text.length));
- var selStart = pos.start + options.before.length;
- if ($pick(select, true)) this.selectRange(selStart, selStart + current.length);
- else this.setCaretPosition(selStart + text.length);
- }
- return this;
- }
-
-});/*
----
-
-script: Elements.From.js
-
-description: Returns a collection of elements from a string of html.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element
-- /MooTools.More
-
-provides: [Elements.from]
-
-...
-*/
-
-Elements.from = function(text, excludeScripts){
- if ($pick(excludeScripts, true)) text = text.stripScripts();
-
- var container, match = text.match(/^\s*<(t[dhr]|tbody|tfoot|thead)/i);
-
- if (match){
- container = new Element('table');
- var tag = match[1].toLowerCase();
- if (['td', 'th', 'tr'].contains(tag)){
- container = new Element('tbody').inject(container);
- if (tag != 'tr') container = new Element('tr').inject(container);
- }
- }
-
- return (container || new Element('div')).set('html', text).getChildren();
-};/*
----
-
-script: Element.Delegation.js
-
-description: Extends the Element native object to include the delegate method for more efficient event management.
-
-credits:
-- "Event checking based on the work of Daniel Steigerwald. License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-- Daniel Steigerwald
-
-requires:
-- core:1.2.4/Element.Event
-- core:1.2.4/Selectors
-- /MooTools.More
-
-provides: [Element.Delegation]
-
-...
-*/
-(function(){
-
- var match = /(.*?):relay\(([^)]+)\)$/,
- combinators = /[+>~\s]/,
- splitType = function(type){
- var bits = type.match(match);
- return !bits ? {event: type} : {
- event: bits[1],
- selector: bits[2]
- };
- },
- check = function(e, selector){
- var t = e.target;
- if (combinators.test(selector = selector.trim())){
- var els = this.getElements(selector);
- for (var i = els.length; i--; ){
- var el = els[i];
- if (t == el || el.hasChild(t)) return el;
- }
- } else {
- for ( ; t && t != this; t = t.parentNode){
- if (Element.match(t, selector)) return document.id(t);
- }
- }
- return null;
- };
-
- var oldAddEvent = Element.prototype.addEvent,
- oldRemoveEvent = Element.prototype.removeEvent;
-
- Element.implement({
-
- addEvent: function(type, fn){
- var splitted = splitType(type);
- if (splitted.selector){
- var monitors = this.retrieve('$moo:delegateMonitors', {});
- if (!monitors[type]){
- var monitor = function(e){
- var el = check.call(this, e, splitted.selector);
- if (el) this.fireEvent(type, [e, el], 0, el);
- }.bind(this);
- monitors[type] = monitor;
- oldAddEvent.call(this, splitted.event, monitor);
- }
- }
- return oldAddEvent.apply(this, arguments);
- },
-
- removeEvent: function(type, fn){
- var splitted = splitType(type);
- if (splitted.selector){
- var events = this.retrieve('events');
- if (!events || !events[type] || (fn && !events[type].keys.contains(fn))) return this;
-
- if (fn) oldRemoveEvent.apply(this, [type, fn]);
- else oldRemoveEvent.apply(this, type);
-
- events = this.retrieve('events');
- if (events && events[type] && events[type].length == 0){
- var monitors = this.retrieve('$moo:delegateMonitors', {});
- oldRemoveEvent.apply(this, [splitted.event, monitors[type]]);
- delete monitors[type];
- }
- return this;
- }
-
- return oldRemoveEvent.apply(this, arguments);
- },
-
- fireEvent: function(type, args, delay, bind){
- var events = this.retrieve('events');
- if (!events || !events[type]) return this;
- events[type].keys.each(function(fn){
- fn.create({bind: bind || this, delay: delay, arguments: args})();
- }, this);
- return this;
- }
-
- });
-
-})();/*
----
-
-script: Element.Measure.js
-
-description: Extends the Element native object to include methods useful in measuring dimensions.
-
-credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element.Style
-- core:1.2.4/Element.Dimensions
-- /MooTools.More
-
-provides: [Element.Measure]
-
-...
-*/
-
-Element.implement({
-
- measure: function(fn){
- var vis = function(el) {
- return !!(!el || el.offsetHeight || el.offsetWidth);
- };
- if (vis(this)) return fn.apply(this);
- var parent = this.getParent(),
- restorers = [],
- toMeasure = [];
- while (!vis(parent) && parent != document.body) {
- toMeasure.push(parent.expose());
- parent = parent.getParent();
- }
- var restore = this.expose();
- var result = fn.apply(this);
- restore();
- toMeasure.each(function(restore){
- restore();
- });
- return result;
- },
-
- expose: function(){
- if (this.getStyle('display') != 'none') return $empty;
- var before = this.style.cssText;
- this.setStyles({
- display: 'block',
- position: 'absolute',
- visibility: 'hidden'
- });
- return function(){
- this.style.cssText = before;
- }.bind(this);
- },
-
- getDimensions: function(options){
- options = $merge({computeSize: false},options);
- var dim = {};
- var getSize = function(el, options){
- return (options.computeSize)?el.getComputedSize(options):el.getSize();
- };
- var parent = this.getParent('body');
- if (parent && this.getStyle('display') == 'none'){
- dim = this.measure(function(){
- return getSize(this, options);
- });
- } else if (parent){
- try { //safari sometimes crashes here, so catch it
- dim = getSize(this, options);
- }catch(e){}
- } else {
- dim = {x: 0, y: 0};
- }
- return $chk(dim.x) ? $extend(dim, {width: dim.x, height: dim.y}) : $extend(dim, {x: dim.width, y: dim.height});
- },
-
- getComputedSize: function(options){
- options = $merge({
- styles: ['padding','border'],
- plains: {
- height: ['top','bottom'],
- width: ['left','right']
- },
- mode: 'both'
- }, options);
- var size = {width: 0,height: 0};
- switch (options.mode){
- case 'vertical':
- delete size.width;
- delete options.plains.width;
- break;
- case 'horizontal':
- delete size.height;
- delete options.plains.height;
- break;
- }
- var getStyles = [];
- //this function might be useful in other places; perhaps it should be outside this function?
- $each(options.plains, function(plain, key){
- plain.each(function(edge){
- options.styles.each(function(style){
- getStyles.push((style == 'border') ? style + '-' + edge + '-' + 'width' : style + '-' + edge);
- });
- });
- });
- var styles = {};
- getStyles.each(function(style){ styles[style] = this.getComputedStyle(style); }, this);
- var subtracted = [];
- $each(options.plains, function(plain, key){ //keys: width, height, plains: ['left', 'right'], ['top','bottom']
- var capitalized = key.capitalize();
- size['total' + capitalized] = size['computed' + capitalized] = 0;
- plain.each(function(edge){ //top, left, right, bottom
- size['computed' + edge.capitalize()] = 0;
- getStyles.each(function(style, i){ //padding, border, etc.
- //'padding-left'.test('left') size['totalWidth'] = size['width'] + [padding-left]
- if (style.test(edge)){
- styles[style] = styles[style].toInt() || 0; //styles['padding-left'] = 5;
- size['total' + capitalized] = size['total' + capitalized] + styles[style];
- size['computed' + edge.capitalize()] = size['computed' + edge.capitalize()] + styles[style];
- }
- //if width != width (so, padding-left, for instance), then subtract that from the total
- if (style.test(edge) && key != style &&
- (style.test('border') || style.test('padding')) && !subtracted.contains(style)){
- subtracted.push(style);
- size['computed' + capitalized] = size['computed' + capitalized]-styles[style];
- }
- });
- });
- });
-
- ['Width', 'Height'].each(function(value){
- var lower = value.toLowerCase();
- if(!$chk(size[lower])) return;
-
- size[lower] = size[lower] + this['offset' + value] + size['computed' + value];
- size['total' + value] = size[lower] + size['total' + value];
- delete size['computed' + value];
- }, this);
-
- return $extend(styles, size);
- }
-
-});/*
----
-
-script: Element.Pin.js
-
-description: Extends the Element native object to include the pin method useful for fixed positioning for elements.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Dimensions
-- core:1.2.4/Element.Style
-- /MooTools.More
-
-provides: [Element.Pin]
-
-...
-*/
-
-(function(){
- var supportsPositionFixed = false;
- window.addEvent('domready', function(){
- var test = new Element('div').setStyles({
- position: 'fixed',
- top: 0,
- right: 0
- }).inject(document.body);
- supportsPositionFixed = (test.offsetTop === 0);
- test.dispose();
- });
-
- Element.implement({
-
- pin: function(enable){
- if (this.getStyle('display') == 'none') return null;
-
- var p,
- scroll = window.getScroll();
- if (enable !== false){
- p = this.getPosition();
- if (!this.retrieve('pinned')){
- var pos = {
- top: p.y - scroll.y,
- left: p.x - scroll.x
- };
- if (supportsPositionFixed){
- this.setStyle('position', 'fixed').setStyles(pos);
- } else {
- this.store('pinnedByJS', true);
- this.setStyles({
- position: 'absolute',
- top: p.y,
- left: p.x
- }).addClass('isPinned');
- this.store('scrollFixer', (function(){
- if (this.retrieve('pinned'))
- var scroll = window.getScroll();
- this.setStyles({
- top: pos.top.toInt() + scroll.y,
- left: pos.left.toInt() + scroll.x
- });
- }).bind(this));
- window.addEvent('scroll', this.retrieve('scrollFixer'));
- }
- this.store('pinned', true);
- }
- } else {
- var op;
- if (!Browser.Engine.trident){
- var parent = this.getParent();
- op = (parent.getComputedStyle('position') != 'static' ? parent : parent.getOffsetParent());
- }
- p = this.getPosition(op);
- this.store('pinned', false);
- var reposition;
- if (supportsPositionFixed && !this.retrieve('pinnedByJS')){
- reposition = {
- top: p.y + scroll.y,
- left: p.x + scroll.x
- };
- } else {
- this.store('pinnedByJS', false);
- window.removeEvent('scroll', this.retrieve('scrollFixer'));
- reposition = {
- top: p.y,
- left: p.x
- };
- }
- this.setStyles($merge(reposition, {position: 'absolute'})).removeClass('isPinned');
- }
- return this;
- },
-
- unpin: function(){
- return this.pin(false);
- },
-
- togglepin: function(){
- this.pin(!this.retrieve('pinned'));
- }
-
- });
-
-})();/*
----
-
-script: Element.Position.js
-
-description: Extends the Element native object to include methods useful positioning elements relative to others.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element.Dimensions
-- /Element.Measure
-
-provides: [Elements.Position]
-
-...
-*/
-
-(function(){
-
-var original = Element.prototype.position;
-
-Element.implement({
-
- position: function(options){
- //call original position if the options are x/y values
- if (options && ($defined(options.x) || $defined(options.y))) return original ? original.apply(this, arguments) : this;
- $each(options||{}, function(v, k){ if (!$defined(v)) delete options[k]; });
- options = $merge({
- // minimum: { x: 0, y: 0 },
- // maximum: { x: 0, y: 0},
- relativeTo: document.body,
- position: {
- x: 'center', //left, center, right
- y: 'center' //top, center, bottom
- },
- edge: false,
- offset: {x: 0, y: 0},
- returnPos: false,
- relFixedPosition: false,
- ignoreMargins: false,
- ignoreScroll: false,
- allowNegative: false
- }, options);
- //compute the offset of the parent positioned element if this element is in one
- var parentOffset = {x: 0, y: 0},
- parentPositioned = false;
- /* dollar around getOffsetParent should not be necessary, but as it does not return
- * a mootools extended element in IE, an error occurs on the call to expose. See:
- * http://mootools.lighthouseapp.com/projects/2706/tickets/333-element-getoffsetparent-inconsistency-between-ie-and-other-browsers */
- var offsetParent = this.measure(function(){
- return document.id(this.getOffsetParent());
- });
- if (offsetParent && offsetParent != this.getDocument().body){
- parentOffset = offsetParent.measure(function(){
- return this.getPosition();
- });
- parentPositioned = offsetParent != document.id(options.relativeTo);
- options.offset.x = options.offset.x - parentOffset.x;
- options.offset.y = options.offset.y - parentOffset.y;
- }
- //upperRight, bottomRight, centerRight, upperLeft, bottomLeft, centerLeft
- //topRight, topLeft, centerTop, centerBottom, center
- var fixValue = function(option){
- if ($type(option) != 'string') return option;
- option = option.toLowerCase();
- var val = {};
- if (option.test('left')) val.x = 'left';
- else if (option.test('right')) val.x = 'right';
- else val.x = 'center';
- if (option.test('upper') || option.test('top')) val.y = 'top';
- else if (option.test('bottom')) val.y = 'bottom';
- else val.y = 'center';
- return val;
- };
- options.edge = fixValue(options.edge);
- options.position = fixValue(options.position);
- if (!options.edge){
- if (options.position.x == 'center' && options.position.y == 'center') options.edge = {x:'center', y:'center'};
- else options.edge = {x:'left', y:'top'};
- }
-
- this.setStyle('position', 'absolute');
- var rel = document.id(options.relativeTo) || document.body,
- calc = rel == document.body ? window.getScroll() : rel.getPosition(),
- top = calc.y, left = calc.x;
-
- var scrolls = rel.getScrolls();
- top += scrolls.y;
- left += scrolls.x;
-
- var dim = this.getDimensions({computeSize: true, styles:['padding', 'border','margin']});
- var pos = {},
- prefY = options.offset.y,
- prefX = options.offset.x,
- winSize = window.getSize();
- switch(options.position.x){
- case 'left':
- pos.x = left + prefX;
- break;
- case 'right':
- pos.x = left + prefX + rel.offsetWidth;
- break;
- default: //center
- pos.x = left + ((rel == document.body ? winSize.x : rel.offsetWidth)/2) + prefX;
- break;
- }
- switch(options.position.y){
- case 'top':
- pos.y = top + prefY;
- break;
- case 'bottom':
- pos.y = top + prefY + rel.offsetHeight;
- break;
- default: //center
- pos.y = top + ((rel == document.body ? winSize.y : rel.offsetHeight)/2) + prefY;
- break;
- }
- if (options.edge){
- var edgeOffset = {};
-
- switch(options.edge.x){
- case 'left':
- edgeOffset.x = 0;
- break;
- case 'right':
- edgeOffset.x = -dim.x-dim.computedRight-dim.computedLeft;
- break;
- default: //center
- edgeOffset.x = -(dim.totalWidth/2);
- break;
- }
- switch(options.edge.y){
- case 'top':
- edgeOffset.y = 0;
- break;
- case 'bottom':
- edgeOffset.y = -dim.y-dim.computedTop-dim.computedBottom;
- break;
- default: //center
- edgeOffset.y = -(dim.totalHeight/2);
- break;
- }
- pos.x += edgeOffset.x;
- pos.y += edgeOffset.y;
- }
- pos = {
- left: ((pos.x >= 0 || parentPositioned || options.allowNegative) ? pos.x : 0).toInt(),
- top: ((pos.y >= 0 || parentPositioned || options.allowNegative) ? pos.y : 0).toInt()
- };
- var xy = {left: 'x', top: 'y'};
- ['minimum', 'maximum'].each(function(minmax) {
- ['left', 'top'].each(function(lr) {
- var val = options[minmax] ? options[minmax][xy[lr]] : null;
- if (val != null && pos[lr] < val) pos[lr] = val;
- });
- });
- if (rel.getStyle('position') == 'fixed' || options.relFixedPosition){
- var winScroll = window.getScroll();
- pos.top+= winScroll.y;
- pos.left+= winScroll.x;
- }
- if (options.ignoreScroll) {
- var relScroll = rel.getScroll();
- pos.top-= relScroll.y;
- pos.left-= relScroll.x;
- }
- if (options.ignoreMargins) {
- pos.left += (
- options.edge.x == 'right' ? dim['margin-right'] :
- options.edge.x == 'center' ? -dim['margin-left'] + ((dim['margin-right'] + dim['margin-left'])/2) :
- - dim['margin-left']
- );
- pos.top += (
- options.edge.y == 'bottom' ? dim['margin-bottom'] :
- options.edge.y == 'center' ? -dim['margin-top'] + ((dim['margin-bottom'] + dim['margin-top'])/2) :
- - dim['margin-top']
- );
- }
- pos.left = Math.ceil(pos.left);
- pos.top = Math.ceil(pos.top);
- if (options.returnPos) return pos;
- else this.setStyles(pos);
- return this;
- }
-
-});
-
-})();/*
----
-
-script: Element.Shortcuts.js
-
-description: Extends the Element native object to include some shortcut methods.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element.Style
-- /MooTools.More
-
-provides: [Element.Shortcuts]
-
-...
-*/
-
-Element.implement({
-
- isDisplayed: function(){
- return this.getStyle('display') != 'none';
- },
-
- isVisible: function(){
- var w = this.offsetWidth,
- h = this.offsetHeight;
- return (w == 0 && h == 0) ? false : (w > 0 && h > 0) ? true : this.isDisplayed();
- },
-
- toggle: function(){
- return this[this.isDisplayed() ? 'hide' : 'show']();
- },
-
- hide: function(){
- var d;
- try {
- // IE fails here if the element is not in the dom
- if ((d = this.getStyle('display')) == 'none') d = null;
- } catch(e){}
-
- return this.store('originalDisplay', d || 'block').setStyle('display', 'none');
- },
-
- show: function(display){
- return this.setStyle('display', display || this.retrieve('originalDisplay') || 'block');
- },
-
- swapClass: function(remove, add){
- return this.removeClass(remove).addClass(add);
- }
-
-});
-/*
----
-
-script: IframeShim.js
-
-description: Defines IframeShim, a class for obscuring select lists and flash objects in IE.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Style
-- core:1.2.4/Options Events
-- /Element.Position
-- /Class.Occlude
-
-provides: [IframeShim]
-
-...
-*/
-
-var IframeShim = new Class({
-
- Implements: [Options, Events, Class.Occlude],
-
- options: {
- className: 'iframeShim',
- src: 'javascript:false;document.write("");',
- display: false,
- zIndex: null,
- margin: 0,
- offset: {x: 0, y: 0},
- browsers: (Browser.Engine.trident4 || (Browser.Engine.gecko && !Browser.Engine.gecko19 && Browser.Platform.mac))
- },
-
- property: 'IframeShim',
-
- initialize: function(element, options){
- this.element = document.id(element);
- if (this.occlude()) return this.occluded;
- this.setOptions(options);
- this.makeShim();
- return this;
- },
-
- makeShim: function(){
- if(this.options.browsers){
- var zIndex = this.element.getStyle('zIndex').toInt();
-
- if (!zIndex){
- zIndex = 1;
- var pos = this.element.getStyle('position');
- if (pos == 'static' || !pos) this.element.setStyle('position', 'relative');
- this.element.setStyle('zIndex', zIndex);
- }
- zIndex = ($chk(this.options.zIndex) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1;
- if (zIndex < 0) zIndex = 1;
- this.shim = new Element('iframe', {
- src: this.options.src,
- scrolling: 'no',
- frameborder: 0,
- styles: {
- zIndex: zIndex,
- position: 'absolute',
- border: 'none',
- filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'
- },
- 'class': this.options.className
- }).store('IframeShim', this);
- var inject = (function(){
- this.shim.inject(this.element, 'after');
- this[this.options.display ? 'show' : 'hide']();
- this.fireEvent('inject');
- }).bind(this);
- if (IframeShim.ready) window.addEvent('load', inject);
- else inject();
- } else {
- this.position = this.hide = this.show = this.dispose = $lambda(this);
- }
- },
-
- position: function(){
- if (!IframeShim.ready || !this.shim) return this;
- var size = this.element.measure(function(){
- return this.getSize();
- });
- if (this.options.margin != undefined){
- size.x = size.x - (this.options.margin * 2);
- size.y = size.y - (this.options.margin * 2);
- this.options.offset.x += this.options.margin;
- this.options.offset.y += this.options.margin;
- }
- this.shim.set({width: size.x, height: size.y}).position({
- relativeTo: this.element,
- offset: this.options.offset
- });
- return this;
- },
-
- hide: function(){
- if (this.shim) this.shim.setStyle('display', 'none');
- return this;
- },
-
- show: function(){
- if (this.shim) this.shim.setStyle('display', 'block');
- return this.position();
- },
-
- dispose: function(){
- if (this.shim) this.shim.dispose();
- return this;
- },
-
- destroy: function(){
- if (this.shim) this.shim.destroy();
- return this;
- }
-
-});
-
-window.addEvent('load', function(){
- IframeShim.ready = true;
-});/*
----
-
-script: Mask.js
-
-description: Creates a mask element to cover another.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- core:1.2.4/Element.Event
-- /Class.Binds
-- /Element.Position
-- /IframeShim
-
-provides: [Mask]
-
-...
-*/
-
-var Mask = new Class({
-
- Implements: [Options, Events],
-
- Binds: ['resize'],
-
- options: {
- // onShow: $empty,
- // onHide: $empty,
- // onDestroy: $empty,
- // onClick: $empty,
- //inject: {
- // where: 'after',
- // target: null,
- //},
- // hideOnClick: false,
- // id: null,
- // destroyOnHide: false,
- style: {},
- 'class': 'mask',
- maskMargins: false,
- useIframeShim: true
- },
-
- initialize: function(target, options){
- this.target = document.id(target) || document.body;
- this.target.store('mask', this);
- this.setOptions(options);
- this.render();
- this.inject();
- },
-
- render: function() {
- this.element = new Element('div', {
- 'class': this.options['class'],
- id: this.options.id || 'mask-' + $time(),
- styles: $merge(this.options.style, {
- display: 'none'
- }),
- events: {
- click: function(){
- this.fireEvent('click');
- if (this.options.hideOnClick) this.hide();
- }.bind(this)
- }
- });
- this.hidden = true;
- },
-
- toElement: function(){
- return this.element;
- },
-
- inject: function(target, where){
- where = where || this.options.inject ? this.options.inject.where : '' || this.target == document.body ? 'inside' : 'after';
- target = target || this.options.inject ? this.options.inject.target : '' || this.target;
- this.element.inject(target, where);
- if (this.options.useIframeShim) {
- this.shim = new IframeShim(this.element);
- this.addEvents({
- show: this.shim.show.bind(this.shim),
- hide: this.shim.hide.bind(this.shim),
- destroy: this.shim.destroy.bind(this.shim)
- });
- }
- },
-
- position: function(){
- this.resize(this.options.width, this.options.height);
- this.element.position({
- relativeTo: this.target,
- position: 'topLeft',
- ignoreMargins: !this.options.maskMargins,
- ignoreScroll: this.target == document.body
- });
- return this;
- },
-
- resize: function(x, y){
- var opt = {
- styles: ['padding', 'border']
- };
- if (this.options.maskMargins) opt.styles.push('margin');
- var dim = this.target.getComputedSize(opt);
- if (this.target == document.body) {
- var win = window.getSize();
- if (dim.totalHeight < win.y) dim.totalHeight = win.y;
- if (dim.totalWidth < win.x) dim.totalWidth = win.x;
- }
- this.element.setStyles({
- width: $pick(x, dim.totalWidth, dim.x),
- height: $pick(y, dim.totalHeight, dim.y)
- });
- return this;
- },
-
- show: function(){
- if (!this.hidden) return this;
- this.target.addEvent('resize', this.resize);
- if (this.target != document.body) document.id(document.body).addEvent('resize', this.resize);
- this.position();
- this.showMask.apply(this, arguments);
- return this;
- },
-
- showMask: function(){
- this.element.setStyle('display', 'block');
- this.hidden = false;
- this.fireEvent('show');
- },
-
- hide: function(){
- if (this.hidden) return this;
- this.target.removeEvent('resize', this.resize);
- this.hideMask.apply(this, arguments);
- if (this.options.destroyOnHide) return this.destroy();
- return this;
- },
-
- hideMask: function(){
- this.element.setStyle('display', 'none');
- this.hidden = true;
- this.fireEvent('hide');
- },
-
- toggle: function(){
- this[this.hidden ? 'show' : 'hide']();
- },
-
- destroy: function(){
- this.hide();
- this.element.destroy();
- this.fireEvent('destroy');
- this.target.eliminate('mask');
- }
-
-});
-
-Element.Properties.mask = {
-
- set: function(options){
- var mask = this.retrieve('mask');
- return this.eliminate('mask').store('mask:options', options);
- },
-
- get: function(options){
- if (options || !this.retrieve('mask')){
- if (this.retrieve('mask')) this.retrieve('mask').destroy();
- if (options || !this.retrieve('mask:options')) this.set('mask', options);
- this.store('mask', new Mask(this, this.retrieve('mask:options')));
- }
- return this.retrieve('mask');
- }
-
-};
-
-Element.implement({
-
- mask: function(options){
- this.get('mask', options).show();
- return this;
- },
-
- unmask: function(){
- this.get('mask').hide();
- return this;
- }
-
-});/*
----
-
-script: Spinner.js
-
-description: Adds a semi-transparent overlay over a dom element with a spinnin ajax icon.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Fx.Tween
-- /Class.refactor
-- /Mask
-
-provides: [Spinner]
-
-...
-*/
-
-var Spinner = new Class({
-
- Extends: Mask,
-
- options: {
- /*message: false,*/
- 'class':'spinner',
- containerPosition: {},
- content: {
- 'class':'spinner-content'
- },
- messageContainer: {
- 'class':'spinner-msg'
- },
- img: {
- 'class':'spinner-img'
- },
- fxOptions: {
- link: 'chain'
- }
- },
-
- initialize: function(){
- this.parent.apply(this, arguments);
- this.target.store('spinner', this);
-
- //add this to events for when noFx is true; parent methods handle hide/show
- var deactivate = function(){ this.active = false; }.bind(this);
- this.addEvents({
- hide: deactivate,
- show: deactivate
- });
- },
-
- render: function(){
- this.parent();
- this.element.set('id', this.options.id || 'spinner-'+$time());
- this.content = document.id(this.options.content) || new Element('div', this.options.content);
- this.content.inject(this.element);
- if (this.options.message) {
- this.msg = document.id(this.options.message) || new Element('p', this.options.messageContainer).appendText(this.options.message);
- this.msg.inject(this.content);
- }
- if (this.options.img) {
- this.img = document.id(this.options.img) || new Element('div', this.options.img);
- this.img.inject(this.content);
- }
- this.element.set('tween', this.options.fxOptions);
- },
-
- show: function(noFx){
- if (this.active) return this.chain(this.show.bind(this));
- if (!this.hidden) {
- this.callChain.delay(20, this);
- return this;
- }
- this.active = true;
- return this.parent(noFx);
- },
-
- showMask: function(noFx){
- var pos = function(){
- this.content.position($merge({
- relativeTo: this.element
- }, this.options.containerPosition));
- }.bind(this);
- if (noFx) {
- this.parent();
- pos();
- } else {
- this.element.setStyles({
- display: 'block',
- opacity: 0
- }).tween('opacity', this.options.style.opacity || 0.9);
- pos();
- this.hidden = false;
- this.fireEvent('show');
- this.callChain();
- }
- },
-
- hide: function(noFx){
- if (this.active) return this.chain(this.hide.bind(this));
- if (this.hidden) {
- this.callChain.delay(20, this);
- return this;
- }
- this.active = true;
- return this.parent();
- },
-
- hideMask: function(noFx){
- if (noFx) return this.parent();
- this.element.tween('opacity', 0).get('tween').chain(function(){
- this.element.setStyle('display', 'none');
- this.hidden = true;
- this.fireEvent('hide');
- this.callChain();
- }.bind(this));
- },
-
- destroy: function(){
- this.content.destroy();
- this.parent();
- this.target.eliminate('spinner');
- }
-
-});
-
-Spinner.implement(new Chain);
-
-if (window.Request) {
- Request = Class.refactor(Request, {
- options: {
- useSpinner: false,
- spinnerOptions: {},
- spinnerTarget: false
- },
- initialize: function(options){
- this._send = this.send;
- this.send = function(options){
- if (this.spinner) this.spinner.chain(this._send.bind(this, options)).show();
- else this._send(options);
- return this;
- };
- this.previous(options);
- var update = document.id(this.options.spinnerTarget) || document.id(this.options.update);
- if (this.options.useSpinner && update) {
- this.spinner = update.get('spinner', this.options.spinnerOptions);
- ['onComplete', 'onException', 'onCancel'].each(function(event){
- this.addEvent(event, this.spinner.hide.bind(this.spinner));
- }, this);
- }
- }
- });
-}
-
-Element.Properties.spinner = {
-
- set: function(options){
- var spinner = this.retrieve('spinner');
- return this.eliminate('spinner').store('spinner:options', options);
- },
-
- get: function(options){
- if (options || !this.retrieve('spinner')){
- if (this.retrieve('spinner')) this.retrieve('spinner').destroy();
- if (options || !this.retrieve('spinner:options')) this.set('spinner', options);
- new Spinner(this, this.retrieve('spinner:options'));
- }
- return this.retrieve('spinner');
- }
-
-};
-
-Element.implement({
-
- spin: function(options){
- this.get('spinner', options).show();
- return this;
- },
-
- unspin: function(){
- var opt = Array.link(arguments, {options: Object.type, callback: Function.type});
- this.get('spinner', opt.options).hide(opt.callback);
- return this;
- }
-
-});/*
----
-
-script: Form.Request.js
-
-description: Handles the basic functionality of submitting a form and updating a dom element with the result.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element.Event
-- core:1.2.4/Request.HTML
-- /Class.Binds
-- /Class.Occlude
-- /Spinner
-- /String.QueryString
-
-provides: [Form.Request]
-
-...
-*/
-
-if (!window.Form) window.Form = {};
-
-(function(){
-
- Form.Request = new Class({
-
- Binds: ['onSubmit', 'onFormValidate'],
-
- Implements: [Options, Events, Class.Occlude],
-
- options: {
- //onFailure: $empty,
- //onSuccess: #empty, //aliased to onComplete,
- //onSend: $empty
- requestOptions: {
- evalScripts: true,
- useSpinner: true,
- emulation: false,
- link: 'ignore'
- },
- extraData: {},
- resetForm: true
- },
-
- property: 'form.request',
-
- initialize: function(form, update, options) {
- this.element = document.id(form);
- if (this.occlude()) return this.occluded;
- this.update = document.id(update);
- this.setOptions(options);
- this.makeRequest();
- if (this.options.resetForm) {
- this.request.addEvent('success', function(){
- $try(function(){ this.element.reset(); }.bind(this));
- if (window.OverText) OverText.update();
- }.bind(this));
- }
- this.attach();
- },
-
- toElement: function() {
- return this.element;
- },
-
- makeRequest: function(){
- this.request = new Request.HTML($merge({
- url: this.element.get('action'),
- update: this.update,
- emulation: false,
- spinnerTarget: this.element,
- method: this.element.get('method') || 'post'
- }, this.options.requestOptions)).addEvents({
- success: function(text, xml){
- ['success', 'complete'].each(function(evt){
- this.fireEvent(evt, [this.update, text, xml]);
- }, this);
- }.bind(this),
- failure: function(xhr){
- this.fireEvent('failure', xhr);
- }.bind(this),
- exception: function(){
- this.fireEvent('failure', xhr);
- }.bind(this)
- });
- },
-
- attach: function(attach){
- attach = $pick(attach, true);
- method = attach ? 'addEvent' : 'removeEvent';
-
- var fv = this.element.retrieve('validator');
- if (fv) fv[method]('onFormValidate', this.onFormValidate);
- if (!fv || !attach) this.element[method]('submit', this.onSubmit);
- },
-
- detach: function(){
- this.attach(false);
- },
-
- //public method
- enable: function(){
- this.attach();
- },
-
- //public method
- disable: function(){
- this.detach();
- },
-
- onFormValidate: function(valid, form, e) {
- if (valid || !fv.options.stopOnFailure) {
- if (e && e.stop) e.stop();
- this.send();
- }
- },
-
- onSubmit: function(e){
- if (this.element.retrieve('validator')) {
- //form validator was created after Form.Request
- this.detach();
- this.addFormEvent();
- return;
- }
- e.stop();
- this.send();
- },
-
- send: function(){
- var str = this.element.toQueryString().trim();
- var data = $H(this.options.extraData).toQueryString();
- if (str) str += "&" + data;
- else str = data;
- this.fireEvent('send', [this.element, str]);
- this.request.send({data: str});
- return this;
- }
-
- });
-
- Element.Properties.formRequest = {
-
- set: function(){
- var opt = Array.link(arguments, {options: Object.type, update: Element.type, updateId: String.type});
- var update = opt.update || opt.updateId;
- var updater = this.retrieve('form.request');
- if (update) {
- if (updater) updater.update = document.id(update);
- this.store('form.request:update', update);
- }
- if (opt.options) {
- if (updater) updater.setOptions(opt.options);
- this.store('form.request:options', opt.options);
- }
- return this;
- },
-
- get: function(){
- var opt = Array.link(arguments, {options: Object.type, update: Element.type, updateId: String.type});
- var update = opt.update || opt.updateId;
- if (opt.options || update || !this.retrieve('form.request')){
- if (opt.options || !this.retrieve('form.request:options')) this.set('form.request', opt.options);
- if (update) this.set('form.request', update);
- this.store('form.request', new Form.Request(this, this.retrieve('form.request:update'), this.retrieve('form.request:options')));
- }
- return this.retrieve('form.request');
- }
-
- };
-
- Element.implement({
-
- formUpdate: function(update, options){
- this.get('form.request', update, options).send();
- return this;
- }
-
- });
-
-})();/*
----
-
-script: Fx.Reveal.js
-
-description: Defines Fx.Reveal, a class that shows and hides elements with a transition.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Fx.Morph
-- /Element.Shortcuts
-- /Element.Measure
-
-provides: [Fx.Reveal]
-
-...
-*/
-
-Fx.Reveal = new Class({
-
- Extends: Fx.Morph,
-
- options: {/*
- onShow: $empty(thisElement),
- onHide: $empty(thisElement),
- onComplete: $empty(thisElement),
- heightOverride: null,
- widthOverride: null, */
- link: 'cancel',
- styles: ['padding', 'border', 'margin'],
- transitionOpacity: !Browser.Engine.trident4,
- mode: 'vertical',
- display: 'block',
- hideInputs: Browser.Engine.trident ? 'select, input, textarea, object, embed' : false
- },
-
- dissolve: function(){
- try {
- if (!this.hiding && !this.showing){
- if (this.element.getStyle('display') != 'none'){
- this.hiding = true;
- this.showing = false;
- this.hidden = true;
- var startStyles = this.element.getComputedSize({
- styles: this.options.styles,
- mode: this.options.mode
- });
- var setToAuto = (this.element.style.height === ''||this.element.style.height == 'auto');
- this.element.setStyle('display', 'block');
- if (this.options.transitionOpacity) startStyles.opacity = 1;
- var zero = {};
- $each(startStyles, function(style, name){
- zero[name] = [style, 0];
- }, this);
- var overflowBefore = this.element.getStyle('overflow');
- this.element.setStyle('overflow', 'hidden');
- var hideThese = this.options.hideInputs ? this.element.getElements(this.options.hideInputs) : null;
- this.$chain.unshift(function(){
- if (this.hidden){
- this.hiding = false;
- $each(startStyles, function(style, name){
- startStyles[name] = style;
- }, this);
- this.element.setStyles($merge({display: 'none', overflow: overflowBefore}, startStyles));
- if (setToAuto){
- if (['vertical', 'both'].contains(this.options.mode)) this.element.style.height = '';
- if (['width', 'both'].contains(this.options.mode)) this.element.style.width = '';
- }
- if (hideThese) hideThese.setStyle('visibility', 'visible');
- }
- this.fireEvent('hide', this.element);
- this.callChain();
- }.bind(this));
- if (hideThese) hideThese.setStyle('visibility', 'hidden');
- this.start(zero);
- } else {
- this.callChain.delay(10, this);
- this.fireEvent('complete', this.element);
- this.fireEvent('hide', this.element);
- }
- } else if (this.options.link == 'chain'){
- this.chain(this.dissolve.bind(this));
- } else if (this.options.link == 'cancel' && !this.hiding){
- this.cancel();
- this.dissolve();
- }
- } catch(e){
- this.hiding = false;
- this.element.setStyle('display', 'none');
- this.callChain.delay(10, this);
- this.fireEvent('complete', this.element);
- this.fireEvent('hide', this.element);
- }
- return this;
- },
-
- reveal: function(){
- try {
- if (!this.showing && !this.hiding){
- if (this.element.getStyle('display') == 'none' ||
- this.element.getStyle('visiblity') == 'hidden' ||
- this.element.getStyle('opacity') == 0){
- this.showing = true;
- this.hiding = this.hidden = false;
- var setToAuto, startStyles;
- //toggle display, but hide it
- this.element.measure(function(){
- setToAuto = (this.element.style.height === '' || this.element.style.height == 'auto');
- //create the styles for the opened/visible state
- startStyles = this.element.getComputedSize({
- styles: this.options.styles,
- mode: this.options.mode
- });
- }.bind(this));
- $each(startStyles, function(style, name){
- startStyles[name] = style;
- });
- //if we're overridding height/width
- if ($chk(this.options.heightOverride)) startStyles.height = this.options.heightOverride.toInt();
- if ($chk(this.options.widthOverride)) startStyles.width = this.options.widthOverride.toInt();
- if (this.options.transitionOpacity) {
- this.element.setStyle('opacity', 0);
- startStyles.opacity = 1;
- }
- //create the zero state for the beginning of the transition
- var zero = {
- height: 0,
- display: this.options.display
- };
- $each(startStyles, function(style, name){ zero[name] = 0; });
- var overflowBefore = this.element.getStyle('overflow');
- //set to zero
- this.element.setStyles($merge(zero, {overflow: 'hidden'}));
- //hide inputs
- var hideThese = this.options.hideInputs ? this.element.getElements(this.options.hideInputs) : null;
- if (hideThese) hideThese.setStyle('visibility', 'hidden');
- //start the effect
- this.start(startStyles);
- this.$chain.unshift(function(){
- this.element.setStyle('overflow', overflowBefore);
- if (!this.options.heightOverride && setToAuto){
- if (['vertical', 'both'].contains(this.options.mode)) this.element.style.height = '';
- if (['width', 'both'].contains(this.options.mode)) this.element.style.width = '';
- }
- if (!this.hidden) this.showing = false;
- if (hideThese) hideThese.setStyle('visibility', 'visible');
- this.callChain();
- this.fireEvent('show', this.element);
- }.bind(this));
- } else {
- this.callChain();
- this.fireEvent('complete', this.element);
- this.fireEvent('show', this.element);
- }
- } else if (this.options.link == 'chain'){
- this.chain(this.reveal.bind(this));
- } else if (this.options.link == 'cancel' && !this.showing){
- this.cancel();
- this.reveal();
- }
- } catch(e){
- this.element.setStyles({
- display: this.options.display,
- visiblity: 'visible',
- opacity: 1
- });
- this.showing = false;
- this.callChain.delay(10, this);
- this.fireEvent('complete', this.element);
- this.fireEvent('show', this.element);
- }
- return this;
- },
-
- toggle: function(){
- if (this.element.getStyle('display') == 'none' ||
- this.element.getStyle('visiblity') == 'hidden' ||
- this.element.getStyle('opacity') == 0){
- this.reveal();
- } else {
- this.dissolve();
- }
- return this;
- },
-
- cancel: function(){
- this.parent.apply(this, arguments);
- this.hidding = false;
- this.showing = false;
- }
-
-});
-
-Element.Properties.reveal = {
-
- set: function(options){
- var reveal = this.retrieve('reveal');
- if (reveal) reveal.cancel();
- return this.eliminate('reveal').store('reveal:options', options);
- },
-
- get: function(options){
- if (options || !this.retrieve('reveal')){
- if (options || !this.retrieve('reveal:options')) this.set('reveal', options);
- this.store('reveal', new Fx.Reveal(this, this.retrieve('reveal:options')));
- }
- return this.retrieve('reveal');
- }
-
-};
-
-Element.Properties.dissolve = Element.Properties.reveal;
-
-Element.implement({
-
- reveal: function(options){
- this.get('reveal', options).reveal();
- return this;
- },
-
- dissolve: function(options){
- this.get('reveal', options).dissolve();
- return this;
- },
-
- nix: function(){
- var params = Array.link(arguments, {destroy: Boolean.type, options: Object.type});
- this.get('reveal', params.options).dissolve().chain(function(){
- this[params.destroy ? 'destroy' : 'dispose']();
- }.bind(this));
- return this;
- },
-
- wink: function(){
- var params = Array.link(arguments, {duration: Number.type, options: Object.type});
- var reveal = this.get('reveal', params.options);
- reveal.reveal().chain(function(){
- (function(){
- reveal.dissolve();
- }).delay(params.duration || 2000);
- });
- }
-
-
-});/*
----
-
-script: Form.Request.Append.js
-
-description: Handles the basic functionality of submitting a form and updating a dom element with the result. The result is appended to the DOM element instead of replacing its contents.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- /Form.Request
-- /Fx.Reveal
-- /Elements.from
-
-provides: [Form.Request.Append]
-
-...
-*/
-
-Form.Request.Append = new Class({
-
- Extends: Form.Request,
-
- options: {
- //onBeforeEffect: $empty,
- useReveal: true,
- revealOptions: {},
- inject: 'bottom'
- },
-
- makeRequest: function(){
- this.request = new Request.HTML($merge({
- url: this.element.get('action'),
- method: this.element.get('method') || 'post',
- spinnerTarget: this.element
- }, this.options.requestOptions, {
- evalScripts: false
- })
- ).addEvents({
- success: function(tree, elements, html, javascript){
- var container;
- var kids = Elements.from(html);
- if (kids.length == 1) {
- container = kids[0];
- } else {
- container = new Element('div', {
- styles: {
- display: 'none'
- }
- }).adopt(kids);
- }
- container.inject(this.update, this.options.inject);
- if (this.options.requestOptions.evalScripts) $exec(javascript);
- this.fireEvent('beforeEffect', container);
- var finish = function(){
- this.fireEvent('success', [container, this.update, tree, elements, html, javascript]);
- }.bind(this);
- if (this.options.useReveal) {
- container.get('reveal', this.options.revealOptions).chain(finish);
- container.reveal();
- } else {
- finish();
- }
- }.bind(this),
- failure: function(xhr){
- this.fireEvent('failure', xhr);
- }.bind(this)
- });
- }
-
-});/*
----
-
-script: Form.Validator.English.js
-
-description: Date messages for English.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.English]
-
-...
-*/
-
-MooTools.lang.set('en-US', 'Form.Validator', {
-
- required:'This field is required.',
- minLength:'Please enter at least {minLength} characters (you entered {length} characters).',
- maxLength:'Please enter no more than {maxLength} characters (you entered {length} characters).',
- integer:'Please enter an integer in this field. Numbers with decimals (e.g. 1.25) are not permitted.',
- numeric:'Please enter only numeric values in this field (i.e. "1" or "1.1" or "-1" or "-1.1").',
- digits:'Please use numbers and punctuation only in this field (for example, a phone number with dashes or dots is permitted).',
- alpha:'Please use letters only (a-z) with in this field. No spaces or other characters are allowed.',
- alphanum:'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.',
- dateSuchAs:'Please enter a valid date such as {date}',
- dateInFormatMDY:'Please enter a valid date such as MM/DD/YYYY (i.e. "12/31/1999")',
- email:'Please enter a valid email address. For example "fred at domain.com".',
- url:'Please enter a valid URL such as http://www.google.com.',
- currencyDollar:'Please enter a valid $ amount. For example $100.00 .',
- oneRequired:'Please enter something for at least one of these inputs.',
- errorPrefix: 'Error: ',
- warningPrefix: 'Warning: ',
-
- //Form.Validator.Extras
-
- noSpace: 'There can be no spaces in this input.',
- reqChkByNode: 'No items are selected.',
- requiredChk: 'This field is required.',
- reqChkByName: 'Please select a {label}.',
- match: 'This field needs to match the {matchName} field',
- startDate: 'the start date',
- endDate: 'the end date',
- currendDate: 'the current date',
- afterDate: 'The date should be the same or after {label}.',
- beforeDate: 'The date should be the same or before {label}.',
- startMonth: 'Please select a start month',
- sameMonth: 'These two dates must be in the same month - you must change one or the other.',
- creditcard: 'The credit card number entered is invalid. Please check the number and try again. {length} digits entered.'
-
-});/*
----
-
-script: Form.Validator.js
-
-description: A css-class based form validation system.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- core:1.2.4/Selectors
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Style
-- core:1.2.4/JSON
-- /Lang- /Class.Binds
-- /Date Element.Forms
-- /Form.Validator.English
-- /Element.Shortcuts
-
-provides: [Form.Validator, InputValidator, FormValidator.BaseValidators]
-
-...
-*/
-if (!window.Form) window.Form = {};
-
-var InputValidator = new Class({
-
- Implements: [Options],
-
- options: {
- errorMsg: 'Validation failed.',
- test: function(field){return true;}
- },
-
- initialize: function(className, options){
- this.setOptions(options);
- this.className = className;
- },
-
- test: function(field, props){
- if (document.id(field)) return this.options.test(document.id(field), props||this.getProps(field));
- else return false;
- },
-
- getError: function(field, props){
- var err = this.options.errorMsg;
- if ($type(err) == 'function') err = err(document.id(field), props||this.getProps(field));
- return err;
- },
-
- getProps: function(field){
- if (!document.id(field)) return {};
- return field.get('validatorProps');
- }
-
-});
-
-Element.Properties.validatorProps = {
-
- set: function(props){
- return this.eliminate('validatorProps').store('validatorProps', props);
- },
-
- get: function(props){
- if (props) this.set(props);
- if (this.retrieve('validatorProps')) return this.retrieve('validatorProps');
- if (this.getProperty('validatorProps')){
- try {
- this.store('validatorProps', JSON.decode(this.getProperty('validatorProps')));
- }catch(e){
- return {};
- }
- } else {
- var vals = this.get('class').split(' ').filter(function(cls){
- return cls.test(':');
- });
- if (!vals.length){
- this.store('validatorProps', {});
- } else {
- props = {};
- vals.each(function(cls){
- var split = cls.split(':');
- if (split[1]) {
- try {
- props[split[0]] = JSON.decode(split[1]);
- } catch(e) {}
- }
- });
- this.store('validatorProps', props);
- }
- }
- return this.retrieve('validatorProps');
- }
-
-};
-
-Form.Validator = new Class({
-
- Implements:[Options, Events],
-
- Binds: ['onSubmit'],
-
- options: {/*
- onFormValidate: $empty(isValid, form, event),
- onElementValidate: $empty(isValid, field, className, warn),
- onElementPass: $empty(field),
- onElementFail: $empty(field, validatorsFailed) */
- fieldSelectors: 'input, select, textarea',
- ignoreHidden: true,
- ignoreDisabled: true,
- useTitles: false,
- evaluateOnSubmit: true,
- evaluateFieldsOnBlur: true,
- evaluateFieldsOnChange: true,
- serial: true,
- stopOnFailure: true,
- warningPrefix: function(){
- return Form.Validator.getMsg('warningPrefix') || 'Warning: ';
- },
- errorPrefix: function(){
- return Form.Validator.getMsg('errorPrefix') || 'Error: ';
- }
- },
-
- initialize: function(form, options){
- this.setOptions(options);
- this.element = document.id(form);
- this.element.store('validator', this);
- this.warningPrefix = $lambda(this.options.warningPrefix)();
- this.errorPrefix = $lambda(this.options.errorPrefix)();
- if (this.options.evaluateOnSubmit) this.element.addEvent('submit', this.onSubmit);
- if (this.options.evaluateFieldsOnBlur || this.options.evaluateFieldsOnChange) this.watchFields(this.getFields());
- },
-
- toElement: function(){
- return this.element;
- },
-
- getFields: function(){
- return (this.fields = this.element.getElements(this.options.fieldSelectors));
- },
-
- watchFields: function(fields){
- fields.each(function(el){
- if (this.options.evaluateFieldsOnBlur)
- el.addEvent('blur', this.validationMonitor.pass([el, false], this));
- if (this.options.evaluateFieldsOnChange)
- el.addEvent('change', this.validationMonitor.pass([el, true], this));
- }, this);
- },
-
- validationMonitor: function(){
- $clear(this.timer);
- this.timer = this.validateField.delay(50, this, arguments);
- },
-
- onSubmit: function(event){
- if (!this.validate(event) && event) event.preventDefault();
- else this.reset();
- },
-
- reset: function(){
- this.getFields().each(this.resetField, this);
- return this;
- },
-
- validate: function(event){
- var result = this.getFields().map(function(field){
- return this.validateField(field, true);
- }, this).every(function(v){ return v;});
- this.fireEvent('formValidate', [result, this.element, event]);
- if (this.options.stopOnFailure && !result && event) event.preventDefault();
- return result;
- },
-
- validateField: function(field, force){
- if (this.paused) return true;
- field = document.id(field);
- var passed = !field.hasClass('validation-failed');
- var failed, warned;
- if (this.options.serial && !force){
- failed = this.element.getElement('.validation-failed');
- warned = this.element.getElement('.warning');
- }
- if (field && (!failed || force || field.hasClass('validation-failed') || (failed && !this.options.serial))){
- var validators = field.className.split(' ').some(function(cn){
- return this.getValidator(cn);
- }, this);
- var validatorsFailed = [];
- field.className.split(' ').each(function(className){
- if (className && !this.test(className, field)) validatorsFailed.include(className);
- }, this);
- passed = validatorsFailed.length === 0;
- if (validators && !field.hasClass('warnOnly')){
- if (passed){
- field.addClass('validation-passed').removeClass('validation-failed');
- this.fireEvent('elementPass', field);
- } else {
- field.addClass('validation-failed').removeClass('validation-passed');
- this.fireEvent('elementFail', [field, validatorsFailed]);
- }
- }
- if (!warned){
- var warnings = field.className.split(' ').some(function(cn){
- if (cn.test('^warn-') || field.hasClass('warnOnly'))
- return this.getValidator(cn.replace(/^warn-/,''));
- else return null;
- }, this);
- field.removeClass('warning');
- var warnResult = field.className.split(' ').map(function(cn){
- if (cn.test('^warn-') || field.hasClass('warnOnly'))
- return this.test(cn.replace(/^warn-/,''), field, true);
- else return null;
- }, this);
- }
- }
- return passed;
- },
-
- test: function(className, field, warn){
- field = document.id(field);
- if((this.options.ignoreHidden && !field.isVisible()) || (this.options.ignoreDisabled && field.get('disabled'))) return true;
- var validator = this.getValidator(className);
- if (field.hasClass('ignoreValidation')) return true;
- warn = $pick(warn, false);
- if (field.hasClass('warnOnly')) warn = true;
- var isValid = validator ? validator.test(field) : true;
- if (validator && field.isVisible()) this.fireEvent('elementValidate', [isValid, field, className, warn]);
- if (warn) return true;
- return isValid;
- },
-
- resetField: function(field){
- field = document.id(field);
- if (field){
- field.className.split(' ').each(function(className){
- if (className.test('^warn-')) className = className.replace(/^warn-/, '');
- field.removeClass('validation-failed');
- field.removeClass('warning');
- field.removeClass('validation-passed');
- }, this);
- }
- return this;
- },
-
- stop: function(){
- this.paused = true;
- return this;
- },
-
- start: function(){
- this.paused = false;
- return this;
- },
-
- ignoreField: function(field, warn){
- field = document.id(field);
- if (field){
- this.enforceField(field);
- if (warn) field.addClass('warnOnly');
- else field.addClass('ignoreValidation');
- }
- return this;
- },
-
- enforceField: function(field){
- field = document.id(field);
- if (field) field.removeClass('warnOnly').removeClass('ignoreValidation');
- return this;
- }
-
-});
-
-Form.Validator.getMsg = function(key){
- return MooTools.lang.get('Form.Validator', key);
-};
-
-Form.Validator.adders = {
-
- validators:{},
-
- add : function(className, options){
- this.validators[className] = new InputValidator(className, options);
- //if this is a class (this method is used by instances of Form.Validator and the Form.Validator namespace)
- //extend these validators into it
- //this allows validators to be global and/or per instance
- if (!this.initialize){
- this.implement({
- validators: this.validators
- });
- }
- },
-
- addAllThese : function(validators){
- $A(validators).each(function(validator){
- this.add(validator[0], validator[1]);
- }, this);
- },
-
- getValidator: function(className){
- return this.validators[className.split(':')[0]];
- }
-
-};
-
-$extend(Form.Validator, Form.Validator.adders);
-
-Form.Validator.implement(Form.Validator.adders);
-
-Form.Validator.add('IsEmpty', {
-
- errorMsg: false,
- test: function(element){
- if (element.type == 'select-one' || element.type == 'select')
- return !(element.selectedIndex >= 0 && element.options[element.selectedIndex].value != '');
- else
- return ((element.get('value') == null) || (element.get('value').length == 0));
- }
-
-});
-
-Form.Validator.addAllThese([
-
- ['required', {
- errorMsg: function(){
- return Form.Validator.getMsg('required');
- },
- test: function(element){
- return !Form.Validator.getValidator('IsEmpty').test(element);
- }
- }],
-
- ['minLength', {
- errorMsg: function(element, props){
- if ($type(props.minLength))
- return Form.Validator.getMsg('minLength').substitute({minLength:props.minLength,length:element.get('value').length });
- else return '';
- },
- test: function(element, props){
- if ($type(props.minLength)) return (element.get('value').length >= $pick(props.minLength, 0));
- else return true;
- }
- }],
-
- ['maxLength', {
- errorMsg: function(element, props){
- //props is {maxLength:10}
- if ($type(props.maxLength))
- return Form.Validator.getMsg('maxLength').substitute({maxLength:props.maxLength,length:element.get('value').length });
- else return '';
- },
- test: function(element, props){
- //if the value is <= than the maxLength value, element passes test
- return (element.get('value').length <= $pick(props.maxLength, 10000));
- }
- }],
-
- ['validate-integer', {
- errorMsg: Form.Validator.getMsg.pass('integer'),
- test: function(element){
- return Form.Validator.getValidator('IsEmpty').test(element) || (/^(-?[1-9]\d*|0)$/).test(element.get('value'));
- }
- }],
-
- ['validate-numeric', {
- errorMsg: Form.Validator.getMsg.pass('numeric'),
- test: function(element){
- return Form.Validator.getValidator('IsEmpty').test(element) ||
- (/^-?(?:0$0(?=\d*\.)|[1-9]|0)\d*(\.\d+)?$/).test(element.get('value'));
- }
- }],
-
- ['validate-digits', {
- errorMsg: Form.Validator.getMsg.pass('digits'),
- test: function(element){
- return Form.Validator.getValidator('IsEmpty').test(element) || (/^[\d() .:\-\+#]+$/.test(element.get('value')));
- }
- }],
-
- ['validate-alpha', {
- errorMsg: Form.Validator.getMsg.pass('alpha'),
- test: function(element){
- return Form.Validator.getValidator('IsEmpty').test(element) || (/^[a-zA-Z]+$/).test(element.get('value'));
- }
- }],
-
- ['validate-alphanum', {
- errorMsg: Form.Validator.getMsg.pass('alphanum'),
- test: function(element){
- return Form.Validator.getValidator('IsEmpty').test(element) || !(/\W/).test(element.get('value'));
- }
- }],
-
- ['validate-date', {
- errorMsg: function(element, props){
- if (Date.parse){
- var format = props.dateFormat || '%x';
- return Form.Validator.getMsg('dateSuchAs').substitute({date: new Date().format(format)});
- } else {
- return Form.Validator.getMsg('dateInFormatMDY');
- }
- },
- test: function(element, props){
- if (Form.Validator.getValidator('IsEmpty').test(element)) return true;
- var d;
- if (Date.parse){
- var format = props.dateFormat || '%x';
- d = Date.parse(element.get('value'));
- var formatted = d.format(format);
- if (formatted != 'invalid date') element.set('value', formatted);
- return !isNaN(d);
- } else {
- var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
- if (!regex.test(element.get('value'))) return false;
- d = new Date(element.get('value').replace(regex, '$1/$2/$3'));
- return (parseInt(RegExp.$1, 10) == (1 + d.getMonth())) &&
- (parseInt(RegExp.$2, 10) == d.getDate()) &&
- (parseInt(RegExp.$3, 10) == d.getFullYear());
- }
- }
- }],
-
- ['validate-email', {
- errorMsg: Form.Validator.getMsg.pass('email'),
- test: function(element){
- return Form.Validator.getValidator('IsEmpty').test(element) || (/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i).test(element.get('value'));
- }
- }],
-
- ['validate-url', {
- errorMsg: Form.Validator.getMsg.pass('url'),
- test: function(element){
- return Form.Validator.getValidator('IsEmpty').test(element) || (/^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i).test(element.get('value'));
- }
- }],
-
- ['validate-currency-dollar', {
- errorMsg: Form.Validator.getMsg.pass('currencyDollar'),
- test: function(element){
- // [$]1[##][,###]+[.##]
- // [$]1###+[.##]
- // [$]0.##
- // [$].##
- return Form.Validator.getValidator('IsEmpty').test(element) || (/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/).test(element.get('value'));
- }
- }],
-
- ['validate-one-required', {
- errorMsg: Form.Validator.getMsg.pass('oneRequired'),
- test: function(element, props){
- var p = document.id(props['validate-one-required']) || element.getParent();
- return p.getElements('input').some(function(el){
- if (['checkbox', 'radio'].contains(el.get('type'))) return el.get('checked');
- return el.get('value');
- });
- }
- }]
-
-]);
-
-Element.Properties.validator = {
-
- set: function(options){
- var validator = this.retrieve('validator');
- if (validator) validator.setOptions(options);
- return this.store('validator:options');
- },
-
- get: function(options){
- if (options || !this.retrieve('validator')){
- if (options || !this.retrieve('validator:options')) this.set('validator', options);
- this.store('validator', new Form.Validator(this, this.retrieve('validator:options')));
- }
- return this.retrieve('validator');
- }
-
-};
-
-Element.implement({
-
- validate: function(options){
- this.set('validator', options);
- return this.get('validator', options).validate();
- }
-
-});
-//legacy
-var FormValidator = Form.Validator;/*
----
-
-script: Form.Validator.Inline.js
-
-description: Extends Form.Validator to add inline messages.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- /Form.Validator
-
-provides: [Form.Validator.Inline]
-
-...
-*/
-
-Form.Validator.Inline = new Class({
-
- Extends: Form.Validator,
-
- options: {
- scrollToErrorsOnSubmit: true,
- scrollFxOptions: {
- transition: 'quad:out',
- offset: {
- y: -20
- }
- }
- },
-
- initialize: function(form, options){
- this.parent(form, options);
- this.addEvent('onElementValidate', function(isValid, field, className, warn){
- var validator = this.getValidator(className);
- if (!isValid && validator.getError(field)){
- if (warn) field.addClass('warning');
- var advice = this.makeAdvice(className, field, validator.getError(field), warn);
- this.insertAdvice(advice, field);
- this.showAdvice(className, field);
- } else {
- this.hideAdvice(className, field);
- }
- });
- },
-
- makeAdvice: function(className, field, error, warn){
- var errorMsg = (warn)?this.warningPrefix:this.errorPrefix;
- errorMsg += (this.options.useTitles) ? field.title || error:error;
- var cssClass = (warn) ? 'warning-advice' : 'validation-advice';
- var advice = this.getAdvice(className, field);
- if(advice) {
- advice = advice.clone(true, true).set('html', errorMsg).replaces(advice);
- } else {
- advice = new Element('div', {
- html: errorMsg,
- styles: { display: 'none' },
- id: 'advice-' + className + '-' + this.getFieldId(field)
- }).addClass(cssClass);
- }
- field.store('advice-' + className, advice);
- return advice;
- },
-
- getFieldId : function(field){
- return field.id ? field.id : field.id = 'input_' + field.name;
- },
-
- showAdvice: function(className, field){
- var advice = this.getAdvice(className, field);
- if (advice && !field.retrieve(this.getPropName(className))
- && (advice.getStyle('display') == 'none'
- || advice.getStyle('visiblity') == 'hidden'
- || advice.getStyle('opacity') == 0)){
- field.store(this.getPropName(className), true);
- if (advice.reveal) advice.reveal();
- else advice.setStyle('display', 'block');
- }
- },
-
- hideAdvice: function(className, field){
- var advice = this.getAdvice(className, field);
- if (advice && field.retrieve(this.getPropName(className))){
- field.store(this.getPropName(className), false);
- //if Fx.Reveal.js is present, transition the advice out
- if (advice.dissolve) advice.dissolve();
- else advice.setStyle('display', 'none');
- }
- },
-
- getPropName: function(className){
- return 'advice' + className;
- },
-
- resetField: function(field){
- field = document.id(field);
- if (!field) return this;
- this.parent(field);
- field.className.split(' ').each(function(className){
- this.hideAdvice(className, field);
- }, this);
- return this;
- },
-
- getAllAdviceMessages: function(field, force){
- var advice = [];
- if (field.hasClass('ignoreValidation') && !force) return advice;
- var validators = field.className.split(' ').some(function(cn){
- var warner = cn.test('^warn-') || field.hasClass('warnOnly');
- if (warner) cn = cn.replace(/^warn-/, '');
- var validator = this.getValidator(cn);
- if (!validator) return;
- advice.push({
- message: validator.getError(field),
- warnOnly: warner,
- passed: validator.test(),
- validator: validator
- });
- }, this);
- return advice;
- },
-
- getAdvice: function(className, field){
- return field.retrieve('advice-' + className);
- },
-
- insertAdvice: function(advice, field){
- //Check for error position prop
- var props = field.get('validatorProps');
- //Build advice
- if (!props.msgPos || !document.id(props.msgPos)){
- if(field.type.toLowerCase() == 'radio') field.getParent().adopt(advice);
- else advice.inject(document.id(field), 'after');
- } else {
- document.id(props.msgPos).grab(advice);
- }
- },
-
- validateField: function(field, force){
- var result = this.parent(field, force);
- if (this.options.scrollToErrorsOnSubmit && !result){
- var failed = document.id(this).getElement('.validation-failed');
- var par = document.id(this).getParent();
- while (par != document.body && par.getScrollSize().y == par.getSize().y){
- par = par.getParent();
- }
- var fx = par.retrieve('fvScroller');
- if (!fx && window.Fx && Fx.Scroll){
- fx = new Fx.Scroll(par, this.options.scrollFxOptions);
- par.store('fvScroller', fx);
- }
- if (failed){
- if (fx) fx.toElement(failed);
- else par.scrollTo(par.getScroll().x, failed.getPosition(par).y - 20);
- }
- }
- return result;
- }
-
-});
-/*
----
-
-script: Form.Validator.Extras.js
-
-description: Additional validators for the Form.Validator class.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- /Form.Validator
-
-provides: [Form.Validator.Extras]
-
-...
-*/
-Form.Validator.addAllThese([
-
- ['validate-enforce-oncheck', {
- test: function(element, props){
- if (element.checked){
- var fv = element.getParent('form').retrieve('validator');
- if (!fv) return true;
- (props.toEnforce || document.id(props.enforceChildrenOf).getElements('input, select, textarea')).map(function(item){
- fv.enforceField(item);
- });
- }
- return true;
- }
- }],
-
- ['validate-ignore-oncheck', {
- test: function(element, props){
- if (element.checked){
- var fv = element.getParent('form').retrieve('validator');
- if (!fv) return true;
- (props.toIgnore || document.id(props.ignoreChildrenOf).getElements('input, select, textarea')).each(function(item){
- fv.ignoreField(item);
- fv.resetField(item);
- });
- }
- return true;
- }
- }],
-
- ['validate-nospace', {
- errorMsg: function(){
- return Form.Validator.getMsg('noSpace');
- },
- test: function(element, props){
- return !element.get('value').test(/\s/);
- }
- }],
-
- ['validate-toggle-oncheck', {
- test: function(element, props){
- var fv = element.getParent('form').retrieve('validator');
- if (!fv) return true;
- var eleArr = props.toToggle || document.id(props.toToggleChildrenOf).getElements('input, select, textarea');
- if (!element.checked){
- eleArr.each(function(item){
- fv.ignoreField(item);
- fv.resetField(item);
- });
- } else {
- eleArr.each(function(item){
- fv.enforceField(item);
- });
- }
- return true;
- }
- }],
-
- ['validate-reqchk-bynode', {
- errorMsg: function(){
- return Form.Validator.getMsg('reqChkByNode');
- },
- test: function(element, props){
- return (document.id(props.nodeId).getElements(props.selector || 'input[type=checkbox], input[type=radio]')).some(function(item){
- return item.checked;
- });
- }
- }],
-
- ['validate-required-check', {
- errorMsg: function(element, props){
- return props.useTitle ? element.get('title') : Form.Validator.getMsg('requiredChk');
- },
- test: function(element, props){
- return !!element.checked;
- }
- }],
-
- ['validate-reqchk-byname', {
- errorMsg: function(element, props){
- return Form.Validator.getMsg('reqChkByName').substitute({label: props.label || element.get('type')});
- },
- test: function(element, props){
- var grpName = props.groupName || element.get('name');
- var oneCheckedItem = $$(document.getElementsByName(grpName)).some(function(item, index){
- return item.checked;
- });
- var fv = element.getParent('form').retrieve('validator');
- if (oneCheckedItem && fv) fv.resetField(element);
- return oneCheckedItem;
- }
- }],
-
- ['validate-match', {
- errorMsg: function(element, props){
- return Form.Validator.getMsg('match').substitute({matchName: props.matchName || document.id(props.matchInput).get('name')});
- },
- test: function(element, props){
- var eleVal = element.get('value');
- var matchVal = document.id(props.matchInput) && document.id(props.matchInput).get('value');
- return eleVal && matchVal ? eleVal == matchVal : true;
- }
- }],
-
- ['validate-after-date', {
- errorMsg: function(element, props){
- return Form.Validator.getMsg('afterDate').substitute({
- label: props.afterLabel || (props.afterElement ? Form.Validator.getMsg('startDate') : Form.Validator.getMsg('currentDate'))
- });
- },
- test: function(element, props){
- var start = document.id(props.afterElement) ? Date.parse(document.id(props.afterElement).get('value')) : new Date();
- var end = Date.parse(element.get('value'));
- return end && start ? end >= start : true;
- }
- }],
-
- ['validate-before-date', {
- errorMsg: function(element, props){
- return Form.Validator.getMsg('beforeDate').substitute({
- label: props.beforeLabel || (props.beforeElement ? Form.Validator.getMsg('endDate') : Form.Validator.getMsg('currentDate'))
- });
- },
- test: function(element, props){
- var start = Date.parse(element.get('value'));
- var end = document.id(props.beforeElement) ? Date.parse(document.id(props.beforeElement).get('value')) : new Date();
- return end && start ? end >= start : true;
- }
- }],
-
- ['validate-custom-required', {
- errorMsg: function(){
- return Form.Validator.getMsg('required');
- },
- test: function(element, props){
- return element.get('value') != props.emptyValue;
- }
- }],
-
- ['validate-same-month', {
- errorMsg: function(element, props){
- var startMo = document.id(props.sameMonthAs) && document.id(props.sameMonthAs).get('value');
- var eleVal = element.get('value');
- if (eleVal != '') return Form.Validator.getMsg(startMo ? 'sameMonth' : 'startMonth');
- },
- test: function(element, props){
- var d1 = Date.parse(element.get('value'));
- var d2 = Date.parse(document.id(props.sameMonthAs) && document.id(props.sameMonthAs).get('value'));
- return d1 && d2 ? d1.format('%B') == d2.format('%B') : true;
- }
- }],
-
-
- ['validate-cc-num', {
- errorMsg: function(element){
- var ccNum = element.get('value').ccNum.replace(/[^0-9]/g, '');
- return Form.Validator.getMsg('creditcard').substitute({length: ccNum.length});
- },
- test: function(element){
- // required is a different test
- if (Form.Validator.getValidator('IsEmpty').test(element)) { return true; }
-
- // Clean number value
- var ccNum = element.get('value');
- ccNum = ccNum.replace(/[^0-9]/g, '');
-
- var valid_type = false;
-
- if (ccNum.test(/^4[0-9]{12}([0-9]{3})?$/)) valid_type = 'Visa';
- else if (ccNum.test(/^5[1-5]([0-9]{14})$/)) valid_type = 'Master Card';
- else if (ccNum.test(/^3[47][0-9]{13}$/)) valid_type = 'American Express';
- else if (ccNum.test(/^6011[0-9]{12}$/)) valid_type = 'Discover';
-
- if (valid_type) {
- var sum = 0;
- var cur = 0;
-
- for(var i=ccNum.length-1; i>=0; --i) {
- cur = ccNum.charAt(i).toInt();
- if (cur == 0) { continue; }
-
- if ((ccNum.length-i) % 2 == 0) { cur += cur; }
- if (cur > 9) { cur = cur.toString().charAt(0).toInt() + cur.toString().charAt(1).toInt(); }
-
- sum += cur;
- }
- if ((sum % 10) == 0) { return true; }
- }
-
- var chunks = '';
- while (ccNum != '') {
- chunks += ' ' + ccNum.substr(0,4);
- ccNum = ccNum.substr(4);
- }
-
- element.getParent('form').retrieve('validator').ignoreField(element);
- element.set('value', chunks.clean());
- element.getParent('form').retrieve('validator').enforceField(element);
- return false;
- }
- }]
-
-
-]);/*
----
-
-script: OverText.js
-
-description: Shows text over an input that disappears when the user clicks into it. The text remains hidden if the user adds a value.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- core:1.2.4/Element.Event
-- /Class.Binds
-- /Class.Occlude
-- /Element.Position
-- /Element.Shortcuts
-
-provides: [OverText]
-
-...
-*/
-
-var OverText = new Class({
-
- Implements: [Options, Events, Class.Occlude],
-
- Binds: ['reposition', 'assert', 'focus', 'hide'],
-
- options: {/*
- textOverride: null,
- onFocus: $empty()
- onTextHide: $empty(textEl, inputEl),
- onTextShow: $empty(textEl, inputEl), */
- element: 'label',
- positionOptions: {
- position: 'upperLeft',
- edge: 'upperLeft',
- offset: {
- x: 4,
- y: 2
- }
- },
- poll: false,
- pollInterval: 250,
- wrap: false
- },
-
- property: 'OverText',
-
- initialize: function(element, options){
- this.element = document.id(element);
- if (this.occlude()) return this.occluded;
- this.setOptions(options);
- this.attach(this.element);
- OverText.instances.push(this);
- if (this.options.poll) this.poll();
- return this;
- },
-
- toElement: function(){
- return this.element;
- },
-
- attach: function(){
- var val = this.options.textOverride || this.element.get('alt') || this.element.get('title');
- if (!val) return;
- this.text = new Element(this.options.element, {
- 'class': 'overTxtLabel',
- styles: {
- lineHeight: 'normal',
- position: 'absolute',
- cursor: 'text'
- },
- html: val,
- events: {
- click: this.hide.pass(this.options.element == 'label', this)
- }
- }).inject(this.element, 'after');
- if (this.options.element == 'label') {
- if (!this.element.get('id')) this.element.set('id', 'input_' + new Date().getTime());
- this.text.set('for', this.element.get('id'));
- }
-
- if (this.options.wrap) {
- this.textHolder = new Element('div', {
- styles: {
- lineHeight: 'normal',
- position: 'relative'
- },
- 'class':'overTxtWrapper'
- }).adopt(this.text).inject(this.element, 'before');
- }
-
- this.element.addEvents({
- focus: this.focus,
- blur: this.assert,
- change: this.assert
- }).store('OverTextDiv', this.text);
- window.addEvent('resize', this.reposition.bind(this));
- this.assert(true);
- this.reposition();
- },
-
- wrap: function(){
- if (this.options.element == 'label') {
- if (!this.element.get('id')) this.element.set('id', 'input_' + new Date().getTime());
- this.text.set('for', this.element.get('id'));
- }
- },
-
- startPolling: function(){
- this.pollingPaused = false;
- return this.poll();
- },
-
- poll: function(stop){
- //start immediately
- //pause on focus
- //resumeon blur
- if (this.poller && !stop) return this;
- var test = function(){
- if (!this.pollingPaused) this.assert(true);
- }.bind(this);
- if (stop) $clear(this.poller);
- else this.poller = test.periodical(this.options.pollInterval, this);
- return this;
- },
-
- stopPolling: function(){
- this.pollingPaused = true;
- return this.poll(true);
- },
-
- focus: function(){
- if (this.text && (!this.text.isDisplayed() || this.element.get('disabled'))) return;
- this.hide();
- },
-
- hide: function(suppressFocus, force){
- if (this.text && (this.text.isDisplayed() && (!this.element.get('disabled') || force))){
- this.text.hide();
- this.fireEvent('textHide', [this.text, this.element]);
- this.pollingPaused = true;
- try {
- if (!suppressFocus) this.element.fireEvent('focus');
- this.element.focus();
- } catch(e){} //IE barfs if you call focus on hidden elements
- }
- return this;
- },
-
- show: function(){
- if (this.text && !this.text.isDisplayed()){
- this.text.show();
- this.reposition();
- this.fireEvent('textShow', [this.text, this.element]);
- this.pollingPaused = false;
- }
- return this;
- },
-
- assert: function(suppressFocus){
- this[this.test() ? 'show' : 'hide'](suppressFocus);
- },
-
- test: function(){
- var v = this.element.get('value');
- return !v;
- },
-
- reposition: function(){
- this.assert(true);
- if (!this.element.isVisible()) return this.stopPolling().hide();
- if (this.text && this.test()) this.text.position($merge(this.options.positionOptions, {relativeTo: this.element}));
- return this;
- }
-
-});
-
-OverText.instances = [];
-
-$extend(OverText, {
-
- each: function(fn) {
- return OverText.instances.map(function(ot, i){
- if (ot.element && ot.text) return fn.apply(OverText, [ot, i]);
- return null; //the input or the text was destroyed
- });
- },
-
- update: function(){
-
- return OverText.each(function(ot){
- return ot.reposition();
- });
-
- },
-
- hideAll: function(){
-
- return OverText.each(function(ot){
- return ot.hide(true, true);
- });
-
- },
-
- showAll: function(){
- return OverText.each(function(ot) {
- return ot.show();
- });
- }
-
-});
-
-if (window.Fx && Fx.Reveal) {
- Fx.Reveal.implement({
- hideInputs: Browser.Engine.trident ? 'select, input, textarea, object, embed, .overTxtLabel' : false
- });
-}/*
----
-
-script: Fx.Elements.js
-
-description: Effect to change any number of CSS properties of any number of Elements.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Fx.CSS
-- /MooTools.More
-
-provides: [Fx.Elements]
-
-...
-*/
-
-Fx.Elements = new Class({
-
- Extends: Fx.CSS,
-
- initialize: function(elements, options){
- this.elements = this.subject = $$(elements);
- this.parent(options);
- },
-
- compute: function(from, to, delta){
- var now = {};
- for (var i in from){
- var iFrom = from[i], iTo = to[i], iNow = now[i] = {};
- for (var p in iFrom) iNow[p] = this.parent(iFrom[p], iTo[p], delta);
- }
- return now;
- },
-
- set: function(now){
- for (var i in now){
- var iNow = now[i];
- for (var p in iNow) this.render(this.elements[i], p, iNow[p], this.options.unit);
- }
- return this;
- },
-
- start: function(obj){
- if (!this.check(obj)) return this;
- var from = {}, to = {};
- for (var i in obj){
- var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {};
- for (var p in iProps){
- var parsed = this.prepare(this.elements[i], p, iProps[p]);
- iFrom[p] = parsed.from;
- iTo[p] = parsed.to;
- }
- }
- return this.parent(from, to);
- }
-
-});/*
----
-
-script: Fx.Accordion.js
-
-description: An Fx.Elements extension which allows you to easily create accordion type controls.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Element.Event
-- /Fx.Elements
-
-provides: [Fx.Accordion]
-
-...
-*/
-
-var Accordion = Fx.Accordion = new Class({
-
- Extends: Fx.Elements,
-
- options: {/*
- onActive: $empty(toggler, section),
- onBackground: $empty(toggler, section),
- fixedHeight: false,
- fixedWidth: false,
- */
- display: 0,
- show: false,
- height: true,
- width: false,
- opacity: true,
- alwaysHide: false,
- trigger: 'click',
- initialDisplayFx: true,
- returnHeightToAuto: true
- },
-
- 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 = document.id(params.container);
- this.previous = -1;
- this.internalChain = new Chain();
- 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, this.options.initialDisplayFx);
- this.addEvent('complete', this.internalChain.callChain.bind(this.internalChain));
- },
-
- addSection: function(toggler, element){
- toggler = document.id(toggler);
- element = document.id(element);
- var test = this.togglers.contains(toggler);
- this.togglers.include(toggler);
- this.elements.include(element);
- var idx = this.togglers.indexOf(toggler);
- var displayer = this.display.bind(this, idx);
- toggler.store('accordion:display', displayer);
- toggler.addEvent(this.options.trigger, displayer);
- 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;
- },
-
- detach: function(){
- this.togglers.each(function(toggler) {
- toggler.removeEvent(this.options.trigger, toggler.retrieve('accordion:display'));
- }, this);
- },
-
- display: function(index, useFx){
- if (!this.check(index, useFx)) return this;
- useFx = $pick(useFx, true);
- if (this.options.returnHeightToAuto) {
- var prev = this.elements[this.previous];
- if (prev) {
- for (var fx in this.effects) {
- prev.setStyle(fx, prev[this.effects[fx]]);
- }
- }
- }
- 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.options.height) ||
- el.offsetWidth > 0 && this.options.width));
- 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);
- this.internalChain.chain(function(){
- if (this.options.returnHeightToAuto) {
- var el = this.elements[index];
- el.setStyle('height', 'auto');
- };
- }.bind(this));
- return useFx ? this.start(obj) : this.set(obj);
- }
-
-});/*
----
-
-script: Fx.Move.js
-
-description: Defines Fx.Move, a class that works with Element.Position.js to transition an element from one location to another.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Fx.Morph
-- /Element.Position
-
-provides: [Fx.Move]
-
-...
-*/
-
-Fx.Move = new Class({
-
- Extends: Fx.Morph,
-
- options: {
- relativeTo: document.body,
- position: 'center',
- edge: false,
- offset: {x: 0, y: 0}
- },
-
- start: function(destination){
- return this.parent(this.element.position($merge(this.options, destination, {returnPos: true})));
- }
-
-});
-
-Element.Properties.move = {
-
- set: function(options){
- var morph = this.retrieve('move');
- if (morph) morph.cancel();
- return this.eliminate('move').store('move:options', $extend({link: 'cancel'}, options));
- },
-
- get: function(options){
- if (options || !this.retrieve('move')){
- if (options || !this.retrieve('move:options')) this.set('move', options);
- this.store('move', new Fx.Move(this, this.retrieve('move:options')));
- }
- return this.retrieve('move');
- }
-
-};
-
-Element.implement({
-
- move: function(options){
- this.get('move').start(options);
- return this;
- }
-
-});
-/*
----
-
-script: Fx.Scroll.js
-
-description: Effect to smoothly scroll any element, including the window.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Fx
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Dimensions
-- /MooTools.More
-
-provides: [Fx.Scroll]
-
-...
-*/
-
-Fx.Scroll = new Class({
-
- Extends: Fx,
-
- options: {
- offset: {x: 0, y: 0},
- wheelStops: true
- },
-
- initialize: function(element, options){
- this.element = this.subject = document.id(element);
- this.parent(options);
- var cancel = this.cancel.bind(this, false);
-
- if ($type(this.element) != 'element') this.element = document.id(this.element.getDocument().body);
-
- var stopper = this.element;
-
- if (this.options.wheelStops){
- this.addEvent('start', function(){
- stopper.addEvent('mousewheel', cancel);
- }, true);
- this.addEvent('complete', function(){
- stopper.removeEvent('mousewheel', cancel);
- }, true);
- }
- },
-
- set: function(){
- var now = Array.flatten(arguments);
- if (Browser.Engine.gecko) now = [Math.round(now[0]), Math.round(now[1])];
- this.element.scrollTo(now[0], now[1]);
- },
-
- compute: function(from, to, delta){
- return [0, 1].map(function(i){
- return Fx.compute(from[i], to[i], delta);
- });
- },
-
- start: function(x, y){
- if (!this.check(x, y)) return this;
- var scrollSize = this.element.getScrollSize(),
- scroll = this.element.getScroll(),
- values = {x: x, y: y};
- for (var z in values){
- var max = scrollSize[z];
- if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z] : 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);
- },
-
- toLeft: function(){
- return this.start(0, false);
- },
-
- toRight: function(){
- return this.start('right', false);
- },
-
- toBottom: function(){
- return this.start(false, 'bottom');
- },
-
- toElement: function(el){
- var position = document.id(el).getPosition(this.element);
- return this.start(position.x, position.y);
- },
-
- scrollIntoView: function(el, axes, offset){
- axes = axes ? $splat(axes) : ['x','y'];
- var to = {};
- el = document.id(el);
- var pos = el.getPosition(this.element);
- var size = el.getSize();
- var scroll = this.element.getScroll();
- var containerSize = this.element.getSize();
- var edge = {
- x: pos.x + size.x,
- y: pos.y + size.y
- };
- ['x','y'].each(function(axis) {
- if (axes.contains(axis)) {
- if (edge[axis] > scroll[axis] + containerSize[axis]) to[axis] = edge[axis] - containerSize[axis];
- if (pos[axis] < scroll[axis]) to[axis] = pos[axis];
- }
- if (to[axis] == null) to[axis] = scroll[axis];
- if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
- }, this);
- if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
- return this;
- },
-
- scrollToCenter: function(el, axes, offset){
- axes = axes ? $splat(axes) : ['x', 'y'];
- el = $(el);
- var to = {},
- pos = el.getPosition(this.element),
- size = el.getSize(),
- scroll = this.element.getScroll(),
- containerSize = this.element.getSize(),
- edge = {
- x: pos.x + size.x,
- y: pos.y + size.y
- };
-
- ['x','y'].each(function(axis){
- if(axes.contains(axis)){
- to[axis] = pos[axis] - (containerSize[axis] - size[axis])/2;
- }
- if(to[axis] == null) to[axis] = scroll[axis];
- if(offset && offset[axis]) to[axis] = to[axis] + offset[axis];
- }, this);
- if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
- return this;
- }
-
-});
-/*
----
-
-script: Fx.Slide.js
-
-description: Effect to slide an element in and out of view.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Fx Element.Style
-- /MooTools.More
-
-provides: [Fx.Slide]
-
-...
-*/
-
-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 = document.id(element);
- this.parent(options);
- var wrapper = this.element.retrieve('wrapper');
- this.wrapper = wrapper || new Element('div', {
- styles: this.element.getStyles('margin', 'position', 'overflow')
- }).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){
- return [0, 1].map(function(i){
- return Fx.compute(from[i], to[i], delta);
- });
- },
-
- 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;
- }
- 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;
- }
-
-});
-/*
----
-
-script: Fx.SmoothScroll.js
-
-description: Class for creating a smooth scrolling effect to all internal links on the page.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Selectors
-- /Fx.Scroll
-
-provides: [Fx.SmoothScroll]
-
-...
-*/
-
-var SmoothScroll = Fx.SmoothScroll = new Class({
-
- Extends: Fx.Scroll,
-
- initialize: function(options, context){
- context = context || document;
- this.doc = context.getDocument();
- var win = context.getWindow();
- this.parent(this.doc, options);
- this.links = $$(this.options.links || this.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) this.useLink(link, anchor);
- }, this);
- if (!Browser.Engine.webkit419) {
- this.addEvent('complete', function(){
- win.location.hash = this.anchor;
- }, true);
- }
- },
-
- useLink: function(link, anchor){
- var el;
- link.addEvent('click', function(event){
- if (el !== false && !el) el = document.id(anchor) || this.doc.getElement('a[name=' + anchor + ']');
- if (el) {
- event.preventDefault();
- this.anchor = anchor;
- this.toElement(el);
- link.blur();
- }
- }.bind(this));
- }
-});/*
----
-
-script: Fx.Sort.js
-
-description: Defines Fx.Sort, a class that reorders lists with a transition.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element.Dimensions
-- /Fx.Elements
-- /Element.Measure
-
-provides: [Fx.Sort]
-
-...
-*/
-
-Fx.Sort = new Class({
-
- Extends: Fx.Elements,
-
- options: {
- mode: 'vertical'
- },
-
- initialize: function(elements, options){
- this.parent(elements, options);
- this.elements.each(function(el){
- if (el.getStyle('position') == 'static') el.setStyle('position', 'relative');
- });
- this.setDefaultOrder();
- },
-
- setDefaultOrder: function(){
- this.currentOrder = this.elements.map(function(el, index){
- return index;
- });
- },
-
- sort: function(newOrder){
- if ($type(newOrder) != 'array') return false;
- var top = 0,
- left = 0,
- next = {},
- zero = {},
- vert = this.options.mode == 'vertical';
- var current = this.elements.map(function(el, index){
- var size = el.getComputedSize({styles: ['border', 'padding', 'margin']});
- var val;
- if (vert){
- val = {
- top: top,
- margin: size['margin-top'],
- height: size.totalHeight
- };
- top += val.height - size['margin-top'];
- } else {
- val = {
- left: left,
- margin: size['margin-left'],
- width: size.totalWidth
- };
- left += val.width;
- }
- var plain = vert ? 'top' : 'left';
- zero[index] = {};
- var start = el.getStyle(plain).toInt();
- zero[index][plain] = start || 0;
- return val;
- }, this);
- this.set(zero);
- newOrder = newOrder.map(function(i){ return i.toInt(); });
- if (newOrder.length != this.elements.length){
- this.currentOrder.each(function(index){
- if (!newOrder.contains(index)) newOrder.push(index);
- });
- if (newOrder.length > this.elements.length)
- newOrder.splice(this.elements.length-1, newOrder.length - this.elements.length);
- }
- var margin = top = left = 0;
- newOrder.each(function(item, index){
- var newPos = {};
- if (vert){
- newPos.top = top - current[item].top - margin;
- top += current[item].height;
- } else {
- newPos.left = left - current[item].left;
- left += current[item].width;
- }
- margin = margin + current[item].margin;
- next[item]=newPos;
- }, this);
- var mapped = {};
- $A(newOrder).sort().each(function(index){
- mapped[index] = next[index];
- });
- this.start(mapped);
- this.currentOrder = newOrder;
- return this;
- },
-
- rearrangeDOM: function(newOrder){
- newOrder = newOrder || this.currentOrder;
- var parent = this.elements[0].getParent();
- var rearranged = [];
- this.elements.setStyle('opacity', 0);
- //move each element and store the new default order
- newOrder.each(function(index){
- rearranged.push(this.elements[index].inject(parent).setStyles({
- top: 0,
- left: 0
- }));
- }, this);
- this.elements.setStyle('opacity', 1);
- this.elements = $$(rearranged);
- this.setDefaultOrder();
- return this;
- },
-
- getDefaultOrder: function(){
- return this.elements.map(function(el, index){
- return index;
- });
- },
-
- forward: function(){
- return this.sort(this.getDefaultOrder());
- },
-
- backward: function(){
- return this.sort(this.getDefaultOrder().reverse());
- },
-
- reverse: function(){
- return this.sort(this.currentOrder.reverse());
- },
-
- sortByElements: function(elements){
- return this.sort(elements.map(function(el){
- return this.elements.indexOf(el);
- }, this));
- },
-
- swap: function(one, two){
- if ($type(one) == 'element') one = this.elements.indexOf(one);
- if ($type(two) == 'element') two = this.elements.indexOf(two);
-
- var newOrder = $A(this.currentOrder);
- newOrder[this.currentOrder.indexOf(one)] = two;
- newOrder[this.currentOrder.indexOf(two)] = one;
- return this.sort(newOrder);
- }
-
-});/*
----
-
-script: Drag.js
-
-description: The base Drag Class. Can be used to drag and resize Elements using mouse events.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-- Tom Occhinno
-- Jan Kassens
-
-requires:
-- core:1.2.4/Events
-- core:1.2.4/Options
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Style
-- /MooTools.More
-
-provides: [Drag]
-
-*/
-
-var Drag = new Class({
-
- Implements: [Events, Options],
-
- options: {/*
- onBeforeStart: $empty(thisElement),
- onStart: $empty(thisElement, event),
- onSnap: $empty(thisElement)
- onDrag: $empty(thisElement, event),
- onCancel: $empty(thisElement),
- onComplete: $empty(thisElement, event),*/
- 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 = document.id(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) : document.id(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 (event.rightClick) return;
- if (this.options.preventDefault) event.preventDefault();
- this.mouse.start = event.page;
- this.fireEvent('beforeStart', this.element);
- 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, event]).fireEvent('snap', this.element);
- }
- },
-
- 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.limit[z][0]||0)) % 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, event]);
- },
-
- 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, event]);
- }
-
-});
-
-Element.implement({
-
- makeResizable: function(options){
- var drag = new Drag(this, $merge({modifiers: {x: 'width', y: 'height'}}, options));
- this.store('resizer', drag);
- return drag.addEvent('drag', function(){
- this.fireEvent('resize', drag);
- }.bind(this));
- }
-
-});
-/*
----
-
-script: Drag.Move.js
-
-description: A Drag extension that provides support for the constraining of draggables to containers and droppables.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-- Tom Occhinno
-- Jan Kassens
-- Aaron Newton
-- Scott Kyle
-
-requires:
-- core:1.2.4/Element.Dimensions
-- /Drag
-
-provides: [Drag.Move]
-
-...
-*/
-
-Drag.Move = new Class({
-
- Extends: Drag,
-
- options: {/*
- onEnter: $empty(thisElement, overed),
- onLeave: $empty(thisElement, overed),
- onDrop: $empty(thisElement, overed, event),*/
- droppables: [],
- container: false,
- precalculate: false,
- includeMargins: true,
- checkDroppables: true
- },
-
- initialize: function(element, options){
- this.parent(element, options);
- element = this.element;
-
- this.droppables = $$(this.options.droppables);
- this.container = document.id(this.options.container);
-
- if (this.container && $type(this.container) != 'element')
- this.container = document.id(this.container.getDocument().body);
-
- var styles = element.getStyles('left', 'right', 'position');
- if (styles.left == 'auto' || styles.top == 'auto')
- element.setPosition(element.getPosition(element.getOffsetParent()));
-
- if (styles.position == 'static')
- element.setStyle('position', 'absolute');
-
- this.addEvent('start', this.checkDroppables, true);
-
- this.overed = null;
- },
-
- start: function(event){
- if (this.container) this.options.limit = this.calculateLimit();
-
- if (this.options.precalculate){
- this.positions = this.droppables.map(function(el){
- return el.getCoordinates();
- });
- }
-
- this.parent(event);
- },
-
- calculateLimit: function(){
- var offsetParent = this.element.getOffsetParent(),
- containerCoordinates = this.container.getCoordinates(offsetParent),
- containerBorder = {},
- elementMargin = {},
- elementBorder = {},
- containerMargin = {},
- offsetParentPadding = {};
-
- ['top', 'right', 'bottom', 'left'].each(function(pad){
- containerBorder[pad] = this.container.getStyle('border-' + pad).toInt();
- elementBorder[pad] = this.element.getStyle('border-' + pad).toInt();
- elementMargin[pad] = this.element.getStyle('margin-' + pad).toInt();
- containerMargin[pad] = this.container.getStyle('margin-' + pad).toInt();
- offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt();
- }, this);
-
- var width = this.element.offsetWidth + elementMargin.left + elementMargin.right,
- height = this.element.offsetHeight + elementMargin.top + elementMargin.bottom,
- left = 0,
- top = 0,
- right = containerCoordinates.right - containerBorder.right - width,
- bottom = containerCoordinates.bottom - containerBorder.bottom - height;
-
- if (this.options.includeMargins){
- left += elementMargin.left;
- top += elementMargin.top;
- } else {
- right += elementMargin.right;
- bottom += elementMargin.bottom;
- }
-
- if (this.element.getStyle('position') == 'relative'){
- var coords = this.element.getCoordinates(offsetParent);
- coords.left -= this.element.getStyle('left').toInt();
- coords.top -= this.element.getStyle('top').toInt();
-
- left += containerBorder.left - coords.left;
- top += containerBorder.top - coords.top;
- right += elementMargin.left - coords.left;
- bottom += elementMargin.top - coords.top;
-
- if (this.container != offsetParent){
- left += containerMargin.left + offsetParentPadding.left;
- top += (Browser.Engine.trident4 ? 0 : containerMargin.top) + offsetParentPadding.top;
- }
- } else {
- left -= elementMargin.left;
- top -= elementMargin.top;
-
- if (this.container == offsetParent){
- right -= containerBorder.left;
- bottom -= containerBorder.top;
- } else {
- left += containerCoordinates.left + containerBorder.left;
- top += containerCoordinates.top + containerBorder.top;
- }
- }
-
- return {
- x: [left, right],
- y: [top, bottom]
- };
- },
-
- checkAgainst: function(el, i){
- el = (this.positions) ? this.positions[i] : el.getCoordinates();
- var now = this.mouse.now;
- return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
- },
-
- 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.fireEvent('enter', [this.element, overed]);
- this.overed = overed;
- }
- },
-
- drag: function(event){
- this.parent(event);
- if (this.options.checkDroppables && this.droppables.length) this.checkDroppables();
- },
-
- stop: function(event){
- this.checkDroppables();
- this.fireEvent('drop', [this.element, this.overed, event]);
- this.overed = null;
- return this.parent(event);
- }
-
-});
-
-Element.implement({
-
- makeDraggable: function(options){
- var drag = new Drag.Move(this, options);
- this.store('dragger', drag);
- return drag;
- }
-
-});
-/*
----
-
-script: Slider.js
-
-description: Class for creating horizontal and vertical slider controls.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Element.Dimensions
-- /Class.Binds
-- /Drag
-- /Element.Dimensions
-- /Element.Measure
-
-provides: [Slider]
-
-...
-*/
-
-var Slider = new Class({
-
- Implements: [Events, Options],
-
- Binds: ['clickedElement', 'draggedKnob', 'scrolledElement'],
-
- options: {/*
- onTick: $empty(intPosition),
- onChange: $empty(intStep),
- onComplete: $empty(strStep),*/
- onTick: function(position){
- if (this.options.snap) position = this.toPosition(this.step);
- this.knob.setStyle(this.property, position);
- },
- initialStep: 0,
- snap: false,
- offset: 0,
- range: false,
- wheel: false,
- steps: 100,
- mode: 'horizontal'
- },
-
- initialize: function(element, knob, options){
- this.setOptions(options);
- this.element = document.id(element);
- this.knob = document.id(knob);
- this.previousChange = this.previousEnd = this.step = -1;
- 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.full = this.element.measure(function(){
- this.half = this.knob[offset] / 2;
- return this.element[offset] - this.knob[offset] + (this.options.offset * 2);
- }.bind(this));
-
- 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.initialStep ? this.toPosition(this.options.initialStep) : - this.options.offset);
- modifiers[this.axis] = this.property;
- limit[this.axis] = [- this.options.offset, this.full - this.options.offset];
-
- var dragOptions = {
- snap: 0,
- limit: limit,
- modifiers: modifiers,
- onDrag: this.draggedKnob,
- onStart: this.draggedKnob,
- onBeforeStart: (function(){
- this.isDragging = true;
- }).bind(this),
- onCancel: function() {
- this.isDragging = false;
- }.bind(this),
- onComplete: function(){
- this.isDragging = false;
- this.draggedKnob();
- this.end();
- }.bind(this)
- };
- if (this.options.snap){
- dragOptions.grid = Math.ceil(this.stepWidth);
- dragOptions.limit[this.axis][1] = this.full;
- }
-
- this.drag = new Drag(this.knob, dragOptions);
- this.attach();
- },
-
- attach: function(){
- this.element.addEvent('mousedown', this.clickedElement);
- if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement);
- this.drag.attach();
- return this;
- },
-
- detach: function(){
- this.element.removeEvent('mousedown', this.clickedElement);
- this.element.removeEvent('mousewheel', this.scrolledElement);
- this.drag.detach();
- return this;
- },
-
- 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.fireEvent('tick', this.toPosition(this.step));
- this.end();
- return this;
- },
-
- clickedElement: function(event){
- if (this.isDragging || event.target == this.knob) return;
-
- 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.fireEvent('tick', position);
- this.end();
- },
-
- 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: Sortables.js
-
-description: Class for creating a drag and drop sorting interface for lists of items.
-
-license: MIT-style license
-
-authors:
-- Tom Occhino
-
-requires:
-- /Drag.Move
-
-provides: [Slider]
-
-...
-*/
-
-var Sortables = new Class({
-
- Implements: [Events, Options],
-
- options: {/*
- onSort: $empty(element, clone),
- onStart: $empty(element, clone),
- onComplete: $empty(element),*/
- 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($$(document.id(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(){
- return $$(Array.flatten(arguments).map(function(element){
- this.elements.erase(element);
- var start = element.retrieve('sortables:start');
- (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start);
-
- return element;
- }, this));
- },
-
- removeLists: function(){
- return $$(Array.flatten(arguments).map(function(list){
- this.lists.erase(list);
- this.removeItems(list.getChildren());
-
- return list;
- }, this));
- },
-
- 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).setPosition(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: Request.JSONP.js
-
-description: Defines Request.JSONP, a class for cross domain javascript via script injection.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-- Guillermo Rauch
-
-requires:
-- core:1.2.4/Element
-- core:1.2.4/Request
-- /Log
-
-provides: [Request.JSONP]
-
-...
-*/
-
-Request.JSONP = new Class({
-
- Implements: [Chain, Events, Options, Log],
-
- options: {/*
- onRetry: $empty(intRetries),
- onRequest: $empty(scriptElement),
- onComplete: $empty(data),
- onSuccess: $empty(data),
- onCancel: $empty(),
- log: false,
- */
- url: '',
- data: {},
- retries: 0,
- timeout: 0,
- link: 'ignore',
- callbackKey: 'callback',
- injectScript: document.head
- },
-
- initialize: function(options){
- this.setOptions(options);
- if (this.options.log) this.enableLog();
- this.running = false;
- this.requests = 0;
- this.triesRemaining = [];
- },
-
- check: function(){
- if (!this.running) 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;
- },
-
- send: function(options){
- if (!$chk(arguments[1]) && !this.check(options)) return this;
-
- var type = $type(options),
- old = this.options,
- index = $chk(arguments[1]) ? arguments[1] : this.requests++;
- if (type == 'string' || type == 'element') options = {data: options};
-
- options = $extend({data: old.data, url: old.url}, options);
-
- if (!$chk(this.triesRemaining[index])) this.triesRemaining[index] = this.options.retries;
- var remaining = this.triesRemaining[index];
-
- (function(){
- var script = this.getScript(options);
- this.log('JSONP retrieving script with url: ' + script.get('src'));
- this.fireEvent('request', script);
- this.running = true;
-
- (function(){
- if (remaining){
- this.triesRemaining[index] = remaining - 1;
- if (script){
- script.destroy();
- this.send(options, index).fireEvent('retry', this.triesRemaining[index]);
- }
- } else if(script && this.options.timeout){
- script.destroy();
- this.cancel().fireEvent('failure');
- }
- }).delay(this.options.timeout, this);
- }).delay(Browser.Engine.trident ? 50 : 0, this);
- return this;
- },
-
- cancel: function(){
- if (!this.running) return this;
- this.running = false;
- this.fireEvent('cancel');
- return this;
- },
-
- getScript: function(options){
- var index = Request.JSONP.counter,
- data;
- Request.JSONP.counter++;
-
- switch ($type(options.data)){
- case 'element': data = document.id(options.data).toQueryString(); break;
- case 'object': case 'hash': data = Hash.toQueryString(options.data);
- }
-
- var src = options.url +
- (options.url.test('\\?') ? '&' :'?') +
- (options.callbackKey || this.options.callbackKey) +
- '=Request.JSONP.request_map.request_'+ index +
- (data ? '&' + data : '');
- if (src.length > 2083) this.log('JSONP '+ src +' will fail in Internet Explorer, which enforces a 2083 bytes length limit on URIs');
-
- var script = new Element('script', {type: 'text/javascript', src: src});
- Request.JSONP.request_map['request_' + index] = function(data){ this.success(data, script); }.bind(this);
- return script.inject(this.options.injectScript);
- },
-
- success: function(data, script){
- if (script) script.destroy();
- this.running = false;
- this.log('JSONP successfully retrieved: ', data);
- this.fireEvent('complete', [data]).fireEvent('success', [data]).callChain();
- }
-
-});
-
-Request.JSONP.counter = 0;
-Request.JSONP.request_map = {};/*
----
-
-script: Request.Queue.js
-
-description: Controls several instances of Request and its variants to run only one request at a time.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Element
-- core:1.2.4/Request
-- /Log
-
-provides: [Request.Queue]
-
-...
-*/
-
-Request.Queue = new Class({
-
- Implements: [Options, Events],
-
- Binds: ['attach', 'request', 'complete', 'cancel', 'success', 'failure', 'exception'],
-
- options: {/*
- onRequest: $empty(argsPassedToOnRequest),
- onSuccess: $empty(argsPassedToOnSuccess),
- onComplete: $empty(argsPassedToOnComplete),
- onCancel: $empty(argsPassedToOnCancel),
- onException: $empty(argsPassedToOnException),
- onFailure: $empty(argsPassedToOnFailure),
- onEnd: $empty,
- */
- stopOnFailure: true,
- autoAdvance: true,
- concurrent: 1,
- requests: {}
- },
-
- initialize: function(options){
- if(options){
- var requests = options.requests;
- delete options.requests;
- }
- this.setOptions(options);
- this.requests = new Hash;
- this.queue = [];
- this.reqBinders = {};
-
- if(requests) this.addRequests(requests);
- },
-
- addRequest: function(name, request){
- this.requests.set(name, request);
- this.attach(name, request);
- return this;
- },
-
- addRequests: function(obj){
- $each(obj, function(req, name){
- this.addRequest(name, req);
- }, this);
- return this;
- },
-
- getName: function(req){
- return this.requests.keyOf(req);
- },
-
- attach: function(name, req){
- if (req._groupSend) return this;
- ['request', 'complete', 'cancel', 'success', 'failure', 'exception'].each(function(evt){
- if(!this.reqBinders[name]) this.reqBinders[name] = {};
- this.reqBinders[name][evt] = function(){
- this['on' + evt.capitalize()].apply(this, [name, req].extend(arguments));
- }.bind(this);
- req.addEvent(evt, this.reqBinders[name][evt]);
- }, this);
- req._groupSend = req.send;
- req.send = function(options){
- this.send(name, options);
- return req;
- }.bind(this);
- return this;
- },
-
- removeRequest: function(req){
- var name = $type(req) == 'object' ? this.getName(req) : req;
- if (!name && $type(name) != 'string') return this;
- req = this.requests.get(name);
- if (!req) return this;
- ['request', 'complete', 'cancel', 'success', 'failure', 'exception'].each(function(evt){
- req.removeEvent(evt, this.reqBinders[name][evt]);
- }, this);
- req.send = req._groupSend;
- delete req._groupSend;
- return this;
- },
-
- getRunning: function(){
- return this.requests.filter(function(r){
- return r.running;
- });
- },
-
- isRunning: function(){
- return !!(this.getRunning().getKeys().length);
- },
-
- send: function(name, options){
- var q = function(){
- this.requests.get(name)._groupSend(options);
- this.queue.erase(q);
- }.bind(this);
- q.name = name;
- if (this.getRunning().getKeys().length >= this.options.concurrent || (this.error && this.options.stopOnFailure)) this.queue.push(q);
- else q();
- return this;
- },
-
- hasNext: function(name){
- return (!name) ? !!this.queue.length : !!this.queue.filter(function(q){ return q.name == name; }).length;
- },
-
- resume: function(){
- this.error = false;
- (this.options.concurrent - this.getRunning().getKeys().length).times(this.runNext, this);
- return this;
- },
-
- runNext: function(name){
- if (!this.queue.length) return this;
- if (!name){
- this.queue[0]();
- } else {
- var found;
- this.queue.each(function(q){
- if (!found && q.name == name){
- found = true;
- q();
- }
- });
- }
- return this;
- },
-
- runAll: function() {
- this.queue.each(function(q) {
- q();
- });
- return this;
- },
-
- clear: function(name){
- if (!name){
- this.queue.empty();
- } else {
- this.queue = this.queue.map(function(q){
- if (q.name != name) return q;
- else return false;
- }).filter(function(q){ return q; });
- }
- return this;
- },
-
- cancel: function(name){
- this.requests.get(name).cancel();
- return this;
- },
-
- onRequest: function(){
- this.fireEvent('request', arguments);
- },
-
- onComplete: function(){
- this.fireEvent('complete', arguments);
- if (!this.queue.length) this.fireEvent('end');
- },
-
- onCancel: function(){
- if (this.options.autoAdvance && !this.error) this.runNext();
- this.fireEvent('cancel', arguments);
- },
-
- onSuccess: function(){
- if (this.options.autoAdvance && !this.error) this.runNext();
- this.fireEvent('success', arguments);
- },
-
- onFailure: function(){
- this.error = true;
- if (!this.options.stopOnFailure && this.options.autoAdvance) this.runNext();
- this.fireEvent('failure', arguments);
- },
-
- onException: function(){
- this.error = true;
- if (!this.options.stopOnFailure && this.options.autoAdvance) this.runNext();
- this.fireEvent('exception', arguments);
- }
-
-});
-/*
----
-
-script: Request.Periodical.js
-
-description: Requests the same URL to pull data from a server but increases the intervals if no data is returned to reduce the load
-
-license: MIT-style license
-
-authors:
-- Christoph Pojer
-
-requires:
-- core:1.2.4/Request
-- /MooTools.More
-
-provides: [Request.Periodical]
-
-...
-*/
-
-Request.implement({
-
- options: {
- initialDelay: 5000,
- delay: 5000,
- limit: 60000
- },
-
- startTimer: function(data){
- var fn = function(){
- if (!this.running) this.send({data: data});
- };
- this.timer = fn.delay(this.options.initialDelay, this);
- this.lastDelay = this.options.initialDelay;
- this.completeCheck = function(response){
- $clear(this.timer);
- this.lastDelay = (response) ? this.options.delay : (this.lastDelay + this.options.delay).min(this.options.limit);
- this.timer = fn.delay(this.lastDelay, this);
- };
- return this.addEvent('complete', this.completeCheck);
- },
-
- stopTimer: function(){
- $clear(this.timer);
- return this.removeEvent('complete', this.completeCheck);
- }
-
-});/*
----
-
-script: Assets.js
-
-description: Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Element.Event
-- /MooTools.More
-
-provides: [Assets]
-
-...
-*/
-
-var Asset = {
-
- javascript: function(source, properties){
- properties = $extend({
- onload: $empty,
- 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;
-
- script.addEvents({
- load: load,
- readystatechange: function(){
- if (['loaded', 'complete'].contains(this.readyState)) load();
- }
- }).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
- }, properties)).inject(document.head);
- },
-
- image: function(source, properties){
- properties = $merge({
- onload: $empty,
- onabort: $empty,
- onerror: $empty
- }, properties);
- var image = new Image();
- var element = document.id(image) || new Element('img');
- ['load', 'abort', 'error'].each(function(name){
- var type = 'on' + name;
- var event = properties[type];
- delete properties[type];
- image[type] = function(){
- if (!image) return;
- if (!element.parentNode){
- element.width = image.width;
- element.height = image.height;
- }
- image = image.onload = image.onabort = image.onerror = null;
- event.delay(1, element, element);
- element.fireEvent(name, element, 1);
- };
- });
- image.src = element.src = source;
- if (image && image.complete) image.onload.delay(1);
- return element.set(properties);
- },
-
- images: function(sources, options){
- options = $merge({
- onComplete: $empty,
- onProgress: $empty,
- onError: $empty,
- properties: {}
- }, options);
- sources = $splat(sources);
- var images = [];
- var counter = 0;
- 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();
- }
- }));
- }));
- }
-
-};/*
----
-
-script: Color.js
-
-description: Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Array
-- core:1.2.4/String
-- core:1.2.4/Number
-- core:1.2.4/Hash
-- core:1.2.4/Function
-- core:1.2.4/$util
-
-provides: [Color]
-
-...
-*/
-
-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;
- }
- color.rgb = color.slice(0, 3);
- color.hsb = color.hsb || color.rgbToHsb();
- color.hex = color.rgbToHex();
- return $extend(color, this);
- }
-
-});
-
-Color.implement({
-
- 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');
- },
-
- invert: function(){
- return new Color(this.map(function(value){
- return 255 - value;
- }));
- },
-
- setHue: function(value){
- return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');
- },
-
- setSaturation: function(percent){
- return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');
- },
-
- setBrightness: function(percent){
- return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');
- }
-
-});
-
-var $RGB = function(r, g, b){
- return new Color([r, g, b], 'rgb');
-};
-
-var $HSB = function(h, s, b){
- return new Color([h, s, b], 'hsb');
-};
-
-var $HEX = function(hex){
- return new Color(hex, 'hex');
-};
-
-Array.implement({
-
- rgbToHsb: function(){
- var red = this[0],
- green = this[1],
- blue = this[2],
- hue = 0;
- var max = Math.max(red, green, blue),
- min = Math.min(red, green, blue);
- var delta = max - min;
- var brightness = max / 255,
- saturation = (max != 0) ? delta / max : 0;
- if(saturation != 0) {
- 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)];
- },
-
- 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];
- }
- }
- return false;
- }
-
-});
-
-String.implement({
-
- rgbToHsb: function(){
- var rgb = this.match(/\d{1,3}/g);
- return (rgb) ? rgb.rgbToHsb() : null;
- },
-
- hsbToRgb: function(){
- var hsb = this.match(/\d{1,3}/g);
- return (hsb) ? hsb.hsbToRgb() : null;
- }
-
-});
-/*
----
-
-script: Group.js
-
-description: Class for monitoring collections of events
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Events
-- /MooTools.More
-
-provides: [Group]
-
-...
-*/
-
-var Group = new Class({
-
- initialize: function(){
- this.instances = Array.flatten(arguments);
- this.events = {};
- this.checker = {};
- },
-
- 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;
- },
-
- 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);
- }
-
-});
-/*
----
-
-script: Hash.Cookie.js
-
-description: Class for creating, reading, and deleting Cookies in JSON format.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-- Aaron Newton
-
-requires:
-- core:1.2.4/Cookie
-- core:1.2.4/JSON
-- /MooTools.More
-
-provides: [Hash.Cookie]
-
-...
-*/
-
-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.each(Hash.prototype, function(method, name){
- if (typeof method == 'function') Hash.Cookie.implement(name, function(){
- var value = method.apply(this.hash, arguments);
- if (this.options.autoSave) this.save();
- return value;
- });
-});/*
----
-
-script: HtmlTable.js
-
-description: Builds table elements with methods to add rows.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- /Class.Occlude
-
-provides: [HtmlTable]
-
-...
-*/
-
-var HtmlTable = new Class({
-
- Implements: [Options, Events, Class.Occlude],
-
- options: {
- properties: {
- cellpadding: 0,
- cellspacing: 0,
- border: 0
- },
- rows: [],
- headers: [],
- footers: []
- },
-
- property: 'HtmlTable',
-
- initialize: function(){
- var params = Array.link(arguments, {options: Object.type, table: Element.type});
- this.setOptions(params.options);
- this.element = params.table || new Element('table', this.options.properties);
- if (this.occlude()) return this.occluded;
- this.build();
- },
-
- build: function(){
- this.element.store('HtmlTable', this);
-
- this.body = document.id(this.element.tBodies[0]) || new Element('tbody').inject(this.element);
- $$(this.body.rows);
-
- if (this.options.headers.length) this.setHeaders(this.options.headers);
- else this.thead = document.id(this.element.tHead);
- if (this.thead) this.head = document.id(this.thead.rows[0]);
-
- if (this.options.footers.length) this.setFooters(this.options.footers);
- this.tfoot = document.id(this.element.tFoot);
- if (this.tfoot) this.foot = document.id(this.thead.rows[0]);
-
- this.options.rows.each(this.push.bind(this));
-
- ['adopt', 'inject', 'wraps', 'grab', 'replaces', 'dispose'].each(function(method){
- this[method] = this.element[method].bind(this.element);
- }, this);
- },
-
- toElement: function(){
- return this.element;
- },
-
- empty: function(){
- this.body.empty();
- return this;
- },
-
- setHeaders: function(headers){
- this.thead = (document.id(this.element.tHead) || new Element('thead').inject(this.element, 'top')).empty();
- this.push(headers, this.thead, 'th');
- this.head = document.id(this.thead.rows[0]);
- return this;
- },
-
- setFooters: function(footers){
- this.tfoot = (document.id(this.element.tFoot) || new Element('tfoot').inject(this.element, 'top')).empty();
- this.push(footers, this.tfoot);
- this.foot = document.id(this.thead.rows[0]);
- return this;
- },
-
- push: function(row, target, tag){
- var tds = row.map(function(data){
- var td = new Element(tag || 'td', data.properties),
- type = data.content || data || '',
- element = document.id(type);
-
- if(element) td.adopt(element);
- else td.set('html', type);
-
- return td;
- });
-
- return {
- tr: new Element('tr').inject(target || this.body).adopt(tds),
- tds: tds
- };
- }
-
-});/*
----
-
-script: HtmlTable.Zebra.js
-
-description: Builds a stripy table with methods to add rows.
-
-license: MIT-style license
-
-authors:
-- Harald Kirschner
-- Aaron Newton
-
-requires:
-- /HtmlTable
-- /Class.refactor
-
-provides: [HtmlTable.Zebra]
-
-...
-*/
-
-HtmlTable = Class.refactor(HtmlTable, {
-
- options: {
- classZebra: 'table-tr-odd',
- zebra: true
- },
-
- initialize: function(){
- this.previous.apply(this, arguments);
- if (this.occluded) return this.occluded;
- if (this.options.zebra) this.updateZebras();
- },
-
- updateZebras: function(){
- Array.each(this.body.rows, this.zebra, this);
- },
-
- zebra: function(row, i){
- return row[((i % 2) ? 'remove' : 'add')+'Class'](this.options.classZebra);
- },
-
- push: function(){
- var pushed = this.previous.apply(this, arguments);
- if (this.options.zebra) this.updateZebras();
- return pushed;
- }
-
-});/*
----
-
-script: HtmlTable.Sort.js
-
-description: Builds a stripy, sortable table with methods to add rows.
-
-license: MIT-style license
-
-authors:
-- Harald Kirschner
-- Aaron Newton
-
-requires:
-- core:1.2.4/Hash
-- /HtmlTable
-- /Class.refactor
-- /Element.Delegation
-- /Date
-
-provides: [HtmlTable.Sort]
-
-...
-*/
-
-HtmlTable = Class.refactor(HtmlTable, {
-
- options: {/*
- onSort: $empty, */
- sortIndex: 0,
- sortReverse: false,
- parsers: [],
- defaultParser: 'string',
- classSortable: 'table-sortable',
- classHeadSort: 'table-th-sort',
- classHeadSortRev: 'table-th-sort-rev',
- classNoSort: 'table-th-nosort',
- classGroupHead: 'table-tr-group-head',
- classGroup: 'table-tr-group',
- classCellSort: 'table-td-sort',
- classSortSpan: 'table-th-sort-span',
- sortable: false
- },
-
- initialize: function () {
- this.previous.apply(this, arguments);
- if (this.occluded) return this.occluded;
- this.sorted = {index: null, dir: 1};
- this.bound = {
- headClick: this.headClick.bind(this)
- };
- this.sortSpans = new Elements();
- if (this.options.sortable) {
- this.enableSort();
- if (this.options.sortIndex != null) this.sort(this.options.sortIndex, this.options.sortReverse);
- }
- },
-
- attachSorts: function(attach){
- this.element[$pick(attach, true) ? 'addEvent' : 'removeEvent']('click:relay(th)', this.bound.headClick);
- },
-
- setHeaders: function(){
- this.previous.apply(this, arguments);
- if (this.sortEnabled) this.detectParsers();
- },
-
- detectParsers: function(force){
- if (!this.head) return;
- var parsers = this.options.parsers,
- rows = this.body.rows;
-
- // auto-detect
- this.parsers = $$(this.head.cells).map(function(cell, index) {
- if (!force && (cell.hasClass(this.options.classNoSort) || cell.retrieve('htmltable-sort'))) return cell.retrieve('htmltable-sort');
- var sortSpan = new Element('span', {'html': ' ', 'class': this.options.classSortSpan}).inject(cell, 'top');
- this.sortSpans.push(sortSpan);
-
- var parser = parsers[index],
- cancel;
- switch ($type(parser)) {
- case 'function': parser = {convert: parser}; cancel = true; break;
- case 'string': parser = parser; cancel = true; break;
- }
- if (!cancel) {
- HtmlTable.Parsers.some(function(current) {
- var match = current.match;
- if (!match) return false;
- if (Browser.Engine.trident) return false;
- for (var i = 0, j = rows.length; i < j; i++) {
- var text = rows[i].cells[index].get('html').clean();
- if (text && match.test(text)) {
- parser = current;
- return true;
- }
- }
- });
- }
-
- if (!parser) parser = this.options.defaultParser;
- cell.store('htmltable-parser', parser);
- return parser;
- }, this);
- },
-
- headClick: function(event, el) {
- if (!this.head) return;
- var index = Array.indexOf(this.head.cells, el);
- this.sort(index);
- return false;
- },
-
- sort: function(index, reverse, pre) {
- if (!this.head) return;
- pre = !!(pre);
- var classCellSort = this.options.classCellSort;
- var classGroup = this.options.classGroup,
- classGroupHead = this.options.classGroupHead;
-
- if (!pre) {
- if (index != null) {
- if (this.sorted.index == index) {
- this.sorted.reverse = !(this.sorted.reverse);
- } else {
- if (this.sorted.index != null) {
- this.sorted.reverse = false;
- this.head.cells[this.sorted.index].removeClass(this.options.classHeadSort).removeClass(this.options.classHeadSortRev);
- } else {
- this.sorted.reverse = true;
- }
- this.sorted.index = index;
- }
- } else {
- index = this.sorted.index;
- }
-
- if (reverse != null) this.sorted.reverse = reverse;
-
- var head = document.id(this.head.cells[index]);
- if (head) {
- head.addClass(this.options.classHeadSort);
- if (this.sorted.reverse) head.addClass(this.options.classHeadSortRev);
- else head.removeClass(this.options.classHeadSortRev);
- }
-
- this.body.getElements('td').removeClass(this.options.classCellSort);
- }
-
- var parser = this.parsers[index];
- if ($type(parser) == 'string') parser = HtmlTable.Parsers.get(parser);
- if (!parser) return;
-
- if (!Browser.Engine.trident) {
- var rel = this.body.getParent();
- this.body.dispose();
- }
-
- var data = Array.map(this.body.rows, function(row, i) {
- var value = parser.convert.call(document.id(row.cells[index]));
-
- if (parser.number || $type(value) == 'number') {
- value = String(value).replace(/[^\d]/, '');
- value = '00000000000000000000000000000000'.substr(0, 32 - value.length).concat(value);
- }
-
- return {
- position: i,
- value: value,
- toString: function() {
- return value;
- }
- };
- }, this);
-
- data.reverse(true);
- data.sort();
-
- if (!this.sorted.reverse) data.reverse(true);
-
- var i = data.length, body = this.body;
- var j, position, entry, group;
-
- while (i) {
- var item = data[--i];
- position = item.position;
- var row = body.rows[position];
- if (row.disabled) continue;
-
- if (!pre) {
- if (group === item.value) {
- row.removeClass(classGroupHead).addClass(classGroup);
- } else {
- group = item.value;
- row.removeClass(classGroup).addClass(classGroupHead);
- }
- if (this.zebra) this.zebra(row, i);
-
- row.cells[index].addClass(classCellSort);
- }
-
- body.appendChild(row);
- for (j = 0; j < i; j++) {
- if (data[j].position > position) data[j].position--;
- }
- };
- data = null;
- if (rel) rel.grab(body);
-
- return this.fireEvent('sort', [body, index]);
- },
-
- reSort: function(){
- if (this.sortEnabled) this.sort.call(this, this.sorted.index, this.sorted.reverse);
- return this;
- },
-
- enableSort: function(){
- this.element.addClass(this.options.classSortable);
- this.attachSorts(true);
- this.detectParsers();
- this.sortEnabled = true;
- return this;
- },
-
- disableSort: function(){
- this.element.remove(this.options.classSortable);
- this.attachSorts(false);
- this.sortSpans.each(function(span) { span.destroy(); });
- this.sortSpans.empty();
- this.sortEnabled = false;
- return this;
- }
-
-});
-
-HtmlTable.Parsers = new Hash({
-
- 'date': {
- match: /^\d{4}[^\d]|[^\d]\d{4}$/,
- convert: function() {
- return Date.parse(this.get('text'));
- },
- type: 'date'
- },
- 'input-checked': {
- match: / type="(radio|checkbox)" /,
- convert: function() {
- return this.getElement('input').checked;
- }
- },
- 'input-value': {
- match: /<input/,
- convert: function() {
- return this.getElement('input').value;
- }
- },
- 'number': {
- match: /^\d+[^\d.,]*$/,
- convert: function() {
- return this.get('text').toInt();
- },
- number: true
- },
- 'numberLax': {
- match: /^[^\d]+\d+$/,
- convert: function() {
- return this.get('text').replace(/[^0-9]/, '').toInt();
- },
- number: true
- },
- 'float': {
- match: /^[\d]+\.[\d]+/,
- convert: function() {
- return this.get('text').replace(/[^\d.]/, '').toFloat();
- },
- number: true
- },
- 'floatLax': {
- match: /^[^\d]+[\d]+\.[\d]+$/,
- convert: function() {
- return this.get('text').replace(/[^\d.]/, '');
- },
- number: true
- },
- 'string': {
- match: null,
- convert: function() {
- return this.get('text');
- }
- },
- 'title': {
- match: null,
- convert: function() {
- return this.title;
- }
- }
-
-});/*
----
-
-script: Keyboard.js
-
-description: KeyboardEvents used to intercept events on a class for keyboard and format modifiers in a specific order so as to make alt+shift+c the same as shift+alt+c.
-
-license: MIT-style license
-
-authors:
-- Perrin Westrich
-- Aaron Newton
-- Scott Kyle
-
-requires:
-- core:1.2.4/Events
-- core:1.2.4/Options
-- core:1.2.4/Element.Event
-- /Log
-
-provides: [Keyboard]
-
-...
-*/
-
-(function(){
-
- var parsed = {};
- var modifiers = ['shift', 'control', 'alt', 'meta'];
- var regex = /^(?:shift|control|ctrl|alt|meta)$/;
-
- var parse = function(type, eventType){
- type = type.toLowerCase().replace(/^(keyup|keydown):/, function($0, $1){
- eventType = $1;
- return '';
- });
-
- if (!parsed[type]){
- var key = '', mods = {};
- type.split('+').each(function(part){
- if (regex.test(part)) mods[part] = true;
- else key = part;
- });
-
- mods.control = mods.control || mods.ctrl; // allow both control and ctrl
- var match = '';
- modifiers.each(function(mod){
- if (mods[mod]) match += mod + '+';
- });
-
- parsed[type] = match + key;
- }
-
- return eventType + ':' + parsed[type];
- };
-
- this.Keyboard = new Class({
-
- Extends: Events,
-
- Implements: [Options, Log],
-
- options: {
- /*
- onActivate: $empty,
- onDeactivate: $empty,
- */
- defaultEventType: 'keydown',
- active: false,
- events: {}
- },
-
- initialize: function(options){
- this.setOptions(options);
- //if this is the root manager, nothing manages it
- if (Keyboard.manager) Keyboard.manager.manage(this);
- this.setup();
- },
-
- setup: function(){
- this.addEvents(this.options.events);
- if (this.options.active) this.activate();
- },
-
- handle: function(event, type){
- //Keyboard.stop(event) prevents key propagation
- if (!this.active || event.preventKeyboardPropagation) return;
-
- var bubbles = !!this.manager;
- if (bubbles && this.activeKB){
- this.activeKB.handle(event, type);
- if (event.preventKeyboardPropagation) return;
- }
- this.fireEvent(type, event);
-
- if (!bubbles && this.activeKB) this.activeKB.handle(event, type);
- },
-
- addEvent: function(type, fn, internal) {
- return this.parent(parse(type, this.options.defaultEventType), fn, internal);
- },
-
- removeEvent: function(type, fn) {
- return this.parent(parse(type, this.options.defaultEventType), fn);
- },
-
- activate: function(){
- this.active = true;
- return this.enable();
- },
-
- deactivate: function(){
- this.active = false;
- return this.fireEvent('deactivate');
- },
-
- toggleActive: function(){
- return this[this.active ? 'deactivate' : 'activate']();
- },
-
- enable: function(instance){
- if (instance) {
- //if we're stealing focus, store the last keyboard to have it so the relenquish command works
- if (instance != this.activeKB) this.previous = this.activeKB;
- //if we're enabling a child, assign it so that events are now passed to it
- this.activeKB = instance.fireEvent('activate');
- } else if (this.manager) {
- //else we're enabling ourselves, we must ask our parent to do it for us
- this.manager.enable(this);
- }
- return this;
- },
-
- relenquish: function(){
- if (this.previous) this.enable(this.previous);
- },
-
- //management logic
- manage: function(instance) {
- if (instance.manager) instance.manager.drop(instance);
- this.instances.push(instance);
- instance.manager = this;
- if (!this.activeKB) this.enable(instance);
- else this._disable(instance);
- },
-
- _disable: function(instance) {
- if (this.activeKB == instance) this.activeKB = null;
- },
-
- drop: function(instance) {
- this._disable(instance);
- this.instances.erase(instance);
- },
-
- instances: [],
-
- trace: function(){
- this.enableLog();
- var item = this;
- this.log('the following items have focus: ');
- while (item) {
- this.log(document.id(item.widget) || item.widget || item, 'active: ' + this.active);
- item = item.activeKB;
- }
- }
-
- });
-
- Keyboard.stop = function(event) {
- event.preventKeyboardPropagation = true;
- };
-
- Keyboard.manager = new this.Keyboard({
- active: true
- });
-
- Keyboard.trace = function(){
- Keyboard.manager.trace();
- };
-
- var handler = function(event){
- var mods = '';
- modifiers.each(function(mod){
- if (event[mod]) mods += mod + '+';
- });
- Keyboard.manager.handle(event, event.type + ':' + mods + event.key);
- };
-
- document.addEvents({
- 'keyup': handler,
- 'keydown': handler
- });
-
- Event.Keys.extend({
- 'pageup': 33,
- 'pagedown': 34,
- 'end': 35,
- 'home': 36,
- 'capslock': 20,
- 'numlock': 144,
- 'scrolllock': 145
- });
-
-})();
-/*
----
-
-script: HtmlTable.Select.js
-
-description: Builds a stripy, sortable table with methods to add rows. Rows can be selected with the mouse or keyboard navigation.
-
-license: MIT-style license
-
-authors:
-- Harald Kirschner
-- Aaron Newton
-
-requires:
-- /Keyboard
-- /HtmlTable
-- /Class.refactor
-- /Element.Delegation
-
-provides: [HtmlTable.Select]
-
-...
-*/
-
-HtmlTable = Class.refactor(HtmlTable, {
-
- options: {
- /*onRowSelect: $empty,
- onRowUnselect: $empty,*/
- useKeyboard: true,
- classRowSelected: 'table-tr-selected',
- classRowHovered: 'table-tr-hovered',
- classSelectable: 'table-selectable',
- allowMultiSelect: true,
- selectable: false
- },
-
- initialize: function(){
- this.previous.apply(this, arguments);
- if (this.occluded) return this.occluded;
- this.selectedRows = new Elements();
- this.bound = {
- mouseleave: this.mouseleave.bind(this),
- focusRow: this.focusRow.bind(this)
- };
- if (this.options.selectable) this.enableSelect();
- },
-
- enableSelect: function(){
- this.selectEnabled = true;
- this.attachSelects();
- this.element.addClass(this.options.classSelectable);
- },
-
- disableSelect: function(){
- this.selectEnabled = false;
- this.attach(false);
- this.element.removeClass(this.options.classSelectable);
- },
-
- attachSelects: function(attach){
- attach = $pick(attach, true);
- var method = attach ? 'addEvents' : 'removeEvents';
- this.element[method]({
- mouseleave: this.bound.mouseleave
- });
- this.body[method]({
- 'click:relay(tr)': this.bound.focusRow
- });
- if (this.options.useKeyboard || this.keyboard){
- if (!this.keyboard) this.keyboard = new Keyboard({
- events: {
- down: function(e) {
- e.preventDefault();
- this.shiftFocus(1);
- }.bind(this),
- up: function(e) {
- e.preventDefault();
- this.shiftFocus(-1);
- }.bind(this),
- enter: function(e) {
- e.preventDefault();
- if (this.hover) this.focusRow(this.hover);
- }.bind(this)
- },
- active: true
- });
- this.keyboard[attach ? 'activate' : 'deactivate']();
- }
- this.updateSelects();
- },
-
- mouseleave: function(){
- if (this.hover) this.leaveRow(this.hover);
- },
-
- focus: function(){
- if (this.keyboard) this.keyboard.activate();
- },
-
- blur: function(){
- if (this.keyboard) this.keyboard.deactivate();
- },
-
- push: function(){
- var ret = this.previous.apply(this, arguments);
- this.updateSelects();
- return ret;
- },
-
- updateSelects: function(){
- Array.each(this.body.rows, function(row){
- var binders = row.retrieve('binders');
- if ((binders && this.selectEnabled) || (!binders && !this.selectEnabled)) return;
- if (!binders){
- binders = {
- mouseenter: this.enterRow.bind(this, [row]),
- mouseleave: this.leaveRow.bind(this, [row])
- };
- row.store('binders', binders).addEvents(binders);
- } else {
- row.removeEvents(binders);
- }
- }, this);
- },
-
- enterRow: function(row){
- if (this.hover) this.hover = this.leaveRow(this.hover);
- this.hover = row.addClass(this.options.classRowHovered);
- },
-
- shiftFocus: function(offset){
- if (!this.hover) return this.enterRow(this.body.rows[0]);
- var to = Array.indexOf(this.body.rows, this.hover) + offset;
- if (to < 0) to = 0;
- if (to >= this.body.rows.length) to = this.body.rows.length - 1;
- if (this.hover == this.body.rows[to]) return this;
- this.enterRow(this.body.rows[to]);
- },
-
- leaveRow: function(row){
- row.removeClass(this.options.classRowHovered);
- },
-
- focusRow: function(){
- var row = arguments[1] || arguments[0]; //delegation passes the event first
- var unfocus = function(row){
- this.selectedRows.erase(row);
- row.removeClass(this.options.classRowSelected);
- this.fireEvent('rowUnfocus', [row, this.selectedRows]);
- }.bind(this);
- if (!this.options.allowMultiSelect) this.selectedRows.each(unfocus);
- if (!this.selectedRows.contains(row)) {
- this.selectedRows.push(row);
- row.addClass(this.options.classRowSelected);
- this.fireEvent('rowFocus', [row, this.selectedRows]);
- } else {
- unfocus(row);
- }
- return false;
- },
-
- selectAll: function(status){
- status = $pick(status, true);
- if (!this.options.allowMultiSelect && status) return;
- if (!status) this.selectedRows.removeClass(this.options.classRowSelected).empty();
- else this.selectedRows.combine(this.body.rows).addClass(this.options.classRowSelected);
- return this;
- },
-
- selectNone: function(){
- return this.selectAll(false);
- }
-
-});/*
----
-
-script: Scroller.js
-
-description: Class which scrolls the contents of any Element (including the window) when the mouse reaches the Element's boundaries.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-
-requires:
-- core:1.2.4/Events
-- core:1.2.4/Options
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Dimensions
-
-provides: [Scroller]
-
-...
-*/
-
-var Scroller = new Class({
-
- Implements: [Events, Options],
-
- options: {
- area: 20,
- velocity: 1,
- onChange: function(x, y){
- this.element.scrollTo(x, y);
- },
- fps: 50
- },
-
- initialize: function(element, options){
- this.setOptions(options);
- this.element = document.id(element);
- this.listener = ($type(this.element) != 'element') ? document.id(this.element.getDocument().body) : this.element;
- this.timer = null;
- this.bound = {
- attach: this.attach.bind(this),
- detach: this.detach.bind(this),
- getCoords: this.getCoords.bind(this)
- };
- },
-
- start: function(){
- this.listener.addEvents({
- mouseover: this.bound.attach,
- mouseout: this.bound.detach
- });
- },
-
- stop: function(){
- this.listener.removeEvents({
- mouseover: this.bound.attach,
- mouseout: this.bound.detach
- });
- this.detach();
- this.timer = $clear(this.timer);
- },
-
- attach: function(){
- this.listener.addEvent('mousemove', this.bound.getCoords);
- },
-
- detach: function(){
- this.listener.removeEvent('mousemove', this.bound.getCoords);
- 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(Math.round(1000 / this.options.fps), this);
- },
-
- scroll: function(){
- var size = this.element.getSize(),
- scroll = this.element.getScroll(),
- pos = this.element.getOffsets(),
- scrollSize = this.element.getScrollSize(),
- 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]) && scroll[z] + size[z] != scrollSize[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: Tips.js
-
-description: Class for creating nice tips that follow the mouse cursor when hovering an element.
-
-license: MIT-style license
-
-authors:
-- Valerio Proietti
-- Christoph Pojer
-
-requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Style
-- core:1.2.4/Element.Dimensions
-- /MooTools.More
-
-provides: [Tips]
-
-...
-*/
-
-(function(){
-
-var read = function(option, element){
- return (option) ? ($type(option) == 'function' ? option(element) : element.get(option)) : '';
-};
-
-this.Tips = new Class({
-
- Implements: [Events, Options],
-
- options: {
- /*
- onAttach: $empty(element),
- onDetach: $empty(element),
- */
- onShow: function(){
- this.tip.setStyle('display', 'block');
- },
- onHide: function(){
- this.tip.setStyle('display', 'none');
- },
- title: 'title',
- text: function(element){
- return element.get('rel') || element.get('href');
- },
- showDelay: 100,
- hideDelay: 100,
- className: 'tip-wrap',
- offset: {x: 16, y: 16},
- fixed: false
- },
-
- initialize: function(){
- var params = Array.link(arguments, {options: Object.type, elements: $defined});
- this.setOptions(params.options);
- document.id(this);
-
- if (params.elements) this.attach(params.elements);
- },
-
- toElement: function(){
- if (this.tip) return this.tip;
-
- this.container = new Element('div', {'class': 'tip'});
- return this.tip = new Element('div', {
- 'class': this.options.className,
- styles: {
- display: 'none',
- position: 'absolute',
- top: 0,
- left: 0
- }
- }).adopt(
- new Element('div', {'class': 'tip-top'}),
- this.container,
- new Element('div', {'class': 'tip-bottom'})
- ).inject(document.body);
- },
-
- attach: function(elements){
- $$(elements).each(function(element){
- var title = read(this.options.title, element),
- text = read(this.options.text, element);
-
- element.erase('title').store('tip:native', title).retrieve('tip:title', title);
- element.retrieve('tip:text', text);
- this.fireEvent('attach', [element]);
-
- var events = ['enter', 'leave'];
- if (!this.options.fixed) events.push('move');
-
- events.each(function(value){
- var event = element.retrieve('tip:' + value);
- if (!event) event = this['element' + value.capitalize()].bindWithEvent(this, element);
-
- element.store('tip:' + value, event).addEvent('mouse' + value, event);
- }, this);
- }, this);
-
- return this;
- },
-
- detach: function(elements){
- $$(elements).each(function(element){
- ['enter', 'leave', 'move'].each(function(value){
- element.removeEvent('mouse' + value, element.retrieve('tip:' + value)).eliminate('tip:' + value);
- });
-
- this.fireEvent('detach', [element]);
-
- if (this.options.title == 'title'){ // This is necessary to check if we can revert the title
- var original = element.retrieve('tip:native');
- if (original) element.set('title', original);
- }
- }, this);
-
- return this;
- },
-
- elementEnter: function(event, element){
- this.container.empty();
-
- ['title', 'text'].each(function(value){
- var content = element.retrieve('tip:' + value);
- if (content) this.fill(new Element('div', {'class': 'tip-' + value}).inject(this.container), content);
- }, this);
-
- $clear(this.timer);
- this.timer = this.show.delay(this.options.showDelay, this, element);
- this.position((this.options.fixed) ? {page: element.getPosition()} : event);
- },
-
- elementLeave: function(event, element){
- $clear(this.timer);
- this.timer = this.hide.delay(this.options.hideDelay, this, element);
- this.fireForParent(event, element);
- },
-
- fireForParent: function(event, element) {
- parentNode = element.getParent();
- if (parentNode == document.body) return;
- if (parentNode.retrieve('tip:enter')) parentNode.fireEvent('mouseenter', event);
- else return this.fireForParent(parentNode, event);
- },
-
- elementMove: function(event, element){
- this.position(event);
- },
-
- position: function(event){
- var size = window.getSize(), scroll = window.getScroll(),
- tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight},
- props = {x: 'left', y: 'top'},
- obj = {};
-
- for (var z in props){
- obj[props[z]] = event.page[z] + this.options.offset[z];
- if ((obj[props[z]] + tip[z] - scroll[z]) > size[z]) obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
- }
-
- this.tip.setStyles(obj);
- },
-
- fill: function(element, contents){
- if(typeof contents == 'string') element.set('html', contents);
- else element.adopt(contents);
- },
-
- show: function(element){
- this.fireEvent('show', [element]);
- },
-
- hide: function(element){
- this.fireEvent('hide', [element]);
- }
-
-});
-
-})();/*
----
-
-script: Date.Catalan.US.js
-
-description: Date messages for Catalan.
-
-license: MIT-style license
-
-authors:
-- Alfons Sanchez
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Catalan]
-
-...
-*/
-
-MooTools.lang.set('ca-CA', 'Date', {
-
- months: ['Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juli', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre'],
- days: ['Diumenge', 'Dilluns', 'Dimarts', 'Dimecres', 'Dijous', 'Divendres', 'Dissabte'],
- //culture's date order: MM/DD/YYYY
- dateOrder: ['date', 'month', 'year'],
-
- shortDate: '%d/%m/%Y',
- shortTime: '%H:%M',
-
- AM: 'AM',
- PM: 'PM',
-
- /* Date.Extras */
- ordinal: '',
-
- lessThanMinuteAgo: 'fa menys d`un minut',
- minuteAgo: 'fa un minut',
- minutesAgo: 'fa {delta} minuts',
- hourAgo: 'fa un hora',
- hoursAgo: 'fa unes {delta} hores',
- dayAgo: 'fa un dia',
- daysAgo: 'fa {delta} dies',
- lessThanMinuteUntil: 'menys d`un minut des d`ara',
- minuteUntil: 'un minut des d`ara',
- minutesUntil: '{delta} minuts des d`ara',
- hourUntil: 'un hora des d`ara',
- hoursUntil: 'unes {delta} hores des d`ara',
- dayUntil: '1 dia des d`ara',
- daysUntil: '{delta} dies des d`ara'
-
-});/*
----
-
-script: Date.Danish.js
-
-description: Date messages for Danish.
-
-license: MIT-style license
-
-authors:
-- Martin Overgaard
-- Henrik Hansen
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Danish]
-
-...
-*/
-
-MooTools.lang.set('da-DK', 'Date', {
-
- months: ['Januar', 'Februa', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December'],
- days: ['Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'],
- //culture's date order: DD/MM/YYYY
- dateOrder: ['date', 'month', 'year'],
-
- AM: 'AM',
- PM: 'PM',
-
- shortDate: '%d-%m-%Y',
- shortTime: '%H:%M',
-
- /* Date.Extras */
- ordinal: function(dayOfMonth){
- //1st, 2nd, 3rd, etc.
- return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)];
- },
-
- lessThanMinuteAgo: 'mindre end et minut siden',
- minuteAgo: 'omkring et minut siden',
- minutesAgo: '{delta} minutter siden',
- hourAgo: 'omkring en time siden',
- hoursAgo: 'omkring {delta} timer siden',
- dayAgo: '1 dag siden',
- daysAgo: '{delta} dage siden',
- weekAgo: '1 uge siden',
- weeksAgo: '{delta} uger siden',
- monthAgo: '1 måned siden',
- monthsAgo: '{delta} måneder siden',
- yearthAgo: '1 år siden',
- yearsAgo: '{delta} år siden',
- lessThanMinuteUntil: 'mindre end et minut fra nu',
- minuteUntil: 'omkring et minut fra nu',
- minutesUntil: '{delta} minutter fra nu',
- hourUntil: 'omkring en time fra nu',
- hoursUntil: 'omkring {delta} timer fra nu',
- dayUntil: '1 dag fra nu',
- daysUntil: '{delta} dage fra nu',
- weekUntil: '1 uge fra nu',
- weeksUntil: '{delta} uger fra nu',
- monthUntil: '1 måned fra nu',
- monthsUntil: '{delta} måneder fra nu',
- yearUntil: '1 år fra nu',
- yearsUntil: '{delta} år fra nu'
-
-});
-/*
----
-
-script: Date.Dutch.js
-
-description: Date messages in Dutch.
-
-license: MIT-style license
-
-authors:
-- Lennart Pilon
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Dutch]
-
-...
-*/
-
-MooTools.lang.set('nl-NL', 'Date', {
-
- months: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
- days: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag'],
- //culture's date order: DD/MM/YYYY
- dateOrder: ['date', 'month', 'year'],
-
- AM: 'AM',
- PM: 'PM',
-
- shortDate: '%d/%m/%Y',
- shortTime: '%H:%M',
-
- /* Date.Extras */
- ordinal: 'e',
-
- lessThanMinuteAgo: 'minder dan een minuut geleden',
- minuteAgo: 'ongeveer een minuut geleden',
- minutesAgo: 'minuten geleden',
- hourAgo: 'ongeveer een uur geleden',
- hoursAgo: 'ongeveer {delta} uur geleden',
- dayAgo: '{delta} dag geleden',
- daysAgo: 'dagen geleden',
- weekAgo: 'een week geleden',
- weeksAgo: '{delta} weken geleden',
- monthAgo: 'een maand geleden',
- monthsAgo: '{delta} maanden geleden',
- yearAgo: 'een jaar geleden',
- yearsAgo: '{delta} jaar geleden',
- lessThanMinuteUntil: 'minder dan een minuut vanaf nu',
- minuteUntil: 'ongeveer een minuut vanaf nu',
- minutesUntil: '{delta} minuten vanaf nu',
- hourUntil: 'ongeveer een uur vanaf nu',
- hoursUntil: 'ongeveer {delta} uur vanaf nu',
- dayUntil: '1 dag vanaf nu',
- daysUntil: '{delta} dagen vanaf nu',
- weekAgo: 'een week geleden',
- weeksAgo: '{delta} weken geleden',
- monthAgo: 'een maand geleden',
- monthsAgo: '{delta} maanden geleden',
- yearthAgo: 'een jaar geleden',
- yearsAgo: '{delta} jaar geleden',
-
- weekUntil: 'over een week',
- weeksUntil: 'over {delta} weken',
- monthUntil: 'over een maand',
- monthsUntil: 'over {delta} maanden',
- yearUntil: 'over een jaar',
- yearsUntil: 'over {delta} jaar'
-
-});/*
----
-
-script: Date.English.GB.js
-
-description: Date messages for British English.
-
-license: MIT-style license
-
-authors:
-- Aaron Newton
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.English.GB]
-
-...
-*/
-
-MooTools.lang.set('en-GB', 'Date', {
-
- dateOrder: ['date', 'month', 'year'],
-
- shortDate: '%d/%m/%Y',
- shortTime: '%H:%M'
-
-}).set('cascade', ['en-US']);/*
----
-
-script: Date.Estonian.js
-
-description: Date messages for Estonian.
-
-license: MIT-style license
-
-authors:
-- Kevin Valdek
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Estonian]
-
-...
-*/
-
-MooTools.lang.set('et-EE', 'Date', {
-
- months: ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli', 'august', 'september', 'oktoober', 'november', 'detsember'],
- days: ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev', 'neljapäev', 'reede', 'laupäev'],
- //culture's date order: MM.DD.YYYY
- dateOrder: ['month', 'date', 'year'],
-
- AM: 'AM',
- PM: 'PM',
-
- shortDate: '%m.%d.%Y',
- shortTime: '%H:%M',
-
- /* Date.Extras */
- ordinal: '',
-
- lessThanMinuteAgo: 'vähem kui minut aega tagasi',
- minuteAgo: 'umbes minut aega tagasi',
- minutesAgo: '{delta} minutit tagasi',
- hourAgo: 'umbes tund aega tagasi',
- hoursAgo: 'umbes {delta} tundi tagasi',
- dayAgo: '1 päev tagasi',
- daysAgo: '{delta} päeva tagasi',
- weekAgo: '1 nädal tagasi',
- weeksAgo: '{delta} nädalat tagasi',
- monthAgo: '1 kuu tagasi',
- monthsAgo: '{delta} kuud tagasi',
- yearAgo: '1 aasta tagasi',
- yearsAgo: '{delta} aastat tagasi',
- lessThanMinuteUntil: 'vähem kui minuti aja pärast',
- minuteUntil: 'umbes minuti aja pärast',
- minutesUntil: '{delta} minuti pärast',
- hourUntil: 'umbes tunni aja pärast',
- hoursUntil: 'umbes {delta} tunni pärast',
- dayUntil: '1 päeva pärast',
- daysUntil: '{delta} päeva pärast',
- weekUntil: '1 nädala pärast',
- weeksUntil: '{delta} nädala pärast',
- monthUntil: '1 kuu pärast',
- monthsUntil: '{delta} kuu pärast',
- yearUntil: '1 aasta pärast',
- yearsUntil: '{delta} aasta pärast'
-
-});/*
----
-
-script: Date.French.js
-
-description: Date messages in French.
-
-license: MIT-style license
-
-authors:
-- Nicolas Sorosac
-- Antoine Abt
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.French]
-
-...
-*/
-
-MooTools.lang.set('fr-FR', 'Date', {
-
- months: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
- days: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
- dateOrder: ['date', 'month', 'year'],
-
- AM: 'AM',
- PM: 'PM',
-
- shortDate: '%d/%m/%Y',
- shortTime: '%H:%M',
-
- /* Date.Extras */
- getOrdinal: function(dayOfMonth){
- return (dayOfMonth > 1) ? '' : 'er';
- },
-
- lessThanMinuteAgo: 'il y a moins d\'une minute',
- minuteAgo: 'il y a une minute',
- minutesAgo: 'il y a {delta} minutes',
- hourAgo: 'il y a une heure',
- hoursAgo: 'il y a {delta} heures',
- dayAgo: 'il y a un jour',
- daysAgo: 'il y a {delta} jours',
- weekAgo: 'il y a une semaine',
- weeksAgo: 'il y a {delta} semaines',
- monthAgo: 'il y a 1 mois',
- monthsAgo: 'il y a {delta} mois',
- yearthAgo: 'il y a 1 an',
- yearsAgo: 'il y a {delta} ans',
- lessThanMinuteUntil: 'dans moins d\'une minute',
- minuteUntil: 'dans une minute',
- minutesUntil: 'dans {delta} minutes',
- hourUntil: 'dans une heure',
- hoursUntil: 'dans {delta} heures',
- dayUntil: 'dans un jour',
- daysUntil: 'dans {delta} jours',
- weekUntil: 'dans 1 semaine',
- weeksUntil: 'dans {delta} semaines',
- monthUntil: 'dans 1 mois',
- monthsUntil: 'dans {delta} mois',
- yearUntil: 'dans 1 an',
- yearsUntil: 'dans {delta} ans'
-
-});
-/*
----
-
-script: Date.Italian.js
-
-description: Date messages for Italian.
-
-license: MIT-style license.
-
-authors:
-- Andrea Novero
-- Valerio Proietti
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Italian]
-
-...
-*/
-
-MooTools.lang.set('it-IT', 'Date', {
-
- months: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'],
- days: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'],
- //culture's date order: DD/MM/YYYY
- dateOrder: ['date', 'month', 'year'],
-
- AM: 'AM',
- PM: 'PM',
-
- shortDate: '%d/%m/%Y',
- shortTime: '%H.%M',
-
- /* Date.Extras */
- ordinal: 'º',
-
- lessThanMinuteAgo: 'meno di un minuto fa',
- minuteAgo: 'circa un minuto fa',
- minutesAgo: 'circa {delta} minuti fa',
- hourAgo: 'circa un\'ora fa',
- hoursAgo: 'circa {delta} ore fa',
- dayAgo: 'circa 1 giorno fa',
- daysAgo: 'circa {delta} giorni fa',
- lessThanMinuteUntil: 'tra meno di un minuto',
- minuteUntil: 'tra circa un minuto',
- minutesUntil: 'tra circa {delta} minuti',
- hourUntil: 'tra circa un\'ora',
- hoursUntil: 'tra circa {delta} ore',
- dayUntil: 'tra circa un giorno',
- daysUntil: 'tra circa {delta} giorni'
-
-});/*
----
-
-script: Date.Norwegian.js
-
-description: Date messages in Norwegian.
-
-license: MIT-style license
-
-authors:
-- Espen 'Rexxars' Hovlandsdal
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Norwegian]
-
-...
-*/
-
-MooTools.lang.set('no-NO', 'Date', {
-
- dateOrder: ['date', 'month', 'year'],
-
- shortDate: '%d.%m.%Y',
- shortTime: '%H:%M',
-
- lessThanMinuteAgo: 'kortere enn et minutt siden',
- minuteAgo: 'omtrent et minutt siden',
- minutesAgo: '{delta} minutter siden',
- hourAgo: 'omtrent en time siden',
- hoursAgo: 'omtrent {delta} timer siden',
- dayAgo: '{delta} dag siden',
- daysAgo: '{delta} dager siden'
-
-});/*
----
-
-script: Date.Polish.js
-
-description: Date messages for Polish.
-
-license: MIT-style license
-
-authors:
-- Oskar Krawczyk
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Polish]
-
-...
-*/
-
-MooTools.lang.set('pl-PL', 'Date', {
- months: ['StyczeÅ', 'Luty', 'Marzec', 'KwiecieÅ', 'Maj', 'Czerwiec', 'Lipiec', 'SierpieÅ', 'WrzesieÅ', 'Październik', 'Listopad', 'GrudzieÅ'],
- days: ['Niedziela', 'PoniedziaÅek', 'Wtorek', 'Åroda', 'Czwartek', 'PiÄ
tek', 'Sobota'],
- dateOrder: ['year', 'month', 'date'],
- AM: 'nad ranem',
- PM: 'po poÅudniu',
-
- shortDate: '%Y-%m-%d',
- shortTime: '%H:%M',
-
- /* Date.Extras */
- ordinal: function(dayOfMonth){
- return (dayOfMonth > 3 && dayOfMonth < 21) ? 'ty' : ['ty', 'szy', 'gi', 'ci', 'ty'][Math.min(dayOfMonth % 10, 4)];
- },
-
- lessThanMinuteAgo: 'mniej niż minute temu',
- minuteAgo: 'okoÅo minutÄ temu',
- minutesAgo: '{delta} minut temu',
- hourAgo: 'okoÅo godzinÄ temu',
- hoursAgo: 'okoÅo {delta} godzin temu',
- dayAgo: 'Wczoraj',
- daysAgo: '{delta} dni temu',
- lessThanMinuteUntil: 'za niecaÅÄ
minutÄ',
- minuteUntil: 'za okoÅo minutÄ',
- minutesUntil: 'za {delta} minut',
- hourUntil: 'za okoÅo godzinÄ',
- hoursUntil: 'za okoÅo {delta} godzin',
- dayUntil: 'za 1 dzieÅ',
- daysUntil: 'za {delta} dni'
-});/*
----
-
-script: Date.Portuguese.BR.js
-
-description: Date messages in Portuguese-BR (Brazil).
-
-license: MIT-style license
-
-authors:
-- Fabio Miranda Costa
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Portuguese.BR]
-
-...
-*/
-
-MooTools.lang.set('pt-BR', 'Date', {
-
- months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
- days: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'],
- //culture's date order: DD/MM/YYYY
- dateOrder: ['date', 'month', 'year'],
- shortDate: '%d/%m/%Y',
- shortTime: '%H:%M',
-
- /* Date.Extras */
- ordinal: function(dayOfMonth){
- //1º, 2º, 3º, etc.
- return 'º';
- },
-
- lessThanMinuteAgo: 'há menos de um minuto',
- minuteAgo: 'há cerca de um minuto',
- minutesAgo: 'há {delta} minutos',
- hourAgo: 'há cerca de uma hora',
- hoursAgo: 'há cerca de {delta} horas',
- dayAgo: 'há um dia',
- daysAgo: 'há {delta} dias',
- weekAgo: 'há uma semana',
- weeksAgo: 'há {delta} semanas',
- monthAgo: 'há um mês',
- monthsAgo: 'há {delta} meses',
- yearAgo: 'há um ano',
- yearsAgo: 'há {delta} anos',
- lessThanMinuteUntil: 'em menos de um minuto',
- minuteUntil: 'em um minuto',
- minutesUntil: 'em {delta} minutos',
- hourUntil: 'em uma hora',
- hoursUntil: 'em {delta} horas',
- dayUntil: 'em um dia',
- daysUntil: 'em {delta} dias',
- weekUntil: 'em uma semana',
- weeksUntil: 'em {delta} semanas',
- monthUntil: 'em um mês',
- monthsUntil: 'em {delta} meses',
- yearUntil: 'em um ano',
- yearsUntil: 'em {delta} anos'
-
-});/*
----
-
-script: Date.Spanish.US.js
-
-description: Date messages for Spanish.
-
-license: MIT-style license
-
-authors:
-- Ãlfons Sanchez
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Spanish]
-
-...
-*/
-
-MooTools.lang.set('es-ES', 'Date', {
-
- months: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
- days: ['Domingo', 'Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado'],
- //culture's date order: MM/DD/YYYY
- dateOrder: ['date', 'month', 'year'],
- AM: 'AM',
- PM: 'PM',
-
- shortDate: '%d/%m/%Y',
- shortTime: '%H:%M',
-
- /* Date.Extras */
- ordinal: '',
-
- lessThanMinuteAgo: 'hace menos de un minuto',
- minuteAgo: 'hace un minuto',
- minutesAgo: 'hace {delta} minutos',
- hourAgo: 'hace una hora',
- hoursAgo: 'hace unas {delta} horas',
- dayAgo: 'hace un dia',
- daysAgo: 'hace {delta} dias',
- weekAgo: 'hace una semana',
- weeksAgo: 'hace unas {delta} semanas',
- monthAgo: 'hace un mes',
- monthsAgo: 'hace {delta} meses',
- yearAgo: 'hace un año',
- yearsAgo: 'hace {delta} años',
- lessThanMinuteUntil: 'menos de un minuto desde ahora',
- minuteUntil: 'un minuto desde ahora',
- minutesUntil: '{delta} minutos desde ahora',
- hourUntil: 'una hora desde ahora',
- hoursUntil: 'unas {delta} horas desde ahora',
- dayUntil: 'un dia desde ahora',
- daysUntil: '{delta} dias desde ahora',
- weekUntil: 'una semana desde ahora',
- weeksUntil: 'unas {delta} semanas desde ahora',
- monthUntil: 'un mes desde ahora',
- monthsUntil: '{delta} meses desde ahora',
- yearUntil: 'un año desde ahora',
- yearsUntil: '{delta} años desde ahora'
-
-});/*
----
-
-script: Date.Swedish.js
-
-description: Date messages for Swedish (SE).
-
-license: MIT-style license
-
-authors:
-- Martin Lundgren
-
-requires:
-- /Lang
-- /Date
-
-provides: [Date.Swedish]
-
-...
-*/
-
-MooTools.lang.set('sv-SE', 'Date', {
-
- months: ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december'],
- days: ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lördag'],
- // culture's date order: YYYY-MM-DD
- dateOrder: ['year', 'month', 'date'],
- AM: '',
- PM: '',
-
- shortDate: '%Y-%m-%d',
- shortTime: '%H:%M',
-
- /* Date.Extras */
- ordinal: function(dayOfMonth){
- // Not used in Swedish
- return '';
- },
-
- lessThanMinuteAgo: 'mindre än en minut sedan',
- minuteAgo: 'ungefär en minut sedan',
- minutesAgo: '{delta} minuter sedan',
- hourAgo: 'ungefär en timme sedan',
- hoursAgo: 'ungefär {delta} timmar sedan',
- dayAgo: '1 dag sedan',
- daysAgo: '{delta} dagar sedan',
- lessThanMinuteUntil: 'mindre än en minut sedan',
- minuteUntil: 'ungefär en minut sedan',
- minutesUntil: '{delta} minuter sedan',
- hourUntil: 'ungefär en timme sedan',
- hoursUntil: 'ungefär {delta} timmar sedan',
- dayUntil: '1 dag sedan',
- daysUntil: '{delta} dagar sedan'
-
-});/*
----
-
-script: Form.Validator.Arabic.js
-
-description: Form.Validator messages in Arabic.
-
-license: MIT-style license
-
-authors:
-- Chafik Barbar
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Arabic]
-
-...
-*/
-
-MooTools.lang.set('ar', 'Form.Validator', {
- required:'Ùذا اÙØÙÙ Ù
Ø·ÙÙب.',
- minLength:'رجاء٠إدخا٠{minLength} Ø£Øر٠عÙ٠اÙØ£ÙÙ (تÙ
إدخا٠{length} Ø£ØرÙ).',
- maxLength:'اÙرجاء عدÙ
إدخا٠أÙثر Ù
Ù {maxLength} Ø£Øر٠(تÙ
إدخا٠{length} Ø£ØرÙ).',
- integer:'اÙرجاء إدخا٠عدد صØÙØ ÙÙ Ùذا اÙØÙÙ. أ٠رÙÙ
Ø°Ù Ùسر عشر٠أ٠Ù
ئÙÙ (Ù
ثا٠1.25 ) غÙر Ù
سÙ
ÙØ.',
- numeric:'اÙرجاء إدخا٠ÙÙÙ
رÙÙ
ÙØ© ÙÙ Ùذا اÙØÙÙ (Ù
ثا٠"1" أ٠"1.1" أ٠"-1" أ٠"-1.1").',
- digits:'اÙرجاء أستخداÙ
ÙÙÙ
رÙÙ
ÙØ© ÙعÙاÙ
ات ترÙÙÙ
ÙØ© ÙÙØ· ÙÙ Ùذا اÙØÙÙ (Ù
ثاÙ, رÙÙ
Ùات٠Ù
ع ÙÙطة Ø£Ù Ø´Øطة)',
- alpha:'اÙرجاء أستخداÙ
Ø£Øر٠ÙÙØ· (ا-Ù) ÙÙ Ùذا اÙØÙÙ. Ø£Ù Ùراغات أ٠عÙاÙ
ات غÙر Ù
سÙ
ÙØØ©.',
- alphanum:'اÙرجاء أستخداÙ
Ø£Øر٠ÙÙØ· (ا-Ù) أ٠أرÙاÙ
(0-9) ÙÙØ· ÙÙ Ùذا اÙØÙÙ. Ø£Ù Ùراغات أ٠عÙاÙ
ات غÙر Ù
سÙ
ÙØØ©.',
- dateSuchAs:'اÙرجاء إدخا٠تارÙØ® صØÙØ ÙاÙتاÙÙ {date}',
- dateInFormatMDY:'اÙرجاء إدخا٠تارÙØ® صØÙØ (Ù
ثاÙ, 31-12-1999)',
- email:'اÙرجاء إدخا٠برÙد Ø¥ÙÙترÙÙ٠صØÙØ.',
- url:'اÙرجاء إدخا٠عÙÙا٠إÙÙترÙÙ٠صØÙØ Ù
Ø«Ù http://www.google.com',
- currencyDollar:'اÙرجاء إدخا٠ÙÙÙ
Ø© $ صØÙØØ©. Ù
ثاÙ, 100.00$',
- oneRequired:'اÙرجاء إدخا٠ÙÙÙ
Ø© Ù٠أØد Ùذ٠اÙØÙÙ٠عÙ٠اÙØ£ÙÙ.',
- errorPrefix: 'خطأ: ',
- warningPrefix: 'تØØ°Ùر: '
-}).set('ar', 'Date', {
- dateOrder: ['date', 'month', 'year', '/']
-});/*
----
-
-script: Form.Validator.Catalan.js
-
-description: Date messages for Catalan.
-
-license: MIT-style license
-
-authors:
-- Miquel Hudin
-- Alfons Sanchez
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Catalan]
-
-...
-*/
-
-MooTools.lang.set('ca-CA', 'Form.Validator', {
-
- required:'Aquest camp es obligatori.',
- minLength:'Per favor introdueix al menys {minLength} caracters (has introduit {length} caracters).',
- maxLength:'Per favor introdueix no mes de {maxLength} caracters (has introduit {length} caracters).',
- integer:'Per favor introdueix un nombre enter en aquest camp. Nombres amb decimals (p.e. 1,25) no estan permesos.',
- numeric:'Per favor introdueix sols valors numerics en aquest camp (p.e. "1" o "1,1" o "-1" o "-1,1").',
- digits:'Per favor usa sols numeros i puntuacio en aquest camp (per exemple, un nombre de telefon amb guions i punts no esta permes).',
- alpha:'Per favor utilitza lletres nomes (a-z) en aquest camp. No s´admiteixen espais ni altres caracters.',
- alphanum:'Per favor, utilitza nomes lletres (a-z) o numeros (0-9) en aquest camp. No s´admiteixen espais ni altres caracters.',
- dateSuchAs:'Per favor introdueix una data valida com {date}',
- dateInFormatMDY:'Per favor introdueix una data valida com DD/MM/YYYY (p.e. "31/12/1999")',
- email:'Per favor, introdueix una adreça de correu electronic valida. Per exemple, "fred at domain.com".',
- url:'Per favor introdueix una URL valida com http://www.google.com.',
- currencyDollar:'Per favor introdueix una quantitat valida de â¬. Per exemple â¬100,00 .',
- oneRequired:'Per favor introdueix alguna cosa per al menys una d´aquestes entrades.',
- errorPrefix: 'Error: ',
- warningPrefix: 'Avis: ',
-
- //Form.Validator.Extras
-
- noSpace: 'No poden haver espais en aquesta entrada.',
- reqChkByNode: 'No hi han elements seleccionats.',
- requiredChk: 'Aquest camp es obligatori.',
- reqChkByName: 'Per favor selecciona una {label}.',
- match: 'Aquest camp necessita coincidir amb el camp {matchName}',
- startDate: 'la data de inici',
- endDate: 'la data de fi',
- currendDate: 'la data actual',
- afterDate: 'La data deu ser igual o posterior a {label}.',
- beforeDate: 'La data deu ser igual o anterior a {label}.',
- startMonth: 'Per favor selecciona un mes d´orige',
- sameMonth: 'Aquestes dos dates deuen estar dins del mateix mes - deus canviar una o altra.'
-
-});/*
----
-
-script: Form.Validator.Chinese.js
-
-description: Form.Validator messages in chinese (both simplified and traditional).
-
-license: MIT-style license
-
-authors:
-- éæ¡å - guidy <at> ixuer [dot] net
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Chinese]
-
-...
-*/
-
-/*
-In Chinese:
-------------
-éè¦æåºçæ¯ï¼
-ç®ä½ä¸æéç¨äºä¸å½å¤§éï¼
-ç¹ä½ä¸æéç¨äºé¦æ¸¯ãæ¾³é¨åå°æ¹¾çã
-ç®ä½ä¸æåç¹ä½ä¸æå¨åä½åè¯æ³ä¸æå¾å¤çä¸åä¹å¤ã
-
-æå¯ä»¥ç¡®ä¿ç®ä½ä¸æè¯è¨å
çåç¡®æ§ï¼
-ä½å¯¹äºç¹ä½ä¸æï¼æå¯ä»¥ä¿è¯ç¨æ·å¯ä»¥åç¡®çç解ï¼ä½æ æ³ä¿è¯è¯å¥ç¬¦åä»ä»¬çé
è¯»ä¹ æ¯ã
-å¦ææ¨ä¸è½ç¡®è®¤çè¯ï¼å¯ä»¥åªä½¿ç¨ç®ä½ä¸æè¯è¨å
ï¼å 为å®æ¯æéç¨çã
-
-In English:
-------------
-It should be noted that:
-Simplified Chinese apply to mainland Chinese,
-Traditional Chinese apply to Hong Kong, Macao and Taiwan Province.
-There are a lot of different from Simplified Chinese and Traditional Chinese , Contains font and syntax .
-
-I can assure Simplified Chinese language pack accuracy .
-For Traditional Chinese, I can only guarantee that users can understand, but not necessarily in line with their reading habits.
-If you are unsure, you can only use the simplified Chinese language pack, as it is the most common.
-
-*/
-
-// Simplified Chinese
-MooTools.lang.set('zhs-CN', 'Form.Validator', {
- required:'è¿æ¯å¿
填项ã',
- minLength:'请è³å°è¾å
¥ {minLength} 个å符 (å·²è¾å
¥ {length} 个)ã',
- maxLength:'æå¤åªè½è¾å
¥ {maxLength} 个å符 (å·²è¾å
¥ {length} 个)ã',
- integer:'请è¾å
¥ä¸ä¸ªæ´æ°ï¼ä¸è½å
å«å°æ°ç¹ãä¾å¦ï¼"1", "200"ã',
- numeric:'请è¾å
¥ä¸ä¸ªæ°åï¼ä¾å¦ï¼"1", "1.1", "-1", "-1.1"ã',
- digits:'è¿éåªè½æ¥åæ°ååæ ç¹çè¾å
¥ï¼æ ç¹å¯ä»¥æ¯ï¼"(", ")", ".", ":", "-", "+", "#"åç©ºæ ¼ã',
- alpha:'请è¾å
¥ A-Z ç 26 个åæ¯ï¼ä¸è½å
å«ç©ºæ ¼æä»»ä½å
¶ä»å符ã',
- alphanum:'请è¾å
¥ A-Z ç 26 个åæ¯æ 0-9 ç 10 个æ°åï¼ä¸è½å
å«ç©ºæ ¼æä»»ä½å
¶ä»å符ã',
- dateSuchAs:'请è¾å
¥åæ³çæ¥ææ ¼å¼ï¼å¦ï¼{date}ã',
- dateInFormatMDY:'请è¾å
¥åæ³çæ¥ææ ¼å¼ï¼ä¾å¦ï¼MM/DD/YYYY ("12/31/1999")ã',
- email:'请è¾å
¥åæ³ççµåä¿¡ç®±å°åï¼ä¾å¦ï¼"fred at domain.com"ã',
- url:'请è¾å
¥åæ³ç Url å°åï¼ä¾å¦ï¼http://www.google.comã',
- currencyDollar:'请è¾å
¥åæ³çè´§å¸ç¬¦å·ï¼ä¾å¦ï¼ï¿¥',
- oneRequired:'请è³å°éæ©ä¸é¡¹ã',
- errorPrefix: 'é误ï¼',
- warningPrefix: 'è¦åï¼'
-});
-
-// Traditional Chinese
-MooTools.lang.set('zht-CN', 'Form.Validator', {
- required:'éæ¯å¿
å¡«é
ã',
- minLength:'è«è³å°éµå
¥ {minLength} åå符(å·²éµå
¥ {length} å)ã',
- maxLength:'æå¤åªè½éµå
¥ {maxLength} åå符(å·²éµå
¥ {length} å)ã',
- integer:'è«éµå
¥ä¸åæ´æ¸ï¼ä¸è½å
å«å°æ¸é»ãä¾å¦ï¼"1", "200"ã',
- numeric:'è«éµå
¥ä¸åæ¸åï¼ä¾å¦ï¼"1", "1.1", "-1", "-1.1"ã',
- digits:'é裡åªè½æ¥åæ¸ååæ¨é»çéµå
¥ï¼æ¨é»å¯ä»¥æ¯ï¼"(", ")", ".", ":", "-", "+", "#"åç©ºæ ¼ã',
- alpha:'è«éµå
¥ A-Z ç 26 ååæ¯ï¼ä¸è½å
å«ç©ºæ ¼æä»»ä½å
¶ä»å符ã',
- alphanum:'è«éµå
¥ A-Z ç 26 ååæ¯æ 0-9 ç 10 åæ¸åï¼ä¸è½å
å«ç©ºæ ¼æä»»ä½å
¶ä»å符ã',
- dateSuchAs:'è«éµå
¥åæ³çæ¥ææ ¼å¼ï¼å¦ï¼{date}ã',
- dateInFormatMDY:'è«éµå
¥åæ³çæ¥ææ ¼å¼ï¼ä¾å¦ï¼MM/DD/YYYY ("12/31/1999")ã',
- email:'è«éµå
¥åæ³çé»åä¿¡ç®±å°åï¼ä¾å¦ï¼"fred at domain.com"ã',
- url:'è«éµå
¥åæ³ç Url å°åï¼ä¾å¦ï¼http://www.google.comã',
- currencyYuan:'è«éµå
¥åæ³ç貨幣符èï¼ä¾å¦ï¼ï¿¥',
- oneRequired:'è«è³å°é¸æä¸é
ã',
- errorPrefix: 'é¯èª¤ï¼',
- warningPrefix: 'è¦åï¼'
-});
-
-Form.Validator.add('validate-currency-yuan', {
- errorMsg: function(){
- return Form.Validator.getMsg('currencyYuan');
- },
- test: function(element) {
- // [ï¿¥]1[##][,###]+[.##]
- // [ï¿¥]1###+[.##]
- // [ï¿¥]0.##
- // [ï¿¥].##
- return Form.Validator.getValidator('IsEmpty').test(element) || (/^ï¿¥?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/).test(element.get('value'));
- }
-});
-/*
----
-
-script: Form.Validator.Dutch.js
-
-description: Form.Validator messages in Dutch.
-
-license: MIT-style license
-
-authors:
-- Lennart Pilon
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Dutch]
-
-...
-*/
-
-MooTools.lang.set('nl-NL', 'Form.Validator', {
- required:'Dit veld is verplicht.',
- minLength:'Vul minimaal {minLength} karakters in (je hebt {length} karakters ingevoerd).',
- maxLength:'Vul niet meer dan {maxLength} karakters in (je hebt {length} karakters ingevoerd).',
- integer:'Vul een getal in. Getallen met decimalen (bijvoorbeeld 1,25) zijn niet toegestaan.',
- numeric:'Vul alleen numerieke waarden in (bijvoorbeeld. "1" of "1.1" of "-1" of "-1.1").',
- digits:'Vul alleen nummers en leestekens in (bijvoorbeeld een telefoonnummer met een streepje).',
- alpha:'Vul alleen letters in (a-z). Spaties en andere karakters zijn niet toegestaan.',
- alphanum:'Vul alleen letters in (a-z) of nummers (0-9). Spaties en andere karakters zijn niet toegestaan.',
- dateSuchAs:'Vul een geldige datum in, zoals {date}',
- dateInFormatMDY:'Vul een geldige datum, in het formaat MM/DD/YYYY (bijvoorbeeld "12/31/1999")',
- email:'Vul een geldig e-mailadres in. Bijvoorbeeld "fred at domein.nl".',
- url:'Vul een geldige URL in, zoals http://www.google.nl.',
- currencyDollar:'Vul een geldig $ bedrag in. Bijvoorbeeld $100.00 .',
- oneRequired:'Vul iets in bij minimaal een van de invoervelden.',
- warningPrefix: 'Waarschuwing: ',
- errorPrefix: 'Fout: '
-});/*
----
-
-script: Form.Validator.Estonian.js
-
-description: Date messages for Estonian.
-
-license: MIT-style license
-
-authors:
-- Kevin Valdek
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Estonian]
-
-...
-*/
-
-MooTools.lang.set('et-EE', 'Form.Validator', {
-
- required:'Väli peab olema täidetud.',
- minLength:'Palun sisestage vähemalt {minLength} tähte (te sisestasite {length} tähte).',
- maxLength:'Palun ärge sisestage rohkem kui {maxLength} tähte (te sisestasite {length} tähte).',
- integer:'Palun sisestage väljale täisarv. Kümnendarvud (näiteks 1.25) ei ole lubatud.',
- numeric:'Palun sisestage ainult numbreid väljale (näiteks "1", "1.1", "-1" või "-1.1").',
- digits:'Palun kasutage ainult numbreid ja kirjavahemärke (telefoninumbri sisestamisel on lubatud kasutada kriipse ja punkte).',
- alpha:'Palun kasutage ainult tähti (a-z). Tühikud ja teised sümbolid on keelatud.',
- alphanum:'Palun kasutage ainult tähti (a-z) või numbreid (0-9). Tühikud ja teised sümbolid on keelatud.',
- dateSuchAs:'Palun sisestage kehtiv kuupäev kujul {date}',
- dateInFormatMDY:'Palun sisestage kehtiv kuupäev kujul MM.DD.YYYY (näiteks: "12.31.1999").',
- email:'Palun sisestage kehtiv e-maili aadress (näiteks: "fred at domain.com").',
- url:'Palun sisestage kehtiv URL (näiteks: http://www.google.com).',
- currencyDollar:'Palun sisestage kehtiv $ summa (näiteks: $100.00).',
- oneRequired:'Palun sisestage midagi vähemalt ühele antud väljadest.',
- errorPrefix: 'Viga: ',
- warningPrefix: 'Hoiatus: ',
-
- //Form.Validator.Extras
-
- noSpace: 'Väli ei tohi sisaldada tühikuid.',
- reqChkByNode: 'Ãkski väljadest pole valitud.',
- requiredChk: 'Välja täitmine on vajalik.',
- reqChkByName: 'Palun valige üks {label}.',
- match: 'Väli peab sobima {matchName} väljaga',
- startDate: 'algkuupäev',
- endDate: 'lõppkuupäev',
- currendDate: 'praegune kuupäev',
- afterDate: 'Kuupäev peab olema võrdne või pärast {label}.',
- beforeDate: 'Kuupäev peab olema võrdne või enne {label}.',
- startMonth: 'Palun valige algkuupäev.',
- sameMonth: 'Antud kaks kuupäeva peavad olema samas kuus - peate muutma ühte kuupäeva.'
-
-});/*
----
-
-script: Form.Validator.French.js
-
-description: Form.Validator messages in French.
-
-license: MIT-style license
-
-authors:
-- Miquel Hudin
-- Nicolas Sorosac <nicolas <dot> sorosac <at> gmail <dot> com>
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.French]
-
-...
-*/
-
-MooTools.lang.set('fr-FR', 'Form.Validator', {
- required:'Ce champ est obligatoire.',
- minLength:'Veuillez saisir un minimum de {minLength} caractère(s) (vous avez saisi {length} caractère(s)).',
- maxLength:'Veuillez saisir un maximum de {maxLength} caractère(s) (vous avez saisi {length} caractère(s)).',
- integer:'Veuillez saisir un nombre entier dans ce champ. Les nombres décimaux (ex : "1,25") ne sont pas autorisés.',
- numeric:'Veuillez saisir uniquement des chiffres dans ce champ (ex : "1" ou "1,1" ou "-1" ou "-1,1").',
- digits:'Veuillez saisir uniquement des chiffres et des signes de ponctuation dans ce champ (ex : un numéro de téléphone avec des traits d\'union est autorisé).',
- alpha:'Veuillez saisir uniquement des lettres (a-z) dans ce champ. Les espaces ou autres caractères ne sont pas autorisés.',
- alphanum:'Veuillez saisir uniquement des lettres (a-z) ou des chiffres (0-9) dans ce champ. Les espaces ou autres caractères ne sont pas autorisés.',
- dateSuchAs:'Veuillez saisir une date correcte comme {date}',
- dateInFormatMDY:'Veuillez saisir une date correcte, au format JJ/MM/AAAA (ex : "31/11/1999").',
- email:'Veuillez saisir une adresse de courrier électronique. Par example "fred at domaine.com".',
- url:'Veuillez saisir une URL, comme http://www.google.com.',
- currencyDollar:'Veuillez saisir une quantité correcte. Par example 100,00€.',
- oneRequired:'Veuillez sélectionner au moins une de ces options.',
- errorPrefix: 'Erreur : ',
- warningPrefix: 'Attention : ',
-
- //Form.Validator.Extras
-
- noSpace: 'Ce champ n\'accepte pas les espaces.',
- reqChkByNode: 'Aucun élément n\'est sélectionné.',
- requiredChk: 'Ce champ est obligatoire.',
- reqChkByName: 'Veuillez sélectionner un(e) {label}.',
- match: 'Ce champ doit correspondre avec le champ {matchName}.',
- startDate: 'date de début',
- endDate: 'date de fin',
- currendDate: 'date actuelle',
- afterDate: 'La date doit être identique ou postérieure à {label}.',
- beforeDate: 'La date doit être identique ou antérieure à {label}.',
- startMonth: 'Veuillez sélectionner un mois de début.',
- sameMonth: 'Ces deux dates doivent être dans le même mois - vous devez en modifier une.'
-
-});/*
----
-
-script: Form.Validator.Italian.js
-
-description: Form.Validator messages in Italian.
-
-license: MIT-style license
-
-authors:
-- Leonardo Laureti
-- Andrea Novero
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Italian]
-
-...
-*/
-
-MooTools.lang.set('it-IT', 'Form.Validator', {
-
- required:'Il campo è obbligatorio.',
- minLength:'Inserire almeno {minLength} caratteri (ne sono stati inseriti {length}).',
- maxLength:'Inserire al massimo {maxLength} caratteri (ne sono stati inseriti {length}).',
- integer:'Inserire un numero intero. Non sono consentiti decimali (es.: 1.25).',
- numeric:'Inserire solo valori numerici (es.: "1" oppure "1.1" oppure "-1" oppure "-1.1").',
- digits:'Inserire solo numeri e caratteri di punteggiatura. Per esempio è consentito un numero telefonico con trattini o punti.',
- alpha:'Inserire solo lettere (a-z). Non sono consentiti spazi o altri caratteri.',
- alphanum:'Inserire solo lettere (a-z) o numeri (0-9). Non sono consentiti spazi o altri caratteri.',
- dateSuchAs:'Inserire una data valida del tipo {date}',
- dateInFormatMDY:'Inserire una data valida nel formato MM/GG/AAAA (es.: "12/31/1999")',
- email:'Inserire un indirizzo email valido. Per esempio "nome at dominio.com".',
- url:'Inserire un indirizzo valido. Per esempio "http://www.dominio.com".',
- currencyDollar:'Inserire un importo valido. Per esempio "$100.00".',
- oneRequired:'Completare almeno uno dei campi richiesti.',
- errorPrefix: 'Errore: ',
- warningPrefix: 'Attenzione: ',
-
- //Form.Validator.Extras
-
- noSpace: 'Non sono consentiti spazi.',
- reqChkByNode: 'Nessuna voce selezionata.',
- requiredChk: 'Il campo è obbligatorio.',
- reqChkByName: 'Selezionare un(a) {label}.',
- match: 'Il valore deve corrispondere al campo {matchName}',
- startDate: 'data d\'inizio',
- endDate: 'data di fine',
- currendDate: 'data attuale',
- afterDate: 'La data deve corrispondere o essere successiva al {label}.',
- beforeDate: 'La data deve corrispondere o essere precedente al {label}.',
- startMonth: 'Selezionare un mese d\'inizio',
- sameMonth: 'Le due date devono essere dello stesso mese - occorre modificarne una.'
-
-});/*
----
-
-script: Form.Validator.Norwegian.js
-
-description: Form.Validator messages in Norwegian.
-
-license: MIT-style license
-
-authors:
-- Espen 'Rexxars' Hovlandsdal
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Norwegian]
-
-...
-*/
-
-MooTools.lang.set('no-NO', 'Form.Validator', {
- required:'Dette feltet er pÃÂ¥krevd.',
- minLength:'Vennligst skriv inn minst {minLength} tegn (du skrev {length} tegn).',
- maxLength:'Vennligst skriv inn maksimalt {maxLength} tegn (du skrev {length} tegn).',
- integer:'Vennligst skriv inn et tall i dette feltet. Tall med desimaler (for eksempel 1,25) er ikke tillat.',
- numeric:'Vennligst skriv inn kun numeriske verdier i dette feltet (for eksempel "1", "1.1", "-1" eller "-1.1").',
- digits:'Vennligst bruk kun nummer og skilletegn i dette feltet.',
- alpha:'Vennligst bruk kun bokstaver (a-z) i dette feltet. Ingen mellomrom eller andre tegn er tillat.',
- alphanum:'Vennligst bruk kun bokstaver (a-z) eller nummer (0-9) i dette feltet. Ingen mellomrom eller andre tegn er tillat.',
- dateSuchAs:'Vennligst skriv inn en gyldig dato, som {date}',
- dateInFormatMDY:'Vennligst skriv inn en gyldig dato, i formatet MM/DD/YYYY (for eksempel "12/31/1999")',
- email:'Vennligst skriv inn en gyldig epost-adresse. For eksempel "espen at domene.no".',
- url:'Vennligst skriv inn en gyldig URL, for eksempel http://www.google.no.',
- currencyDollar:'Vennligst fyll ut et gyldig $ beløp. For eksempel $100.00 .',
- oneRequired:'Vennligst fyll ut noe i minst ett av disse feltene.',
- errorPrefix: 'Feil: ',
- warningPrefix: 'Advarsel: '
-});/*
----
-
-script: Form.Validator.Polish.js
-
-description: Date messages for Polish.
-
-license: MIT-style license
-
-authors:
-- Oskar Krawczyk
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Polish]
-
-...
-*/
-
-MooTools.lang.set('pl-PL', 'Form.Validator', {
-
- required:'To pole jest wymagane.',
- minLength:'Wymagane jest przynajmniej {minLenght} znaków (wpisanych zostaÅo tylko {length}).',
- maxLength:'Dozwolone jest nie wiÄcej niż {maxLenght} znaków (wpisanych zostaÅo {length})',
- integer:'To pole wymaga liczb caÅych. Liczby dziesiÄtne (np. 1.25) sÄ
niedozwolone.',
- numeric:'Prosimy używaÄ tylko numerycznych wartoÅci w tym polu (np. "1", "1.1", "-1" lub "-1.1").',
- digits:'Prosimy używaÄ liczb oraz zankow punktuacyjnych w typ polu (dla przykÅadu, przy numerze telefonu myÅlniki i kropki sÄ
dozwolone).',
- alpha:'Prosimy używaÄ tylko liter (a-z) w tym polu. Spacje oraz inne znaki sÄ
niedozwolone.',
- alphanum:'Prosimy używaÄ tylko liter (a-z) lub liczb (0-9) w tym polu. Spacje oraz inne znaki sÄ
niedozwolone.',
- dateSuchAs:'Prosimy podaÄ prawidÅowÄ
datÄ w formacie: {date}',
- dateInFormatMDY:'Prosimy podaÄ poprawnÄ
date w formacie DD.MM.RRRR (i.e. "12.01.2009")',
- email:'Prosimy podaÄ prawidÅowy adres e-mail, np. "jan at domena.pl".',
- url:'Prosimy podaÄ prawidÅowy adres URL, np. http://www.google.pl.',
- currencyDollar:'Prosimy podaÄ prawidÅowÄ
sumÄ w PLN. Dla przykÅadu: 100.00 PLN.',
- oneRequired:'Prosimy wypeÅniÄ chociaż jedno z pól.',
- errorPrefix: 'BÅÄ
d: ',
- warningPrefix: 'Uwaga: ',
-
- //Form.Validator.Extras
-
- noSpace: 'W tym polu nie mogÄ
znajdowaÄ siÄ spacje.',
- reqChkByNode: 'Brak zaznaczonych elementów.',
- requiredChk: 'To pole jest wymagane.',
- reqChkByName: 'Prosimy wybraÄ z {label}.',
- match: 'To pole musi byÄ takie samo jak {matchName}',
- startDate: 'data poczÄ
tkowa',
- endDate: 'data koÅcowa',
- currendDate: 'aktualna data',
- afterDate: 'Podana data poinna byÄ taka sama lub po {label}.',
- beforeDate: 'Podana data poinna byÄ taka sama lub przed {label}.',
- startMonth: 'Prosimy wybraÄ poczÄ
tkowy miesiÄ
c.',
- sameMonth: 'Te dwie daty muszÄ
byÄ w zakresie tego samego miesiÄ
ca - wymagana jest zmiana któregoŠz pól.'
-
-});/*
----
-
-script: Form.Validator.Portuguese.js
-
-description: Form.Validator messages in Portuguese.
-
-license: MIT-style license
-
-authors:
-- Miquel Hudin
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Portuguese]
-
-...
-*/
-
-MooTools.lang.set('pt-PT', 'Form.Validator', {
- required:'Este campo é necessário.',
- minLength:'Digite pelo menos{minLength} caracteres (comprimento {length} caracteres).',
- maxLength:'Não insira mais de {maxLength} caracteres (comprimento {length} caracteres).',
- integer:'Digite um número inteiro neste domÃnio. Com números decimais (por exemplo, 1,25), não são permitidas.',
- numeric:'Digite apenas valores numéricos neste domÃnio (p.ex., "1" ou "1.1" ou "-1" ou "-1,1").',
- digits:'Por favor, use números e pontuação apenas neste campo (p.ex., um número de telefone com traços ou pontos é permitida).',
- alpha:'Por favor use somente letras (a-z), com nesta área. Não utilize espaços nem outros caracteres são permitidos.',
- alphanum:'Use somente letras (a-z) ou números (0-9) neste campo. Não utilize espaços nem outros caracteres são permitidos.',
- dateSuchAs:'Digite uma data válida, como {date}',
- dateInFormatMDY:'Digite uma data válida, como DD/MM/YYYY (p.ex. "31/12/1999")',
- email:'Digite um endereço de email válido. Por exemplo "fred at domain.com".',
- url:'Digite uma URL válida, como http://www.google.com.',
- currencyDollar:'Digite um valor válido $. Por exemplo $ 100,00. ',
- oneRequired:'Digite algo para pelo menos um desses insumos.',
- errorPrefix: 'Erro: ',
- warningPrefix: 'Aviso: '
-
-}).set('pt-PT', 'Date', {
- dateOrder: ['date', 'month', 'year', '/']
-});/*
----
-
-script: Form.Validator.Portuguese.BR.js
-
-description: Form.Validator messages in Portuguese-BR.
-
-license: MIT-style license
-
-authors:
-- Fábio Miranda Costa
-
-requires:
-- /Lang
-- /Form.Validator.Portuguese
-
-provides: [Form.Validator.Portuguese.BR]
-
-...
-*/
-
-MooTools.lang.set('pt-BR', 'Form.Validator', {
-
- required: 'Este campo é obrigatório.',
- minLength: 'Digite pelo menos {minLength} caracteres (tamanho atual: {length}).',
- maxLength: 'Não digite mais de {maxLength} caracteres (tamanho atual: {length}).',
- integer: 'Por favor digite apenas um número inteiro neste campo. Não são permitidos números decimais (por exemplo, 1,25).',
- numeric: 'Por favor digite apenas valores numéricos neste campo (por exemplo, "1" ou "1.1" ou "-1" ou "-1,1").',
- digits: 'Por favor use apenas números e pontuação neste campo (por exemplo, um número de telefone com traços ou pontos é permitido).',
- alpha: 'Por favor use somente letras (a-z). Espaço e outros caracteres não são permitidos.',
- alphanum: 'Use somente letras (a-z) ou números (0-9) neste campo. Espaço e outros caracteres não são permitidos.',
- dateSuchAs: 'Digite uma data válida, como {date}',
- dateInFormatMDY: 'Digite uma data válida, como DD/MM/YYYY (por exemplo, "31/12/1999")',
- email: 'Digite um endereço de email válido. Por exemplo "nome at dominio.com".',
- url: 'Digite uma URL válida. Exemplo: http://www.google.com.',
- currencyDollar: 'Digite um valor em dinheiro válido. Exemplo: R$100,00 .',
- oneRequired: 'Digite algo para pelo menos um desses campos.',
- errorPrefix: 'Erro: ',
- warningPrefix: 'Aviso: ',
-
- //Form.Validator.Extras
-
- noSpace: 'Não é possÃvel digitar espaços neste campo.',
- reqChkByNode: 'Não foi selecionado nenhum item.',
- requiredChk: 'Este campo é obrigatório.',
- reqChkByName: 'Por favor digite um {label}.',
- match: 'Este campo deve ser igual ao campo {matchName}.',
- startDate: 'a data inicial',
- endDate: 'a data final',
- currendDate: 'a data atual',
- afterDate: 'A data deve ser igual ou posterior a {label}.',
- beforeDate: 'A data deve ser igual ou anterior a {label}.',
- startMonth: 'Por favor selecione uma data inicial.',
- sameMonth: 'Estas duas datas devem ter o mesmo mês - você deve modificar uma das duas.',
- creditcard: 'O número do cartão de crédito informado é inválido. Por favor verifique o valor e tente novamente. {length} números informados.'
-
-});/*
----
-
-script: Form.Validator.Russian.js
-
-description: Form.Validator messages in Russian (utf-8 and cp1251).
-
-license: MIT-style license
-
-authors:
-- Chernodarov Egor
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Russian]
-
-...
-*/
-
-MooTools.lang.set('ru-RU-unicode', 'Form.Validator', {
- required:'ÐÑо поле обÑзаÑелÑно к заполнениÑ.',
- minLength:'ÐожалÑйÑÑа, введиÑе Ñ
оÑÑ Ð±Ñ {minLength} Ñимволов (ÐÑ Ð²Ð²ÐµÐ»Ð¸ {length}).',
- maxLength:'ÐожалÑйÑÑа, введиÑе не болÑÑе {maxLength} Ñимволов (ÐÑ Ð²Ð²ÐµÐ»Ð¸ {length}).',
- integer:'ÐожалÑйÑÑа, введиÑе в ÑÑо поле ÑиÑло. ÐÑобнÑе ÑиÑла (напÑÐ¸Ð¼ÐµÑ 1.25) ÑÑÑ Ð½Ðµ ÑазÑеÑенÑ.',
- numeric:'ÐожалÑйÑÑа, введиÑе в ÑÑо поле ÑиÑло (напÑÐ¸Ð¼ÐµÑ "1" или "1.1", или "-1", или "-1.1").',
- digits:'Ð ÑÑом поле ÐÑ Ð¼Ð¾Ð¶ÐµÑе иÑполÑзоваÑÑ ÑолÑко ÑиÑÑÑ Ð¸ знаки пÑнкÑÑаÑии (напÑимеÑ, ÑелеÑоннÑй Ð½Ð¾Ð¼ÐµÑ Ñо знаками деÑиÑа или Ñ ÑоÑками).',
- alpha:'Ð ÑÑом поле можно иÑполÑзоваÑÑ ÑолÑко лаÑинÑкие бÑÐºÐ²Ñ (a-z). ÐÑÐ¾Ð±ÐµÐ»Ñ Ð¸ дÑÑгие ÑÐ¸Ð¼Ð²Ð¾Ð»Ñ Ð·Ð°Ð¿ÑеÑенÑ.',
- alphanum:'Ð ÑÑом поле можно иÑполÑзоваÑÑ ÑолÑко лаÑинÑкие бÑÐºÐ²Ñ (a-z) и ÑиÑÑÑ (0-9). ÐÑÐ¾Ð±ÐµÐ»Ñ Ð¸ дÑÑгие ÑÐ¸Ð¼Ð²Ð¾Ð»Ñ Ð·Ð°Ð¿ÑеÑенÑ.',
- dateSuchAs:'ÐожалÑйÑÑа, введиÑе коÑÑекÑнÑÑ Ð´Ð°ÑÑ {date}',
- dateInFormatMDY:'ÐожалÑйÑÑа, введиÑе даÑÑ Ð² ÑоÑмаÑе ÐÐ/ÐÐ/ÐÐÐÐ (напÑÐ¸Ð¼ÐµÑ "12/31/1999")',
- email:'ÐожалÑйÑÑа, введиÑе коÑÑекÑнÑй емейл-адÑеÑ. ÐÐ»Ñ Ð¿ÑимеÑа "fred at domain.com".',
- url:'ÐожалÑйÑÑа, введиÑе пÑавилÑнÑÑ ÑÑÑÐ»ÐºÑ Ð²Ð¸Ð´Ð° http://www.google.com.',
- currencyDollar:'ÐожалÑйÑÑа, введиÑе ÑÑÐ¼Ð¼Ñ Ð² доллаÑаÑ
. ÐапÑимеÑ: $100.00 .',
- oneRequired:'ÐожалÑйÑÑа, вÑбеÑиÑе Ñ
оÑÑ ÑÑо-нибÑÐ´Ñ Ð² одном из ÑÑиÑ
полей.',
- errorPrefix: 'ÐÑибка: ',
- warningPrefix: 'Ðнимание: '
-});
-
-//translation in windows-1251 codepage
-MooTools.lang.set('ru-RU', 'Form.Validator', {
- required:'Ãòî ïîëå îáÿçà òåëüÃî ê çà ïîëÃÃ¥Ãèþ.',
- minLength:'Ãîæà ëóéñòà , ââåäèòå õîòÿ áû {minLength} ñèìâîëîâ (Ãû ââåëè {length}).',
- maxLength:'Ãîæà ëóéñòà , ââåäèòå ÃÃ¥ áîëüøå {maxLength} ñèìâîëîâ (Ãû ââåëè {length}).',
- integer:'Ãîæà ëóéñòà , ââåäèòå â ýòî ïîëå ÷èñëî. ÃðîáÃûå ÷èñëà (Ãà ïðèìåð 1.25) òóò ÃÃ¥ ðà çðåøåÃû.',
- numeric:'Ãîæà ëóéñòà , ââåäèòå â ýòî ïîëå ÷èñëî (Ãà ïðèìåð "1" èëè "1.1", èëè "-1", èëè "-1.1").',
- digits:'à ýòîì ïîëå Ãû ìîæåòå èñïîëüçîâà òü òîëüêî öèôðû è çÃà êè ïóÃêòóà öèè (Ãà ïðèìåð, òåëåôîÃÃûé Ãîìåð ñî çÃà êà ìè äåôèñà èëè ñ òî÷êà ìè).',
- alpha:'à ýòîì ïîëå ìîæÃî èñïîëüçîâà òü òîëüêî ëà òèÃñêèå áóêâû (a-z). Ãðîáåëû è äðóãèå ñèìâîëû çà ïðåùåÃû.',
- alphanum:'à ýòîì ïîëå ìîæÃî èñïîëüçîâà òü òîëüêî ëà òèÃñêèå áóêâû (a-z) è öèôðû (0-9). Ãðîáåëû è äðóãèå ñèìâîëû çà ïðåùåÃû.',
- dateSuchAs:'Ãîæà ëóéñòà , ââåäèòå êîððåêòÃóþ äà òó {date}',
- dateInFormatMDY:'Ãîæà ëóéñòà , ââåäèòå äà òó â ôîðìà òå ÃÃ/ÃÃ/ÃÃÃà (Ãà ïðèìåð "12/31/1999")',
- email:'Ãîæà ëóéñòà , ââåäèòå êîððåêòÃûé åìåéë-à äðåñ. Ãëÿ ïðèìåðà "fred at domain.com".',
- url:'Ãîæà ëóéñòà , ââåäèòå ïðà âèëüÃóþ ññûëêó âèäà http://www.google.com.',
- currencyDollar:'Ãîæà ëóéñòà , ââåäèòå ñóììó â äîëëà ðà õ. Ãà ïðèìåð: $100.00 .',
- oneRequired:'Ãîæà ëóéñòà , âûáåðèòå õîòü ÷òî-Ãèáóäü â îäÃîì èç ýòèõ ïîëåé.',
- errorPrefix: 'Ãøèáêà : ',
- warningPrefix: 'ÃÃèìà Ãèå: '
-});/*
----
-
-script: Form.Validator.Spanish.js
-
-description: Date messages for Spanish.
-
-license: MIT-style license
-
-authors:
-- Ãlfons Sanchez
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Spanish]
-
-...
-*/
-
-MooTools.lang.set('es-ES', 'Form.Validator', {
-
- required:'Este campo es obligatorio.',
- minLength:'Por favor introduce al menos {minLength} caracteres (has introducido {length} caracteres).',
- maxLength:'Por favor introduce no mas de {maxLength} caracteres (has introducido {length} caracteres).',
- integer:'Por favor introduce un numero entero en este campo. Numeros con decimales (p.e. 1,25) no se permiten.',
- numeric:'Por favor introduce solo valores numericos en este campo (p.e. "1" o "1,1" o "-1" o "-1,1").',
- digits:'Por favor usa solo numeros y puntuacion en este campo (por ejemplo, un numero de telefono con guines y puntos no esta permitido).',
- alpha:'Por favor usa letras solo (a-z) en este campo. No se admiten espacios ni otros caracteres.',
- alphanum:'Por favor, usa solo letras (a-z) o numeros (0-9) en este campo. No se admiten espacios ni otros caracteres.',
- dateSuchAs:'Por favor introduce una fecha valida como {date}',
- dateInFormatMDY:'Por favor introduce una fecha valida como DD/MM/YYYY (p.e. "31/12/1999")',
- email:'Por favor, introduce una direccione de email valida. Por ejemplo, "fred at domain.com".',
- url:'Por favor introduce una URL valida como http://www.google.com.',
- currencyDollar:'Por favor introduce una cantidad valida de â¬. Por ejemplo â¬100,00 .',
- oneRequired:'Por favor introduce algo para por lo menos una de estas entradas.',
- errorPrefix: 'Error: ',
- warningPrefix: 'Aviso: ',
-
- //Form.Validator.Extras
-
- noSpace: 'No pueden haber espacios en esta entrada.',
- reqChkByNode: 'No hay elementos seleccionados.',
- requiredChk: 'Este campo es obligatorio.',
- reqChkByName: 'Por favor selecciona una {label}.',
- match: 'Este campo necesita coincidir con el campo {matchName}',
- startDate: 'la fecha de inicio',
- endDate: 'la fecha de fin',
- currendDate: 'la fecha actual',
- afterDate: 'La fecha debe ser igual o posterior a {label}.',
- beforeDate: 'La fecha debe ser igual o anterior a {label}.',
- startMonth: 'Por favor selecciona un mes de origen',
- sameMonth: 'Estas dos fechas deben estar en el mismo mes - debes cambiar una u otra.'
-
-});/*
----
-
-script: Form.Validator.Swedish.js
-
-description: Date messages for Swedish.
-
-license: MIT-style license
-
-authors:
-- Martin Lundgren
-
-requires:
-- /Lang
-- /Form.Validator
-
-provides: [Form.Validator.Swedish]
-
-...
-*/
-
-MooTools.lang.set('sv-SE', 'Form.Validator', {
-
- required:'Fältet är obligatoriskt.',
- minLength:'Ange minst {minLength} tecken (du angav {length} tecken).',
- maxLength:'Ange högst {maxLength} tecken (du angav {length} tecken). ',
- integer:'Ange ett heltal i fältet. Tal med decimaler (t.ex. 1,25) är inte tillåtna.',
- numeric:'Ange endast numeriska värden i detta fält (t.ex. "1" eller "1.1" eller "-1" eller "-1,1").',
- digits:'Använd endast siffror och skiljetecken i detta fält (till exempel ett telefonnummer med bindestreck tillåtet).',
- alpha:'Använd endast bokstäver (a-ö) i detta fält. Inga mellanslag eller andra tecken är tillåtna.',
- alphanum:'Använd endast bokstäver (a-ö) och siffror (0-9) i detta fält. Inga mellanslag eller andra tecken är tillåtna.',
- dateSuchAs:'Ange ett giltigt datum som t.ex. {date}',
- dateInFormatMDY:'Ange ett giltigt datum som t.ex. YYYY-MM-DD (i.e. "1999-12-31")',
- email:'Ange en giltig e-postadress. Till exempel "erik at domain.com".',
- url:'Ange en giltig webbadress som http://www.google.com.',
- currencyDollar:'Ange en giltig belopp. Exempelvis 100,00.',
- oneRequired:'Vänligen ange minst ett av dessa alternativ.',
- errorPrefix: 'Fel: ',
- warningPrefix: 'Varning: ',
-
- //Form.Validator.Extras
-
- noSpace: 'Det får inte finnas några mellanslag i detta fält.',
- reqChkByNode: 'Inga objekt är valda.',
- requiredChk: 'Detta är ett obligatoriskt fält.',
- reqChkByName: 'Välj en {label}.',
- match: 'Detta fält måste matcha {matchName}',
- startDate: 'startdatumet',
- endDate: 'slutdatum',
- currendDate: 'dagens datum',
- afterDate: 'Datumet bör vara samma eller senare än {label}.',
- beforeDate: 'Datumet bör vara samma eller tidigare än {label}.',
- startMonth: 'Välj en start månad',
- sameMonth: 'Dessa två datum måste vara i samma månad - du måste ändra det ena eller det andra.'
-
-});// $Id: common.js 625 2009-11-20 13:19:50Z pagameba $
+/*
+---
+
+script: Core.js
+
+description: The core of MooTools, contains all the base functions and the Native and Hash implementations. Required by all the other scripts.
+
+license: MIT-style license.
+
+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.5dev',
+ 'build': '%build%'
+};
+
+var Native = function(options){
+ options = options || {};
+ var name = options.name;
+ var legacy = options.legacy;
+ var protect = options.protect;
+ 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'};
+ if (legacy && initialize) object.prototype = legacy.prototype;
+ object.prototype.constructor = object;
+
+ if (name){
+ var family = name.toLowerCase();
+ object.prototype.$family = {name: family};
+ Native.typize(object, family);
+ }
+
+ var add = function(obj, name, method, force){
+ if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method;
+ if (generics) Native.genericize(obj, name, protect);
+ afterImplement.call(obj, name, method);
+ return obj;
+ };
+
+ object.alias = function(a1, a2, a3){
+ if (typeof a1 == 'string'){
+ 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;
+ };
+
+ 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;
+ };
+
+ if (methods) object.implement(methods);
+
+ return object;
+};
+
+Native.genericize = function(object, property, check){
+ if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){
+ var args = Array.prototype.slice.call(arguments);
+ return object.prototype[property].apply(args.shift(), args);
+ };
+};
+
+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);
+ };
+};
+
+(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({
+
+ 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 $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 $arguments(i){
+ return function(){
+ return arguments[i];
+ };
+};
+
+function $chk(obj){
+ return !!(obj || obj === 0);
+};
+
+function $clear(timer){
+ clearTimeout(timer);
+ clearInterval(timer);
+ return null;
+};
+
+function $defined(obj){
+ return (obj != undefined);
+};
+
+function $each(iterable, fn, bind){
+ var type = $type(iterable);
+ ((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind);
+};
+
+function $empty(){};
+
+function $extend(original, extended){
+ for (var key in (extended || {})) original[key] = extended[key];
+ return original;
+};
+
+function $H(object){
+ return new Hash(object);
+};
+
+function $lambda(value){
+ return ($type(value) == 'function') ? value : function(){
+ return value;
+ };
+};
+
+function $merge(){
+ 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') ? $mixin(mp, op) : $unlink(op);
+ }
+ }
+ return mix;
+};
+
+function $pick(){
+ for (var i = 0, l = arguments.length; i < l; i++){
+ if (arguments[i] != undefined) return arguments[i];
+ }
+ return null;
+};
+
+function $random(min, max){
+ return Math.floor(Math.random() * (max - min + 1) + min);
+};
+
+function $splat(obj){
+ var type = $type(obj);
+ return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : [];
+};
+
+var $time = Date.now || function(){
+ return +new Date;
+};
+
+function $try(){
+ for (var i = 0, l = arguments.length; i < l; i++){
+ try {
+ return arguments[i]();
+ } catch(e){}
+ }
+ return null;
+};
+
+function $type(obj){
+ if (obj == undefined) return false;
+ if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name;
+ if (obj.nodeName){
+ switch (obj.nodeType){
+ case 1: return 'element';
+ case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
+ }
+ } else if (typeof obj.length == 'number'){
+ if (obj.callee) return 'arguments';
+ else if (obj.item) return 'collection';
+ }
+ return typeof obj;
+};
+
+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;
+};
+/*
+---
+
+script: Browser.js
+
+description: The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash.
+
+license: MIT-style license.
+
+requires:
+- /Native
+- /$util
+
+provides: [Browser, Window, Document, $exec]
+
+...
+*/
+
+var Browser = $merge({
+
+ Engine: {name: 'unknown', version: 0},
+
+ Platform: {name: (window.orientation != undefined) ? 'ipod' : (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()},
+
+ Features: {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)},
+
+ Plugins: {},
+
+ Engines: {
+
+ presto: function(){
+ return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925));
+ },
+
+ trident: function(){
+ return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4);
+ },
+
+ webkit: function(){
+ return (navigator.taintEnabled) ? false : ((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) : 419);
+ },
+
+ gecko: function(){
+ return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18);
+ }
+
+ }
+
+}, 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');
+ });
+};
+
+Browser.Features.xhr = !!(Browser.Request());
+
+Browser.Plugins.Flash = (function(){
+ var version = ($try(function(){
+ return navigator.plugins['Shockwave Flash'].description;
+ }, function(){
+ return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
+ }) || '0 r0').match(/\d+/g);
+ return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
+})();
+
+function $exec(text){
+ if (!text) return text;
+ if (window.execScript){
+ window.execScript(text);
+ } else {
+ var script = document.createElement('script');
+ script.setAttribute('type', 'text/javascript');
+ script[(Browser.Engine.webkit && Browser.Engine.version < 420) ? 'innerText' : 'text'] = text;
+ document.head.appendChild(script);
+ document.head.removeChild(script);
+ }
+ return text;
+};
+
+Native.UID = 1;
+
+var $uid = (Browser.Engine.trident) ? function(item){
+ return (item.uid || (item.uid = [Native.UID++]))[0];
+} : function(item){
+ return item.uid || (item.uid = Native.UID++);
+};
+
+var Window = new Native({
+
+ name: 'Window',
+
+ legacy: (Browser.Engine.trident) ? null: window.Window,
+
+ initialize: function(win){
+ $uid(win);
+ if (!win.Element){
+ win.Element = $empty;
+ 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);
+ },
+
+ afterImplement: function(property, value){
+ window[property] = Window.Prototype[property] = value;
+ }
+
+});
+
+Window.Prototype = {$family: {name: 'window'}};
+
+new Window(window);
+
+var Document = new Native({
+
+ name: 'Document',
+
+ legacy: (Browser.Engine.trident) ? null: window.Document,
+
+ initialize: function(doc){
+ $uid(doc);
+ doc.head = doc.getElementsByTagName('head')[0];
+ doc.html = doc.getElementsByTagName('html')[0];
+ 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);
+ },
+
+ afterImplement: function(property, value){
+ document[property] = Document.Prototype[property] = value;
+ }
+
+});
+
+Document.Prototype = {$family: {name: 'document'}};
+
+new Document(document);
+/*
+---
+
+script: Array.js
+
+description: Contains Array Prototypes like each, contains, and erase.
+
+license: MIT-style license.
+
+requires:
+- /$util
+- /Array.each
+
+provides: [Array]
+
+...
+*/
+
+Array.implement({
+
+ every: function(fn, bind){
+ for (var i = 0, l = this.length; i < l; i++){
+ if (!fn.call(bind, this[i], i, this)) return false;
+ }
+ return true;
+ },
+
+ filter: function(fn, bind){
+ var results = [];
+ for (var i = 0, l = this.length; i < l; i++){
+ if (fn.call(bind, this[i], i, this)) results.push(this[i]);
+ }
+ return results;
+ },
+
+ clean: function(){
+ return this.filter($defined);
+ },
+
+ indexOf: function(item, from){
+ var len = this.length;
+ for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
+ if (this[i] === item) return i;
+ }
+ return -1;
+ },
+
+ map: function(fn, bind){
+ var results = [];
+ for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this);
+ return results;
+ },
+
+ some: function(fn, bind){
+ for (var i = 0, l = this.length; i < l; i++){
+ if (fn.call(bind, this[i], i, this)) return true;
+ }
+ return false;
+ },
+
+ associate: function(keys){
+ var obj = {}, length = Math.min(this.length, keys.length);
+ for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
+ return obj;
+ },
+
+ link: function(object){
+ var result = {};
+ for (var i = 0, l = this.length; i < l; i++){
+ for (var key in object){
+ if (object[key](this[i])){
+ result[key] = this[i];
+ delete object[key];
+ break;
+ }
+ }
+ }
+ return result;
+ },
+
+ contains: function(item, from){
+ return this.indexOf(item, from) != -1;
+ },
+
+ extend: function(array){
+ 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;
+ },
+
+ getRandom: function(){
+ return (this.length) ? this[$random(0, this.length - 1)] : null;
+ },
+
+ include: function(item){
+ if (!this.contains(item)) this.push(item);
+ return this;
+ },
+
+ combine: function(array){
+ for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
+ return this;
+ },
+
+ erase: function(item){
+ for (var i = this.length; i--; i){
+ if (this[i] === item) this.splice(i, 1);
+ }
+ return this;
+ },
+
+ empty: function(){
+ this.length = 0;
+ return this;
+ },
+
+ flatten: function(){
+ var array = [];
+ for (var i = 0, l = this.length; i < l; i++){
+ var type = $type(this[i]);
+ if (!type) continue;
+ array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? Array.flatten(this[i]) : this[i]);
+ }
+ return array;
+ },
+
+ hexToRgb: function(array){
+ if (this.length != 3) return null;
+ var rgb = this.map(function(value){
+ if (value.length == 1) value += value;
+ return value.toInt(16);
+ });
+ return (array) ? rgb : 'rgb(' + rgb + ')';
+ },
+
+ rgbToHex: function(array){
+ if (this.length < 3) return null;
+ if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
+ var hex = [];
+ for (var i = 0; i < 3; i++){
+ var bit = (this[i] - 0).toString(16);
+ hex.push((bit.length == 1) ? '0' + bit : bit);
+ }
+ return (array) ? hex : '#' + hex.join('');
+ }
+
+});
+/*
+---
+
+script: Function.js
+
+description: Contains Function Prototypes like create, bind, pass, and delay.
+
+license: MIT-style license.
+
+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;
+ },
+
+ times: function(fn, bind){
+ for (var i = 0; i < this; i++) fn.call(bind, i, this);
+ },
+
+ toFloat: function(){
+ return parseFloat(this);
+ },
+
+ toInt: function(base){
+ return parseInt(this, base || 10);
+ }
+
+});
+
+Number.alias('times', 'each');
+
+(function(math){
+ var methods = {};
+ math.each(function(name){
+ if (!Number[name]) methods[name] = function(){
+ return Math[name].apply(null, [this].concat($A(arguments)));
+ };
+ });
+ Number.implement(methods);
+})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
+/*
+---
+
+script: String.js
+
+description: Contains String Prototypes like camelCase, capitalize, test, and toInt.
+
+license: MIT-style license.
+
+requires:
+- /Native
+
+provides: [String]
+
+...
+*/
+
+String.implement({
+
+ test: function(regex, params){
+ return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this);
+ },
+
+ contains: function(string, separator){
+ return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
+ },
+
+ trim: function(){
+ return this.replace(/^\s+|\s+$/g, '');
+ },
+
+ clean: function(){
+ return this.replace(/\s+/g, ' ').trim();
+ },
+
+ camelCase: function(){
+ return this.replace(/-\D/g, function(match){
+ return match.charAt(1).toUpperCase();
+ });
+ },
+
+ hyphenate: function(){
+ return this.replace(/[A-Z]/g, function(match){
+ return ('-' + match.charAt(0).toLowerCase());
+ });
+ },
+
+ capitalize: function(){
+ return this.replace(/\b[a-z]/g, function(match){
+ return match.toUpperCase();
+ });
+ },
+
+ escapeRegExp: function(){
+ return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
+ },
+
+ toInt: function(base){
+ return parseInt(this, base || 10);
+ },
+
+ toFloat: function(){
+ return parseFloat(this);
+ },
+
+ hexToRgb: function(array){
+ var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
+ return (hex) ? hex.slice(1).hexToRgb(array) : null;
+ },
+
+ rgbToHex: function(array){
+ var rgb = this.match(/\d{1,3}/g);
+ return (rgb) ? rgb.rgbToHex(array) : null;
+ },
+
+ stripScripts: function(option){
+ var scripts = '';
+ var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
+ scripts += arguments[1] + '\n';
+ return '';
+ });
+ if (option === true) $exec(scripts);
+ else if ($type(option) == 'function') option(scripts, text);
+ return text;
+ },
+
+ substitute: function(object, regexp){
+ return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
+ if (match.charAt(0) == '\\') return match.slice(1);
+ return (object[name] != undefined) ? object[name] : '';
+ });
+ }
+
+});
+/*
+---
+
+script: Hash.js
+
+description: Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.
+
+license: MIT-style license.
+
+requires:
+- /Hash.base
+
+provides: [Hash]
+
+...
+*/
+
+Hash.implement({
+
+ has: Object.prototype.hasOwnProperty,
+
+ keyOf: function(value){
+ for (var key in this){
+ if (this.hasOwnProperty(key) && this[key] === value) return key;
+ }
+ return null;
+ },
+
+ hasValue: function(value){
+ return (Hash.keyOf(this, value) !== null);
+ },
+
+ extend: function(properties){
+ Hash.each(properties || {}, function(value, key){
+ Hash.set(this, key, value);
+ }, this);
+ return this;
+ },
+
+ combine: function(properties){
+ Hash.each(properties || {}, function(value, key){
+ Hash.include(this, key, value);
+ }, this);
+ return this;
+ },
+
+ erase: function(key){
+ if (this.hasOwnProperty(key)) delete this[key];
+ return this;
+ },
+
+ get: function(key){
+ return (this.hasOwnProperty(key)) ? this[key] : null;
+ },
+
+ set: function(key, value){
+ if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
+ return this;
+ },
+
+ empty: function(){
+ Hash.each(this, function(value, key){
+ delete this[key];
+ }, this);
+ return this;
+ },
+
+ include: function(key, value){
+ if (this[key] == undefined) this[key] = value;
+ return this;
+ },
+
+ map: function(fn, bind){
+ var results = new Hash;
+ Hash.each(this, function(value, key){
+ results.set(key, fn.call(bind, value, key, this));
+ }, this);
+ return results;
+ },
+
+ filter: function(fn, bind){
+ var results = new Hash;
+ Hash.each(this, function(value, key){
+ if (fn.call(bind, value, key, this)) results.set(key, value);
+ }, this);
+ return results;
+ },
+
+ every: function(fn, bind){
+ for (var key in this){
+ if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
+ }
+ return true;
+ },
+
+ some: function(fn, bind){
+ for (var key in this){
+ if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
+ }
+ return false;
+ },
+
+ getKeys: function(){
+ var keys = [];
+ Hash.each(this, function(value, key){
+ keys.push(key);
+ });
+ return keys;
+ },
+
+ getValues: function(){
+ var values = [];
+ Hash.each(this, function(value){
+ values.push(value);
+ });
+ return values;
+ },
+
+ toQueryString: function(base){
+ var queryString = [];
+ Hash.each(this, function(value, key){
+ if (base) key = base + '[' + key + ']';
+ var result;
+ switch ($type(value)){
+ case 'object': result = Hash.toQueryString(value, key); break;
+ case 'array':
+ var qs = {};
+ value.each(function(val, i){
+ qs[i] = val;
+ });
+ result = Hash.toQueryString(qs, key);
+ break;
+ default: result = key + '=' + encodeURIComponent(value);
+ }
+ if (value != undefined) queryString.push(result);
+ });
+
+ return queryString.join('&');
+ }
+
+});
+
+Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});
+/*
+---
+
+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({
+
+ name: 'Event',
+
+ initialize: function(event, win){
+ win = win || window;
+ var doc = win.document;
+ event = event || win.event;
+ if (event.$extended) return event;
+ this.$extended = true;
+ 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);
+ if (type == 'keydown'){
+ var fKey = code - 111;
+ if (fKey > 0 && fKey < 13) key = 'f' + fKey;
+ }
+ key = key || String.fromCharCode(code).toLowerCase();
+ } else if (type.match(/(click|mouse|menu)/i)){
+ doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
+ var page = {
+ x: event.pageX || event.clientX + doc.scrollLeft,
+ y: event.pageY || event.clientY + doc.scrollTop
+ };
+ var client = {
+ x: (event.pageX) ? event.pageX - win.pageXOffset : event.clientX,
+ y: (event.pageY) ? event.pageY - win.pageYOffset : event.clientY
+ };
+ if (type.match(/DOMMouseScroll|mousewheel/)){
+ var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
+ }
+ var rightClick = (event.which == 3) || (event.button == 2);
+ var related = null;
+ if (type.match(/over|out/)){
+ switch (type){
+ case 'mouseover': related = event.relatedTarget || event.fromElement; break;
+ case 'mouseout': related = event.relatedTarget || event.toElement;
+ }
+ if (!(function(){
+ while (related && related.nodeType == 3) related = related.parentNode;
+ return true;
+ }).create({attempt: Browser.Engine.gecko})()) related = false;
+ }
+ }
+
+ 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,
+ meta: event.metaKey
+ });
+ }
+
+});
+
+Event.Keys = new Hash({
+ 'enter': 13,
+ 'up': 38,
+ 'down': 40,
+ 'left': 37,
+ 'right': 39,
+ 'esc': 27,
+ 'space': 32,
+ 'backspace': 8,
+ 'tab': 9,
+ 'delete': 46
+});
+
+Event.implement({
+
+ stop: function(){
+ return this.stopPropagation().preventDefault();
+ },
+
+ stopPropagation: function(){
+ if (this.event.stopPropagation) this.event.stopPropagation();
+ else this.event.cancelBubble = true;
+ return this;
+ },
+
+ preventDefault: function(){
+ if (this.event.preventDefault) this.event.preventDefault();
+ else this.event.returnValue = false;
+ return this;
+ }
+
+});
+/*
+---
+
+script: Class.js
+
+description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
+
+license: MIT-style license.
+
+requires:
+- /$util
+- /Native
+- /Array
+- /String
+- /Function
+- /Number
+- /Hash
+
+provides: [Class]
+
+...
+*/
+
+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;
+
+ return newClass;
+
+};
+
+Function.prototype.protect = function(){
+ this._protected = true;
+ return this;
+};
+
+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;
+
+ }
+
+ return this;
+
+ }
+
+});
+
+Class.Mutators = {
+
+ 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
+
+description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
+
+license: MIT-style license.
+
+requires:
+- /Class
+
+provides: [Chain, Events, Options]
+
+...
+*/
+
+var Chain = new Class({
+
+ $chain: [],
+
+ chain: function(){
+ this.$chain.extend(Array.flatten(arguments));
+ return this;
+ },
+
+ callChain: function(){
+ return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
+ },
+
+ clearChain: function(){
+ this.$chain.empty();
+ return this;
+ }
+
+});
+
+var Events = new Class({
+
+ $events: {},
+
+ addEvent: function(type, fn, internal){
+ type = Events.removeOn(type);
+ if (fn != $empty){
+ this.$events[type] = this.$events[type] || [];
+ this.$events[type].include(fn);
+ if (internal) fn.internal = true;
+ }
+ return this;
+ },
+
+ addEvents: function(events){
+ for (var type in events) this.addEvent(type, events[type]);
+ return this;
+ },
+
+ fireEvent: function(type, args, delay){
+ type = Events.removeOn(type);
+ if (!this.$events || !this.$events[type]) return this;
+ this.$events[type].each(function(fn){
+ fn.create({'bind': this, 'delay': delay, 'arguments': args})();
+ }, this);
+ return this;
+ },
+
+ removeEvent: function(type, fn){
+ type = Events.removeOn(type);
+ if (!this.$events[type]) return this;
+ if (!fn.internal) this.$events[type].erase(fn);
+ return this;
+ },
+
+ 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;
+ }
+
+});
+
+Events.removeOn = function(string){
+ return string.replace(/^on([A-Z])/, function(full, first){
+ return first.toLowerCase();
+ });
+};
+
+var Options = new Class({
+
+ setOptions: function(){
+ this.options = $merge.run([this.options].extend(arguments));
+ if (!this.addEvent) return this;
+ for (var option in this.options){
+ if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
+ this.addEvent(option, this.options[option]);
+ delete this.options[option];
+ }
+ return this;
+ }
+
+});
+/*
+---
+
+script: Element.js
+
+description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements.
+
+license: MIT-style license.
+
+requires:
+- /Window
+- /Document
+- /Array
+- /String
+- /Function
+- /Number
+- /Hash
+
+provides: [Element, Elements, $, $$, Iframe]
+
+...
+*/
+
+var Element = new Native({
+
+ name: 'Element',
+
+ legacy: window.Element,
+
+ initialize: function(tag, props){
+ var konstructor = Element.Constructors.get(tag);
+ if (konstructor) return konstructor(props);
+ if (typeof tag == 'string') return document.newElement(tag, props);
+ return document.id(tag).set(props);
+ },
+
+ afterImplement: function(key, value){
+ 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;
+ });
+ }
+
+});
+
+Element.Prototype = {$family: {name: 'element'}};
+
+Element.Constructors = new Hash;
+
+var IFrame = new Native({
+
+ name: 'IFrame',
+
+ generics: false,
+
+ initialize: function(){
+ var params = Array.link(arguments, {properties: Object.type, iframe: $defined});
+ var props = params.properties || {};
+ var iframe = document.id(params.iframe);
+ var onload = props.onload || $empty;
+ delete props.onload;
+ 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){
+ var win = new Window(iframe.contentWindow);
+ new Document(iframe.contentWindow.document);
+ $extend(win.Element.prototype, Element.Prototype);
+ }
+ onload.call(iframe.contentWindow, iframe.contentWindow.document);
+ };
+ var contentWindow = $try(function(){
+ return iframe.contentWindow;
+ });
+ ((contentWindow && contentWindow.document.body) || window.frames[props.id]) ? onFrameLoad() : iframe.addListener('load', onFrameLoad);
+ return iframe;
+ }
+
+});
+
+var Elements = new Native({
+
+ initialize: function(elements, options){
+ options = $extend({ddup: true, cash: true}, options);
+ elements = elements || [];
+ if (options.ddup || options.cash){
+ var uniques = {}, returned = [];
+ for (var i = 0, l = elements.length; i < l; i++){
+ var el = document.id(elements[i], !options.cash);
+ if (options.ddup){
+ if (uniques[el.uid]) continue;
+ uniques[el.uid] = true;
+ }
+ if (el) returned.push(el);
+ }
+ elements = returned;
+ }
+ return (options.cash) ? $extend(elements, this) : elements;
+ }
+
+});
+
+Elements.implement({
+
+ filter: function(filter, bind){
+ if (!filter) return this;
+ return new Elements(Array.filter(this, (typeof filter == 'string') ? function(item){
+ return item.match(filter);
+ } : filter, bind));
+ }
+
+});
+
+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 document.id(this.createElement(tag)).set(props);
+ },
+
+ newTextNode: function(text){
+ return this.createTextNode(text);
+ },
+
+ getDocument: function(){
+ return this;
+ },
+
+ 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);
+ var elements = [];
+ var args = Array.flatten(arguments);
+ for (var i = 0, l = args.length; i < l; i++){
+ var item = args[i];
+ switch ($type(item)){
+ case 'element': elements.push(item); break;
+ case 'string': elements.extend(this.document.getElements(item, true));
+ }
+ }
+ return new Elements(elements);
+ },
+
+ getDocument: function(){
+ return this.document;
+ },
+
+ getWindow: function(){
+ return this;
+ }
+
+});
+
+Native.implement([Element, Document], {
+
+ getElement: function(selector, nocash){
+ return document.id(this.getElements(selector, true)[0] || null, nocash);
+ },
+
+ getElements: function(tags, nocash){
+ tags = tags.split(',');
+ var elements = [];
+ var ddup = (tags.length > 1);
+ tags.each(function(tag){
+ var partial = this.getElementsByTagName(tag.trim());
+ (ddup) ? elements.extend(partial) : elements = partial;
+ }, this);
+ return new Elements(elements, {ddup: ddup, cash: !nocash});
+ }
+
+});
+
+(function(){
+
+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] = {}));
+};
+
+var clean = function(item, retain){
+ if (!item) return;
+ var uid = item.uid;
+ if (retain !== true) retain = false;
+ 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;
+};
+
+var purge = function(){
+ Hash.each(collected, clean);
+ if (Browser.Engine.trident) $A(document.getElementsByTagName('object')).each(clean);
+ if (window.CollectGarbage) CollectGarbage();
+ collected = storage = null;
+};
+
+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);
+ }
+
+};
+
+inserters.inside = inserters.bottom;
+
+Hash.each(inserters, function(inserter, where){
+
+ where = where.capitalize();
+
+ Element.implement('inject' + where, function(el){
+ inserter(this, document.id(el, true));
+ return this;
+ });
+
+ Element.implement('grab' + where, function(el){
+ inserter(document.id(el, true), this);
+ return this;
+ });
+
+});
+
+Element.implement({
+
+ set: function(prop, value){
+ switch ($type(prop)){
+ case 'object':
+ for (var p in prop) this.set(p, prop[p]);
+ break;
+ case 'string':
+ var property = Element.Properties.get(prop);
+ (property && property.set) ? property.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(prop, value);
+ }
+ return this;
+ },
+
+ get: function(prop){
+ var property = Element.Properties.get(prop);
+ return (property && property.get) ? property.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(prop);
+ },
+
+ erase: function(prop){
+ var property = Element.Properties.get(prop);
+ (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
+ return this;
+ },
+
+ 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;
+ },
+
+ setProperties: function(attributes){
+ for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
+ 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;
+ },
+
+ getProperties: function(){
+ var args = $A(arguments);
+ return args.map(this.getProperty, this).associate(args);
+ },
+
+ removeProperty: function(attribute){
+ var key = attributes[attribute];
+ (key) ? this[key] = (key && bools[attribute]) ? false : '' : this.removeAttribute(attribute);
+ return this;
+ },
+
+ removeProperties: function(){
+ Array.each(arguments, this.removeProperty, this);
+ return this;
+ },
+
+ hasClass: function(className){
+ return this.className.contains(className, ' ');
+ },
+
+ addClass: function(className){
+ if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
+ return this;
+ },
+
+ removeClass: function(className){
+ this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
+ return this;
+ },
+
+ toggleClass: function(className){
+ return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
+ },
+
+ adopt: function(){
+ Array.flatten(arguments).each(function(element){
+ element = document.id(element, true);
+ if (element) this.appendChild(element);
+ }, this);
+ return this;
+ },
+
+ appendText: function(text, where){
+ return this.grab(this.getDocument().newTextNode(text), where);
+ },
+
+ grab: function(el, where){
+ inserters[where || 'bottom'](document.id(el, true), this);
+ return this;
+ },
+
+ inject: function(el, where){
+ inserters[where || 'bottom'](this, document.id(el, true));
+ return this;
+ },
+
+ replaces: function(el){
+ el = document.id(el, true);
+ el.parentNode.replaceChild(this, el);
+ return this;
+ },
+
+ 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);
+ },
+
+ getAllPrevious: function(match, nocash){
+ return walk(this, 'previousSibling', null, match, true, nocash);
+ },
+
+ getNext: function(match, nocash){
+ return walk(this, 'nextSibling', null, match, false, nocash);
+ },
+
+ getAllNext: function(match, nocash){
+ return walk(this, 'nextSibling', null, match, true, nocash);
+ },
+
+ getFirst: function(match, nocash){
+ return walk(this, 'nextSibling', 'firstChild', match, false, nocash);
+ },
+
+ getLast: function(match, nocash){
+ return walk(this, 'previousSibling', 'lastChild', match, false, nocash);
+ },
+
+ getParent: function(match, nocash){
+ return walk(this, 'parentNode', null, match, false, nocash);
+ },
+
+ 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);
+ },
+
+ 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);
+ },
+
+ getSelected: function(){
+ return new Elements($A(this.options).filter(function(option){
+ return option.selected;
+ }));
+ },
+
+ 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;
+ },
+
+ 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('&');
+ },
+
+ 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);
+ },
+
+ 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;
+ },
+
+ dispose: function(){
+ return (this.parentNode) ? this.parentNode.removeChild(this) : this;
+ },
+
+ 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);
+ },
+
+ 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;
+ },
+
+ removeListener: function(type, fn){
+ if (this.removeEventListener) this.removeEventListener(type, fn, false);
+ else this.detachEvent('on' + type, fn);
+ return this;
+ },
+
+ retrieve: function(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 = get(this.uid);
+ storage[property] = value;
+ return this;
+ },
+
+ eliminate: function(property){
+ var storage = get(this.uid);
+ delete storage[property];
+ return this;
+ }
+
+});
+
+window.addListener('unload', purge);
+
+})();
+
+Element.Properties = new Hash;
+
+Element.Properties.style = {
+
+ set: function(style){
+ this.style.cssText = style;
+ },
+
+ get: function(){
+ return this.style.cssText;
+ },
+
+ erase: function(){
+ this.style.cssText = '';
+ }
+
+};
+
+Element.Properties.tag = {
+
+ get: function(){
+ return this.tagName.toLowerCase();
+ }
+
+};
+
+Element.Properties.html = (function(){
+ var wrapper = document.createElement('div');
+
+ var translations = {
+ table: [1, '<table>', '</table>'],
+ select: [1, '<select>', '</select>'],
+ tbody: [2, '<table><tbody>', '</tbody></table>'],
+ tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
+ };
+ 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 = {
+
+ set: function(opacity, novisibility){
+ if (!novisibility){
+ if (opacity == 0){
+ if (this.style.visibility != 'hidden') this.style.visibility = 'hidden';
+ } else {
+ if (this.style.visibility != 'visible') this.style.visibility = 'visible';
+ }
+ }
+ if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
+ if (Browser.Engine.trident) this.style.filter = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')';
+ this.style.opacity = opacity;
+ this.store('opacity', opacity);
+ },
+
+ get: function(){
+ return this.retrieve('opacity', 1);
+ }
+
+};
+
+Element.implement({
+
+ setOpacity: function(value){
+ return this.set('opacity', value, true);
+ },
+
+ getOpacity: function(){
+ return this.get('opacity');
+ },
+
+ setStyle: function(property, value){
+ switch (property){
+ case 'opacity': return this.set('opacity', parseFloat(value));
+ case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
+ }
+ property = property.camelCase();
+ if ($type(value) != 'string'){
+ var map = (Element.Styles.get(property) || '@').split(' ');
+ value = $splat(value).map(function(val, i){
+ if (!map[i]) return '';
+ return ($type(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
+ }).join(' ');
+ } else if (value == String(Number(value))){
+ value = Math.round(value);
+ }
+ this.style[property] = value;
+ return this;
+ },
+
+ getStyle: function(property){
+ switch (property){
+ case 'opacity': return this.get('opacity');
+ case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
+ }
+ property = property.camelCase();
+ var result = this.style[property];
+ if (!$chk(result)){
+ result = [];
+ for (var style in Element.ShortStyles){
+ if (property != style) continue;
+ for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
+ return result.join(' ');
+ }
+ result = this.getComputedStyle(property);
+ }
+ if (result){
+ result = String(result);
+ 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, 10)))){
+ if (property.test(/^(height|width)$/)){
+ var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
+ values.each(function(value){
+ size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
+ }, this);
+ return this['offset' + property.capitalize()] - size + 'px';
+ }
+ if ((Browser.Engine.presto) && String(result).test('px')) return result;
+ if (property.test(/(border(.+)Width|margin|padding)/)) return '0px';
+ }
+ return result;
+ },
+
+ setStyles: function(styles){
+ for (var style in styles) this.setStyle(style, styles[style]);
+ return this;
+ },
+
+ getStyles: function(){
+ var result = {};
+ Array.flatten(arguments).each(function(key){
+ result[key] = this.getStyle(key);
+ }, this);
+ return result;
+ }
+
+});
+
+Element.Styles = new Hash({
+ left: '@px', top: '@px', bottom: '@px', right: '@px',
+ width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
+ backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
+ fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
+ margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
+ borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
+ zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
+});
+
+Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};
+
+['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
+ var Short = Element.ShortStyles;
+ var All = Element.Styles;
+ ['margin', 'padding'].each(function(style){
+ var sd = style + direction;
+ Short[style][sd] = All[sd] = '@px';
+ });
+ var bd = 'border' + direction;
+ Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
+ var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
+ Short[bd] = {};
+ Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
+ Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
+ Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
+});
+/*
+---
+
+script: Element.Dimensions.js
+
+description: Contains methods to work with size, scroll, or positioning of Elements and the window object.
+
+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).
+
+requires:
+- /Element
+
+provides: [Element.Dimensions]
+
+...
+*/
+
+(function(){
+
+Element.implement({
+
+ scrollTo: function(x, y){
+ if (isBody(this)){
+ this.getWindow().scrollTo(x, y);
+ } else {
+ this.scrollLeft = x;
+ this.scrollTop = y;
+ }
+ return this;
+ },
+
+ getSize: function(){
+ if (isBody(this)) return this.getWindow().getSize();
+ return {x: this.offsetWidth, y: this.offsetHeight};
+ },
+
+ getScrollSize: function(){
+ if (isBody(this)) return this.getWindow().getScrollSize();
+ return {x: this.scrollWidth, y: this.scrollHeight};
+ },
+
+ getScroll: function(){
+ if (isBody(this)) return this.getWindow().getScroll();
+ return {x: this.scrollLeft, y: this.scrollTop};
+ },
+
+ getScrolls: function(){
+ var element = this, position = {x: 0, y: 0};
+ while (element && !isBody(element)){
+ position.x += element.scrollLeft;
+ position.y += element.scrollTop;
+ element = element.parentNode;
+ }
+ return position;
+ },
+
+ getOffsetParent: function(){
+ var element = this;
+ if (isBody(element)) return null;
+ if (!Browser.Engine.trident) return element.offsetParent;
+ 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;
+
+ while (element && !isBody(element)){
+ position.x += element.offsetLeft;
+ position.y += element.offsetTop;
+
+ if (Browser.Engine.gecko){
+ if (!borderBox(element)){
+ position.x += leftBorder(element);
+ position.y += topBorder(element);
+ }
+ var parent = element.parentNode;
+ if (parent && styleString(parent, 'overflow') != 'visible'){
+ position.x += leftBorder(parent);
+ position.y += topBorder(parent);
+ }
+ } else if (element != this && Browser.Engine.webkit){
+ position.x += leftBorder(element);
+ position.y += topBorder(element);
+ }
+
+ element = element.offsetParent;
+ }
+ if (Browser.Engine.gecko && !borderBox(this)){
+ position.x -= leftBorder(this);
+ position.y -= topBorder(this);
+ }
+ return position;
+ },
+
+ getPosition: function(relative){
+ if (isBody(this)) return {x: 0, y: 0};
+ var offset = this.getOffsets(),
+ scroll = this.getScrolls();
+ var position = {
+ x: offset.x - scroll.x,
+ y: offset.y - scroll.y
+ };
+ 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
+ };
+ 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')
+ };
+ },
+
+ setPosition: function(obj){
+ return this.setStyles(this.computePosition(obj));
+ }
+
+});
+
+
+Native.implement([Document, Window], {
+
+ getSize: function(){
+ 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(), doc = getCompatElement(this);
+ return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
+ },
+
+ getScrollSize: function(){
+ var doc = getCompatElement(this), min = this.getSize();
+ return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)};
+ },
+
+ getPosition: function(){
+ return {x: 0, y: 0};
+ },
+
+ getCoordinates: function(){
+ var size = this.getSize();
+ return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
+ }
+
+});
+
+// private methods
+
+var styleString = Element.getComputedStyle;
+
+function styleNumber(element, style){
+ return styleString(element, style).toInt() || 0;
+};
+
+function borderBox(element){
+ return styleString(element, '-moz-box-sizing') == 'border-box';
+};
+
+function topBorder(element){
+ return styleNumber(element, 'border-top-width');
+};
+
+function leftBorder(element){
+ return styleNumber(element, 'border-left-width');
+};
+
+function isBody(element){
+ return (/^(?:body|html)$/i).test(element.tagName);
+};
+
+function getCompatElement(element){
+ var doc = element.getDocument();
+ return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
+};
+
+})();
+
+//aliases
+Element.alias('setPosition', 'position'); //compatability
+
+Native.implement([Window, Document, Element], {
+
+ getHeight: function(){
+ return this.getSize().y;
+ },
+
+ getWidth: function(){
+ return this.getSize().x;
+ },
+
+ getScrollTop: function(){
+ return this.getScroll().y;
+ },
+
+ getScrollLeft: function(){
+ return this.getScroll().x;
+ },
+
+ getScrollHeight: function(){
+ return this.getScrollSize().y;
+ },
+
+ getScrollWidth: function(){
+ return this.getScrollSize().x;
+ },
+
+ getTop: function(){
+ return this.getPosition().y;
+ },
+
+ getLeft: function(){
+ return this.getPosition().x;
+ }
+
+});
+/*
+---
+
+script: Selectors.js
+
+description: Adds advanced CSS-style querying capabilities for targeting HTML Elements. Includes pseudo selectors.
+
+license: MIT-style license.
+
+requires:
+- /Element
+
+provides: [Selectors]
+
+...
+*/
+
+Native.implement([Document, Element], {
+
+ getElements: function(expression, nocash){
+ expression = expression.split(',');
+ var items, local = {};
+ for (var i = 0, l = expression.length; i < l; i++){
+ var selector = expression[i], elements = Selectors.Utils.search(this, selector, local);
+ if (i != 0 && elements.item) elements = $A(elements);
+ items = (i == 0) ? elements : (items.item) ? $A(items).concat(elements) : items.concat(elements);
+ }
+ return new Elements(items, {ddup: (expression.length > 1), cash: !nocash});
+ }
+
+});
+
+Element.implement({
+
+ match: function(selector){
+ 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: {}}};
+
+Selectors.RegExps = {
+ id: (/#([\w-]+)/),
+ tag: (/^(\w+|\*)/),
+ quick: (/^(\w+|\*)$/),
+ splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/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], 10);
+ var a = (inta || inta === 0) ? inta : 1;
+ var special = parsed[2] || false;
+ var b = parseInt(parsed[3], 10) || 0;
+ if (a != 0){
+ b--;
+ while (b < 1) b += a;
+ while (b >= a) b -= a;
+ } else {
+ a = b;
+ special = 'index';
+ }
+ 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 '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[5], pn = m[6], pa = m[7];
+ if (cn){
+ parsed.classes.push(cn);
+ } else if (pn){
+ var parser = Selectors.Pseudo.get(pn);
+ if (parser) parsed.pseudos.push({parser: parser, argument: pa});
+ else parsed.attributes.push({name: pn, operator: '=', value: pa});
+ } else if (an){
+ parsed.attributes.push({name: an, operator: ao, value: av});
+ }
+ }
+ if (!parsed.classes.length) delete parsed.classes;
+ if (!parsed.attributes.length) delete parsed.attributes;
+ if (!parsed.pseudos.length) delete parsed.pseudos;
+ 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){
+ for (i = parsed.classes.length; i--; i){
+ var cn = parsed.classes[i];
+ if (!Selectors.Filters.byClass(item, cn)) return false;
+ }
+ }
+ if (parsed.attributes){
+ for (i = parsed.attributes.length; i--; i){
+ var att = parsed.attributes[i];
+ if (!Selectors.Filters.byAttribute(item, att.name, att.operator, att.value)) return false;
+ }
+ }
+ if (parsed.pseudos){
+ for (i = parsed.pseudos.length; i--; i){
+ var psd = parsed.pseudos[i];
+ if (!Selectors.Filters.byPseudo(item, psd.parser, psd.argument, local)) return false;
+ }
+ }
+ return true;
+ },
+
+ getByTagAndID: function(ctx, tag, id){
+ if (id){
+ var item = (ctx.getElementById) ? ctx.getElementById(id, true) : Element.getElementById(ctx, id, true);
+ return (item && Selectors.Filters.byTag(item, tag)) ? [item] : [];
+ } else {
+ 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, 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];
+
+ if (i == 0){
+ items = Selectors.Utils.getByTagAndID(self, tag, id);
+ } else {
+ var uniques = {}, found = [];
+ 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++){
+ item = items[m];
+ if (Selectors.Utils.filter(item, parsed, local)) filtered.push(item);
+ }
+ 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++){
+ var item = items[i];
+ if (Selectors.Utils.chk(item, uniques)) found.push(item);
+ }
+ 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++){
+ var child = children[i];
+ if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child);
+ }
+ return found;
+ },
+
+ '+': function(found, self, tag, id, uniques){
+ while ((self = self.nextSibling)){
+ if (self.nodeType == 1){
+ if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
+ break;
+ }
+ }
+ 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 && 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 (operator == '!=');
+ if (!operator || value == undefined) return true;
+ switch (operator){
+ case '=': return (result == value);
+ case '*=': return (result.contains(value));
+ case '^=': return (result.substr(0, value.length) == value);
+ case '$=': return (result.substr(result.length - value.length) == value);
+ case '!=': return (result != value);
+ case '~=': return result.contains(value, ' ');
+ case '|=': return result.contains(value, '-');
+ }
+ 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)){
+ if (element.nodeType == 1) return false;
+ }
+ return true;
+ },
+
+ 'only-child': function(){
+ var prev = this;
+ while ((prev = prev.previousSibling)){
+ if (prev.nodeType == 1) return false;
+ }
+ var next = this;
+ while ((next = next.nextSibling)){
+ if (next.nodeType == 1) return false;
+ }
+ return true;
+ },
+
+ 'nth-child': function(argument, local){
+ argument = (argument == undefined) ? 'n' : argument;
+ var parsed = Selectors.Utils.parseNthArgument(argument);
+ if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local);
+ var count = 0;
+ local.positions = local.positions || {};
+ var uid = $uid(this);
+ if (!local.positions[uid]){
+ var self = this;
+ while ((self = self.previousSibling)){
+ if (self.nodeType != 1) continue;
+ count ++;
+ var position = local.positions[$uid(self)];
+ if (position != undefined){
+ count = position + count;
+ break;
+ }
+ }
+ local.positions[uid] = count;
+ }
+ return (local.positions[uid] % parsed.a == parsed.b);
+ },
+
+ // custom pseudo selectors
+
+ index: function(index){
+ var element = this, count = 0;
+ while ((element = element.previousSibling)){
+ if (element.nodeType == 1 && ++count > index) return false;
+ }
+ 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
+
+description: Contains the custom event domready.
+
+license: MIT-style license.
+
+requires:
+- /Element.Event
+
+provides: [DomReady]
+
+...
+*/
+
+Element.Events.domready = {
+
+ onAdd: function(fn){
+ if (Browser.loaded) fn.call(this);
+ }
+
+};
+
+(function(){
+
+ var domready = function(){
+ if (Browser.loaded) return;
+ Browser.loaded = true;
+ window.fireEvent('domready');
+ document.fireEvent('domready');
+ };
+
+ 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);
+ })();
+ } else {
+ document.addEvent('DOMContentLoaded', domready);
+ }
+
+})();
+/*
+---
+
+script: JSON.js
+
+description: JSON encoder and decoder.
+
+license: MIT-style license.
+
+See Also: <http://www.json.org/>
+
+requires:
+- /Array
+- /String
+- /Number
+- /Function
+- /Hash
+
+provides: [JSON]
+
+...
+*/
+
+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).clean()) + ']';
+ case 'object': case 'hash':
+ var string = [];
+ Hash.each(obj, function(value, key){
+ var json = JSON.encode(value);
+ if (json) string.push(JSON.encode(key) + ':' + json);
+ });
+ return '{' + string + '}';
+ case 'number': case 'boolean': return String(obj);
+ case false: return 'null';
+ }
+ return null;
+ },
+
+ 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;
+ return eval('(' + string + ')');
+ }
+
+});
+
+Native.implement([Hash, Array, String, Number], {
+
+ toJSON: function(){
+ return JSON.encode(this);
+ }
+
+});
+/*
+---
+
+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
+
+provides: [Cookie]
+
+...
+*/
+
+var Cookie = new Class({
+
+ Implements: Options,
+
+ options: {
+ path: false,
+ domain: false,
+ duration: false,
+ secure: false,
+ document: document
+ },
+
+ initialize: function(key, options){
+ this.key = key;
+ this.setOptions(options);
+ },
+
+ write: function(value){
+ value = encodeURIComponent(value);
+ if (this.options.domain) value += '; domain=' + this.options.domain;
+ if (this.options.path) value += '; path=' + this.options.path;
+ if (this.options.duration){
+ var date = new Date();
+ date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
+ value += '; expires=' + date.toGMTString();
+ }
+ if (this.options.secure) value += '; secure';
+ this.options.document.cookie = this.key + '=' + value;
+ return this;
+ },
+
+ read: function(){
+ var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
+ return (value) ? decodeURIComponent(value[1]) : null;
+ },
+
+ dispose: function(){
+ new Cookie(this.key, $merge(this.options, {duration: -1})).write('');
+ return this;
+ }
+
+});
+
+Cookie.write = function(key, value, options){
+ return new Cookie(key, options).write(value);
+};
+
+Cookie.read = function(key){
+ return new Cookie(key).read();
+};
+
+Cookie.dispose = function(key, options){
+ return new Cookie(key, options).dispose();
+};
+/*
+---
+
+script: Swiff.js
+
+description: Wrapper for embedding SWF movies. Supports External Interface Communication.
+
+license: MIT-style license.
+
+credits:
+- Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject.
+
+requires:
+- /Options
+- /$util
+
+provides: [Swiff]
+
+...
+*/
+
+var Swiff = new Class({
+
+ Implements: [Options],
+
+ options: {
+ id: null,
+ height: 1,
+ width: 1,
+ container: null,
+ properties: {},
+ params: {
+ quality: 'high',
+ allowScriptAccess: 'always',
+ wMode: 'transparent',
+ swLiveConnect: true
+ },
+ callBacks: {},
+ vars: {}
+ },
+
+ toElement: function(){
+ return this.object;
+ },
+
+ initialize: function(path, options){
+ this.instance = 'Swiff_' + $time();
+
+ this.setOptions(options);
+ options = this.options;
+ var id = this.id = options.id || this.instance;
+ var container = document.id(options.container);
+
+ Swiff.CallBacks[this.instance] = {};
+
+ var params = options.params, vars = options.vars, callBacks = options.callBacks;
+ var properties = $extend({height: options.height, width: options.width}, options.properties);
+
+ var self = this;
+
+ for (var callBack in callBacks){
+ Swiff.CallBacks[this.instance][callBack] = (function(option){
+ return function(){
+ return option.apply(self.object, arguments);
+ };
+ })(callBacks[callBack]);
+ vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;
+ }
+
+ params.flashVars = Hash.toQueryString(vars);
+ if (Browser.Engine.trident){
+ properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
+ params.movie = path;
+ } else {
+ properties.type = 'application/x-shockwave-flash';
+ properties.data = path;
+ }
+ var build = '<object id="' + id + '"';
+ for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
+ build += '>';
+ for (var param in params){
+ if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';
+ }
+ build += '</object>';
+ this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;
+ },
+
+ replaces: function(element){
+ element = document.id(element, true);
+ element.parentNode.replaceChild(this.toElement(), element);
+ return this;
+ },
+
+ inject: function(element){
+ document.id(element, true).appendChild(this.toElement());
+ return this;
+ },
+
+ remote: function(){
+ return Swiff.remote.apply(Swiff, [this.toElement()].extend(arguments));
+ }
+
+});
+
+Swiff.CallBacks = {};
+
+Swiff.remote = function(obj, fn){
+ var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
+ return eval(rs);
+};
+/*
+---
+
+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
+
+description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.
+
+license: MIT-style license.
+
+requires:
+- /Fx
+- /Element.Style
+
+provides: [Fx.CSS]
+
+...
+*/
+
+Fx.CSS = new Class({
+
+ Extends: Fx,
+
+ //prepares the base from/to object
+
+ prepare: function(element, property, values){
+ values = $splat(values);
+ var values1 = values[1];
+ if (!$chk(values1)){
+ values[1] = values[0];
+ values[0] = element.getStyle(property);
+ }
+ var parsed = values.map(this.parse);
+ return {from: parsed[0], to: parsed[1]};
+ },
+
+ //parses a value into an array
+
+ parse: function(value){
+ value = $lambda(value)();
+ value = (typeof value == 'string') ? value.split(' ') : $splat(value);
+ return value.map(function(val){
+ val = String(val);
+ var found = false;
+ Fx.CSS.Parsers.each(function(parser, key){
+ if (found) return;
+ var parsed = parser.parse(val);
+ if ($chk(parsed)) found = {value: parsed, parser: parser};
+ });
+ found = found || {value: val, parser: Fx.CSS.Parsers.String};
+ return found;
+ });
+ },
+
+ //computes by a from and to prepared objects, using their parsers.
+
+ compute: function(from, to, delta){
+ var computed = [];
+ (Math.min(from.length, to.length)).times(function(i){
+ computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
+ });
+ computed.$family = {name: 'fx:css:value'};
+ return computed;
+ },
+
+ //serves the value as settable
+
+ serve: function(value, unit){
+ if ($type(value) != 'fx:css:value') value = this.parse(value);
+ var returned = [];
+ value.each(function(bit){
+ returned = returned.concat(bit.parser.serve(bit.value, unit));
+ });
+ return returned;
+ },
+
+ //renders the change to an element
+
+ render: function(element, property, value, unit){
+ element.setStyle(property, this.serve(value, unit));
+ },
+
+ //searches inside the page css to find the values for a selector
+
+ search: function(selector){
+ if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
+ var to = {};
+ Array.each(document.styleSheets, function(sheet, j){
+ var href = sheet.href;
+ if (href && href.contains('://') && !href.contains(document.domain)) return;
+ var rules = sheet.rules || sheet.cssRules;
+ Array.each(rules, function(rule, i){
+ if (!rule.style) return;
+ var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
+ return m.toLowerCase();
+ }) : null;
+ if (!selectorText || !selectorText.test('^' + selector + '$')) return;
+ Element.Styles.each(function(value, style){
+ if (!rule.style[style] || Element.ShortStyles[style]) return;
+ value = String(rule.style[style]);
+ to[style] = (value.test(/^rgb/)) ? value.rgbToHex() : value;
+ });
+ });
+ });
+ return Fx.CSS.Cache[selector] = to;
+ }
+
+});
+
+Fx.CSS.Cache = {};
+
+Fx.CSS.Parsers = new Hash({
+
+ Color: {
+ parse: function(value){
+ if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
+ return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
+ },
+ compute: function(from, to, delta){
+ return from.map(function(value, i){
+ return Math.round(Fx.compute(from[i], to[i], delta));
+ });
+ },
+ serve: function(value){
+ return value.map(Number);
+ }
+ },
+
+ Number: {
+ parse: parseFloat,
+ compute: Fx.compute,
+ serve: function(value, unit){
+ return (unit) ? value + unit : value;
+ }
+ },
+
+ String: {
+ parse: $lambda(false),
+ compute: $arguments(1),
+ serve: $arguments(0)
+ }
+
+});
+/*
+---
+
+script: Fx.Tween.js
+
+description: Formerly Fx.Style, effect to transition any CSS property for an element.
+
+license: MIT-style license.
+
+requires:
+- /Fx.CSS
+
+provides: [Fx.Tween, Element.fade, Element.highlight]
+
+...
+*/
+
+Fx.Tween = new Class({
+
+ Extends: Fx.CSS,
+
+ initialize: function(element, options){
+ this.element = this.subject = document.id(element);
+ this.parent(options);
+ },
+
+ set: function(property, now){
+ if (arguments.length == 1){
+ now = property;
+ property = this.property || this.options.property;
+ }
+ this.render(this.element, property, now, this.options.unit);
+ return this;
+ },
+
+ start: function(property, from, to){
+ 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);
+ return this.parent(parsed.from, parsed.to);
+ }
+
+});
+
+Element.Properties.tween = {
+
+ set: function(options){
+ var tween = this.retrieve('tween');
+ if (tween) tween.cancel();
+ return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options));
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('tween')){
+ if (options || !this.retrieve('tween:options')) this.set('tween', options);
+ this.store('tween', new Fx.Tween(this, this.retrieve('tween:options')));
+ }
+ return this.retrieve('tween');
+ }
+
+};
+
+Element.implement({
+
+ tween: function(property, from, to){
+ this.get('tween').start(arguments);
+ return this;
+ },
+
+ fade: function(how){
+ var fade = this.get('tween'), o = 'opacity', toggle;
+ how = $pick(how, 'toggle');
+ switch (how){
+ case 'in': fade.start(o, 1); break;
+ case 'out': fade.start(o, 0); break;
+ case 'show': fade.set(o, 1); break;
+ case 'hide': fade.set(o, 0); break;
+ case 'toggle':
+ var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
+ fade.start(o, (flag) ? 0 : 1);
+ this.store('fade:flag', !flag);
+ toggle = true;
+ break;
+ default: fade.start(o, arguments);
+ }
+ if (!toggle) this.eliminate('fade:flag');
+ return this;
+ },
+
+ highlight: function(start, end){
+ if (!end){
+ end = this.retrieve('highlight:original', this.getStyle('background-color'));
+ end = (end == 'transparent') ? '#fff' : end;
+ }
+ var tween = this.get('tween');
+ tween.start('background-color', start || '#ffff88', end).chain(function(){
+ this.setStyle('background-color', this.retrieve('highlight:original'));
+ tween.callChain();
+ }.bind(this));
+ return this;
+ }
+
+});
+/*
+---
+
+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.
+
+requires:
+- /Fx.CSS
+
+provides: [Fx.Morph]
+
+...
+*/
+
+Fx.Morph = new Class({
+
+ Extends: Fx.CSS,
+
+ initialize: function(element, options){
+ this.element = this.subject = document.id(element);
+ this.parent(options);
+ },
+
+ set: function(now){
+ if (typeof now == 'string') now = this.search(now);
+ for (var p in now) this.render(this.element, p, now[p], this.options.unit);
+ return this;
+ },
+
+ compute: function(from, to, delta){
+ var now = {};
+ for (var p in from) now[p] = this.parent(from[p], to[p], delta);
+ return now;
+ },
+
+ start: function(properties){
+ if (!this.check(properties)) return this;
+ if (typeof properties == 'string') properties = this.search(properties);
+ var from = {}, to = {};
+ for (var p in properties){
+ var parsed = this.prepare(this.element, p, properties[p]);
+ from[p] = parsed.from;
+ to[p] = parsed.to;
+ }
+ return this.parent(from, to);
+ }
+
+});
+
+Element.Properties.morph = {
+
+ set: function(options){
+ var morph = this.retrieve('morph');
+ if (morph) morph.cancel();
+ return this.eliminate('morph').store('morph:options', $extend({link: 'cancel'}, options));
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('morph')){
+ if (options || !this.retrieve('morph:options')) this.set('morph', options);
+ this.store('morph', new Fx.Morph(this, this.retrieve('morph:options')));
+ }
+ return this.retrieve('morph');
+ }
+
+};
+
+Element.implement({
+
+ morph: function(props){
+ this.get('morph').start(props);
+ return this;
+ }
+
+});
+/*
+---
+
+script: Fx.Transitions.js
+
+description: Contains a set of advanced transitions to be used with any of the Fx Classes.
+
+license: MIT-style license.
+
+credits:
+- Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.
+
+requires:
+- /Fx
+
+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);
+ return $extend(transition, {
+ easeIn: function(pos){
+ return transition(pos, params);
+ },
+ easeOut: function(pos){
+ return 1 - transition(1 - pos, params);
+ },
+ easeInOut: function(pos){
+ return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2;
+ }
+ });
+};
+
+Fx.Transitions = new Hash({
+
+ linear: $arguments(0)
+
+});
+
+Fx.Transitions.extend = function(transitions){
+ for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
+};
+
+Fx.Transitions.extend({
+
+ Pow: function(p, x){
+ return Math.pow(p, x[0] || 6);
+ },
+
+ Expo: function(p){
+ return Math.pow(2, 8 * (p - 1));
+ },
+
+ Circ: function(p){
+ return 1 - Math.sin(Math.acos(p));
+ },
+
+ Sine: function(p){
+ return 1 - Math.sin((1 - p) * Math.PI / 2);
+ },
+
+ Back: function(p, x){
+ x = x[0] || 1.618;
+ return Math.pow(p, 2) * ((x + 1) * p - x);
+ },
+
+ Bounce: function(p){
+ var value;
+ for (var a = 0, b = 1; 1; a += b, b /= 2){
+ if (p >= (7 - 4 * a) / 11){
+ value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
+ break;
+ }
+ }
+ return value;
+ },
+
+ Elastic: function(p, x){
+ return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3);
+ }
+
+});
+
+['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
+ Fx.Transitions[transition] = new Fx.Transition(function(p){
+ return Math.pow(p, [i + 2]);
+ });
+});
+/*
+---
+
+script: Request.js
+
+description: Powerful all purpose Request Class. Uses XMLHTTPRequest.
+
+license: MIT-style license.
+
+requires:
+- /Element
+- /Chain
+- /Events
+- /Options
+- /Browser
+
+provides: [Request]
+
+...
+*/
+
+var Request = new Class({
+
+ Implements: [Chain, Events, Options],
+
+ options: {/*
+ onRequest: $empty,
+ onComplete: $empty,
+ onCancel: $empty,
+ onSuccess: $empty,
+ onFailure: $empty,
+ onException: $empty,*/
+ url: '',
+ data: '',
+ headers: {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ },
+ async: true,
+ format: false,
+ method: 'post',
+ link: 'ignore',
+ isSuccess: null,
+ emulation: true,
+ urlEncoded: true,
+ encoding: 'utf-8',
+ evalScripts: false,
+ evalResponse: false,
+ noCache: false
+ },
+
+ initialize: function(options){
+ this.xhr = new Browser.Request();
+ this.setOptions(options);
+ this.options.isSuccess = this.options.isSuccess || this.isSuccess;
+ this.headers = new Hash(this.options.headers);
+ },
+
+ onStateChange: function(){
+ if (this.xhr.readyState != 4 || !this.running) return;
+ this.running = false;
+ this.status = 0;
+ $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);
+ } else {
+ this.response = {text: null, xml: null};
+ this.failure();
+ }
+ },
+
+ isSuccess: function(){
+ return ((this.status >= 200) && (this.status < 300));
+ },
+
+ processScripts: function(text){
+ if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return $exec(text);
+ return text.stripScripts(this.options.evalScripts);
+ },
+
+ success: function(text, xml){
+ this.onSuccess(this.processScripts(text), xml);
+ },
+
+ onSuccess: function(){
+ this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
+ },
+
+ failure: function(){
+ this.onFailure();
+ },
+
+ onFailure: function(){
+ this.fireEvent('complete').fireEvent('failure', this.xhr);
+ },
+
+ setHeader: function(name, value){
+ this.headers.set(name, value);
+ return this;
+ },
+
+ getHeader: function(name){
+ return $try(function(){
+ return this.xhr.getResponseHeader(name);
+ }.bind(this));
+ },
+
+ check: function(){
+ if (!this.running) 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;
+ },
+
+ send: function(options){
+ if (!this.check(options)) return this;
+ this.running = true;
+
+ var type = $type(options);
+ if (type == 'string' || type == 'element') options = {data: options};
+
+ var old = this.options;
+ options = $extend({data: old.data, url: old.url, method: old.method}, options);
+ var data = options.data, url = String(options.url), method = options.method.toLowerCase();
+
+ switch ($type(data)){
+ case 'element': data = document.id(data).toQueryString(); break;
+ case 'object': case 'hash': data = Hash.toQueryString(data);
+ }
+
+ if (this.options.format){
+ var format = 'format=' + this.options.format;
+ data = (data) ? format + '&' + data : format;
+ }
+
+ if (this.options.emulation && !['get', 'post'].contains(method)){
+ var _method = '_method=' + method;
+ data = (data) ? _method + '&' + data : _method;
+ method = 'post';
+ }
+
+ if (this.options.urlEncoded && method == 'post'){
+ var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
+ 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;
+ }
+
+ this.xhr.open(method.toUpperCase(), url, this.options.async);
+
+ this.xhr.onreadystatechange = this.onStateChange.bind(this);
+
+ this.headers.each(function(value, key){
+ try {
+ this.xhr.setRequestHeader(key, value);
+ } catch (e){
+ this.fireEvent('exception', [key, value]);
+ }
+ }, this);
+
+ this.fireEvent('request');
+ this.xhr.send(data);
+ if (!this.options.async) this.onStateChange();
+ return this;
+ },
+
+ cancel: function(){
+ if (!this.running) return this;
+ this.running = false;
+ this.xhr.abort();
+ this.xhr.onreadystatechange = $empty;
+ this.xhr = new Browser.Request();
+ this.fireEvent('cancel');
+ return this;
+ }
+
+});
+
+(function(){
+
+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}));
+ };
+});
+
+Request.implement(methods);
+
+})();
+
+Element.Properties.send = {
+
+ set: function(options){
+ var send = this.retrieve('send');
+ if (send) send.cancel();
+ return this.eliminate('send').store('send:options', $extend({
+ data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
+ }, options));
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('send')){
+ if (options || !this.retrieve('send:options')) this.set('send', options);
+ this.store('send', new Request(this.retrieve('send:options')));
+ }
+ return this.retrieve('send');
+ }
+
+};
+
+Element.implement({
+
+ send: function(url){
+ var sender = this.get('send');
+ sender.send({data: this, url: url || sender.options.url});
+ return this;
+ }
+
+});
+/*
+---
+
+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({
+
+ Extends: Request,
+
+ options: {
+ update: false,
+ append: false,
+ evalScripts: true,
+ filter: false
+ },
+
+ processHTML: function(text){
+ var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
+ text = (match) ? match[1] : text;
+
+ var container = new Element('div');
+
+ return $try(function(){
+ var root = '<root>' + text + '</root>', doc;
+ if (Browser.Engine.trident){
+ doc = new ActiveXObject('Microsoft.XMLDOM');
+ doc.async = false;
+ doc.loadXML(root);
+ } else {
+ 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);
+ }
+ return container;
+ }) || container.set('html', text);
+ },
+
+ 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) 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) load.cancel();
+ return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options));
+ },
+
+ get: function(options){
+ if (options || ! this.retrieve('load')){
+ if (options || !this.retrieve('load:options')) this.set('load', options);
+ this.store('load', new Request.HTML(this.retrieve('load:options')));
+ }
+ return this.retrieve('load');
+ }
+
+};
+
+Element.implement({
+
+ load: function(){
+ this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type}));
+ return this;
+ }
+
+});
+/*
+---
+
+script: Request.JSON.js
+
+description: Extends the basic Request Class with additional methods for sending and receiving JSON data.
+
+license: MIT-style license.
+
+requires:
+- /Request JSON
+
+provides: [Request.HTML]
+
+...
+*/
+
+Request.JSON = new Class({
+
+ Extends: Request,
+
+ options: {
+ secure: true
+ },
+
+ initialize: function(options){
+ this.parent(options);
+ this.headers.extend({'Accept': 'application/json', 'X-Request': 'JSON'});
+ },
+
+ success: function(text){
+ this.response.json = JSON.decode(text, this.options.secure);
+ this.onSuccess(this.response.json, text);
+ }
+
+});
+/*
+---
+
+script: More.js
+
+description: MooTools More
+
+license: MIT-style license
+
+authors:
+- Guillermo Rauch
+- Thomas Aylott
+- Scott Kyle
+
+requires:
+- core:1.2.4/MooTools
+
+provides: [MooTools.More]
+
+...
+*/
+
+MooTools.More = {
+ 'version': '1.2.4.4',
+ 'build': '6f6057dc645fdb7547689183b2311063bd653ddf'
+};/*
+---
+
+script: MooTools.Lang.js
+
+description: Provides methods for localization.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Events
+- /MooTools.More
+
+provides: [MooTools.Lang]
+
+...
+*/
+
+(function(){
+
+ var data = {
+ language: 'en-US',
+ languages: {
+ 'en-US': {}
+ },
+ cascades: ['en-US']
+ };
+
+ var cascaded;
+
+ MooTools.lang = new Events();
+
+ $extend(MooTools.lang, {
+
+ setLanguage: function(lang){
+ if (!data.languages[lang]) return this;
+ data.language = lang;
+ this.load();
+ this.fireEvent('langChange', lang);
+ return this;
+ },
+
+ load: function() {
+ var langs = this.cascade(this.getCurrentLanguage());
+ cascaded = {};
+ $each(langs, function(set, setName){
+ cascaded[setName] = this.lambda(set);
+ }, this);
+ },
+
+ getCurrentLanguage: function(){
+ return data.language;
+ },
+
+ addLanguage: function(lang){
+ data.languages[lang] = data.languages[lang] || {};
+ return this;
+ },
+
+ cascade: function(lang){
+ var cascades = (data.languages[lang] || {}).cascades || [];
+ cascades.combine(data.cascades);
+ cascades.erase(lang).push(lang);
+ var langs = cascades.map(function(lng){
+ return data.languages[lng];
+ }, this);
+ return $merge.apply(this, langs);
+ },
+
+ lambda: function(set) {
+ (set || {}).get = function(key, args){
+ return $lambda(set[key]).apply(this, $splat(args));
+ };
+ return set;
+ },
+
+ get: function(set, key, args){
+ if (cascaded && cascaded[set]) return (key ? cascaded[set].get(key, args) : cascaded[set]);
+ },
+
+ set: function(lang, set, members){
+ this.addLanguage(lang);
+ langData = data.languages[lang];
+ if (!langData[set]) langData[set] = {};
+ $extend(langData[set], members);
+ if (lang == this.getCurrentLanguage()){
+ this.load();
+ this.fireEvent('langChange', lang);
+ }
+ return this;
+ },
+
+ list: function(){
+ return Hash.getKeys(data.languages);
+ }
+
+ });
+
+})();/*
+---
+
+script: Log.js
+
+description: Provides basic logging functionality for plugins to implement.
+
+license: MIT-style license
+
+authors:
+- Guillermo Rauch
+- Thomas Aylott
+- Scott Kyle
+
+requires:
+- core:1.2.4/Class
+- /MooTools.More
+
+provides: [Log]
+
+...
+*/
+
+(function(){
+
+var global = this;
+
+var log = function(){
+ if (global.console && console.log){
+ try {
+ console.log.apply(console, arguments);
+ } catch(e) {
+ console.log(Array.slice(arguments));
+ }
+ } else {
+ Log.logged.push(arguments);
+ }
+ return this;
+};
+
+var disabled = function(){
+ this.logged.push(arguments);
+ return this;
+};
+
+this.Log = new Class({
+
+ logged: [],
+
+ log: disabled,
+
+ resetLog: function(){
+ this.logged.empty();
+ return this;
+ },
+
+ enableLog: function(){
+ this.log = log;
+ this.logged.each(function(args){
+ this.log.apply(this, args);
+ }, this);
+ return this.resetLog();
+ },
+
+ disableLog: function(){
+ this.log = disabled;
+ return this;
+ }
+
+});
+
+Log.extend(new Log).enableLog();
+
+// legacy
+Log.logger = function(){
+ return this.log.apply(this, arguments);
+};
+
+})();/*
+---
+
+script: Depender.js
+
+description: A stand alone dependency loader for the MooTools library.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element.Events
+- core:1.2.4/Request.JSON
+- /MooTools.More
+- /Log
+
+provides: Depender
+
+...
+*/
+
+var Depender = {
+
+ options: {
+ /*
+ onRequire: $empty(options),
+ onRequirementLoaded: $empty([scripts, options]),
+ onScriptLoaded: $empty({
+ script: script,
+ totalLoaded: percentOfTotalLoaded,
+ loaded: scriptsState
+ }),
+ serial: false,
+ target: null,
+ noCache: false,
+ log: false,*/
+ loadedSources: [],
+ loadedScripts: ['Core', 'Browser', 'Array', 'String', 'Function', 'Number', 'Hash', 'Element', 'Event', 'Element.Event', 'Class', 'DomReady', 'Class.Extras', 'Request', 'JSON', 'Request.JSON', 'More', 'Depender', 'Log'],
+ useScriptInjection: true
+ },
+
+ loaded: [],
+
+ sources: {},
+
+ libs: {},
+
+ include: function(libs){
+ this.log('include: ', libs);
+ this.mapLoaded = false;
+ var loader = function(data){
+ this.libs = $merge(this.libs, data);
+ $each(this.libs, function(data, lib){
+ if (data.scripts) this.loadSource(lib, data.scripts);
+ }, this);
+ }.bind(this);
+ if ($type(libs) == 'string'){
+ this.log('fetching libs ', libs);
+ this.request(libs, loader);
+ } else {
+ loader(libs);
+ }
+ return this;
+ },
+
+ required: [],
+
+ require: function(options){
+ var loaded = function(){
+ var scripts = this.calculateDependencies(options.scripts);
+ if (options.sources){
+ options.sources.each(function(source){
+ scripts.combine(this.libs[source].files);
+ }, this);
+ }
+ if (options.serial) scripts.combine(this.getLoadedScripts());
+ options.scripts = scripts;
+ this.required.push(options);
+ this.fireEvent('require', options);
+ this.loadScripts(options.scripts);
+ };
+ if (this.mapLoaded) loaded.call(this);
+ else this.addEvent('mapLoaded', loaded.bind(this));
+ return this;
+ },
+
+ cleanDoubleSlash: function(str){
+ if (!str) return str;
+ var prefix = '';
+ if (str.test(/^http:\/\//)){
+ prefix = 'http://';
+ str = str.substring(7, str.length);
+ }
+ str = str.replace(/\/\//g, '/');
+ return prefix + str;
+ },
+
+ request: function(url, callback){
+ new Request.JSON({
+ url: url,
+ secure: false,
+ onSuccess: callback
+ }).send();
+ },
+
+ loadSource: function(lib, source){
+ if (this.libs[lib].files){
+ this.dataLoaded();
+ return;
+ }
+ this.log('loading source: ', source);
+ this.request(this.cleanDoubleSlash(source + '/scripts.json'), function(result){
+ this.log('loaded source: ', source);
+ this.libs[lib].files = result;
+ this.dataLoaded();
+ }.bind(this));
+ },
+
+ dataLoaded: function(){
+ var loaded = true;
+ $each(this.libs, function(v, k){
+ if (!this.libs[k].files) loaded = false;
+ }, this);
+ if (loaded){
+ this.mapTree();
+ this.mapLoaded = true;
+ this.calculateLoaded();
+ this.lastLoaded = this.getLoadedScripts().getLength();
+ this.fireEvent('mapLoaded');
+ this.removeEvents('mapLoaded');
+ }
+ },
+
+ calculateLoaded: function(){
+ var set = function(script){
+ this.scriptsState[script] = true;
+ }.bind(this);
+ if (this.options.loadedScripts) this.options.loadedScripts.each(set);
+ if (this.options.loadedSources){
+ this.options.loadedSources.each(function(lib){
+ $each(this.libs[lib].files, function(dir){
+ $each(dir, function(data, file){
+ set(file);
+ }, this);
+ }, this);
+ }, this);
+ }
+ },
+
+ deps: {},
+
+ pathMap: {},
+
+ mapTree: function(){
+ $each(this.libs, function(data, source){
+ $each(data.files, function(scripts, folder){
+ $each(scripts, function(details, script){
+ var path = source + ':' + folder + ':' + script;
+ if (this.deps[path]) return;
+ this.deps[path] = details.deps;
+ this.pathMap[script] = path;
+ }, this);
+ }, this);
+ }, this);
+ },
+
+ getDepsForScript: function(script){
+ return this.deps[this.pathMap[script]] || [];
+ },
+
+ calculateDependencies: function(scripts){
+ var reqs = [];
+ $splat(scripts).each(function(script){
+ if (script == 'None' || !script) return;
+ var deps = this.getDepsForScript(script);
+ if (!deps){
+ if (window.console && console.warn) console.warn('dependencies not mapped: script: %o, map: %o, :deps: %o', script, this.pathMap, this.deps);
+ } else {
+ deps.each(function(scr){
+ if (scr == script || scr == 'None' || !scr) return;
+ if (!reqs.contains(scr)) reqs.combine(this.calculateDependencies(scr));
+ reqs.include(scr);
+ }, this);
+ }
+ reqs.include(script);
+ }, this);
+ return reqs;
+ },
+
+ getPath: function(script){
+ try {
+ var chunks = this.pathMap[script].split(':');
+ var lib = this.libs[chunks[0]];
+ var dir = (lib.path || lib.scripts) + '/';
+ chunks.shift();
+ return this.cleanDoubleSlash(dir + chunks.join('/') + '.js');
+ } catch(e){
+ return script;
+ }
+ },
+
+ loadScripts: function(scripts){
+ scripts = scripts.filter(function(s){
+ if (!this.scriptsState[s] && s != 'None'){
+ this.scriptsState[s] = false;
+ return true;
+ }
+ }, this);
+ if (scripts.length){
+ scripts.each(function(scr){
+ this.loadScript(scr);
+ }, this);
+ } else {
+ this.check();
+ }
+ },
+
+ toLoad: [],
+
+ loadScript: function(script){
+ if (this.scriptsState[script] && this.toLoad.length){
+ this.loadScript(this.toLoad.shift());
+ return;
+ } else if (this.loading){
+ this.toLoad.push(script);
+ return;
+ }
+ var finish = function(){
+ this.loading = false;
+ this.scriptLoaded(script);
+ if (this.toLoad.length) this.loadScript(this.toLoad.shift());
+ }.bind(this);
+ var error = function(){
+ this.log('could not load: ', scriptPath);
+ }.bind(this);
+ this.loading = true;
+ var scriptPath = this.getPath(script);
+ if (this.options.useScriptInjection){
+ this.log('injecting script: ', scriptPath);
+ var loaded = function(){
+ this.log('loaded script: ', scriptPath);
+ finish();
+ }.bind(this);
+ new Element('script', {
+ src: scriptPath + (this.options.noCache ? '?noCache=' + new Date().getTime() : ''),
+ events: {
+ load: loaded,
+ readystatechange: function(){
+ if (['loaded', 'complete'].contains(this.readyState)) loaded();
+ },
+ error: error
+ }
+ }).inject(this.options.target || document.head);
+ } else {
+ this.log('requesting script: ', scriptPath);
+ new Request({
+ url: scriptPath,
+ noCache: this.options.noCache,
+ onComplete: function(js){
+ this.log('loaded script: ', scriptPath);
+ $exec(js);
+ finish();
+ }.bind(this),
+ onFailure: error,
+ onException: error
+ }).send();
+ }
+ },
+
+ scriptsState: $H(),
+
+ getLoadedScripts: function(){
+ return this.scriptsState.filter(function(state){
+ return state;
+ });
+ },
+
+ scriptLoaded: function(script){
+ this.log('loaded script: ', script);
+ this.scriptsState[script] = true;
+ this.check();
+ var loaded = this.getLoadedScripts();
+ var loadedLength = loaded.getLength();
+ var toLoad = this.scriptsState.getLength();
+ this.fireEvent('scriptLoaded', {
+ script: script,
+ totalLoaded: (loadedLength / toLoad * 100).round(),
+ currentLoaded: ((loadedLength - this.lastLoaded) / (toLoad - this.lastLoaded) * 100).round(),
+ loaded: loaded
+ });
+ if (loadedLength == toLoad) this.lastLoaded = loadedLength;
+ },
+
+ lastLoaded: 0,
+
+ check: function(){
+ var incomplete = [];
+ this.required.each(function(required){
+ var loaded = [];
+ required.scripts.each(function(script){
+ if (this.scriptsState[script]) loaded.push(script);
+ }, this);
+ if (required.onStep){
+ required.onStep({
+ percent: loaded.length / required.scripts.length * 100,
+ scripts: loaded
+ });
+ };
+ if (required.scripts.length != loaded.length) return;
+ required.callback();
+ this.required.erase(required);
+ this.fireEvent('requirementLoaded', [loaded, required]);
+ }, this);
+ }
+
+};
+
+$extend(Depender, new Events);
+$extend(Depender, new Options);
+$extend(Depender, new Log);
+
+Depender._setOptions = Depender.setOptions;
+Depender.setOptions = function(){
+ Depender._setOptions.apply(Depender, arguments);
+ if (this.options.log) Depender.enableLog();
+ return this;
+};
+/*
+---
+
+script: Class.Refactor.js
+
+description: Extends a class onto itself with new property, preserving any items attached to the class's namespace.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Class
+- /MooTools.More
+
+provides: [Class.refactor]
+
+...
+*/
+
+Class.refactor = function(original, refactors){
+
+ $each(refactors, function(item, name){
+ var origin = original.prototype[name];
+ if (origin && (origin = origin._origin) && typeof item == 'function') original.implement(name, function(){
+ var old = this.previous;
+ this.previous = origin;
+ var value = item.apply(this, arguments);
+ this.previous = old;
+ return value;
+ }); else original.implement(name, item);
+ });
+
+ return original;
+
+};/*
+---
+
+script: Class.Binds.js
+
+description: Automagically binds specified methods in a class to the instance of the class.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Class
+- /MooTools.More
+
+provides: [Class.Binds]
+
+...
+*/
+
+Class.Mutators.Binds = function(binds){
+ return binds;
+};
+
+Class.Mutators.initialize = function(initialize){
+ return function(){
+ $splat(this.Binds).each(function(name){
+ var original = this[name];
+ if (original) this[name] = original.bind(this);
+ }, this);
+ return initialize.apply(this, arguments);
+ };
+};
+/*
+---
+
+script: Class.Occlude.js
+
+description: Prevents a class from being applied to a DOM element twice.
+
+license: MIT-style license.
+
+authors:
+- Aaron Newton
+
+requires:
+- core/1.2.4/Class
+- core:1.2.4/Element
+- /MooTools.More
+
+provides: [Class.Occlude]
+
+...
+*/
+
+Class.Occlude = new Class({
+
+ occlude: function(property, element){
+ element = document.id(element || this.element);
+ var instance = element.retrieve(property || this.property);
+ if (instance && !$defined(this.occluded))
+ return this.occluded = instance;
+
+ this.occluded = false;
+ element.store(property || this.property, this);
+ return this.occluded;
+ }
+
+});/*
+---
+
+script: Chain.Wait.js
+
+description: value, Adds a method to inject pauses between chained events.
+
+license: MIT-style license.
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Chain
+- core:1.2.4/Element
+- core:1.2.4/Fx
+- /MooTools.More
+
+provides: [Chain.Wait]
+
+...
+*/
+
+(function(){
+
+ var wait = {
+ wait: function(duration){
+ return this.chain(function(){
+ this.callChain.delay($pick(duration, 500), this);
+ }.bind(this));
+ }
+ };
+
+ Chain.implement(wait);
+
+ if (window.Fx){
+ Fx.implement(wait);
+ ['Css', 'Tween', 'Elements'].each(function(cls){
+ if (Fx[cls]) Fx[cls].implement(wait);
+ });
+ }
+
+ Element.implement({
+ chains: function(effects){
+ $splat($pick(effects, ['tween', 'morph', 'reveal'])).each(function(effect){
+ effect = this.get(effect);
+ if (!effect) return;
+ effect.setOptions({
+ link:'chain'
+ });
+ }, this);
+ return this;
+ },
+ pauseFx: function(duration, effect){
+ this.chains(effect).get($pick(effect, 'tween')).wait(duration);
+ return this;
+ }
+ });
+
+})();/*
+---
+
+script: Array.Extras.js
+
+description: Extends the Array native object to include useful methods to work with arrays.
+
+license: MIT-style license
+
+authors:
+- Christoph Pojer
+
+requires:
+- core:1.2.4/Array
+
+provides: [Array.Extras]
+
+...
+*/
+Array.implement({
+
+ min: function(){
+ return Math.min.apply(null, this);
+ },
+
+ max: function(){
+ return Math.max.apply(null, this);
+ },
+
+ average: function(){
+ return this.length ? this.sum() / this.length : 0;
+ },
+
+ sum: function(){
+ var result = 0, l = this.length;
+ if (l){
+ do {
+ result += this[--l];
+ } while (l);
+ }
+ return result;
+ },
+
+ unique: function(){
+ return [].combine(this);
+ },
+
+ shuffle: function(){
+ for (var i = this.length; i && --i;){
+ var temp = this[i], r = Math.floor(Math.random() * ( i + 1 ));
+ this[i] = this[r];
+ this[r] = temp;
+ }
+ return this;
+ }
+
+});/*
+---
+
+script: Date.English.US.js
+
+description: Date messages for US English.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.English.US]
+
+...
+*/
+
+MooTools.lang.set('en-US', 'Date', {
+
+ months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+ days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+ //culture's date order: MM/DD/YYYY
+ dateOrder: ['month', 'date', 'year'],
+ shortDate: '%m/%d/%Y',
+ shortTime: '%I:%M%p',
+ AM: 'AM',
+ PM: 'PM',
+
+ /* Date.Extras */
+ ordinal: function(dayOfMonth){
+ //1st, 2nd, 3rd, etc.
+ return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)];
+ },
+
+ lessThanMinuteAgo: 'less than a minute ago',
+ minuteAgo: 'about a minute ago',
+ minutesAgo: '{delta} minutes ago',
+ hourAgo: 'about an hour ago',
+ hoursAgo: 'about {delta} hours ago',
+ dayAgo: '1 day ago',
+ daysAgo: '{delta} days ago',
+ weekAgo: '1 week ago',
+ weeksAgo: '{delta} weeks ago',
+ monthAgo: '1 month ago',
+ monthsAgo: '{delta} months ago',
+ yearAgo: '1 year ago',
+ yearsAgo: '{delta} years ago',
+ lessThanMinuteUntil: 'less than a minute from now',
+ minuteUntil: 'about a minute from now',
+ minutesUntil: '{delta} minutes from now',
+ hourUntil: 'about an hour from now',
+ hoursUntil: 'about {delta} hours from now',
+ dayUntil: '1 day from now',
+ daysUntil: '{delta} days from now',
+ weekUntil: '1 week from now',
+ weeksUntil: '{delta} weeks from now',
+ monthUntil: '1 month from now',
+ monthsUntil: '{delta} months from now',
+ yearUntil: '1 year from now',
+ yearsUntil: '{delta} years from now'
+
+});
+/*
+---
+
+script: Date.js
+
+description: Extends the Date native object to include methods useful in managing dates.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+- Nicholas Barthelemy - https://svn.nbarthelemy.com/date-js/
+- Harald Kirshner - mail [at] digitarald.de; http://digitarald.de
+- Scott Kyle - scott [at] appden.com; http://appden.com
+
+requires:
+- core:1.2.4/Array
+- core:1.2.4/String
+- core:1.2.4/Number
+- core:1.2.4/Lang
+- core:1.2.4/Date.English.US
+- /MooTools.More
+
+provides: [Date]
+
+...
+*/
+
+(function(){
+
+var Date = this.Date;
+
+if (!Date.now) Date.now = $time;
+
+Date.Methods = {
+ ms: 'Milliseconds',
+ year: 'FullYear',
+ min: 'Minutes',
+ mo: 'Month',
+ sec: 'Seconds',
+ hr: 'Hours'
+};
+
+['Date', 'Day', 'FullYear', 'Hours', 'Milliseconds', 'Minutes', 'Month', 'Seconds', 'Time', 'TimezoneOffset',
+ 'Week', 'Timezone', 'GMTOffset', 'DayOfYear', 'LastMonth', 'LastDayOfMonth', 'UTCDate', 'UTCDay', 'UTCFullYear',
+ 'AMPM', 'Ordinal', 'UTCHours', 'UTCMilliseconds', 'UTCMinutes', 'UTCMonth', 'UTCSeconds'].each(function(method){
+ Date.Methods[method.toLowerCase()] = method;
+});
+
+var pad = function(what, length){
+ return new Array(length - String(what).length + 1).join('0') + what;
+};
+
+Date.implement({
+
+ set: function(prop, value){
+ switch ($type(prop)){
+ case 'object':
+ for (var p in prop) this.set(p, prop[p]);
+ break;
+ case 'string':
+ prop = prop.toLowerCase();
+ var m = Date.Methods;
+ if (m[prop]) this['set' + m[prop]](value);
+ }
+ return this;
+ },
+
+ get: function(prop){
+ prop = prop.toLowerCase();
+ var m = Date.Methods;
+ if (m[prop]) return this['get' + m[prop]]();
+ return null;
+ },
+
+ clone: function(){
+ return new Date(this.get('time'));
+ },
+
+ increment: function(interval, times){
+ interval = interval || 'day';
+ times = $pick(times, 1);
+
+ switch (interval){
+ case 'year':
+ return this.increment('month', times * 12);
+ case 'month':
+ var d = this.get('date');
+ this.set('date', 1).set('mo', this.get('mo') + times);
+ return this.set('date', d.min(this.get('lastdayofmonth')));
+ case 'week':
+ return this.increment('day', times * 7);
+ case 'day':
+ return this.set('date', this.get('date') + times);
+ }
+
+ if (!Date.units[interval]) throw new Error(interval + ' is not a supported interval');
+
+ return this.set('time', this.get('time') + times * Date.units[interval]());
+ },
+
+ decrement: function(interval, times){
+ return this.increment(interval, -1 * $pick(times, 1));
+ },
+
+ isLeapYear: function(){
+ return Date.isLeapYear(this.get('year'));
+ },
+
+ clearTime: function(){
+ return this.set({hr: 0, min: 0, sec: 0, ms: 0});
+ },
+
+ diff: function(date, resolution){
+ if ($type(date) == 'string') date = Date.parse(date);
+
+ return ((date - this) / Date.units[resolution || 'day'](3, 3)).toInt(); // non-leap year, 30-day month
+ },
+
+ getLastDayOfMonth: function(){
+ return Date.daysInMonth(this.get('mo'), this.get('year'));
+ },
+
+ getDayOfYear: function(){
+ return (Date.UTC(this.get('year'), this.get('mo'), this.get('date') + 1)
+ - Date.UTC(this.get('year'), 0, 1)) / Date.units.day();
+ },
+
+ getWeek: function(){
+ return (this.get('dayofyear') / 7).ceil();
+ },
+
+ getOrdinal: function(day){
+ return Date.getMsg('ordinal', day || this.get('date'));
+ },
+
+ getTimezone: function(){
+ return this.toString()
+ .replace(/^.*? ([A-Z]{3}).[0-9]{4}.*$/, '$1')
+ .replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, '$1$2$3');
+ },
+
+ getGMTOffset: function(){
+ var off = this.get('timezoneOffset');
+ return ((off > 0) ? '-' : '+') + pad((off.abs() / 60).floor(), 2) + pad(off % 60, 2);
+ },
+
+ setAMPM: function(ampm){
+ ampm = ampm.toUpperCase();
+ var hr = this.get('hr');
+ if (hr > 11 && ampm == 'AM') return this.decrement('hour', 12);
+ else if (hr < 12 && ampm == 'PM') return this.increment('hour', 12);
+ return this;
+ },
+
+ getAMPM: function(){
+ return (this.get('hr') < 12) ? 'AM' : 'PM';
+ },
+
+ parse: function(str){
+ this.set('time', Date.parse(str));
+ return this;
+ },
+
+ isValid: function(date) {
+ return !!(date || this).valueOf();
+ },
+
+ format: function(f){
+ if (!this.isValid()) return 'invalid date';
+ f = f || '%x %X';
+ f = formats[f.toLowerCase()] || f; // replace short-hand with actual format
+ var d = this;
+ return f.replace(/%([a-z%])/gi,
+ function($0, $1){
+ switch ($1){
+ case 'a': return Date.getMsg('days')[d.get('day')].substr(0, 3);
+ case 'A': return Date.getMsg('days')[d.get('day')];
+ case 'b': return Date.getMsg('months')[d.get('month')].substr(0, 3);
+ case 'B': return Date.getMsg('months')[d.get('month')];
+ case 'c': return d.toString();
+ case 'd': return pad(d.get('date'), 2);
+ case 'H': return pad(d.get('hr'), 2);
+ case 'I': return ((d.get('hr') % 12) || 12);
+ case 'j': return pad(d.get('dayofyear'), 3);
+ case 'm': return pad((d.get('mo') + 1), 2);
+ case 'M': return pad(d.get('min'), 2);
+ case 'o': return d.get('ordinal');
+ case 'p': return Date.getMsg(d.get('ampm'));
+ case 'S': return pad(d.get('seconds'), 2);
+ case 'U': return pad(d.get('week'), 2);
+ case 'w': return d.get('day');
+ case 'x': return d.format(Date.getMsg('shortDate'));
+ case 'X': return d.format(Date.getMsg('shortTime'));
+ case 'y': return d.get('year').toString().substr(2);
+ case 'Y': return d.get('year');
+ case 'T': return d.get('GMTOffset');
+ case 'Z': return d.get('Timezone');
+ }
+ return $1;
+ }
+ );
+ },
+
+ toISOString: function(){
+ return this.format('iso8601');
+ }
+
+});
+
+Date.alias('toISOString', 'toJSON');
+Date.alias('diff', 'compare');
+Date.alias('format', 'strftime');
+
+var formats = {
+ db: '%Y-%m-%d %H:%M:%S',
+ compact: '%Y%m%dT%H%M%S',
+ iso8601: '%Y-%m-%dT%H:%M:%S%T',
+ rfc822: '%a, %d %b %Y %H:%M:%S %Z',
+ 'short': '%d %b %H:%M',
+ 'long': '%B %d, %Y %H:%M'
+};
+
+var parsePatterns = [];
+var nativeParse = Date.parse;
+
+var parseWord = function(type, word, num){
+ var ret = -1;
+ var translated = Date.getMsg(type + 's');
+
+ switch ($type(word)){
+ case 'object':
+ ret = translated[word.get(type)];
+ break;
+ case 'number':
+ ret = translated[month - 1];
+ if (!ret) throw new Error('Invalid ' + type + ' index: ' + index);
+ break;
+ case 'string':
+ var match = translated.filter(function(name){
+ return this.test(name);
+ }, new RegExp('^' + word, 'i'));
+ if (!match.length) throw new Error('Invalid ' + type + ' string');
+ if (match.length > 1) throw new Error('Ambiguous ' + type);
+ ret = match[0];
+ }
+
+ return (num) ? translated.indexOf(ret) : ret;
+};
+
+Date.extend({
+
+ getMsg: function(key, args) {
+ return MooTools.lang.get('Date', key, args);
+ },
+
+ units: {
+ ms: $lambda(1),
+ second: $lambda(1000),
+ minute: $lambda(60000),
+ hour: $lambda(3600000),
+ day: $lambda(86400000),
+ week: $lambda(608400000),
+ month: function(month, year){
+ var d = new Date;
+ return Date.daysInMonth($pick(month, d.get('mo')), $pick(year, d.get('year'))) * 86400000;
+ },
+ year: function(year){
+ year = year || new Date().get('year');
+ return Date.isLeapYear(year) ? 31622400000 : 31536000000;
+ }
+ },
+
+ daysInMonth: function(month, year){
+ return [31, Date.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
+ },
+
+ isLeapYear: function(year){
+ return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
+ },
+
+ parse: function(from){
+ var t = $type(from);
+ if (t == 'number') return new Date(from);
+ if (t != 'string') return from;
+ from = from.clean();
+ if (!from.length) return null;
+
+ var parsed;
+ parsePatterns.some(function(pattern){
+ var bits = pattern.re.exec(from);
+ return (bits) ? (parsed = pattern.handler(bits)) : false;
+ });
+
+ return parsed || new Date(nativeParse(from));
+ },
+
+ parseDay: function(day, num){
+ return parseWord('day', day, num);
+ },
+
+ parseMonth: function(month, num){
+ return parseWord('month', month, num);
+ },
+
+ parseUTC: function(value){
+ var localDate = new Date(value);
+ var utcSeconds = Date.UTC(
+ localDate.get('year'),
+ localDate.get('mo'),
+ localDate.get('date'),
+ localDate.get('hr'),
+ localDate.get('min'),
+ localDate.get('sec')
+ );
+ return new Date(utcSeconds);
+ },
+
+ orderIndex: function(unit){
+ return Date.getMsg('dateOrder').indexOf(unit) + 1;
+ },
+
+ defineFormat: function(name, format){
+ formats[name] = format;
+ },
+
+ defineFormats: function(formats){
+ for (var name in formats) Date.defineFormat(name, formats[name]);
+ },
+
+ parsePatterns: parsePatterns, // this is deprecated
+
+ defineParser: function(pattern){
+ parsePatterns.push((pattern.re && pattern.handler) ? pattern : build(pattern));
+ },
+
+ defineParsers: function(){
+ Array.flatten(arguments).each(Date.defineParser);
+ },
+
+ define2DigitYearStart: function(year){
+ startYear = year % 100;
+ startCentury = year - startYear;
+ }
+
+});
+
+var startCentury = 1900;
+var startYear = 70;
+
+var regexOf = function(type){
+ return new RegExp('(?:' + Date.getMsg(type).map(function(name){
+ return name.substr(0, 3);
+ }).join('|') + ')[a-z]*');
+};
+
+var replacers = function(key){
+ switch(key){
+ case 'x': // iso8601 covers yyyy-mm-dd, so just check if month is first
+ return ((Date.orderIndex('month') == 1) ? '%m[.-/]%d' : '%d[.-/]%m') + '([.-/]%y)?';
+ case 'X':
+ return '%H([.:]%M)?([.:]%S([.:]%s)?)? ?%p? ?%T?';
+ }
+ return null;
+};
+
+var keys = {
+ d: /[0-2]?[0-9]|3[01]/,
+ H: /[01]?[0-9]|2[0-3]/,
+ I: /0?[1-9]|1[0-2]/,
+ M: /[0-5]?\d/,
+ s: /\d+/,
+ o: /[a-z]*/,
+ p: /[ap]\.?m\.?/,
+ y: /\d{2}|\d{4}/,
+ Y: /\d{4}/,
+ T: /Z|[+-]\d{2}(?::?\d{2})?/
+};
+
+keys.m = keys.I;
+keys.S = keys.M;
+
+var currentLanguage;
+
+var recompile = function(language){
+ currentLanguage = language;
+
+ keys.a = keys.A = regexOf('days');
+ keys.b = keys.B = regexOf('months');
+
+ parsePatterns.each(function(pattern, i){
+ if (pattern.format) parsePatterns[i] = build(pattern.format);
+ });
+};
+
+var build = function(format){
+ if (!currentLanguage) return {format: format};
+
+ var parsed = [];
+ var re = (format.source || format) // allow format to be regex
+ .replace(/%([a-z])/gi,
+ function($0, $1){
+ return replacers($1) || $0;
+ }
+ ).replace(/\((?!\?)/g, '(?:') // make all groups non-capturing
+ .replace(/ (?!\?|\*)/g, ',? ') // be forgiving with spaces and commas
+ .replace(/%([a-z%])/gi,
+ function($0, $1){
+ var p = keys[$1];
+ if (!p) return $1;
+ parsed.push($1);
+ return '(' + p.source + ')';
+ }
+ ).replace(/\[a-z\]/gi, '[a-z\\u00c0-\\uffff]'); // handle unicode words
+
+ return {
+ format: format,
+ re: new RegExp('^' + re + '$', 'i'),
+ handler: function(bits){
+ bits = bits.slice(1).associate(parsed);
+ var date = new Date().clearTime();
+ if ('d' in bits) handle.call(date, 'd', 1);
+ if ('m' in bits || 'b' in bits || 'B' in bits) handle.call(date, 'm', 1);
+ for (var key in bits) handle.call(date, key, bits[key]);
+ return date;
+ }
+ };
+};
+
+var handle = function(key, value){
+ if (!value) return this;
+
+ switch(key){
+ case 'a': case 'A': return this.set('day', Date.parseDay(value, true));
+ case 'b': case 'B': return this.set('mo', Date.parseMonth(value, true));
+ case 'd': return this.set('date', value);
+ case 'H': case 'I': return this.set('hr', value);
+ case 'm': return this.set('mo', value - 1);
+ case 'M': return this.set('min', value);
+ case 'p': return this.set('ampm', value.replace(/\./g, ''));
+ case 'S': return this.set('sec', value);
+ case 's': return this.set('ms', ('0.' + value) * 1000);
+ case 'w': return this.set('day', value);
+ case 'Y': return this.set('year', value);
+ case 'y':
+ value = +value;
+ if (value < 100) value += startCentury + (value < startYear ? 100 : 0);
+ return this.set('year', value);
+ case 'T':
+ if (value == 'Z') value = '+00';
+ var offset = value.match(/([+-])(\d{2}):?(\d{2})?/);
+ offset = (offset[1] + '1') * (offset[2] * 60 + (+offset[3] || 0)) + this.getTimezoneOffset();
+ return this.set('time', this - offset * 60000);
+ }
+
+ return this;
+};
+
+Date.defineParsers(
+ '%Y([-./]%m([-./]%d((T| )%X)?)?)?', // "1999-12-31", "1999-12-31 11:59pm", "1999-12-31 23:59:59", ISO8601
+ '%Y%m%d(T%H(%M%S?)?)?', // "19991231", "19991231T1159", compact
+ '%x( %X)?', // "12/31", "12.31.99", "12-31-1999", "12/31/2008 11:59 PM"
+ '%d%o( %b( %Y)?)?( %X)?', // "31st", "31st December", "31 Dec 1999", "31 Dec 1999 11:59pm"
+ '%b( %d%o)?( %Y)?( %X)?', // Same as above with month and day switched
+ '%Y %b( %d%o( %X)?)?', // Same as above with year coming first
+ '%o %b %d %X %T %Y' // "Thu Oct 22 08:11:23 +0000 2009"
+);
+
+MooTools.lang.addEvent('langChange', function(language){
+ if (MooTools.lang.get('Date')) recompile(language);
+}).fireEvent('langChange', MooTools.lang.getCurrentLanguage());
+
+})();/*
+---
+
+script: Date.Extras.js
+
+description: Extends the Date native object to include extra methods (on top of those in Date.js).
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+- Scott Kyle
+
+requires:
+- /Date
+
+provides: [Date.Extras]
+
+...
+*/
+
+Date.implement({
+
+ timeDiffInWords: function(relative_to){
+ return Date.distanceOfTimeInWords(this, relative_to || new Date);
+ },
+
+ timeDiff: function(to, joiner){
+ if (to == null) to = new Date;
+ var delta = ((to - this) / 1000).toInt();
+ if (!delta) return '0s';
+
+ var durations = {s: 60, m: 60, h: 24, d: 365, y: 0};
+ var duration, vals = [];
+
+ for (var step in durations){
+ if (!delta) break;
+ if ((duration = durations[step])){
+ vals.unshift((delta % duration) + step);
+ delta = (delta / duration).toInt();
+ } else {
+ vals.unshift(delta + step);
+ }
+ }
+
+ return vals.join(joiner || ':');
+ }
+
+});
+
+Date.alias('timeDiffInWords', 'timeAgoInWords');
+
+Date.extend({
+
+ distanceOfTimeInWords: function(from, to){
+ return Date.getTimePhrase(((to - from) / 1000).toInt());
+ },
+
+ getTimePhrase: function(delta){
+ var suffix = (delta < 0) ? 'Until' : 'Ago';
+ if (delta < 0) delta *= -1;
+
+ var units = {
+ minute: 60,
+ hour: 60,
+ day: 24,
+ week: 7,
+ month: 52 / 12,
+ year: 12,
+ eon: Infinity
+ };
+
+ var msg = 'lessThanMinute';
+
+ for (var unit in units){
+ var interval = units[unit];
+ if (delta < 1.5 * interval){
+ if (delta > 0.75 * interval) msg = unit;
+ break;
+ }
+ delta /= interval;
+ msg = unit + 's';
+ }
+
+ return Date.getMsg(msg + suffix).substitute({delta: delta.round()});
+ }
+
+});
+
+
+Date.defineParsers(
+
+ {
+ // "today", "tomorrow", "yesterday"
+ re: /^(?:tod|tom|yes)/i,
+ handler: function(bits){
+ var d = new Date().clearTime();
+ switch(bits[0]){
+ case 'tom': return d.increment();
+ case 'yes': return d.decrement();
+ default: return d;
+ }
+ }
+ },
+
+ {
+ // "next Wednesday", "last Thursday"
+ re: /^(next|last) ([a-z]+)$/i,
+ handler: function(bits){
+ var d = new Date().clearTime();
+ var day = d.getDay();
+ var newDay = Date.parseDay(bits[2], true);
+ var addDays = newDay - day;
+ if (newDay <= day) addDays += 7;
+ if (bits[1] == 'last') addDays -= 7;
+ return d.set('date', d.getDate() + addDays);
+ }
+ }
+
+);
+/*
+---
+
+script: Hash.Extras.js
+
+description: Extends the Hash native object to include getFromPath which allows a path notation to child elements.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Hash.base
+- /MooTools.More
+
+provides: [Hash.Extras]
+
+...
+*/
+
+Hash.implement({
+
+ getFromPath: function(notation){
+ var source = this.getClean();
+ notation.replace(/\[([^\]]+)\]|\.([^.[]+)|[^[.]+/g, function(match){
+ if (!source) return null;
+ var prop = arguments[2] || arguments[1] || arguments[0];
+ source = (prop in source) ? source[prop] : null;
+ return match;
+ });
+ return source;
+ },
+
+ cleanValues: function(method){
+ method = method || $defined;
+ this.each(function(v, k){
+ if (!method(v)) this.erase(k);
+ }, this);
+ return this;
+ },
+
+ run: function(){
+ var args = arguments;
+ this.each(function(v, k){
+ if ($type(v) == 'function') v.run(args);
+ });
+ }
+
+});/*
+---
+
+script: String.Extras.js
+
+description: Extends the String native object to include methods useful in managing various kinds of strings (query strings, urls, html, etc).
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+- Guillermo Rauch
+
+requires:
+- core:1.2.4/String
+- core:1.2.4/$util
+- core:1.2.4/Array
+
+provides: [String.Extras]
+
+...
+*/
+
+(function(){
+
+var special = ['Ã','à ','Ã?','á','Ã','â','Ã','ã','Ã','ä','Ã
','Ã¥','Ä','Ä','Ä','Ä
','Ä','Ä','Ä','Ä?','Ã','ç', 'Ä','Ä?','Ä?','Ä', 'Ã','è','Ã','é','Ã','ê','Ã','ë','Ä','Ä','Ä','Ä', 'Ä','Ä','Ã','ì','Ã?','Ã','Ã','î','Ã?','ï', 'Ĺ','ĺ','Ľ','ľ','Å?','Å', 'Ã','ñ','Å','Å','Å','Å','Ã','ò','Ã','ó','Ã','ô','Ã','õ','Ã','ö','Ã','ø','Å','Å','Å','Å','Å','Å ','Å¡','Å','Å','Å','Å', 'Ť','Å¥','Ť','Å¥','Å¢','Å£','Ã','ù','Ã','ú','Ã','û','Ã','ü','Å®','ů', 'Ÿ','ÿ','ý','Ã?','Ž','ž','Ź','ź','Å»','ż', 'Ã','þ','Ã?','ð','Ã','Å','Å','Ã','æ','µ'];
+
+var standard = ['A','a','A','a','A','a','A','a','Ae','ae','A','a','A','a','A','a','C','c','C','c','C','c','D','d','D','d', 'E','e','E','e','E','e','E','e','E','e','E','e','G','g','I','i','I','i','I','i','I','i','L','l','L','l','L','l', 'N','n','N','n','N','n', 'O','o','O','o','O','o','O','o','Oe','oe','O','o','o', 'R','r','R','r', 'S','s','S','s','S','s','T','t','T','t','T','t', 'U','u','U','u','U','u','Ue','ue','U','u','Y','y','Y','y','Z','z','Z','z','Z','z','TH','th','DH','dh','ss','OE','oe','AE','ae','u'];
+
+var tidymap = {
+ "[\xa0\u2002\u2003\u2009]": " ",
+ "\xb7": "*",
+ "[\u2018\u2019]": "'",
+ "[\u201c\u201d]": '"',
+ "\u2026": "...",
+ "\u2013": "-",
+ "\u2014": "--",
+ "\uFFFD": "»"
+};
+
+var getRegForTag = function(tag, contents) {
+ tag = tag || '';
+ var regstr = contents ? "<" + tag + "[^>]*>([\\s\\S]*?)<\/" + tag + ">" : "<\/?" + tag + "([^>]+)?>";
+ reg = new RegExp(regstr, "gi");
+ return reg;
+};
+
+String.implement({
+
+ standardize: function(){
+ var text = this;
+ special.each(function(ch, i){
+ text = text.replace(new RegExp(ch, 'g'), standard[i]);
+ });
+ return text;
+ },
+
+ repeat: function(times){
+ return new Array(times + 1).join(this);
+ },
+
+ pad: function(length, str, dir){
+ if (this.length >= length) return this;
+ var pad = (str == null ? ' ' : '' + str).repeat(length - this.length).substr(0, length - this.length);
+ if (!dir || dir == 'right') return this + pad;
+ if (dir == 'left') return pad + this;
+ return pad.substr(0, (pad.length / 2).floor()) + this + pad.substr(0, (pad.length / 2).ceil());
+ },
+
+ getTags: function(tag, contents){
+ return this.match(getRegForTag(tag, contents)) || [];
+ },
+
+ stripTags: function(tag, contents){
+ return this.replace(getRegForTag(tag, contents), '');
+ },
+
+ tidy: function(){
+ var txt = this.toString();
+ $each(tidymap, function(value, key){
+ txt = txt.replace(new RegExp(key, 'g'), value);
+ });
+ return txt;
+ }
+
+});
+
+})();/*
+---
+
+script: String.QueryString.js
+
+description: Methods for dealing with URI query strings.
+
+license: MIT-style license
+
+authors:
+- Sebastian Markbåge, Aaron Newton, Lennart Pilon, Valerio Proietti
+
+requires:
+- core:1.2.4/Array
+- core:1.2.4/String
+- /MooTools.More
+
+provides: [String.QueryString]
+
+...
+*/
+
+String.implement({
+
+ parseQueryString: function(){
+ var vars = this.split(/[&;]/), res = {};
+ if (vars.length) vars.each(function(val){
+ var index = val.indexOf('='),
+ keys = index < 0 ? [''] : val.substr(0, index).match(/[^\]\[]+/g),
+ value = decodeURIComponent(val.substr(index + 1)),
+ obj = res;
+ keys.each(function(key, i){
+ var current = obj[key];
+ if(i < keys.length - 1)
+ obj = obj[key] = current || {};
+ else if($type(current) == 'array')
+ current.push(value);
+ else
+ obj[key] = $defined(current) ? [current, value] : value;
+ });
+ });
+ return res;
+ },
+
+ cleanQueryString: function(method){
+ return this.split('&').filter(function(val){
+ var index = val.indexOf('='),
+ key = index < 0 ? '' : val.substr(0, index),
+ value = val.substr(index + 1);
+ return method ? method.run([key, value]) : $chk(value);
+ }).join('&');
+ }
+
+});/*
+---
+
+script: URI.js
+
+description: Provides methods useful in managing the window location and uris.
+
+license: MIT-style license
+
+authors:
+- Sebastian Markbåge
+- Aaron Newton
+
+requires:
+- core:1.2.4/Selectors
+- /String.QueryString
+
+provides: URI
+
+...
+*/
+
+var URI = new Class({
+
+ Implements: Options,
+
+ options: {
+ /*base: false*/
+ },
+
+ regex: /^(?:(\w+):)?(?:\/\/(?:(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)?(\.\.?$|(?:[^?#\/]*\/)*)([^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
+ parts: ['scheme', 'user', 'password', 'host', 'port', 'directory', 'file', 'query', 'fragment'],
+ schemes: {http: 80, https: 443, ftp: 21, rtsp: 554, mms: 1755, file: 0},
+
+ initialize: function(uri, options){
+ this.setOptions(options);
+ var base = this.options.base || URI.base;
+ if(!uri) uri = base;
+
+ if (uri && uri.parsed) this.parsed = $unlink(uri.parsed);
+ else this.set('value', uri.href || uri.toString(), base ? new URI(base) : false);
+ },
+
+ parse: function(value, base){
+ var bits = value.match(this.regex);
+ if (!bits) return false;
+ bits.shift();
+ return this.merge(bits.associate(this.parts), base);
+ },
+
+ merge: function(bits, base){
+ if ((!bits || !bits.scheme) && (!base || !base.scheme)) return false;
+ if (base){
+ this.parts.every(function(part){
+ if (bits[part]) return false;
+ bits[part] = base[part] || '';
+ return true;
+ });
+ }
+ bits.port = bits.port || this.schemes[bits.scheme.toLowerCase()];
+ bits.directory = bits.directory ? this.parseDirectory(bits.directory, base ? base.directory : '') : '/';
+ return bits;
+ },
+
+ parseDirectory: function(directory, baseDirectory) {
+ directory = (directory.substr(0, 1) == '/' ? '' : (baseDirectory || '/')) + directory;
+ if (!directory.test(URI.regs.directoryDot)) return directory;
+ var result = [];
+ directory.replace(URI.regs.endSlash, '').split('/').each(function(dir){
+ if (dir == '..' && result.length > 0) result.pop();
+ else if (dir != '.') result.push(dir);
+ });
+ return result.join('/') + '/';
+ },
+
+ combine: function(bits){
+ return bits.value || bits.scheme + '://' +
+ (bits.user ? bits.user + (bits.password ? ':' + bits.password : '') + '@' : '') +
+ (bits.host || '') + (bits.port && bits.port != this.schemes[bits.scheme] ? ':' + bits.port : '') +
+ (bits.directory || '/') + (bits.file || '') +
+ (bits.query ? '?' + bits.query : '') +
+ (bits.fragment ? '#' + bits.fragment : '');
+ },
+
+ set: function(part, value, base){
+ if (part == 'value'){
+ var scheme = value.match(URI.regs.scheme);
+ if (scheme) scheme = scheme[1];
+ if (scheme && !$defined(this.schemes[scheme.toLowerCase()])) this.parsed = { scheme: scheme, value: value };
+ else this.parsed = this.parse(value, (base || this).parsed) || (scheme ? { scheme: scheme, value: value } : { value: value });
+ } else if (part == 'data') {
+ this.setData(value);
+ } else {
+ this.parsed[part] = value;
+ }
+ return this;
+ },
+
+ get: function(part, base){
+ switch(part){
+ case 'value': return this.combine(this.parsed, base ? base.parsed : false);
+ case 'data' : return this.getData();
+ }
+ return this.parsed[part] || '';
+ },
+
+ go: function(){
+ document.location.href = this.toString();
+ },
+
+ toURI: function(){
+ return this;
+ },
+
+ getData: function(key, part){
+ var qs = this.get(part || 'query');
+ if (!$chk(qs)) return key ? null : {};
+ var obj = qs.parseQueryString();
+ return key ? obj[key] : obj;
+ },
+
+ setData: function(values, merge, part){
+ if (typeof values == 'string'){
+ data = this.getData();
+ data[arguments[0]] = arguments[1];
+ values = data;
+ } else if (merge) {
+ values = $merge(this.getData(), values);
+ }
+ return this.set(part || 'query', Hash.toQueryString(values));
+ },
+
+ clearData: function(part){
+ return this.set(part || 'query', '');
+ }
+
+});
+
+URI.prototype.toString = URI.prototype.valueOf = function(){
+ return this.get('value');
+};
+
+URI.regs = {
+ endSlash: /\/$/,
+ scheme: /^(\w+):/,
+ directoryDot: /\.\/|\.$/
+};
+
+URI.base = new URI(document.getElements('base[href]', true).getLast(), {base: document.location});
+
+String.implement({
+
+ toURI: function(options){
+ return new URI(this, options);
+ }
+
+});/*
+---
+
+script: URI.Relative.js
+
+description: Extends the URI class to add methods for computing relative and absolute urls.
+
+license: MIT-style license
+
+authors:
+- Sebastian Markbåge
+
+
+requires:
+- /Class.refactor
+- /URI
+
+provides: [URI.Relative]
+
+...
+*/
+
+URI = Class.refactor(URI, {
+
+ combine: function(bits, base){
+ if (!base || bits.scheme != base.scheme || bits.host != base.host || bits.port != base.port)
+ return this.previous.apply(this, arguments);
+ var end = bits.file + (bits.query ? '?' + bits.query : '') + (bits.fragment ? '#' + bits.fragment : '');
+
+ if (!base.directory) return (bits.directory || (bits.file ? '' : './')) + end;
+
+ var baseDir = base.directory.split('/'),
+ relDir = bits.directory.split('/'),
+ path = '',
+ offset;
+
+ var i = 0;
+ for(offset = 0; offset < baseDir.length && offset < relDir.length && baseDir[offset] == relDir[offset]; offset++);
+ for(i = 0; i < baseDir.length - offset - 1; i++) path += '../';
+ for(i = offset; i < relDir.length - 1; i++) path += relDir[i] + '/';
+
+ return (path || (bits.file ? '' : './')) + end;
+ },
+
+ toAbsolute: function(base){
+ base = new URI(base);
+ if (base) base.set('directory', '').set('file', '');
+ return this.toRelative(base);
+ },
+
+ toRelative: function(base){
+ return this.get('value', new URI(base));
+ }
+
+});/*
+---
+
+script: Element.Forms.js
+
+description: Extends the Element native object to include methods useful in managing inputs.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element
+- /MooTools.More
+
+provides: [Element.Forms]
+
+...
+*/
+
+Element.implement({
+
+ tidy: function(){
+ this.set('value', this.get('value').tidy());
+ },
+
+ getTextInRange: function(start, end){
+ return this.get('value').substring(start, end);
+ },
+
+ getSelectedText: function(){
+ if (this.setSelectionRange) return this.getTextInRange(this.getSelectionStart(), this.getSelectionEnd());
+ return document.selection.createRange().text;
+ },
+
+ getSelectedRange: function() {
+ if ($defined(this.selectionStart)) return {start: this.selectionStart, end: this.selectionEnd};
+ var pos = {start: 0, end: 0};
+ var range = this.getDocument().selection.createRange();
+ if (!range || range.parentElement() != this) return pos;
+ var dup = range.duplicate();
+ if (this.type == 'text') {
+ pos.start = 0 - dup.moveStart('character', -100000);
+ pos.end = pos.start + range.text.length;
+ } else {
+ var value = this.get('value');
+ var offset = value.length;
+ dup.moveToElementText(this);
+ dup.setEndPoint('StartToEnd', range);
+ if(dup.text.length) offset -= value.match(/[\n\r]*$/)[0].length;
+ pos.end = offset - dup.text.length;
+ dup.setEndPoint('StartToStart', range);
+ pos.start = offset - dup.text.length;
+ }
+ return pos;
+ },
+
+ getSelectionStart: function(){
+ return this.getSelectedRange().start;
+ },
+
+ getSelectionEnd: function(){
+ return this.getSelectedRange().end;
+ },
+
+ setCaretPosition: function(pos){
+ if (pos == 'end') pos = this.get('value').length;
+ this.selectRange(pos, pos);
+ return this;
+ },
+
+ getCaretPosition: function(){
+ return this.getSelectedRange().start;
+ },
+
+ selectRange: function(start, end){
+ if (this.setSelectionRange) {
+ this.focus();
+ this.setSelectionRange(start, end);
+ } else {
+ var value = this.get('value');
+ var diff = value.substr(start, end - start).replace(/\r/g, '').length;
+ start = value.substr(0, start).replace(/\r/g, '').length;
+ var range = this.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', start + diff);
+ range.moveStart('character', start);
+ range.select();
+ }
+ return this;
+ },
+
+ insertAtCursor: function(value, select){
+ var pos = this.getSelectedRange();
+ var text = this.get('value');
+ this.set('value', text.substring(0, pos.start) + value + text.substring(pos.end, text.length));
+ if ($pick(select, true)) this.selectRange(pos.start, pos.start + value.length);
+ else this.setCaretPosition(pos.start + value.length);
+ return this;
+ },
+
+ insertAroundCursor: function(options, select){
+ options = $extend({
+ before: '',
+ defaultMiddle: '',
+ after: ''
+ }, options);
+ var value = this.getSelectedText() || options.defaultMiddle;
+ var pos = this.getSelectedRange();
+ var text = this.get('value');
+ if (pos.start == pos.end){
+ this.set('value', text.substring(0, pos.start) + options.before + value + options.after + text.substring(pos.end, text.length));
+ this.selectRange(pos.start + options.before.length, pos.end + options.before.length + value.length);
+ } else {
+ var current = text.substring(pos.start, pos.end);
+ this.set('value', text.substring(0, pos.start) + options.before + current + options.after + text.substring(pos.end, text.length));
+ var selStart = pos.start + options.before.length;
+ if ($pick(select, true)) this.selectRange(selStart, selStart + current.length);
+ else this.setCaretPosition(selStart + text.length);
+ }
+ return this;
+ }
+
+});/*
+---
+
+script: Elements.From.js
+
+description: Returns a collection of elements from a string of html.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element
+- /MooTools.More
+
+provides: [Elements.from]
+
+...
+*/
+
+Elements.from = function(text, excludeScripts){
+ if ($pick(excludeScripts, true)) text = text.stripScripts();
+
+ var container, match = text.match(/^\s*<(t[dhr]|tbody|tfoot|thead)/i);
+
+ if (match){
+ container = new Element('table');
+ var tag = match[1].toLowerCase();
+ if (['td', 'th', 'tr'].contains(tag)){
+ container = new Element('tbody').inject(container);
+ if (tag != 'tr') container = new Element('tr').inject(container);
+ }
+ }
+
+ return (container || new Element('div')).set('html', text).getChildren();
+};/*
+---
+
+script: Element.Delegation.js
+
+description: Extends the Element native object to include the delegate method for more efficient event management.
+
+credits:
+- "Event checking based on the work of Daniel Steigerwald. License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+- Daniel Steigerwald
+
+requires:
+- core:1.2.4/Element.Event
+- core:1.2.4/Selectors
+- /MooTools.More
+
+provides: [Element.Delegation]
+
+...
+*/
+
+(function(addEvent, removeEvent){
+
+ var match = /(.*?):relay\(([^)]+)\)$/,
+ combinators = /[+>~\s]/,
+ splitType = function(type){
+ var bits = type.match(match);
+ return !bits ? {event: type} : {
+ event: bits[1],
+ selector: bits[2]
+ };
+ },
+ check = function(e, selector){
+ var t = e.target;
+ if (combinators.test(selector = selector.trim())){
+ var els = this.getElements(selector);
+ for (var i = els.length; i--; ){
+ var el = els[i];
+ if (t == el || el.hasChild(t)) return el;
+ }
+ } else {
+ for ( ; t && t != this; t = t.parentNode){
+ if (Element.match(t, selector)) return document.id(t);
+ }
+ }
+ return null;
+ };
+
+ Element.implement({
+
+ addEvent: function(type, fn){
+ var splitted = splitType(type);
+ if (splitted.selector){
+ var monitors = this.retrieve('$moo:delegateMonitors', {});
+ if (!monitors[type]){
+ var monitor = function(e){
+ var el = check.call(this, e, splitted.selector);
+ if (el) this.fireEvent(type, [e, el], 0, el);
+ }.bind(this);
+ monitors[type] = monitor;
+ addEvent.call(this, splitted.event, monitor);
+ }
+ }
+ return addEvent.apply(this, arguments);
+ },
+
+ removeEvent: function(type, fn){
+ var splitted = splitType(type);
+ if (splitted.selector){
+ var events = this.retrieve('events');
+ if (!events || !events[type] || (fn && !events[type].keys.contains(fn))) return this;
+
+ if (fn) removeEvent.apply(this, [type, fn]);
+ else removeEvent.apply(this, type);
+
+ events = this.retrieve('events');
+ if (events && events[type] && events[type].keys.length == 0){
+ var monitors = this.retrieve('$moo:delegateMonitors', {});
+ removeEvent.apply(this, [splitted.event, monitors[type]]);
+ delete monitors[type];
+ }
+ return this;
+ }
+ return removeEvent.apply(this, arguments);
+ },
+
+ fireEvent: function(type, args, delay, bind){
+ var events = this.retrieve('events');
+ if (!events || !events[type]) return this;
+ events[type].keys.each(function(fn){
+ fn.create({bind: bind || this, delay: delay, arguments: args})();
+ }, this);
+ return this;
+ }
+
+ });
+
+})(Element.prototype.addEvent, Element.prototype.removeEvent);/*
+---
+
+script: Element.Measure.js
+
+description: Extends the Element native object to include methods useful in measuring dimensions.
+
+credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element.Style
+- core:1.2.4/Element.Dimensions
+- /MooTools.More
+
+provides: [Element.Measure]
+
+...
+*/
+
+Element.implement({
+
+ measure: function(fn){
+ var vis = function(el) {
+ return !!(!el || el.offsetHeight || el.offsetWidth);
+ };
+ if (vis(this)) return fn.apply(this);
+ var parent = this.getParent(),
+ restorers = [],
+ toMeasure = [];
+ while (!vis(parent) && parent != document.body) {
+ toMeasure.push(parent.expose());
+ parent = parent.getParent();
+ }
+ var restore = this.expose();
+ var result = fn.apply(this);
+ restore();
+ toMeasure.each(function(restore){
+ restore();
+ });
+ return result;
+ },
+
+ expose: function(){
+ if (this.getStyle('display') != 'none') return $empty;
+ var before = this.style.cssText;
+ this.setStyles({
+ display: 'block',
+ position: 'absolute',
+ visibility: 'hidden'
+ });
+ return function(){
+ this.style.cssText = before;
+ }.bind(this);
+ },
+
+ getDimensions: function(options){
+ options = $merge({computeSize: false},options);
+ var dim = {};
+ var getSize = function(el, options){
+ return (options.computeSize)?el.getComputedSize(options):el.getSize();
+ };
+ var parent = this.getParent('body');
+ if (parent && this.getStyle('display') == 'none'){
+ dim = this.measure(function(){
+ return getSize(this, options);
+ });
+ } else if (parent){
+ try { //safari sometimes crashes here, so catch it
+ dim = getSize(this, options);
+ }catch(e){}
+ } else {
+ dim = {x: 0, y: 0};
+ }
+ return $chk(dim.x) ? $extend(dim, {width: dim.x, height: dim.y}) : $extend(dim, {x: dim.width, y: dim.height});
+ },
+
+ getComputedSize: function(options){
+ options = $merge({
+ styles: ['padding','border'],
+ plains: {
+ height: ['top','bottom'],
+ width: ['left','right']
+ },
+ mode: 'both'
+ }, options);
+ var size = {width: 0,height: 0};
+ switch (options.mode){
+ case 'vertical':
+ delete size.width;
+ delete options.plains.width;
+ break;
+ case 'horizontal':
+ delete size.height;
+ delete options.plains.height;
+ break;
+ }
+ var getStyles = [];
+ //this function might be useful in other places; perhaps it should be outside this function?
+ $each(options.plains, function(plain, key){
+ plain.each(function(edge){
+ options.styles.each(function(style){
+ getStyles.push((style == 'border') ? style + '-' + edge + '-' + 'width' : style + '-' + edge);
+ });
+ });
+ });
+ var styles = {};
+ getStyles.each(function(style){ styles[style] = this.getComputedStyle(style); }, this);
+ var subtracted = [];
+ $each(options.plains, function(plain, key){ //keys: width, height, plains: ['left', 'right'], ['top','bottom']
+ var capitalized = key.capitalize();
+ size['total' + capitalized] = size['computed' + capitalized] = 0;
+ plain.each(function(edge){ //top, left, right, bottom
+ size['computed' + edge.capitalize()] = 0;
+ getStyles.each(function(style, i){ //padding, border, etc.
+ //'padding-left'.test('left') size['totalWidth'] = size['width'] + [padding-left]
+ if (style.test(edge)){
+ styles[style] = styles[style].toInt() || 0; //styles['padding-left'] = 5;
+ size['total' + capitalized] = size['total' + capitalized] + styles[style];
+ size['computed' + edge.capitalize()] = size['computed' + edge.capitalize()] + styles[style];
+ }
+ //if width != width (so, padding-left, for instance), then subtract that from the total
+ if (style.test(edge) && key != style &&
+ (style.test('border') || style.test('padding')) && !subtracted.contains(style)){
+ subtracted.push(style);
+ size['computed' + capitalized] = size['computed' + capitalized]-styles[style];
+ }
+ });
+ });
+ });
+
+ ['Width', 'Height'].each(function(value){
+ var lower = value.toLowerCase();
+ if(!$chk(size[lower])) return;
+
+ size[lower] = size[lower] + this['offset' + value] + size['computed' + value];
+ size['total' + value] = size[lower] + size['total' + value];
+ delete size['computed' + value];
+ }, this);
+
+ return $extend(styles, size);
+ }
+
+});/*
+---
+
+script: Element.Pin.js
+
+description: Extends the Element native object to include the pin method useful for fixed positioning for elements.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element.Event
+- core:1.2.4/Element.Dimensions
+- core:1.2.4/Element.Style
+- /MooTools.More
+
+provides: [Element.Pin]
+
+...
+*/
+
+(function(){
+ var supportsPositionFixed = false;
+ window.addEvent('domready', function(){
+ var test = new Element('div').setStyles({
+ position: 'fixed',
+ top: 0,
+ right: 0
+ }).inject(document.body);
+ supportsPositionFixed = (test.offsetTop === 0);
+ test.dispose();
+ });
+
+ Element.implement({
+
+ pin: function(enable){
+ if (this.getStyle('display') == 'none') return null;
+
+ var p,
+ scroll = window.getScroll();
+ if (enable !== false){
+ p = this.getPosition();
+ if (!this.retrieve('pinned')){
+ var pos = {
+ top: p.y - scroll.y,
+ left: p.x - scroll.x
+ };
+ if (supportsPositionFixed){
+ this.setStyle('position', 'fixed').setStyles(pos);
+ } else {
+ this.store('pinnedByJS', true);
+ this.setStyles({
+ position: 'absolute',
+ top: p.y,
+ left: p.x
+ }).addClass('isPinned');
+ this.store('scrollFixer', (function(){
+ if (this.retrieve('pinned'))
+ var scroll = window.getScroll();
+ this.setStyles({
+ top: pos.top.toInt() + scroll.y,
+ left: pos.left.toInt() + scroll.x
+ });
+ }).bind(this));
+ window.addEvent('scroll', this.retrieve('scrollFixer'));
+ }
+ this.store('pinned', true);
+ }
+ } else {
+ var op;
+ if (!Browser.Engine.trident){
+ var parent = this.getParent();
+ op = (parent.getComputedStyle('position') != 'static' ? parent : parent.getOffsetParent());
+ }
+ p = this.getPosition(op);
+ this.store('pinned', false);
+ var reposition;
+ if (supportsPositionFixed && !this.retrieve('pinnedByJS')){
+ reposition = {
+ top: p.y + scroll.y,
+ left: p.x + scroll.x
+ };
+ } else {
+ this.store('pinnedByJS', false);
+ window.removeEvent('scroll', this.retrieve('scrollFixer'));
+ reposition = {
+ top: p.y,
+ left: p.x
+ };
+ }
+ this.setStyles($merge(reposition, {position: 'absolute'})).removeClass('isPinned');
+ }
+ return this;
+ },
+
+ unpin: function(){
+ return this.pin(false);
+ },
+
+ togglepin: function(){
+ this.pin(!this.retrieve('pinned'));
+ }
+
+ });
+
+})();/*
+---
+
+script: Element.Position.js
+
+description: Extends the Element native object to include methods useful positioning elements relative to others.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element.Dimensions
+- /Element.Measure
+
+provides: [Elements.Position]
+
+...
+*/
+
+(function(){
+
+var original = Element.prototype.position;
+
+Element.implement({
+
+ position: function(options){
+ //call original position if the options are x/y values
+ if (options && ($defined(options.x) || $defined(options.y))) return original ? original.apply(this, arguments) : this;
+ $each(options||{}, function(v, k){ if (!$defined(v)) delete options[k]; });
+ options = $merge({
+ // minimum: { x: 0, y: 0 },
+ // maximum: { x: 0, y: 0},
+ relativeTo: document.body,
+ position: {
+ x: 'center', //left, center, right
+ y: 'center' //top, center, bottom
+ },
+ edge: false,
+ offset: {x: 0, y: 0},
+ returnPos: false,
+ relFixedPosition: false,
+ ignoreMargins: false,
+ ignoreScroll: false,
+ allowNegative: false
+ }, options);
+ //compute the offset of the parent positioned element if this element is in one
+ var parentOffset = {x: 0, y: 0},
+ parentPositioned = false;
+ /* dollar around getOffsetParent should not be necessary, but as it does not return
+ * a mootools extended element in IE, an error occurs on the call to expose. See:
+ * http://mootools.lighthouseapp.com/projects/2706/tickets/333-element-getoffsetparent-inconsistency-between-ie-and-other-browsers */
+ var offsetParent = this.measure(function(){
+ return document.id(this.getOffsetParent());
+ });
+ if (offsetParent && offsetParent != this.getDocument().body){
+ parentOffset = offsetParent.measure(function(){
+ return this.getPosition();
+ });
+ parentPositioned = offsetParent != document.id(options.relativeTo);
+ options.offset.x = options.offset.x - parentOffset.x;
+ options.offset.y = options.offset.y - parentOffset.y;
+ }
+ //upperRight, bottomRight, centerRight, upperLeft, bottomLeft, centerLeft
+ //topRight, topLeft, centerTop, centerBottom, center
+ var fixValue = function(option){
+ if ($type(option) != 'string') return option;
+ option = option.toLowerCase();
+ var val = {};
+ if (option.test('left')) val.x = 'left';
+ else if (option.test('right')) val.x = 'right';
+ else val.x = 'center';
+ if (option.test('upper') || option.test('top')) val.y = 'top';
+ else if (option.test('bottom')) val.y = 'bottom';
+ else val.y = 'center';
+ return val;
+ };
+ options.edge = fixValue(options.edge);
+ options.position = fixValue(options.position);
+ if (!options.edge){
+ if (options.position.x == 'center' && options.position.y == 'center') options.edge = {x:'center', y:'center'};
+ else options.edge = {x:'left', y:'top'};
+ }
+
+ this.setStyle('position', 'absolute');
+ var rel = document.id(options.relativeTo) || document.body,
+ calc = rel == document.body ? window.getScroll() : rel.getPosition(),
+ top = calc.y, left = calc.x;
+
+ var dim = this.getDimensions({computeSize: true, styles:['padding', 'border','margin']});
+ var pos = {},
+ prefY = options.offset.y,
+ prefX = options.offset.x,
+ winSize = window.getSize();
+ switch(options.position.x){
+ case 'left':
+ pos.x = left + prefX;
+ break;
+ case 'right':
+ pos.x = left + prefX + rel.offsetWidth;
+ break;
+ default: //center
+ pos.x = left + ((rel == document.body ? winSize.x : rel.offsetWidth)/2) + prefX;
+ break;
+ }
+ switch(options.position.y){
+ case 'top':
+ pos.y = top + prefY;
+ break;
+ case 'bottom':
+ pos.y = top + prefY + rel.offsetHeight;
+ break;
+ default: //center
+ pos.y = top + ((rel == document.body ? winSize.y : rel.offsetHeight)/2) + prefY;
+ break;
+ }
+ if (options.edge){
+ var edgeOffset = {};
+
+ switch(options.edge.x){
+ case 'left':
+ edgeOffset.x = 0;
+ break;
+ case 'right':
+ edgeOffset.x = -dim.x-dim.computedRight-dim.computedLeft;
+ break;
+ default: //center
+ edgeOffset.x = -(dim.totalWidth/2);
+ break;
+ }
+ switch(options.edge.y){
+ case 'top':
+ edgeOffset.y = 0;
+ break;
+ case 'bottom':
+ edgeOffset.y = -dim.y-dim.computedTop-dim.computedBottom;
+ break;
+ default: //center
+ edgeOffset.y = -(dim.totalHeight/2);
+ break;
+ }
+ pos.x += edgeOffset.x;
+ pos.y += edgeOffset.y;
+ }
+ pos = {
+ left: ((pos.x >= 0 || parentPositioned || options.allowNegative) ? pos.x : 0).toInt(),
+ top: ((pos.y >= 0 || parentPositioned || options.allowNegative) ? pos.y : 0).toInt()
+ };
+ var xy = {left: 'x', top: 'y'};
+ ['minimum', 'maximum'].each(function(minmax) {
+ ['left', 'top'].each(function(lr) {
+ var val = options[minmax] ? options[minmax][xy[lr]] : null;
+ if (val != null && pos[lr] < val) pos[lr] = val;
+ });
+ });
+ if (rel.getStyle('position') == 'fixed' || options.relFixedPosition){
+ var winScroll = window.getScroll();
+ pos.top+= winScroll.y;
+ pos.left+= winScroll.x;
+ }
+ if (options.ignoreScroll) {
+ var relScroll = rel.getScroll();
+ pos.top-= relScroll.y;
+ pos.left-= relScroll.x;
+ }
+ if (options.ignoreMargins) {
+ pos.left += (
+ options.edge.x == 'right' ? dim['margin-right'] :
+ options.edge.x == 'center' ? -dim['margin-left'] + ((dim['margin-right'] + dim['margin-left'])/2) :
+ - dim['margin-left']
+ );
+ pos.top += (
+ options.edge.y == 'bottom' ? dim['margin-bottom'] :
+ options.edge.y == 'center' ? -dim['margin-top'] + ((dim['margin-bottom'] + dim['margin-top'])/2) :
+ - dim['margin-top']
+ );
+ }
+ pos.left = Math.ceil(pos.left);
+ pos.top = Math.ceil(pos.top);
+ if (options.returnPos) return pos;
+ else this.setStyles(pos);
+ return this;
+ }
+
+});
+
+})();/*
+---
+
+script: Element.Shortcuts.js
+
+description: Extends the Element native object to include some shortcut methods.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element.Style
+- /MooTools.More
+
+provides: [Element.Shortcuts]
+
+...
+*/
+
+Element.implement({
+
+ isDisplayed: function(){
+ return this.getStyle('display') != 'none';
+ },
+
+ isVisible: function(){
+ var w = this.offsetWidth,
+ h = this.offsetHeight;
+ return (w == 0 && h == 0) ? false : (w > 0 && h > 0) ? true : this.isDisplayed();
+ },
+
+ toggle: function(){
+ return this[this.isDisplayed() ? 'hide' : 'show']();
+ },
+
+ hide: function(){
+ var d;
+ try {
+ //IE fails here if the element is not in the dom
+ d = this.getStyle('display');
+ } catch(e){}
+ return this.store('originalDisplay', d || '').setStyle('display', 'none');
+ },
+
+ show: function(display){
+ display = display || this.retrieve('originalDisplay') || 'block';
+ return this.setStyle('display', (display == 'none') ? 'block' : display);
+ },
+
+ swapClass: function(remove, add){
+ return this.removeClass(remove).addClass(add);
+ }
+
+});
+/*
+---
+
+script: IframeShim.js
+
+description: Defines IframeShim, a class for obscuring select lists and flash objects in IE.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element.Event
+- core:1.2.4/Element.Style
+- core:1.2.4/Options Events
+- /Element.Position
+- /Class.Occlude
+
+provides: [IframeShim]
+
+...
+*/
+
+var IframeShim = new Class({
+
+ Implements: [Options, Events, Class.Occlude],
+
+ options: {
+ className: 'iframeShim',
+ src: 'javascript:false;document.write("");',
+ display: false,
+ zIndex: null,
+ margin: 0,
+ offset: {x: 0, y: 0},
+ browsers: (Browser.Engine.trident4 || (Browser.Engine.gecko && !Browser.Engine.gecko19 && Browser.Platform.mac))
+ },
+
+ property: 'IframeShim',
+
+ initialize: function(element, options){
+ this.element = document.id(element);
+ if (this.occlude()) return this.occluded;
+ this.setOptions(options);
+ this.makeShim();
+ return this;
+ },
+
+ makeShim: function(){
+ if(this.options.browsers){
+ var zIndex = this.element.getStyle('zIndex').toInt();
+
+ if (!zIndex){
+ zIndex = 1;
+ var pos = this.element.getStyle('position');
+ if (pos == 'static' || !pos) this.element.setStyle('position', 'relative');
+ this.element.setStyle('zIndex', zIndex);
+ }
+ zIndex = ($chk(this.options.zIndex) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1;
+ if (zIndex < 0) zIndex = 1;
+ this.shim = new Element('iframe', {
+ src: this.options.src,
+ scrolling: 'no',
+ frameborder: 0,
+ styles: {
+ zIndex: zIndex,
+ position: 'absolute',
+ border: 'none',
+ filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'
+ },
+ 'class': this.options.className
+ }).store('IframeShim', this);
+ var inject = (function(){
+ this.shim.inject(this.element, 'after');
+ this[this.options.display ? 'show' : 'hide']();
+ this.fireEvent('inject');
+ }).bind(this);
+ if (!IframeShim.ready) window.addEvent('load', inject);
+ else inject();
+ } else {
+ this.position = this.hide = this.show = this.dispose = $lambda(this);
+ }
+ },
+
+ position: function(){
+ if (!IframeShim.ready || !this.shim) return this;
+ var size = this.element.measure(function(){
+ return this.getSize();
+ });
+ if (this.options.margin != undefined){
+ size.x = size.x - (this.options.margin * 2);
+ size.y = size.y - (this.options.margin * 2);
+ this.options.offset.x += this.options.margin;
+ this.options.offset.y += this.options.margin;
+ }
+ this.shim.set({width: size.x, height: size.y}).position({
+ relativeTo: this.element,
+ offset: this.options.offset
+ });
+ return this;
+ },
+
+ hide: function(){
+ if (this.shim) this.shim.setStyle('display', 'none');
+ return this;
+ },
+
+ show: function(){
+ if (this.shim) this.shim.setStyle('display', 'block');
+ return this.position();
+ },
+
+ dispose: function(){
+ if (this.shim) this.shim.dispose();
+ return this;
+ },
+
+ destroy: function(){
+ if (this.shim) this.shim.destroy();
+ return this;
+ }
+
+});
+
+window.addEvent('load', function(){
+ IframeShim.ready = true;
+});/*
+---
+
+script: Mask.js
+
+description: Creates a mask element to cover another.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Options
+- core:1.2.4/Events
+- core:1.2.4/Element.Event
+- /Class.Binds
+- /Element.Position
+- /IframeShim
+
+provides: [Mask]
+
+...
+*/
+
+var Mask = new Class({
+
+ Implements: [Options, Events],
+
+ Binds: ['position'],
+
+ options: {
+ // onShow: $empty,
+ // onHide: $empty,
+ // onDestroy: $empty,
+ // onClick: $empty,
+ //inject: {
+ // where: 'after',
+ // target: null,
+ //},
+ // hideOnClick: false,
+ // id: null,
+ // destroyOnHide: false,
+ style: {},
+ 'class': 'mask',
+ maskMargins: false,
+ useIframeShim: true,
+ iframeShimOptions: {}
+ },
+
+ initialize: function(target, options){
+ this.target = document.id(target) || document.id(document.body);
+ this.target.store('Mask', this);
+ this.setOptions(options);
+ this.render();
+ this.inject();
+ },
+
+ render: function() {
+ this.element = new Element('div', {
+ 'class': this.options['class'],
+ id: this.options.id || 'mask-' + $time(),
+ styles: $merge(this.options.style, {
+ display: 'none'
+ }),
+ events: {
+ click: function(){
+ this.fireEvent('click');
+ if (this.options.hideOnClick) this.hide();
+ }.bind(this)
+ }
+ });
+ this.hidden = true;
+ },
+
+ toElement: function(){
+ return this.element;
+ },
+
+ inject: function(target, where){
+ where = where || this.options.inject ? this.options.inject.where : '' || this.target == document.body ? 'inside' : 'after';
+ target = target || this.options.inject ? this.options.inject.target : '' || this.target;
+ this.element.inject(target, where);
+ if (this.options.useIframeShim) {
+ this.shim = new IframeShim(this.element, this.options.iframeShimOptions);
+ this.addEvents({
+ show: this.shim.show.bind(this.shim),
+ hide: this.shim.hide.bind(this.shim),
+ destroy: this.shim.destroy.bind(this.shim)
+ });
+ }
+ },
+
+ position: function(){
+ this.resize(this.options.width, this.options.height);
+ this.element.position({
+ relativeTo: this.target,
+ position: 'topLeft',
+ ignoreMargins: !this.options.maskMargins,
+ ignoreScroll: this.target == document.body
+ });
+ return this;
+ },
+
+ resize: function(x, y){
+ var opt = {
+ styles: ['padding', 'border']
+ };
+ if (this.options.maskMargins) opt.styles.push('margin');
+ var dim = this.target.getComputedSize(opt);
+ if (this.target == document.body) {
+ var win = window.getSize();
+ if (dim.totalHeight < win.y) dim.totalHeight = win.y;
+ if (dim.totalWidth < win.x) dim.totalWidth = win.x;
+ }
+ this.element.setStyles({
+ width: $pick(x, dim.totalWidth, dim.x),
+ height: $pick(y, dim.totalHeight, dim.y)
+ });
+ return this;
+ },
+
+ show: function(){
+ if (!this.hidden) return this;
+ window.addEvent('resize', this.position);
+ this.position();
+ this.showMask.apply(this, arguments);
+ return this;
+ },
+
+ showMask: function(){
+ this.element.setStyle('display', 'block');
+ this.hidden = false;
+ this.fireEvent('show');
+ },
+
+ hide: function(){
+ if (this.hidden) return this;
+ window.removeEvent('resize', this.position);
+ this.hideMask.apply(this, arguments);
+ if (this.options.destroyOnHide) return this.destroy();
+ return this;
+ },
+
+ hideMask: function(){
+ this.element.setStyle('display', 'none');
+ this.hidden = true;
+ this.fireEvent('hide');
+ },
+
+ toggle: function(){
+ this[this.hidden ? 'show' : 'hide']();
+ },
+
+ destroy: function(){
+ this.hide();
+ this.element.destroy();
+ this.fireEvent('destroy');
+ this.target.eliminate('mask');
+ }
+
+});
+
+Element.Properties.mask = {
+
+ set: function(options){
+ var mask = this.retrieve('mask');
+ return this.eliminate('mask').store('mask:options', options);
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('mask')){
+ if (this.retrieve('mask')) this.retrieve('mask').destroy();
+ if (options || !this.retrieve('mask:options')) this.set('mask', options);
+ this.store('mask', new Mask(this, this.retrieve('mask:options')));
+ }
+ return this.retrieve('mask');
+ }
+
+};
+
+Element.implement({
+
+ mask: function(options){
+ this.get('mask', options).show();
+ return this;
+ },
+
+ unmask: function(){
+ this.get('mask').hide();
+ return this;
+ }
+
+});/*
+---
+
+script: Spinner.js
+
+description: Adds a semi-transparent overlay over a dom element with a spinnin ajax icon.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Fx.Tween
+- /Class.refactor
+- /Mask
+
+provides: [Spinner]
+
+...
+*/
+
+var Spinner = new Class({
+
+ Extends: Mask,
+
+ options: {
+ /*message: false,*/
+ 'class':'spinner',
+ containerPosition: {},
+ content: {
+ 'class':'spinner-content'
+ },
+ messageContainer: {
+ 'class':'spinner-msg'
+ },
+ img: {
+ 'class':'spinner-img'
+ },
+ fxOptions: {
+ link: 'chain'
+ }
+ },
+
+ initialize: function(){
+ this.parent.apply(this, arguments);
+ this.target.store('spinner', this);
+
+ //add this to events for when noFx is true; parent methods handle hide/show
+ var deactivate = function(){ this.active = false; }.bind(this);
+ this.addEvents({
+ hide: deactivate,
+ show: deactivate
+ });
+ },
+
+ render: function(){
+ this.parent();
+ this.element.set('id', this.options.id || 'spinner-'+$time());
+ this.content = document.id(this.options.content) || new Element('div', this.options.content);
+ this.content.inject(this.element);
+ if (this.options.message) {
+ this.msg = document.id(this.options.message) || new Element('p', this.options.messageContainer).appendText(this.options.message);
+ this.msg.inject(this.content);
+ }
+ if (this.options.img) {
+ this.img = document.id(this.options.img) || new Element('div', this.options.img);
+ this.img.inject(this.content);
+ }
+ this.element.set('tween', this.options.fxOptions);
+ },
+
+ show: function(noFx){
+ if (this.active) return this.chain(this.show.bind(this));
+ if (!this.hidden) {
+ this.callChain.delay(20, this);
+ return this;
+ }
+ this.active = true;
+ return this.parent(noFx);
+ },
+
+ showMask: function(noFx){
+ var pos = function(){
+ this.content.position($merge({
+ relativeTo: this.element
+ }, this.options.containerPosition));
+ }.bind(this);
+ if (noFx) {
+ this.parent();
+ pos();
+ } else {
+ this.element.setStyles({
+ display: 'block',
+ opacity: 0
+ }).tween('opacity', this.options.style.opacity || 0.9);
+ pos();
+ this.hidden = false;
+ this.fireEvent('show');
+ this.callChain();
+ }
+ },
+
+ hide: function(noFx){
+ if (this.active) return this.chain(this.hide.bind(this));
+ if (this.hidden) {
+ this.callChain.delay(20, this);
+ return this;
+ }
+ this.active = true;
+ return this.parent(noFx);
+ },
+
+ hideMask: function(noFx){
+ if (noFx) return this.parent();
+ this.element.tween('opacity', 0).get('tween').chain(function(){
+ this.element.setStyle('display', 'none');
+ this.hidden = true;
+ this.fireEvent('hide');
+ this.callChain();
+ }.bind(this));
+ },
+
+ destroy: function(){
+ this.content.destroy();
+ this.parent();
+ this.target.eliminate('spinner');
+ }
+
+});
+
+Spinner.implement(new Chain);
+
+if (window.Request) {
+ Request = Class.refactor(Request, {
+
+ options: {
+ useSpinner: false,
+ spinnerOptions: {},
+ spinnerTarget: false
+ },
+
+ initialize: function(options){
+ this._send = this.send;
+ this.send = function(options){
+ if (this.spinner) this.spinner.chain(this._send.bind(this, options)).show();
+ else this._send(options);
+ return this;
+ };
+ this.previous(options);
+ var update = document.id(this.options.spinnerTarget) || document.id(this.options.update);
+ if (this.options.useSpinner && update) {
+ this.spinner = update.get('spinner', this.options.spinnerOptions);
+ ['onComplete', 'onException', 'onCancel'].each(function(event){
+ this.addEvent(event, this.spinner.hide.bind(this.spinner));
+ }, this);
+ }
+ },
+
+ getSpinner: function(){
+ return this.spinner;
+ }
+
+ });
+}
+
+Element.Properties.spinner = {
+
+ set: function(options){
+ var spinner = this.retrieve('spinner');
+ return this.eliminate('spinner').store('spinner:options', options);
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('spinner')){
+ if (this.retrieve('spinner')) this.retrieve('spinner').destroy();
+ if (options || !this.retrieve('spinner:options')) this.set('spinner', options);
+ new Spinner(this, this.retrieve('spinner:options'));
+ }
+ return this.retrieve('spinner');
+ }
+
+};
+
+Element.implement({
+
+ spin: function(options){
+ this.get('spinner', options).show();
+ return this;
+ },
+
+ unspin: function(){
+ var opt = Array.link(arguments, {options: Object.type, callback: Function.type});
+ this.get('spinner', opt.options).hide(opt.callback);
+ return this;
+ }
+
+});/*
+---
+
+script: Form.Request.js
+
+description: Handles the basic functionality of submitting a form and updating a dom element with the result.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element.Event
+- core:1.2.4/Request.HTML
+- /Class.Binds
+- /Class.Occlude
+- /Spinner
+- /String.QueryString
+
+provides: [Form.Request]
+
+...
+*/
+
+if (!window.Form) window.Form = {};
+
+(function(){
+
+ Form.Request = new Class({
+
+ Binds: ['onSubmit', 'onFormValidate'],
+
+ Implements: [Options, Events, Class.Occlude],
+
+ options: {
+ //onFailure: $empty,
+ //onSuccess: #empty, //aliased to onComplete,
+ //onSend: $empty
+ requestOptions: {
+ evalScripts: true,
+ useSpinner: true,
+ emulation: false,
+ link: 'ignore'
+ },
+ extraData: {},
+ resetForm: true
+ },
+
+ property: 'form.request',
+
+ initialize: function(form, update, options) {
+ this.element = document.id(form);
+ if (this.occlude()) return this.occluded;
+ this.update = document.id(update);
+ this.setOptions(options);
+ this.makeRequest();
+ if (this.options.resetForm) {
+ this.request.addEvent('success', function(){
+ $try(function(){ this.element.reset(); }.bind(this));
+ if (window.OverText) OverText.update();
+ }.bind(this));
+ }
+ this.attach();
+ },
+
+ toElement: function() {
+ return this.element;
+ },
+
+ makeRequest: function(){
+ this.request = new Request.HTML($merge({
+ update: this.update,
+ emulation: false,
+ spinnerTarget: this.element,
+ method: this.element.get('method') || 'post'
+ }, this.options.requestOptions)).addEvents({
+ success: function(text, xml){
+ ['complete', 'success'].each(function(evt){
+ this.fireEvent(evt, [this.update, text, xml]);
+ }, this);
+ }.bind(this),
+ failure: function(xhr){
+ this.fireEvent('complete').fireEvent('failure', xhr);
+ }.bind(this),
+ exception: function(){
+ this.fireEvent('failure', xhr);
+ }.bind(this)
+ });
+ },
+
+ attach: function(attach){
+ attach = $pick(attach, true);
+ method = attach ? 'addEvent' : 'removeEvent';
+
+ var fv = this.element.retrieve('validator');
+ if (fv) fv[method]('onFormValidate', this.onFormValidate);
+ if (!fv || !attach) this.element[method]('submit', this.onSubmit);
+ },
+
+ detach: function(){
+ this.attach(false);
+ },
+
+ //public method
+ enable: function(){
+ this.attach();
+ },
+
+ //public method
+ disable: function(){
+ this.detach();
+ },
+
+ onFormValidate: function(valid, form, e) {
+ var fv = this.element.retrieve('validator');
+ if (valid || (fv && !fv.options.stopOnFailure)) {
+ if (e && e.stop) e.stop();
+ this.send();
+ }
+ },
+
+ onSubmit: function(e){
+ if (this.element.retrieve('validator')) {
+ //form validator was created after Form.Request
+ this.detach();
+ return;
+ }
+ e.stop();
+ this.send();
+ },
+
+ send: function(){
+ var str = this.element.toQueryString().trim();
+ var data = $H(this.options.extraData).toQueryString();
+ if (str) str += "&" + data;
+ else str = data;
+ this.fireEvent('send', [this.element, str.parseQueryString()]);
+ this.request.send({data: str, url: this.element.get("action")});
+ return this;
+ }
+
+ });
+
+ Element.Properties.formRequest = {
+
+ set: function(){
+ var opt = Array.link(arguments, {options: Object.type, update: Element.type, updateId: String.type});
+ var update = opt.update || opt.updateId;
+ var updater = this.retrieve('form.request');
+ if (update) {
+ if (updater) updater.update = document.id(update);
+ this.store('form.request:update', update);
+ }
+ if (opt.options) {
+ if (updater) updater.setOptions(opt.options);
+ this.store('form.request:options', opt.options);
+ }
+ return this;
+ },
+
+ get: function(){
+ var opt = Array.link(arguments, {options: Object.type, update: Element.type, updateId: String.type});
+ var update = opt.update || opt.updateId;
+ if (opt.options || update || !this.retrieve('form.request')){
+ if (opt.options || !this.retrieve('form.request:options')) this.set('form.request', opt.options);
+ if (update) this.set('form.request', update);
+ this.store('form.request', new Form.Request(this, this.retrieve('form.request:update'), this.retrieve('form.request:options')));
+ }
+ return this.retrieve('form.request');
+ }
+
+ };
+
+ Element.implement({
+
+ formUpdate: function(update, options){
+ this.get('form.request', update, options).send();
+ return this;
+ }
+
+ });
+
+})();/*
+---
+
+script: Fx.Reveal.js
+
+description: Defines Fx.Reveal, a class that shows and hides elements with a transition.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Fx.Morph
+- /Element.Shortcuts
+- /Element.Measure
+
+provides: [Fx.Reveal]
+
+...
+*/
+
+Fx.Reveal = new Class({
+
+ Extends: Fx.Morph,
+
+ options: {/*
+ onShow: $empty(thisElement),
+ onHide: $empty(thisElement),
+ onComplete: $empty(thisElement),
+ heightOverride: null,
+ widthOverride: null, */
+ link: 'cancel',
+ styles: ['padding', 'border', 'margin'],
+ transitionOpacity: !Browser.Engine.trident4,
+ mode: 'vertical',
+ display: 'block',
+ hideInputs: Browser.Engine.trident ? 'select, input, textarea, object, embed' : false
+ },
+
+ dissolve: function(){
+ try {
+ if (!this.hiding && !this.showing){
+ if (this.element.getStyle('display') != 'none'){
+ this.hiding = true;
+ this.showing = false;
+ this.hidden = true;
+ this.cssText = this.element.style.cssText;
+ var startStyles = this.element.getComputedSize({
+ styles: this.options.styles,
+ mode: this.options.mode
+ });
+ this.element.setStyle('display', this.options.display);
+ if (this.options.transitionOpacity) startStyles.opacity = 1;
+ var zero = {};
+ $each(startStyles, function(style, name){
+ zero[name] = [style, 0];
+ }, this);
+ this.element.setStyle('overflow', 'hidden');
+ var hideThese = this.options.hideInputs ? this.element.getElements(this.options.hideInputs) : null;
+ this.$chain.unshift(function(){
+ if (this.hidden){
+ this.hiding = false;
+ $each(startStyles, function(style, name){
+ startStyles[name] = style;
+ }, this);
+ this.element.style.cssText = this.cssText;
+ this.element.setStyle('display', 'none');
+ if (hideThese) hideThese.setStyle('visibility', 'visible');
+ }
+ this.fireEvent('hide', this.element);
+ this.callChain();
+ }.bind(this));
+ if (hideThese) hideThese.setStyle('visibility', 'hidden');
+ this.start(zero);
+ } else {
+ this.callChain.delay(10, this);
+ this.fireEvent('complete', this.element);
+ this.fireEvent('hide', this.element);
+ }
+ } else if (this.options.link == 'chain'){
+ this.chain(this.dissolve.bind(this));
+ } else if (this.options.link == 'cancel' && !this.hiding){
+ this.cancel();
+ this.dissolve();
+ }
+ } catch(e){
+ this.hiding = false;
+ this.element.setStyle('display', 'none');
+ this.callChain.delay(10, this);
+ this.fireEvent('complete', this.element);
+ this.fireEvent('hide', this.element);
+ }
+ return this;
+ },
+
+ reveal: function(){
+ try {
+ if (!this.showing && !this.hiding){
+ if (this.element.getStyle('display') == 'none' ||
+ this.element.getStyle('visiblity') == 'hidden' ||
+ this.element.getStyle('opacity') == 0){
+ this.showing = true;
+ this.hiding = this.hidden = false;
+ var startStyles;
+ this.cssText = this.element.style.cssText;
+ //toggle display, but hide it
+ this.element.measure(function(){
+ //create the styles for the opened/visible state
+ startStyles = this.element.getComputedSize({
+ styles: this.options.styles,
+ mode: this.options.mode
+ });
+ }.bind(this));
+ $each(startStyles, function(style, name){
+ startStyles[name] = style;
+ });
+ //if we're overridding height/width
+ if ($chk(this.options.heightOverride)) startStyles.height = this.options.heightOverride.toInt();
+ if ($chk(this.options.widthOverride)) startStyles.width = this.options.widthOverride.toInt();
+ if (this.options.transitionOpacity) {
+ this.element.setStyle('opacity', 0);
+ startStyles.opacity = 1;
+ }
+ //create the zero state for the beginning of the transition
+ var zero = {
+ height: 0,
+ display: this.options.display
+ };
+ $each(startStyles, function(style, name){ zero[name] = 0; });
+ //set to zero
+ this.element.setStyles($merge(zero, {overflow: 'hidden'}));
+ //hide inputs
+ var hideThese = this.options.hideInputs ? this.element.getElements(this.options.hideInputs) : null;
+ if (hideThese) hideThese.setStyle('visibility', 'hidden');
+ //start the effect
+ this.start(startStyles);
+ this.$chain.unshift(function(){
+ this.element.style.cssText = this.cssText;
+ this.element.setStyle('display', this.options.display);
+ if (!this.hidden) this.showing = false;
+ if (hideThese) hideThese.setStyle('visibility', 'visible');
+ this.callChain();
+ this.fireEvent('show', this.element);
+ }.bind(this));
+ } else {
+ this.callChain();
+ this.fireEvent('complete', this.element);
+ this.fireEvent('show', this.element);
+ }
+ } else if (this.options.link == 'chain'){
+ this.chain(this.reveal.bind(this));
+ } else if (this.options.link == 'cancel' && !this.showing){
+ this.cancel();
+ this.reveal();
+ }
+ } catch(e){
+ this.element.setStyles({
+ display: this.options.display,
+ visiblity: 'visible',
+ opacity: 1
+ });
+ this.showing = false;
+ this.callChain.delay(10, this);
+ this.fireEvent('complete', this.element);
+ this.fireEvent('show', this.element);
+ }
+ return this;
+ },
+
+ toggle: function(){
+ if (this.element.getStyle('display') == 'none' ||
+ this.element.getStyle('visiblity') == 'hidden' ||
+ this.element.getStyle('opacity') == 0){
+ this.reveal();
+ } else {
+ this.dissolve();
+ }
+ return this;
+ },
+
+ cancel: function(){
+ this.parent.apply(this, arguments);
+ this.element.style.cssText = this.cssText;
+ this.hidding = false;
+ this.showing = false;
+ }
+
+});
+
+Element.Properties.reveal = {
+
+ set: function(options){
+ var reveal = this.retrieve('reveal');
+ if (reveal) reveal.cancel();
+ return this.eliminate('reveal').store('reveal:options', options);
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('reveal')){
+ if (options || !this.retrieve('reveal:options')) this.set('reveal', options);
+ this.store('reveal', new Fx.Reveal(this, this.retrieve('reveal:options')));
+ }
+ return this.retrieve('reveal');
+ }
+
+};
+
+Element.Properties.dissolve = Element.Properties.reveal;
+
+Element.implement({
+
+ reveal: function(options){
+ this.get('reveal', options).reveal();
+ return this;
+ },
+
+ dissolve: function(options){
+ this.get('reveal', options).dissolve();
+ return this;
+ },
+
+ nix: function(){
+ var params = Array.link(arguments, {destroy: Boolean.type, options: Object.type});
+ this.get('reveal', params.options).dissolve().chain(function(){
+ this[params.destroy ? 'destroy' : 'dispose']();
+ }.bind(this));
+ return this;
+ },
+
+ wink: function(){
+ var params = Array.link(arguments, {duration: Number.type, options: Object.type});
+ var reveal = this.get('reveal', params.options);
+ reveal.reveal().chain(function(){
+ (function(){
+ reveal.dissolve();
+ }).delay(params.duration || 2000);
+ });
+ }
+
+
+});/*
+---
+
+script: Form.Request.Append.js
+
+description: Handles the basic functionality of submitting a form and updating a dom element with the result. The result is appended to the DOM element instead of replacing its contents.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- /Form.Request
+- /Fx.Reveal
+- /Elements.from
+
+provides: [Form.Request.Append]
+
+...
+*/
+
+Form.Request.Append = new Class({
+
+ Extends: Form.Request,
+
+ options: {
+ //onBeforeEffect: $empty,
+ useReveal: true,
+ revealOptions: {},
+ inject: 'bottom'
+ },
+
+ makeRequest: function(){
+ this.request = new Request.HTML($merge({
+ url: this.element.get('action'),
+ method: this.element.get('method') || 'post',
+ spinnerTarget: this.element
+ }, this.options.requestOptions, {
+ evalScripts: false
+ })
+ ).addEvents({
+ success: function(tree, elements, html, javascript){
+ var container;
+ var kids = Elements.from(html);
+ if (kids.length == 1) {
+ container = kids[0];
+ } else {
+ container = new Element('div', {
+ styles: {
+ display: 'none'
+ }
+ }).adopt(kids);
+ }
+ container.inject(this.update, this.options.inject);
+ if (this.options.requestOptions.evalScripts) $exec(javascript);
+ this.fireEvent('beforeEffect', container);
+ var finish = function(){
+ this.fireEvent('success', [container, this.update, tree, elements, html, javascript]);
+ }.bind(this);
+ if (this.options.useReveal) {
+ container.get('reveal', this.options.revealOptions).chain(finish);
+ container.reveal();
+ } else {
+ finish();
+ }
+ }.bind(this),
+ failure: function(xhr){
+ this.fireEvent('failure', xhr);
+ }.bind(this)
+ });
+ }
+
+});/*
+---
+
+script: Form.Validator.English.js
+
+description: Form Validator messages for English.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.English]
+
+...
+*/
+
+MooTools.lang.set('en-US', 'Form.Validator', {
+
+ required:'This field is required.',
+ minLength:'Please enter at least {minLength} characters (you entered {length} characters).',
+ maxLength:'Please enter no more than {maxLength} characters (you entered {length} characters).',
+ integer:'Please enter an integer in this field. Numbers with decimals (e.g. 1.25) are not permitted.',
+ numeric:'Please enter only numeric values in this field (i.e. "1" or "1.1" or "-1" or "-1.1").',
+ digits:'Please use numbers and punctuation only in this field (for example, a phone number with dashes or dots is permitted).',
+ alpha:'Please use letters only (a-z) with in this field. No spaces or other characters are allowed.',
+ alphanum:'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.',
+ dateSuchAs:'Please enter a valid date such as {date}',
+ dateInFormatMDY:'Please enter a valid date such as MM/DD/YYYY (i.e. "12/31/1999")',
+ email:'Please enter a valid email address. For example "fred at domain.com".',
+ url:'Please enter a valid URL such as http://www.google.com.',
+ currencyDollar:'Please enter a valid $ amount. For example $100.00 .',
+ oneRequired:'Please enter something for at least one of these inputs.',
+ errorPrefix: 'Error: ',
+ warningPrefix: 'Warning: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'There can be no spaces in this input.',
+ reqChkByNode: 'No items are selected.',
+ requiredChk: 'This field is required.',
+ reqChkByName: 'Please select a {label}.',
+ match: 'This field needs to match the {matchName} field',
+ startDate: 'the start date',
+ endDate: 'the end date',
+ currendDate: 'the current date',
+ afterDate: 'The date should be the same or after {label}.',
+ beforeDate: 'The date should be the same or before {label}.',
+ startMonth: 'Please select a start month',
+ sameMonth: 'These two dates must be in the same month - you must change one or the other.',
+ creditcard: 'The credit card number entered is invalid. Please check the number and try again. {length} digits entered.'
+
+});
+/*
+---
+
+script: Form.Validator.js
+
+description: A css-class based form validation system.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Options
+- core:1.2.4/Events
+- core:1.2.4/Selectors
+- core:1.2.4/Element.Event
+- core:1.2.4/Element.Style
+- core:1.2.4/JSON
+- /Lang- /Class.Binds
+- /Date Element.Forms
+- /Form.Validator.English
+- /Element.Shortcuts
+
+provides: [Form.Validator, InputValidator, FormValidator.BaseValidators]
+
+...
+*/
+if (!window.Form) window.Form = {};
+
+var InputValidator = new Class({
+
+ Implements: [Options],
+
+ options: {
+ errorMsg: 'Validation failed.',
+ test: function(field){return true;}
+ },
+
+ initialize: function(className, options){
+ this.setOptions(options);
+ this.className = className;
+ },
+
+ test: function(field, props){
+ if (document.id(field)) return this.options.test(document.id(field), props||this.getProps(field));
+ else return false;
+ },
+
+ getError: function(field, props){
+ var err = this.options.errorMsg;
+ if ($type(err) == 'function') err = err(document.id(field), props||this.getProps(field));
+ return err;
+ },
+
+ getProps: function(field){
+ if (!document.id(field)) return {};
+ return field.get('validatorProps');
+ }
+
+});
+
+Element.Properties.validatorProps = {
+
+ set: function(props){
+ return this.eliminate('validatorProps').store('validatorProps', props);
+ },
+
+ get: function(props){
+ if (props) this.set(props);
+ if (this.retrieve('validatorProps')) return this.retrieve('validatorProps');
+ if (this.getProperty('validatorProps')){
+ try {
+ this.store('validatorProps', JSON.decode(this.getProperty('validatorProps')));
+ }catch(e){
+ return {};
+ }
+ } else {
+ var vals = this.get('class').split(' ').filter(function(cls){
+ return cls.test(':');
+ });
+ if (!vals.length){
+ this.store('validatorProps', {});
+ } else {
+ props = {};
+ vals.each(function(cls){
+ var split = cls.split(':');
+ if (split[1]) {
+ try {
+ props[split[0]] = JSON.decode(split[1]);
+ } catch(e) {}
+ }
+ });
+ this.store('validatorProps', props);
+ }
+ }
+ return this.retrieve('validatorProps');
+ }
+
+};
+
+Form.Validator = new Class({
+
+ Implements:[Options, Events],
+
+ Binds: ['onSubmit'],
+
+ options: {/*
+ onFormValidate: $empty(isValid, form, event),
+ onElementValidate: $empty(isValid, field, className, warn),
+ onElementPass: $empty(field),
+ onElementFail: $empty(field, validatorsFailed) */
+ fieldSelectors: 'input, select, textarea',
+ ignoreHidden: true,
+ ignoreDisabled: true,
+ useTitles: false,
+ evaluateOnSubmit: true,
+ evaluateFieldsOnBlur: true,
+ evaluateFieldsOnChange: true,
+ serial: true,
+ stopOnFailure: true,
+ warningPrefix: function(){
+ return Form.Validator.getMsg('warningPrefix') || 'Warning: ';
+ },
+ errorPrefix: function(){
+ return Form.Validator.getMsg('errorPrefix') || 'Error: ';
+ }
+ },
+
+ initialize: function(form, options){
+ this.setOptions(options);
+ this.element = document.id(form);
+ this.element.store('validator', this);
+ this.warningPrefix = $lambda(this.options.warningPrefix)();
+ this.errorPrefix = $lambda(this.options.errorPrefix)();
+ if (this.options.evaluateOnSubmit) this.element.addEvent('submit', this.onSubmit);
+ if (this.options.evaluateFieldsOnBlur || this.options.evaluateFieldsOnChange) this.watchFields(this.getFields());
+ },
+
+ toElement: function(){
+ return this.element;
+ },
+
+ getFields: function(){
+ return (this.fields = this.element.getElements(this.options.fieldSelectors));
+ },
+
+ watchFields: function(fields){
+ fields.each(function(el){
+ if (this.options.evaluateFieldsOnBlur)
+ el.addEvent('blur', this.validationMonitor.pass([el, false], this));
+ if (this.options.evaluateFieldsOnChange)
+ el.addEvent('change', this.validationMonitor.pass([el, true], this));
+ }, this);
+ },
+
+ validationMonitor: function(){
+ $clear(this.timer);
+ this.timer = this.validateField.delay(50, this, arguments);
+ },
+
+ onSubmit: function(event){
+ if (!this.validate(event) && event) event.preventDefault();
+ else this.reset();
+ },
+
+ reset: function(){
+ this.getFields().each(this.resetField, this);
+ return this;
+ },
+
+ validate: function(event){
+ var result = this.getFields().map(function(field){
+ return this.validateField(field, true);
+ }, this).every(function(v){ return v;});
+ this.fireEvent('formValidate', [result, this.element, event]);
+ if (this.options.stopOnFailure && !result && event) event.preventDefault();
+ return result;
+ },
+
+ validateField: function(field, force){
+ if (this.paused) return true;
+ field = document.id(field);
+ var passed = !field.hasClass('validation-failed');
+ var failed, warned;
+ if (this.options.serial && !force){
+ failed = this.element.getElement('.validation-failed');
+ warned = this.element.getElement('.warning');
+ }
+ if (field && (!failed || force || field.hasClass('validation-failed') || (failed && !this.options.serial))){
+ var validators = field.className.split(' ').some(function(cn){
+ return this.getValidator(cn);
+ }, this);
+ var validatorsFailed = [];
+ field.className.split(' ').each(function(className){
+ if (className && !this.test(className, field)) validatorsFailed.include(className);
+ }, this);
+ passed = validatorsFailed.length === 0;
+ if (validators && !field.hasClass('warnOnly')){
+ if (passed){
+ field.addClass('validation-passed').removeClass('validation-failed');
+ this.fireEvent('elementPass', field);
+ } else {
+ field.addClass('validation-failed').removeClass('validation-passed');
+ this.fireEvent('elementFail', [field, validatorsFailed]);
+ }
+ }
+ if (!warned){
+ var warnings = field.className.split(' ').some(function(cn){
+ if (cn.test('^warn-') || field.hasClass('warnOnly'))
+ return this.getValidator(cn.replace(/^warn-/,''));
+ else return null;
+ }, this);
+ field.removeClass('warning');
+ var warnResult = field.className.split(' ').map(function(cn){
+ if (cn.test('^warn-') || field.hasClass('warnOnly'))
+ return this.test(cn.replace(/^warn-/,''), field, true);
+ else return null;
+ }, this);
+ }
+ }
+ return passed;
+ },
+
+ test: function(className, field, warn){
+ field = document.id(field);
+ if((this.options.ignoreHidden && !field.isVisible()) || (this.options.ignoreDisabled && field.get('disabled'))) return true;
+ var validator = this.getValidator(className);
+ if (field.hasClass('ignoreValidation')) return true;
+ warn = $pick(warn, false);
+ if (field.hasClass('warnOnly')) warn = true;
+ var isValid = validator ? validator.test(field) : true;
+ if (validator && field.isVisible()) this.fireEvent('elementValidate', [isValid, field, className, warn]);
+ if (warn) return true;
+ return isValid;
+ },
+
+ resetField: function(field){
+ field = document.id(field);
+ if (field){
+ field.className.split(' ').each(function(className){
+ if (className.test('^warn-')) className = className.replace(/^warn-/, '');
+ field.removeClass('validation-failed');
+ field.removeClass('warning');
+ field.removeClass('validation-passed');
+ }, this);
+ }
+ return this;
+ },
+
+ stop: function(){
+ this.paused = true;
+ return this;
+ },
+
+ start: function(){
+ this.paused = false;
+ return this;
+ },
+
+ ignoreField: function(field, warn){
+ field = document.id(field);
+ if (field){
+ this.enforceField(field);
+ if (warn) field.addClass('warnOnly');
+ else field.addClass('ignoreValidation');
+ }
+ return this;
+ },
+
+ enforceField: function(field){
+ field = document.id(field);
+ if (field) field.removeClass('warnOnly').removeClass('ignoreValidation');
+ return this;
+ }
+
+});
+
+Form.Validator.getMsg = function(key){
+ return MooTools.lang.get('Form.Validator', key);
+};
+
+Form.Validator.adders = {
+
+ validators:{},
+
+ add : function(className, options){
+ this.validators[className] = new InputValidator(className, options);
+ //if this is a class (this method is used by instances of Form.Validator and the Form.Validator namespace)
+ //extend these validators into it
+ //this allows validators to be global and/or per instance
+ if (!this.initialize){
+ this.implement({
+ validators: this.validators
+ });
+ }
+ },
+
+ addAllThese : function(validators){
+ $A(validators).each(function(validator){
+ this.add(validator[0], validator[1]);
+ }, this);
+ },
+
+ getValidator: function(className){
+ return this.validators[className.split(':')[0]];
+ }
+
+};
+
+$extend(Form.Validator, Form.Validator.adders);
+
+Form.Validator.implement(Form.Validator.adders);
+
+Form.Validator.add('IsEmpty', {
+
+ errorMsg: false,
+ test: function(element){
+ if (element.type == 'select-one' || element.type == 'select')
+ return !(element.selectedIndex >= 0 && element.options[element.selectedIndex].value != '');
+ else
+ return ((element.get('value') == null) || (element.get('value').length == 0));
+ }
+
+});
+
+Form.Validator.addAllThese([
+
+ ['required', {
+ errorMsg: function(){
+ return Form.Validator.getMsg('required');
+ },
+ test: function(element){
+ return !Form.Validator.getValidator('IsEmpty').test(element);
+ }
+ }],
+
+ ['minLength', {
+ errorMsg: function(element, props){
+ if ($type(props.minLength))
+ return Form.Validator.getMsg('minLength').substitute({minLength:props.minLength,length:element.get('value').length });
+ else return '';
+ },
+ test: function(element, props){
+ if ($type(props.minLength)) return (element.get('value').length >= $pick(props.minLength, 0));
+ else return true;
+ }
+ }],
+
+ ['maxLength', {
+ errorMsg: function(element, props){
+ //props is {maxLength:10}
+ if ($type(props.maxLength))
+ return Form.Validator.getMsg('maxLength').substitute({maxLength:props.maxLength,length:element.get('value').length });
+ else return '';
+ },
+ test: function(element, props){
+ //if the value is <= than the maxLength value, element passes test
+ return (element.get('value').length <= $pick(props.maxLength, 10000));
+ }
+ }],
+
+ ['validate-integer', {
+ errorMsg: Form.Validator.getMsg.pass('integer'),
+ test: function(element){
+ return Form.Validator.getValidator('IsEmpty').test(element) || (/^(-?[1-9]\d*|0)$/).test(element.get('value'));
+ }
+ }],
+
+ ['validate-numeric', {
+ errorMsg: Form.Validator.getMsg.pass('numeric'),
+ test: function(element){
+ return Form.Validator.getValidator('IsEmpty').test(element) ||
+ (/^-?(?:0$0(?=\d*\.)|[1-9]|0)\d*(\.\d+)?$/).test(element.get('value'));
+ }
+ }],
+
+ ['validate-digits', {
+ errorMsg: Form.Validator.getMsg.pass('digits'),
+ test: function(element){
+ return Form.Validator.getValidator('IsEmpty').test(element) || (/^[\d() .:\-\+#]+$/.test(element.get('value')));
+ }
+ }],
+
+ ['validate-alpha', {
+ errorMsg: Form.Validator.getMsg.pass('alpha'),
+ test: function(element){
+ return Form.Validator.getValidator('IsEmpty').test(element) || (/^[a-zA-Z]+$/).test(element.get('value'));
+ }
+ }],
+
+ ['validate-alphanum', {
+ errorMsg: Form.Validator.getMsg.pass('alphanum'),
+ test: function(element){
+ return Form.Validator.getValidator('IsEmpty').test(element) || !(/\W/).test(element.get('value'));
+ }
+ }],
+
+ ['validate-date', {
+ errorMsg: function(element, props){
+ if (Date.parse){
+ var format = props.dateFormat || '%x';
+ return Form.Validator.getMsg('dateSuchAs').substitute({date: new Date().format(format)});
+ } else {
+ return Form.Validator.getMsg('dateInFormatMDY');
+ }
+ },
+ test: function(element, props){
+ if (Form.Validator.getValidator('IsEmpty').test(element)) return true;
+ var d;
+ if (Date.parse){
+ var format = props.dateFormat || '%x';
+ d = Date.parse(element.get('value'));
+ var formatted = d.format(format);
+ if (formatted != 'invalid date') element.set('value', formatted);
+ return !isNaN(d);
+ } else {
+ var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
+ if (!regex.test(element.get('value'))) return false;
+ d = new Date(element.get('value').replace(regex, '$1/$2/$3'));
+ return (parseInt(RegExp.$1, 10) == (1 + d.getMonth())) &&
+ (parseInt(RegExp.$2, 10) == d.getDate()) &&
+ (parseInt(RegExp.$3, 10) == d.getFullYear());
+ }
+ }
+ }],
+
+ ['validate-email', {
+ errorMsg: Form.Validator.getMsg.pass('email'),
+ test: function(element){
+ return Form.Validator.getValidator('IsEmpty').test(element) || (/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i).test(element.get('value'));
+ }
+ }],
+
+ ['validate-url', {
+ errorMsg: Form.Validator.getMsg.pass('url'),
+ test: function(element){
+ return Form.Validator.getValidator('IsEmpty').test(element) || (/^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i).test(element.get('value'));
+ }
+ }],
+
+ ['validate-currency-dollar', {
+ errorMsg: Form.Validator.getMsg.pass('currencyDollar'),
+ test: function(element){
+ // [$]1[##][,###]+[.##]
+ // [$]1###+[.##]
+ // [$]0.##
+ // [$].##
+ return Form.Validator.getValidator('IsEmpty').test(element) || (/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/).test(element.get('value'));
+ }
+ }],
+
+ ['validate-one-required', {
+ errorMsg: Form.Validator.getMsg.pass('oneRequired'),
+ test: function(element, props){
+ var p = document.id(props['validate-one-required']) || element.getParent();
+ return p.getElements('input').some(function(el){
+ if (['checkbox', 'radio'].contains(el.get('type'))) return el.get('checked');
+ return el.get('value');
+ });
+ }
+ }]
+
+]);
+
+Element.Properties.validator = {
+
+ set: function(options){
+ var validator = this.retrieve('validator');
+ if (validator) validator.setOptions(options);
+ return this.store('validator:options');
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('validator')){
+ if (options || !this.retrieve('validator:options')) this.set('validator', options);
+ this.store('validator', new Form.Validator(this, this.retrieve('validator:options')));
+ }
+ return this.retrieve('validator');
+ }
+
+};
+
+Element.implement({
+
+ validate: function(options){
+ this.set('validator', options);
+ return this.get('validator', options).validate();
+ }
+
+});
+//legacy
+var FormValidator = Form.Validator;/*
+---
+
+script: Form.Validator.Inline.js
+
+description: Extends Form.Validator to add inline messages.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- /Form.Validator
+
+provides: [Form.Validator.Inline]
+
+...
+*/
+
+Form.Validator.Inline = new Class({
+
+ Extends: Form.Validator,
+
+ options: {
+ scrollToErrorsOnSubmit: true,
+ scrollFxOptions: {
+ transition: 'quad:out',
+ offset: {
+ y: -20
+ }
+ }
+ },
+
+ initialize: function(form, options){
+ this.parent(form, options);
+ this.addEvent('onElementValidate', function(isValid, field, className, warn){
+ var validator = this.getValidator(className);
+ if (!isValid && validator.getError(field)){
+ if (warn) field.addClass('warning');
+ var advice = this.makeAdvice(className, field, validator.getError(field), warn);
+ this.insertAdvice(advice, field);
+ this.showAdvice(className, field);
+ } else {
+ this.hideAdvice(className, field);
+ }
+ });
+ },
+
+ makeAdvice: function(className, field, error, warn){
+ var errorMsg = (warn)?this.warningPrefix:this.errorPrefix;
+ errorMsg += (this.options.useTitles) ? field.title || error:error;
+ var cssClass = (warn) ? 'warning-advice' : 'validation-advice';
+ var advice = this.getAdvice(className, field);
+ if(advice) {
+ advice = advice.set('html', errorMsg);
+ } else {
+ advice = new Element('div', {
+ html: errorMsg,
+ styles: { display: 'none' },
+ id: 'advice-' + className + '-' + this.getFieldId(field)
+ }).addClass(cssClass);
+ }
+ field.store('advice-' + className, advice);
+ return advice;
+ },
+
+ getFieldId : function(field){
+ return field.id ? field.id : field.id = 'input_' + field.name;
+ },
+
+ showAdvice: function(className, field){
+ var advice = this.getAdvice(className, field);
+ if (advice && !field.retrieve(this.getPropName(className))
+ && (advice.getStyle('display') == 'none'
+ || advice.getStyle('visiblity') == 'hidden'
+ || advice.getStyle('opacity') == 0)){
+ field.store(this.getPropName(className), true);
+ if (advice.reveal) advice.reveal();
+ else advice.setStyle('display', 'block');
+ }
+ },
+
+ hideAdvice: function(className, field){
+ var advice = this.getAdvice(className, field);
+ if (advice && field.retrieve(this.getPropName(className))){
+ field.store(this.getPropName(className), false);
+ //if Fx.Reveal.js is present, transition the advice out
+ if (advice.dissolve) advice.dissolve();
+ else advice.setStyle('display', 'none');
+ }
+ },
+
+ getPropName: function(className){
+ return 'advice' + className;
+ },
+
+ resetField: function(field){
+ field = document.id(field);
+ if (!field) return this;
+ this.parent(field);
+ field.className.split(' ').each(function(className){
+ this.hideAdvice(className, field);
+ }, this);
+ return this;
+ },
+
+ getAllAdviceMessages: function(field, force){
+ var advice = [];
+ if (field.hasClass('ignoreValidation') && !force) return advice;
+ var validators = field.className.split(' ').some(function(cn){
+ var warner = cn.test('^warn-') || field.hasClass('warnOnly');
+ if (warner) cn = cn.replace(/^warn-/, '');
+ var validator = this.getValidator(cn);
+ if (!validator) return;
+ advice.push({
+ message: validator.getError(field),
+ warnOnly: warner,
+ passed: validator.test(),
+ validator: validator
+ });
+ }, this);
+ return advice;
+ },
+
+ getAdvice: function(className, field){
+ return field.retrieve('advice-' + className);
+ },
+
+ insertAdvice: function(advice, field){
+ //Check for error position prop
+ var props = field.get('validatorProps');
+ //Build advice
+ if (!props.msgPos || !document.id(props.msgPos)){
+ if(field.type.toLowerCase() == 'radio') field.getParent().adopt(advice);
+ else advice.inject(document.id(field), 'after');
+ } else {
+ document.id(props.msgPos).grab(advice);
+ }
+ },
+
+ validateField: function(field, force){
+ var result = this.parent(field, force);
+ if (this.options.scrollToErrorsOnSubmit && !result){
+ var failed = document.id(this).getElement('.validation-failed');
+ var par = document.id(this).getParent();
+ while (par != document.body && par.getScrollSize().y == par.getSize().y){
+ par = par.getParent();
+ }
+ var fx = par.retrieve('fvScroller');
+ if (!fx && window.Fx && Fx.Scroll){
+ fx = new Fx.Scroll(par, this.options.scrollFxOptions);
+ par.store('fvScroller', fx);
+ }
+ if (failed){
+ if (fx) fx.toElement(failed);
+ else par.scrollTo(par.getScroll().x, failed.getPosition(par).y - 20);
+ }
+ }
+ return result;
+ }
+
+});
+/*
+---
+
+script: Form.Validator.Extras.js
+
+description: Additional validators for the Form.Validator class.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- /Form.Validator
+
+provides: [Form.Validator.Extras]
+
+...
+*/
+Form.Validator.addAllThese([
+
+ ['validate-enforce-oncheck', {
+ test: function(element, props){
+ if (element.checked){
+ var fv = element.getParent('form').retrieve('validator');
+ if (!fv) return true;
+ (props.toEnforce || document.id(props.enforceChildrenOf).getElements('input, select, textarea')).map(function(item){
+ fv.enforceField(item);
+ });
+ }
+ return true;
+ }
+ }],
+
+ ['validate-ignore-oncheck', {
+ test: function(element, props){
+ if (element.checked){
+ var fv = element.getParent('form').retrieve('validator');
+ if (!fv) return true;
+ (props.toIgnore || document.id(props.ignoreChildrenOf).getElements('input, select, textarea')).each(function(item){
+ fv.ignoreField(item);
+ fv.resetField(item);
+ });
+ }
+ return true;
+ }
+ }],
+
+ ['validate-nospace', {
+ errorMsg: function(){
+ return Form.Validator.getMsg('noSpace');
+ },
+ test: function(element, props){
+ return !element.get('value').test(/\s/);
+ }
+ }],
+
+ ['validate-toggle-oncheck', {
+ test: function(element, props){
+ var fv = element.getParent('form').retrieve('validator');
+ if (!fv) return true;
+ var eleArr = props.toToggle || document.id(props.toToggleChildrenOf).getElements('input, select, textarea');
+ if (!element.checked){
+ eleArr.each(function(item){
+ fv.ignoreField(item);
+ fv.resetField(item);
+ });
+ } else {
+ eleArr.each(function(item){
+ fv.enforceField(item);
+ });
+ }
+ return true;
+ }
+ }],
+
+ ['validate-reqchk-bynode', {
+ errorMsg: function(){
+ return Form.Validator.getMsg('reqChkByNode');
+ },
+ test: function(element, props){
+ return (document.id(props.nodeId).getElements(props.selector || 'input[type=checkbox], input[type=radio]')).some(function(item){
+ return item.checked;
+ });
+ }
+ }],
+
+ ['validate-required-check', {
+ errorMsg: function(element, props){
+ return props.useTitle ? element.get('title') : Form.Validator.getMsg('requiredChk');
+ },
+ test: function(element, props){
+ return !!element.checked;
+ }
+ }],
+
+ ['validate-reqchk-byname', {
+ errorMsg: function(element, props){
+ return Form.Validator.getMsg('reqChkByName').substitute({label: props.label || element.get('type')});
+ },
+ test: function(element, props){
+ var grpName = props.groupName || element.get('name');
+ var oneCheckedItem = $$(document.getElementsByName(grpName)).some(function(item, index){
+ return item.checked;
+ });
+ var fv = element.getParent('form').retrieve('validator');
+ if (oneCheckedItem && fv) fv.resetField(element);
+ return oneCheckedItem;
+ }
+ }],
+
+ ['validate-match', {
+ errorMsg: function(element, props){
+ return Form.Validator.getMsg('match').substitute({matchName: props.matchName || document.id(props.matchInput).get('name')});
+ },
+ test: function(element, props){
+ var eleVal = element.get('value');
+ var matchVal = document.id(props.matchInput) && document.id(props.matchInput).get('value');
+ return eleVal && matchVal ? eleVal == matchVal : true;
+ }
+ }],
+
+ ['validate-after-date', {
+ errorMsg: function(element, props){
+ return Form.Validator.getMsg('afterDate').substitute({
+ label: props.afterLabel || (props.afterElement ? Form.Validator.getMsg('startDate') : Form.Validator.getMsg('currentDate'))
+ });
+ },
+ test: function(element, props){
+ var start = document.id(props.afterElement) ? Date.parse(document.id(props.afterElement).get('value')) : new Date();
+ var end = Date.parse(element.get('value'));
+ return end && start ? end >= start : true;
+ }
+ }],
+
+ ['validate-before-date', {
+ errorMsg: function(element, props){
+ return Form.Validator.getMsg('beforeDate').substitute({
+ label: props.beforeLabel || (props.beforeElement ? Form.Validator.getMsg('endDate') : Form.Validator.getMsg('currentDate'))
+ });
+ },
+ test: function(element, props){
+ var start = Date.parse(element.get('value'));
+ var end = document.id(props.beforeElement) ? Date.parse(document.id(props.beforeElement).get('value')) : new Date();
+ return end && start ? end >= start : true;
+ }
+ }],
+
+ ['validate-custom-required', {
+ errorMsg: function(){
+ return Form.Validator.getMsg('required');
+ },
+ test: function(element, props){
+ return element.get('value') != props.emptyValue;
+ }
+ }],
+
+ ['validate-same-month', {
+ errorMsg: function(element, props){
+ var startMo = document.id(props.sameMonthAs) && document.id(props.sameMonthAs).get('value');
+ var eleVal = element.get('value');
+ if (eleVal != '') return Form.Validator.getMsg(startMo ? 'sameMonth' : 'startMonth');
+ },
+ test: function(element, props){
+ var d1 = Date.parse(element.get('value'));
+ var d2 = Date.parse(document.id(props.sameMonthAs) && document.id(props.sameMonthAs).get('value'));
+ return d1 && d2 ? d1.format('%B') == d2.format('%B') : true;
+ }
+ }],
+
+
+ ['validate-cc-num', {
+ errorMsg: function(element){
+ var ccNum = element.get('value').replace(/[^0-9]/g, '');
+ return Form.Validator.getMsg('creditcard').substitute({length: ccNum.length});
+ },
+ test: function(element){
+ // required is a different test
+ if (Form.Validator.getValidator('IsEmpty').test(element)) { return true; }
+
+ // Clean number value
+ var ccNum = element.get('value');
+ ccNum = ccNum.replace(/[^0-9]/g, '');
+
+ var valid_type = false;
+
+ if (ccNum.test(/^4[0-9]{12}([0-9]{3})?$/)) valid_type = 'Visa';
+ else if (ccNum.test(/^5[1-5]([0-9]{14})$/)) valid_type = 'Master Card';
+ else if (ccNum.test(/^3[47][0-9]{13}$/)) valid_type = 'American Express';
+ else if (ccNum.test(/^6011[0-9]{12}$/)) valid_type = 'Discover';
+
+ if (valid_type) {
+ var sum = 0;
+ var cur = 0;
+
+ for(var i=ccNum.length-1; i>=0; --i) {
+ cur = ccNum.charAt(i).toInt();
+ if (cur == 0) { continue; }
+
+ if ((ccNum.length-i) % 2 == 0) { cur += cur; }
+ if (cur > 9) { cur = cur.toString().charAt(0).toInt() + cur.toString().charAt(1).toInt(); }
+
+ sum += cur;
+ }
+ if ((sum % 10) == 0) { return true; }
+ }
+
+ var chunks = '';
+ while (ccNum != '') {
+ chunks += ' ' + ccNum.substr(0,4);
+ ccNum = ccNum.substr(4);
+ }
+
+ element.getParent('form').retrieve('validator').ignoreField(element);
+ element.set('value', chunks.clean());
+ element.getParent('form').retrieve('validator').enforceField(element);
+ return false;
+ }
+ }]
+
+
+]);/*
+---
+
+script: OverText.js
+
+description: Shows text over an input that disappears when the user clicks into it. The text remains hidden if the user adds a value.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Options
+- core:1.2.4/Events
+- core:1.2.4/Element.Event
+- /Class.Binds
+- /Class.Occlude
+- /Element.Position
+- /Element.Shortcuts
+
+provides: [OverText]
+
+...
+*/
+
+var OverText = new Class({
+
+ Implements: [Options, Events, Class.Occlude],
+
+ Binds: ['reposition', 'assert', 'focus', 'hide'],
+
+ options: {/*
+ textOverride: null,
+ onFocus: $empty()
+ onTextHide: $empty(textEl, inputEl),
+ onTextShow: $empty(textEl, inputEl), */
+ element: 'label',
+ positionOptions: {
+ position: 'upperLeft',
+ edge: 'upperLeft',
+ offset: {
+ x: 4,
+ y: 2
+ }
+ },
+ poll: false,
+ pollInterval: 250,
+ wrap: false
+ },
+
+ property: 'OverText',
+
+ initialize: function(element, options){
+ this.element = document.id(element);
+ if (this.occlude()) return this.occluded;
+ this.setOptions(options);
+ this.attach(this.element);
+ OverText.instances.push(this);
+ if (this.options.poll) this.poll();
+ return this;
+ },
+
+ toElement: function(){
+ return this.element;
+ },
+
+ attach: function(){
+ var val = this.options.textOverride || this.element.get('alt') || this.element.get('title');
+ if (!val) return;
+ this.text = new Element(this.options.element, {
+ 'class': 'overTxtLabel',
+ styles: {
+ lineHeight: 'normal',
+ position: 'absolute',
+ cursor: 'text'
+ },
+ html: val,
+ events: {
+ click: this.hide.pass(this.options.element == 'label', this)
+ }
+ }).inject(this.element, 'after');
+ if (this.options.element == 'label') {
+ if (!this.element.get('id')) this.element.set('id', 'input_' + new Date().getTime());
+ this.text.set('for', this.element.get('id'));
+ }
+
+ if (this.options.wrap) {
+ this.textHolder = new Element('div', {
+ styles: {
+ lineHeight: 'normal',
+ position: 'relative'
+ },
+ 'class':'overTxtWrapper'
+ }).adopt(this.text).inject(this.element, 'before');
+ }
+
+ this.element.addEvents({
+ focus: this.focus,
+ blur: this.assert,
+ change: this.assert
+ }).store('OverTextDiv', this.text);
+ window.addEvent('resize', this.reposition.bind(this));
+ this.assert(true);
+ this.reposition();
+ },
+
+ wrap: function(){
+ if (this.options.element == 'label') {
+ if (!this.element.get('id')) this.element.set('id', 'input_' + new Date().getTime());
+ this.text.set('for', this.element.get('id'));
+ }
+ },
+
+ startPolling: function(){
+ this.pollingPaused = false;
+ return this.poll();
+ },
+
+ poll: function(stop){
+ //start immediately
+ //pause on focus
+ //resumeon blur
+ if (this.poller && !stop) return this;
+ var test = function(){
+ if (!this.pollingPaused) this.assert(true);
+ }.bind(this);
+ if (stop) $clear(this.poller);
+ else this.poller = test.periodical(this.options.pollInterval, this);
+ return this;
+ },
+
+ stopPolling: function(){
+ this.pollingPaused = true;
+ return this.poll(true);
+ },
+
+ focus: function(){
+ if (this.text && (!this.text.isDisplayed() || this.element.get('disabled'))) return;
+ this.hide();
+ },
+
+ hide: function(suppressFocus, force){
+ if (this.text && (this.text.isDisplayed() && (!this.element.get('disabled') || force))){
+ this.text.hide();
+ this.fireEvent('textHide', [this.text, this.element]);
+ this.pollingPaused = true;
+ if (!suppressFocus){
+ try {
+ this.element.fireEvent('focus');
+ this.element.focus();
+ } catch(e){} //IE barfs if you call focus on hidden elements
+ }
+ }
+ return this;
+ },
+
+ show: function(){
+ if (this.text && !this.text.isDisplayed()){
+ this.text.show();
+ this.reposition();
+ this.fireEvent('textShow', [this.text, this.element]);
+ this.pollingPaused = false;
+ }
+ return this;
+ },
+
+ assert: function(suppressFocus){
+ this[this.test() ? 'show' : 'hide'](suppressFocus);
+ },
+
+ test: function(){
+ var v = this.element.get('value');
+ return !v;
+ },
+
+ reposition: function(){
+ this.assert(true);
+ if (!this.element.isVisible()) return this.stopPolling().hide();
+ if (this.text && this.test()) this.text.position($merge(this.options.positionOptions, {relativeTo: this.element}));
+ return this;
+ }
+
+});
+
+OverText.instances = [];
+
+$extend(OverText, {
+
+ each: function(fn) {
+ return OverText.instances.map(function(ot, i){
+ if (ot.element && ot.text) return fn.apply(OverText, [ot, i]);
+ return null; //the input or the text was destroyed
+ });
+ },
+
+ update: function(){
+
+ return OverText.each(function(ot){
+ return ot.reposition();
+ });
+
+ },
+
+ hideAll: function(){
+
+ return OverText.each(function(ot){
+ return ot.hide(true, true);
+ });
+
+ },
+
+ showAll: function(){
+ return OverText.each(function(ot) {
+ return ot.show();
+ });
+ }
+
+});
+
+if (window.Fx && Fx.Reveal) {
+ Fx.Reveal.implement({
+ hideInputs: Browser.Engine.trident ? 'select, input, textarea, object, embed, .overTxtLabel' : false
+ });
+}/*
+---
+
+script: Fx.Elements.js
+
+description: Effect to change any number of CSS properties of any number of Elements.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Fx.CSS
+- /MooTools.More
+
+provides: [Fx.Elements]
+
+...
+*/
+
+Fx.Elements = new Class({
+
+ Extends: Fx.CSS,
+
+ initialize: function(elements, options){
+ this.elements = this.subject = $$(elements);
+ this.parent(options);
+ },
+
+ compute: function(from, to, delta){
+ var now = {};
+ for (var i in from){
+ var iFrom = from[i], iTo = to[i], iNow = now[i] = {};
+ for (var p in iFrom) iNow[p] = this.parent(iFrom[p], iTo[p], delta);
+ }
+ return now;
+ },
+
+ set: function(now){
+ for (var i in now){
+ var iNow = now[i];
+ for (var p in iNow) this.render(this.elements[i], p, iNow[p], this.options.unit);
+ }
+ return this;
+ },
+
+ start: function(obj){
+ if (!this.check(obj)) return this;
+ var from = {}, to = {};
+ for (var i in obj){
+ var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {};
+ for (var p in iProps){
+ var parsed = this.prepare(this.elements[i], p, iProps[p]);
+ iFrom[p] = parsed.from;
+ iTo[p] = parsed.to;
+ }
+ }
+ return this.parent(from, to);
+ }
+
+});/*
+---
+
+script: Fx.Accordion.js
+
+description: An Fx.Elements extension which allows you to easily create accordion type controls.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Element.Event
+- /Fx.Elements
+
+provides: [Fx.Accordion]
+
+...
+*/
+
+Fx.Accordion = new Class({
+
+ Extends: Fx.Elements,
+
+ options: {/*
+ onActive: $empty(toggler, section),
+ onBackground: $empty(toggler, section),
+ fixedHeight: false,
+ fixedWidth: false,
+ */
+ display: 0,
+ show: false,
+ height: true,
+ width: false,
+ opacity: true,
+ alwaysHide: false,
+ trigger: 'click',
+ initialDisplayFx: true,
+ returnHeightToAuto: true
+ },
+
+ initialize: function(){
+ var params = Array.link(arguments, {
+ 'container': Element.type, //deprecated
+ 'options': Object.type,
+ 'togglers': $defined,
+ 'elements': $defined
+ });
+ this.parent(params.elements, params.options);
+ this.togglers = $$(params.togglers);
+ this.previous = -1;
+ this.internalChain = new Chain();
+ 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.options.initialDisplayFx === false) this.display(this.options.display, this.options.initialDisplayFx);
+ if (this.options.fixedHeight !== false) this.options.returnHeightToAuto = false;
+ this.addEvent('complete', this.internalChain.callChain.bind(this.internalChain));
+ },
+
+ addSection: function(toggler, element){
+ toggler = document.id(toggler);
+ element = document.id(element);
+ var test = this.togglers.contains(toggler);
+ this.togglers.include(toggler);
+ this.elements.include(element);
+ var idx = this.togglers.indexOf(toggler);
+ var displayer = this.display.bind(this, idx);
+ toggler.store('accordion:display', displayer);
+ toggler.addEvent(this.options.trigger, displayer);
+ 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;
+ },
+
+ detach: function(){
+ this.togglers.each(function(toggler) {
+ toggler.removeEvent(this.options.trigger, toggler.retrieve('accordion:display'));
+ }, this);
+ },
+
+ display: function(index, useFx){
+ if (!this.check(index, useFx)) return this;
+ useFx = $pick(useFx, true);
+ if (this.options.returnHeightToAuto){
+ var prev = this.elements[this.previous];
+ if (prev && !this.selfHidden){
+ for (var fx in this.effects){
+ prev.setStyle(fx, prev[this.effects[fx]]);
+ }
+ }
+ }
+ 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;
+ if (i != index){
+ hide = true;
+ } else if (this.options.alwaysHide && ((el.offsetHeight > 0 && this.options.height) || el.offsetWidth > 0 && this.options.width)){
+ hide = true;
+ this.selfHidden = true;
+ }
+ 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);
+ this.internalChain.chain(function(){
+ if (this.options.returnHeightToAuto && !this.selfHidden){
+ var el = this.elements[index];
+ if (el) el.setStyle('height', 'auto');
+ };
+ }.bind(this));
+ return useFx ? this.start(obj) : this.set(obj);
+ }
+
+});
+
+/*
+ Compatibility with 1.2.0
+*/
+var Accordion = new Class({
+
+ Extends: Fx.Accordion,
+
+ initialize: function(){
+ this.parent.apply(this, arguments);
+ var params = Array.link(arguments, {'container': Element.type});
+ this.container = params.container;
+ },
+
+ addSection: function(toggler, element, pos){
+ toggler = document.id(toggler);
+ element = document.id(element);
+ var test = this.togglers.contains(toggler);
+ var len = this.togglers.length;
+ 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);
+ }
+ return this.parent.apply(this, arguments);
+ }
+
+});/*
+---
+
+script: Fx.Move.js
+
+description: Defines Fx.Move, a class that works with Element.Position.js to transition an element from one location to another.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Fx.Morph
+- /Element.Position
+
+provides: [Fx.Move]
+
+...
+*/
+
+Fx.Move = new Class({
+
+ Extends: Fx.Morph,
+
+ options: {
+ relativeTo: document.body,
+ position: 'center',
+ edge: false,
+ offset: {x: 0, y: 0}
+ },
+
+ start: function(destination){
+ return this.parent(this.element.position($merge(this.options, destination, {returnPos: true})));
+ }
+
+});
+
+Element.Properties.move = {
+
+ set: function(options){
+ var morph = this.retrieve('move');
+ if (morph) morph.cancel();
+ return this.eliminate('move').store('move:options', $extend({link: 'cancel'}, options));
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('move')){
+ if (options || !this.retrieve('move:options')) this.set('move', options);
+ this.store('move', new Fx.Move(this, this.retrieve('move:options')));
+ }
+ return this.retrieve('move');
+ }
+
+};
+
+Element.implement({
+
+ move: function(options){
+ this.get('move').start(options);
+ return this;
+ }
+
+});
+/*
+---
+
+script: Fx.Scroll.js
+
+description: Effect to smoothly scroll any element, including the window.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Fx
+- core:1.2.4/Element.Event
+- core:1.2.4/Element.Dimensions
+- /MooTools.More
+
+provides: [Fx.Scroll]
+
+...
+*/
+
+Fx.Scroll = new Class({
+
+ Extends: Fx,
+
+ options: {
+ offset: {x: 0, y: 0},
+ wheelStops: true
+ },
+
+ initialize: function(element, options){
+ this.element = this.subject = document.id(element);
+ this.parent(options);
+ var cancel = this.cancel.bind(this, false);
+
+ if ($type(this.element) != 'element') this.element = document.id(this.element.getDocument().body);
+
+ var stopper = this.element;
+
+ if (this.options.wheelStops){
+ this.addEvent('start', function(){
+ stopper.addEvent('mousewheel', cancel);
+ }, true);
+ this.addEvent('complete', function(){
+ stopper.removeEvent('mousewheel', cancel);
+ }, true);
+ }
+ },
+
+ set: function(){
+ var now = Array.flatten(arguments);
+ if (Browser.Engine.gecko) now = [Math.round(now[0]), Math.round(now[1])];
+ this.element.scrollTo(now[0], now[1]);
+ },
+
+ compute: function(from, to, delta){
+ return [0, 1].map(function(i){
+ return Fx.compute(from[i], to[i], delta);
+ });
+ },
+
+ start: function(x, y){
+ if (!this.check(x, y)) return this;
+ var scrollSize = this.element.getScrollSize(),
+ scroll = this.element.getScroll(),
+ values = {x: x, y: y};
+ for (var z in values){
+ var max = scrollSize[z];
+ if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z] : 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);
+ },
+
+ toLeft: function(){
+ return this.start(0, false);
+ },
+
+ toRight: function(){
+ return this.start('right', false);
+ },
+
+ toBottom: function(){
+ return this.start(false, 'bottom');
+ },
+
+ toElement: function(el){
+ var position = document.id(el).getPosition(this.element);
+ return this.start(position.x, position.y);
+ },
+
+ scrollIntoView: function(el, axes, offset){
+ axes = axes ? $splat(axes) : ['x','y'];
+ var to = {};
+ el = document.id(el);
+ var pos = el.getPosition(this.element);
+ var size = el.getSize();
+ var scroll = this.element.getScroll();
+ var containerSize = this.element.getSize();
+ var edge = {
+ x: pos.x + size.x,
+ y: pos.y + size.y
+ };
+ ['x','y'].each(function(axis) {
+ if (axes.contains(axis)) {
+ if (edge[axis] > scroll[axis] + containerSize[axis]) to[axis] = edge[axis] - containerSize[axis];
+ if (pos[axis] < scroll[axis]) to[axis] = pos[axis];
+ }
+ if (to[axis] == null) to[axis] = scroll[axis];
+ if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
+ }, this);
+ if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
+ return this;
+ },
+
+ scrollToCenter: function(el, axes, offset){
+ axes = axes ? $splat(axes) : ['x', 'y'];
+ el = $(el);
+ var to = {},
+ pos = el.getPosition(this.element),
+ size = el.getSize(),
+ scroll = this.element.getScroll(),
+ containerSize = this.element.getSize(),
+ edge = {
+ x: pos.x + size.x,
+ y: pos.y + size.y
+ };
+
+ ['x','y'].each(function(axis){
+ if(axes.contains(axis)){
+ to[axis] = pos[axis] - (containerSize[axis] - size[axis])/2;
+ }
+ if(to[axis] == null) to[axis] = scroll[axis];
+ if(offset && offset[axis]) to[axis] = to[axis] + offset[axis];
+ }, this);
+ if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
+ return this;
+ }
+
+});
+/*
+---
+
+script: Fx.Slide.js
+
+description: Effect to slide an element in and out of view.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Fx Element.Style
+- /MooTools.More
+
+provides: [Fx.Slide]
+
+...
+*/
+
+Fx.Slide = new Class({
+
+ Extends: Fx,
+
+ options: {
+ mode: 'vertical',
+ wrapper: false,
+ hideOverflow: true
+ },
+
+ initialize: function(element, options){
+ this.addEvent('complete', function(){
+ this.open = (this.wrapper['offset' + this.layout.capitalize()] != 0);
+ if (this.open) this.wrapper.setStyle('height', '');
+ 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'});
+ if (this.options.wrapper) wrapper = document.id(this.options.wrapper).setStyles(styles);
+ 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;
+ },
+
+ 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){
+ return [0, 1].map(function(i){
+ return Fx.compute(from[i], to[i], delta);
+ });
+ },
+
+ 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;
+ }
+ 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;
+ }
+
+});
+/*
+---
+
+script: Fx.SmoothScroll.js
+
+description: Class for creating a smooth scrolling effect to all internal links on the page.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Selectors
+- /Fx.Scroll
+
+provides: [Fx.SmoothScroll]
+
+...
+*/
+
+var SmoothScroll = Fx.SmoothScroll = new Class({
+
+ Extends: Fx.Scroll,
+
+ initialize: function(options, context){
+ context = context || document;
+ this.doc = context.getDocument();
+ var win = context.getWindow();
+ this.parent(this.doc, options);
+ this.links = $$(this.options.links || this.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) this.useLink(link, anchor);
+ }, this);
+ if (!Browser.Engine.webkit419) {
+ this.addEvent('complete', function(){
+ win.location.hash = this.anchor;
+ }, true);
+ }
+ },
+
+ useLink: function(link, anchor){
+ var el;
+ link.addEvent('click', function(event){
+ if (el !== false && !el) el = document.id(anchor) || this.doc.getElement('a[name=' + anchor + ']');
+ if (el) {
+ event.preventDefault();
+ this.anchor = anchor;
+ this.toElement(el).chain(function(){
+ this.fireEvent('scrolledTo', [link, el]);
+ }.bind(this));
+ link.blur();
+ }
+ }.bind(this));
+ }
+});/*
+---
+
+script: Fx.Sort.js
+
+description: Defines Fx.Sort, a class that reorders lists with a transition.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element.Dimensions
+- /Fx.Elements
+- /Element.Measure
+
+provides: [Fx.Sort]
+
+...
+*/
+
+Fx.Sort = new Class({
+
+ Extends: Fx.Elements,
+
+ options: {
+ mode: 'vertical'
+ },
+
+ initialize: function(elements, options){
+ this.parent(elements, options);
+ this.elements.each(function(el){
+ if (el.getStyle('position') == 'static') el.setStyle('position', 'relative');
+ });
+ this.setDefaultOrder();
+ },
+
+ setDefaultOrder: function(){
+ this.currentOrder = this.elements.map(function(el, index){
+ return index;
+ });
+ },
+
+ sort: function(newOrder){
+ if ($type(newOrder) != 'array') return false;
+ var top = 0,
+ left = 0,
+ next = {},
+ zero = {},
+ vert = this.options.mode == 'vertical';
+ var current = this.elements.map(function(el, index){
+ var size = el.getComputedSize({styles: ['border', 'padding', 'margin']});
+ var val;
+ if (vert){
+ val = {
+ top: top,
+ margin: size['margin-top'],
+ height: size.totalHeight
+ };
+ top += val.height - size['margin-top'];
+ } else {
+ val = {
+ left: left,
+ margin: size['margin-left'],
+ width: size.totalWidth
+ };
+ left += val.width;
+ }
+ var plain = vert ? 'top' : 'left';
+ zero[index] = {};
+ var start = el.getStyle(plain).toInt();
+ zero[index][plain] = start || 0;
+ return val;
+ }, this);
+ this.set(zero);
+ newOrder = newOrder.map(function(i){ return i.toInt(); });
+ if (newOrder.length != this.elements.length){
+ this.currentOrder.each(function(index){
+ if (!newOrder.contains(index)) newOrder.push(index);
+ });
+ if (newOrder.length > this.elements.length)
+ newOrder.splice(this.elements.length-1, newOrder.length - this.elements.length);
+ }
+ var margin = top = left = 0;
+ newOrder.each(function(item, index){
+ var newPos = {};
+ if (vert){
+ newPos.top = top - current[item].top - margin;
+ top += current[item].height;
+ } else {
+ newPos.left = left - current[item].left;
+ left += current[item].width;
+ }
+ margin = margin + current[item].margin;
+ next[item]=newPos;
+ }, this);
+ var mapped = {};
+ $A(newOrder).sort().each(function(index){
+ mapped[index] = next[index];
+ });
+ this.start(mapped);
+ this.currentOrder = newOrder;
+ return this;
+ },
+
+ rearrangeDOM: function(newOrder){
+ newOrder = newOrder || this.currentOrder;
+ var parent = this.elements[0].getParent();
+ var rearranged = [];
+ this.elements.setStyle('opacity', 0);
+ //move each element and store the new default order
+ newOrder.each(function(index){
+ rearranged.push(this.elements[index].inject(parent).setStyles({
+ top: 0,
+ left: 0
+ }));
+ }, this);
+ this.elements.setStyle('opacity', 1);
+ this.elements = $$(rearranged);
+ this.setDefaultOrder();
+ return this;
+ },
+
+ getDefaultOrder: function(){
+ return this.elements.map(function(el, index){
+ return index;
+ });
+ },
+
+ forward: function(){
+ return this.sort(this.getDefaultOrder());
+ },
+
+ backward: function(){
+ return this.sort(this.getDefaultOrder().reverse());
+ },
+
+ reverse: function(){
+ return this.sort(this.currentOrder.reverse());
+ },
+
+ sortByElements: function(elements){
+ return this.sort(elements.map(function(el){
+ return this.elements.indexOf(el);
+ }, this));
+ },
+
+ swap: function(one, two){
+ if ($type(one) == 'element') one = this.elements.indexOf(one);
+ if ($type(two) == 'element') two = this.elements.indexOf(two);
+
+ var newOrder = $A(this.currentOrder);
+ newOrder[this.currentOrder.indexOf(one)] = two;
+ newOrder[this.currentOrder.indexOf(two)] = one;
+ return this.sort(newOrder);
+ }
+
+});/*
+---
+
+script: Drag.js
+
+description: The base Drag Class. Can be used to drag and resize Elements using mouse events.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+- Tom Occhinno
+- Jan Kassens
+
+requires:
+- core:1.2.4/Events
+- core:1.2.4/Options
+- core:1.2.4/Element.Event
+- core:1.2.4/Element.Style
+- /MooTools.More
+
+provides: [Drag]
+
+*/
+
+var Drag = new Class({
+
+ Implements: [Events, Options],
+
+ options: {/*
+ onBeforeStart: $empty(thisElement),
+ onStart: $empty(thisElement, event),
+ onSnap: $empty(thisElement)
+ onDrag: $empty(thisElement, event),
+ onCancel: $empty(thisElement),
+ onComplete: $empty(thisElement, event),*/
+ snap: 6,
+ unit: 'px',
+ grid: false,
+ style: true,
+ limit: false,
+ handle: false,
+ invert: false,
+ preventDefault: false,
+ stopPropagation: false,
+ modifiers: {x: 'left', y: 'top'}
+ },
+
+ initialize: function(){
+ var params = Array.link(arguments, {'options': Object.type, 'element': $defined});
+ this.element = document.id(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) : document.id(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 (event.rightClick) return;
+ if (this.options.preventDefault) event.preventDefault();
+ if (this.options.stopPropagation) event.stopPropagation();
+ this.mouse.start = event.page;
+ this.fireEvent('beforeStart', this.element);
+ 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, event]).fireEvent('snap', this.element);
+ }
+ },
+
+ 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.limit[z][0]||0)) % 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, event]);
+ },
+
+ 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, event]);
+ }
+
+});
+
+Element.implement({
+
+ makeResizable: function(options){
+ var drag = new Drag(this, $merge({modifiers: {x: 'width', y: 'height'}}, options));
+ this.store('resizer', drag);
+ return drag.addEvent('drag', function(){
+ this.fireEvent('resize', drag);
+ }.bind(this));
+ }
+
+});
+/*
+---
+
+script: Drag.Move.js
+
+description: A Drag extension that provides support for the constraining of draggables to containers and droppables.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+- Tom Occhinno
+- Jan Kassens
+- Aaron Newton
+- Scott Kyle
+
+requires:
+- core:1.2.4/Element.Dimensions
+- /Drag
+
+provides: [Drag.Move]
+
+...
+*/
+
+Drag.Move = new Class({
+
+ Extends: Drag,
+
+ options: {/*
+ onEnter: $empty(thisElement, overed),
+ onLeave: $empty(thisElement, overed),
+ onDrop: $empty(thisElement, overed, event),*/
+ droppables: [],
+ container: false,
+ precalculate: false,
+ includeMargins: true,
+ checkDroppables: true
+ },
+
+ initialize: function(element, options){
+ this.parent(element, options);
+ element = this.element;
+
+ this.droppables = $$(this.options.droppables);
+ this.container = document.id(this.options.container);
+
+ if (this.container && $type(this.container) != 'element')
+ this.container = document.id(this.container.getDocument().body);
+
+ var styles = element.getStyles('left', 'top', 'position');
+ if (styles.left == 'auto' || styles.top == 'auto')
+ element.setPosition(element.getPosition(element.getOffsetParent()));
+
+ if (styles.position == 'static')
+ element.setStyle('position', 'absolute');
+
+ this.addEvent('start', this.checkDroppables, true);
+
+ this.overed = null;
+ },
+
+ start: function(event){
+ if (this.container) this.options.limit = this.calculateLimit();
+
+ if (this.options.precalculate){
+ this.positions = this.droppables.map(function(el){
+ return el.getCoordinates();
+ });
+ }
+
+ this.parent(event);
+ },
+
+ calculateLimit: function(){
+ var offsetParent = this.element.getOffsetParent(),
+ containerCoordinates = this.container.getCoordinates(offsetParent),
+ containerBorder = {},
+ elementMargin = {},
+ elementBorder = {},
+ containerMargin = {},
+ offsetParentPadding = {};
+
+ ['top', 'right', 'bottom', 'left'].each(function(pad){
+ containerBorder[pad] = this.container.getStyle('border-' + pad).toInt();
+ elementBorder[pad] = this.element.getStyle('border-' + pad).toInt();
+ elementMargin[pad] = this.element.getStyle('margin-' + pad).toInt();
+ containerMargin[pad] = this.container.getStyle('margin-' + pad).toInt();
+ offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt();
+ }, this);
+
+ var width = this.element.offsetWidth + elementMargin.left + elementMargin.right,
+ height = this.element.offsetHeight + elementMargin.top + elementMargin.bottom,
+ left = 0,
+ top = 0,
+ right = containerCoordinates.right - containerBorder.right - width,
+ bottom = containerCoordinates.bottom - containerBorder.bottom - height;
+
+ if (this.options.includeMargins){
+ left += elementMargin.left;
+ top += elementMargin.top;
+ } else {
+ right += elementMargin.right;
+ bottom += elementMargin.bottom;
+ }
+
+ if (this.element.getStyle('position') == 'relative'){
+ var coords = this.element.getCoordinates(offsetParent);
+ coords.left -= this.element.getStyle('left').toInt();
+ coords.top -= this.element.getStyle('top').toInt();
+
+ left += containerBorder.left - coords.left;
+ top += containerBorder.top - coords.top;
+ right += elementMargin.left - coords.left;
+ bottom += elementMargin.top - coords.top;
+
+ if (this.container != offsetParent){
+ left += containerMargin.left + offsetParentPadding.left;
+ top += (Browser.Engine.trident4 ? 0 : containerMargin.top) + offsetParentPadding.top;
+ }
+ } else {
+ left -= elementMargin.left;
+ top -= elementMargin.top;
+
+ if (this.container == offsetParent){
+ right -= containerBorder.left;
+ bottom -= containerBorder.top;
+ } else {
+ left += containerCoordinates.left + containerBorder.left;
+ top += containerCoordinates.top + containerBorder.top;
+ }
+ }
+
+ return {
+ x: [left, right],
+ y: [top, bottom]
+ };
+ },
+
+ checkAgainst: function(el, i){
+ el = (this.positions) ? this.positions[i] : el.getCoordinates();
+ var now = this.mouse.now;
+ return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
+ },
+
+ 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.fireEvent('enter', [this.element, overed]);
+ this.overed = overed;
+ }
+ },
+
+ drag: function(event){
+ this.parent(event);
+ if (this.options.checkDroppables && this.droppables.length) this.checkDroppables();
+ },
+
+ stop: function(event){
+ this.checkDroppables();
+ this.fireEvent('drop', [this.element, this.overed, event]);
+ this.overed = null;
+ return this.parent(event);
+ }
+
+});
+
+Element.implement({
+
+ makeDraggable: function(options){
+ var drag = new Drag.Move(this, options);
+ this.store('dragger', drag);
+ return drag;
+ }
+
+});
+/*
+---
+
+script: Slider.js
+
+description: Class for creating horizontal and vertical slider controls.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Element.Dimensions
+- /Class.Binds
+- /Drag
+- /Element.Dimensions
+- /Element.Measure
+
+provides: [Slider]
+
+...
+*/
+
+var Slider = new Class({
+
+ Implements: [Events, Options],
+
+ Binds: ['clickedElement', 'draggedKnob', 'scrolledElement'],
+
+ options: {/*
+ onTick: $empty(intPosition),
+ onChange: $empty(intStep),
+ onComplete: $empty(strStep),*/
+ onTick: function(position){
+ if (this.options.snap) position = this.toPosition(this.step);
+ this.knob.setStyle(this.property, position);
+ },
+ initialStep: 0,
+ snap: false,
+ offset: 0,
+ range: false,
+ wheel: false,
+ steps: 100,
+ mode: 'horizontal'
+ },
+
+ initialize: function(element, knob, options){
+ this.setOptions(options);
+ this.element = document.id(element);
+ this.knob = document.id(knob);
+ this.previousChange = this.previousEnd = this.step = -1;
+ 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.full = this.element.measure(function(){
+ this.half = this.knob[offset] / 2;
+ return this.element[offset] - this.knob[offset] + (this.options.offset * 2);
+ }.bind(this));
+
+ 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.initialStep ? this.toPosition(this.options.initialStep) : - this.options.offset);
+ modifiers[this.axis] = this.property;
+ limit[this.axis] = [- this.options.offset, this.full - this.options.offset];
+
+ var dragOptions = {
+ snap: 0,
+ limit: limit,
+ modifiers: modifiers,
+ onDrag: this.draggedKnob,
+ onStart: this.draggedKnob,
+ onBeforeStart: (function(){
+ this.isDragging = true;
+ }).bind(this),
+ onCancel: function() {
+ this.isDragging = false;
+ }.bind(this),
+ onComplete: function(){
+ this.isDragging = false;
+ this.draggedKnob();
+ this.end();
+ }.bind(this)
+ };
+ if (this.options.snap){
+ dragOptions.grid = Math.ceil(this.stepWidth);
+ dragOptions.limit[this.axis][1] = this.full;
+ }
+
+ this.drag = new Drag(this.knob, dragOptions);
+ this.attach();
+ },
+
+ attach: function(){
+ this.element.addEvent('mousedown', this.clickedElement);
+ if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement);
+ this.drag.attach();
+ return this;
+ },
+
+ detach: function(){
+ this.element.removeEvent('mousedown', this.clickedElement);
+ this.element.removeEvent('mousewheel', this.scrolledElement);
+ this.drag.detach();
+ return this;
+ },
+
+ 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.fireEvent('tick', this.toPosition(this.step));
+ this.end();
+ return this;
+ },
+
+ clickedElement: function(event){
+ if (this.isDragging || event.target == this.knob) return;
+
+ 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.fireEvent('tick', position);
+ this.end();
+ },
+
+ 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: Sortables.js
+
+description: Class for creating a drag and drop sorting interface for lists of items.
+
+license: MIT-style license
+
+authors:
+- Tom Occhino
+
+requires:
+- /Drag.Move
+
+provides: [Slider]
+
+...
+*/
+
+var Sortables = new Class({
+
+ Implements: [Events, Options],
+
+ options: {/*
+ onSort: $empty(element, clone),
+ onStart: $empty(element, clone),
+ onComplete: $empty(element),*/
+ 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($$(document.id(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(){
+ return $$(Array.flatten(arguments).map(function(element){
+ this.elements.erase(element);
+ var start = element.retrieve('sortables:start');
+ (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start);
+
+ return element;
+ }, this));
+ },
+
+ removeLists: function(){
+ return $$(Array.flatten(arguments).map(function(list){
+ this.lists.erase(list);
+ this.removeItems(list.getChildren());
+
+ return list;
+ }, this));
+ },
+
+ 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);
+ var clone = element.clone(true).setStyles({
+ margin: '0px',
+ position: 'absolute',
+ visibility: 'hidden',
+ 'width': element.getStyle('width')
+ });
+ //prevent the duplicated radio inputs from unchecking the real one
+ if (clone.get('html').test('radio')) {
+ clone.getElements('input[type=radio]').each(function(input, i) {
+ input.set('name', 'clone_' + i);
+ });
+ }
+
+ return clone.inject(this.list).setPosition(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: Request.JSONP.js
+
+description: Defines Request.JSONP, a class for cross domain javascript via script injection.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+- Guillermo Rauch
+
+requires:
+- core:1.2.4/Element
+- core:1.2.4/Request
+- /Log
+
+provides: [Request.JSONP]
+
+...
+*/
+
+Request.JSONP = new Class({
+
+ Implements: [Chain, Events, Options, Log],
+
+ options: {/*
+ onRetry: $empty(intRetries),
+ onRequest: $empty(scriptElement),
+ onComplete: $empty(data),
+ onSuccess: $empty(data),
+ onCancel: $empty(),
+ log: false,
+ */
+ url: '',
+ data: {},
+ retries: 0,
+ timeout: 0,
+ link: 'ignore',
+ callbackKey: 'callback',
+ injectScript: document.head
+ },
+
+ initialize: function(options){
+ this.setOptions(options);
+ if (this.options.log) this.enableLog();
+ this.running = false;
+ this.requests = 0;
+ this.triesRemaining = [];
+ },
+
+ check: function(){
+ if (!this.running) 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;
+ },
+
+ send: function(options){
+ if (!$chk(arguments[1]) && !this.check(options)) return this;
+
+ var type = $type(options),
+ old = this.options,
+ index = $chk(arguments[1]) ? arguments[1] : this.requests++;
+ if (type == 'string' || type == 'element') options = {data: options};
+
+ options = $extend({data: old.data, url: old.url}, options);
+
+ if (!$chk(this.triesRemaining[index])) this.triesRemaining[index] = this.options.retries;
+ var remaining = this.triesRemaining[index];
+
+ (function(){
+ var script = this.getScript(options);
+ this.log('JSONP retrieving script with url: ' + script.get('src'));
+ this.fireEvent('request', script);
+ this.running = true;
+
+ (function(){
+ if (remaining){
+ this.triesRemaining[index] = remaining - 1;
+ if (script){
+ script.destroy();
+ this.send(options, index).fireEvent('retry', this.triesRemaining[index]);
+ }
+ } else if(script && this.options.timeout){
+ script.destroy();
+ this.cancel().fireEvent('failure');
+ }
+ }).delay(this.options.timeout, this);
+ }).delay(Browser.Engine.trident ? 50 : 0, this);
+ return this;
+ },
+
+ cancel: function(){
+ if (!this.running) return this;
+ this.running = false;
+ this.fireEvent('cancel');
+ return this;
+ },
+
+ getScript: function(options){
+ var index = Request.JSONP.counter,
+ data;
+ Request.JSONP.counter++;
+
+ switch ($type(options.data)){
+ case 'element': data = document.id(options.data).toQueryString(); break;
+ case 'object': case 'hash': data = Hash.toQueryString(options.data);
+ }
+
+ var src = options.url +
+ (options.url.test('\\?') ? '&' :'?') +
+ (options.callbackKey || this.options.callbackKey) +
+ '=Request.JSONP.request_map.request_'+ index +
+ (data ? '&' + data : '');
+ if (src.length > 2083) this.log('JSONP '+ src +' will fail in Internet Explorer, which enforces a 2083 bytes length limit on URIs');
+
+ var script = new Element('script', {type: 'text/javascript', src: src});
+ Request.JSONP.request_map['request_' + index] = function(){ this.success(arguments, script); }.bind(this);
+ return script.inject(this.options.injectScript);
+ },
+
+ success: function(args, script){
+ if (script) script.destroy();
+ this.running = false;
+ this.log('JSONP successfully retrieved: ', args);
+ this.fireEvent('complete', args).fireEvent('success', args).callChain();
+ }
+
+});
+
+Request.JSONP.counter = 0;
+Request.JSONP.request_map = {};/*
+---
+
+script: Request.Queue.js
+
+description: Controls several instances of Request and its variants to run only one request at a time.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Element
+- core:1.2.4/Request
+- /Log
+
+provides: [Request.Queue]
+
+...
+*/
+
+Request.Queue = new Class({
+
+ Implements: [Options, Events],
+
+ Binds: ['attach', 'request', 'complete', 'cancel', 'success', 'failure', 'exception'],
+
+ options: {/*
+ onRequest: $empty(argsPassedToOnRequest),
+ onSuccess: $empty(argsPassedToOnSuccess),
+ onComplete: $empty(argsPassedToOnComplete),
+ onCancel: $empty(argsPassedToOnCancel),
+ onException: $empty(argsPassedToOnException),
+ onFailure: $empty(argsPassedToOnFailure),
+ onEnd: $empty,
+ */
+ stopOnFailure: true,
+ autoAdvance: true,
+ concurrent: 1,
+ requests: {}
+ },
+
+ initialize: function(options){
+ if(options){
+ var requests = options.requests;
+ delete options.requests;
+ }
+ this.setOptions(options);
+ this.requests = new Hash;
+ this.queue = [];
+ this.reqBinders = {};
+
+ if(requests) this.addRequests(requests);
+ },
+
+ addRequest: function(name, request){
+ this.requests.set(name, request);
+ this.attach(name, request);
+ return this;
+ },
+
+ addRequests: function(obj){
+ $each(obj, function(req, name){
+ this.addRequest(name, req);
+ }, this);
+ return this;
+ },
+
+ getName: function(req){
+ return this.requests.keyOf(req);
+ },
+
+ attach: function(name, req){
+ if (req._groupSend) return this;
+ ['request', 'complete', 'cancel', 'success', 'failure', 'exception'].each(function(evt){
+ if(!this.reqBinders[name]) this.reqBinders[name] = {};
+ this.reqBinders[name][evt] = function(){
+ this['on' + evt.capitalize()].apply(this, [name, req].extend(arguments));
+ }.bind(this);
+ req.addEvent(evt, this.reqBinders[name][evt]);
+ }, this);
+ req._groupSend = req.send;
+ req.send = function(options){
+ this.send(name, options);
+ return req;
+ }.bind(this);
+ return this;
+ },
+
+ removeRequest: function(req){
+ var name = $type(req) == 'object' ? this.getName(req) : req;
+ if (!name && $type(name) != 'string') return this;
+ req = this.requests.get(name);
+ if (!req) return this;
+ ['request', 'complete', 'cancel', 'success', 'failure', 'exception'].each(function(evt){
+ req.removeEvent(evt, this.reqBinders[name][evt]);
+ }, this);
+ req.send = req._groupSend;
+ delete req._groupSend;
+ return this;
+ },
+
+ getRunning: function(){
+ return this.requests.filter(function(r){
+ return r.running;
+ });
+ },
+
+ isRunning: function(){
+ return !!(this.getRunning().getKeys().length);
+ },
+
+ send: function(name, options){
+ var q = function(){
+ this.requests.get(name)._groupSend(options);
+ this.queue.erase(q);
+ }.bind(this);
+ q.name = name;
+ if (this.getRunning().getKeys().length >= this.options.concurrent || (this.error && this.options.stopOnFailure)) this.queue.push(q);
+ else q();
+ return this;
+ },
+
+ hasNext: function(name){
+ return (!name) ? !!this.queue.length : !!this.queue.filter(function(q){ return q.name == name; }).length;
+ },
+
+ resume: function(){
+ this.error = false;
+ (this.options.concurrent - this.getRunning().getKeys().length).times(this.runNext, this);
+ return this;
+ },
+
+ runNext: function(name){
+ if (!this.queue.length) return this;
+ if (!name){
+ this.queue[0]();
+ } else {
+ var found;
+ this.queue.each(function(q){
+ if (!found && q.name == name){
+ found = true;
+ q();
+ }
+ });
+ }
+ return this;
+ },
+
+ runAll: function() {
+ this.queue.each(function(q) {
+ q();
+ });
+ return this;
+ },
+
+ clear: function(name){
+ if (!name){
+ this.queue.empty();
+ } else {
+ this.queue = this.queue.map(function(q){
+ if (q.name != name) return q;
+ else return false;
+ }).filter(function(q){ return q; });
+ }
+ return this;
+ },
+
+ cancel: function(name){
+ this.requests.get(name).cancel();
+ return this;
+ },
+
+ onRequest: function(){
+ this.fireEvent('request', arguments);
+ },
+
+ onComplete: function(){
+ this.fireEvent('complete', arguments);
+ if (!this.queue.length) this.fireEvent('end');
+ },
+
+ onCancel: function(){
+ if (this.options.autoAdvance && !this.error) this.runNext();
+ this.fireEvent('cancel', arguments);
+ },
+
+ onSuccess: function(){
+ if (this.options.autoAdvance && !this.error) this.runNext();
+ this.fireEvent('success', arguments);
+ },
+
+ onFailure: function(){
+ this.error = true;
+ if (!this.options.stopOnFailure && this.options.autoAdvance) this.runNext();
+ this.fireEvent('failure', arguments);
+ },
+
+ onException: function(){
+ this.error = true;
+ if (!this.options.stopOnFailure && this.options.autoAdvance) this.runNext();
+ this.fireEvent('exception', arguments);
+ }
+
+});
+/*
+---
+
+script: Request.Periodical.js
+
+description: Requests the same URL to pull data from a server but increases the intervals if no data is returned to reduce the load
+
+license: MIT-style license
+
+authors:
+- Christoph Pojer
+
+requires:
+- core:1.2.4/Request
+- /MooTools.More
+
+provides: [Request.Periodical]
+
+...
+*/
+
+Request.implement({
+
+ options: {
+ initialDelay: 5000,
+ delay: 5000,
+ limit: 60000
+ },
+
+ startTimer: function(data){
+ var fn = function(){
+ if (!this.running) this.send({data: data});
+ };
+ this.timer = fn.delay(this.options.initialDelay, this);
+ this.lastDelay = this.options.initialDelay;
+ this.completeCheck = function(response){
+ $clear(this.timer);
+ this.lastDelay = (response) ? this.options.delay : (this.lastDelay + this.options.delay).min(this.options.limit);
+ this.timer = fn.delay(this.lastDelay, this);
+ };
+ return this.addEvent('complete', this.completeCheck);
+ },
+
+ stopTimer: function(){
+ $clear(this.timer);
+ return this.removeEvent('complete', this.completeCheck);
+ }
+
+});/*
+---
+
+script: Assets.js
+
+description: Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Element.Event
+- /MooTools.More
+
+provides: [Assets]
+
+...
+*/
+
+var Asset = {
+
+ javascript: function(source, properties){
+ properties = $extend({
+ onload: $empty,
+ document: document,
+ check: $lambda(true)
+ }, properties);
+
+ if (properties.onLoad) properties.onload = properties.onLoad;
+
+ 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();
+ }
+ }).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
+ }, properties)).inject(document.head);
+ },
+
+ image: function(source, properties){
+ properties = $merge({
+ onload: $empty,
+ onabort: $empty,
+ onerror: $empty
+ }, properties);
+ var image = new Image();
+ var element = document.id(image) || new Element('img');
+ ['load', 'abort', 'error'].each(function(name){
+ var type = 'on' + name;
+ var cap = name.capitalize();
+ if (properties['on' + cap]) properties[type] = properties['on' + cap];
+ var event = properties[type];
+ delete properties[type];
+ image[type] = function(){
+ if (!image) return;
+ if (!element.parentNode){
+ element.width = image.width;
+ element.height = image.height;
+ }
+ image = image.onload = image.onabort = image.onerror = null;
+ event.delay(1, element, element);
+ element.fireEvent(name, element, 1);
+ };
+ });
+ image.src = element.src = source;
+ if (image && image.complete) image.onload.delay(1);
+ return element.set(properties);
+ },
+
+ images: function(sources, options){
+ options = $merge({
+ onComplete: $empty,
+ onProgress: $empty,
+ onError: $empty,
+ properties: {}
+ }, options);
+ sources = $splat(sources);
+ var images = [];
+ var counter = 0;
+ 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();
+ }
+ }));
+ }));
+ }
+
+};/*
+---
+
+script: Color.js
+
+description: Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Array
+- core:1.2.4/String
+- core:1.2.4/Number
+- core:1.2.4/Hash
+- core:1.2.4/Function
+- core:1.2.4/$util
+
+provides: [Color]
+
+...
+*/
+
+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;
+ }
+ color.rgb = color.slice(0, 3);
+ color.hsb = color.hsb || color.rgbToHsb();
+ color.hex = color.rgbToHex();
+ return $extend(color, this);
+ }
+
+});
+
+Color.implement({
+
+ 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');
+ },
+
+ invert: function(){
+ return new Color(this.map(function(value){
+ return 255 - value;
+ }));
+ },
+
+ setHue: function(value){
+ return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');
+ },
+
+ setSaturation: function(percent){
+ return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');
+ },
+
+ setBrightness: function(percent){
+ return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');
+ }
+
+});
+
+var $RGB = function(r, g, b){
+ return new Color([r, g, b], 'rgb');
+};
+
+var $HSB = function(h, s, b){
+ return new Color([h, s, b], 'hsb');
+};
+
+var $HEX = function(hex){
+ return new Color(hex, 'hex');
+};
+
+Array.implement({
+
+ rgbToHsb: function(){
+ var red = this[0],
+ green = this[1],
+ blue = this[2],
+ hue = 0;
+ var max = Math.max(red, green, blue),
+ min = Math.min(red, green, blue);
+ var delta = max - min;
+ var brightness = max / 255,
+ saturation = (max != 0) ? delta / max : 0;
+ if(saturation != 0) {
+ 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)];
+ },
+
+ 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];
+ }
+ }
+ return false;
+ }
+
+});
+
+String.implement({
+
+ rgbToHsb: function(){
+ var rgb = this.match(/\d{1,3}/g);
+ return (rgb) ? rgb.rgbToHsb() : null;
+ },
+
+ hsbToRgb: function(){
+ var hsb = this.match(/\d{1,3}/g);
+ return (hsb) ? hsb.hsbToRgb() : null;
+ }
+
+});
+/*
+---
+
+script: Group.js
+
+description: Class for monitoring collections of events
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Events
+- /MooTools.More
+
+provides: [Group]
+
+...
+*/
+
+var Group = new Class({
+
+ initialize: function(){
+ this.instances = Array.flatten(arguments);
+ this.events = {};
+ this.checker = {};
+ },
+
+ 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;
+ },
+
+ 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);
+ }
+
+});
+/*
+---
+
+script: Hash.Cookie.js
+
+description: Class for creating, reading, and deleting Cookies in JSON format.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+- Aaron Newton
+
+requires:
+- core:1.2.4/Cookie
+- core:1.2.4/JSON
+- /MooTools.More
+
+provides: [Hash.Cookie]
+
+...
+*/
+
+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.each(Hash.prototype, function(method, name){
+ if (typeof method == 'function') Hash.Cookie.implement(name, function(){
+ var value = method.apply(this.hash, arguments);
+ if (this.options.autoSave) this.save();
+ return value;
+ });
+});/*
+---
+
+script: HtmlTable.js
+
+description: Builds table elements with methods to add rows.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- core:1.2.4/Options
+- core:1.2.4/Events
+- /Class.Occlude
+
+provides: [HtmlTable]
+
+...
+*/
+
+var HtmlTable = new Class({
+
+ Implements: [Options, Events, Class.Occlude],
+
+ options: {
+ properties: {
+ cellpadding: 0,
+ cellspacing: 0,
+ border: 0
+ },
+ rows: [],
+ headers: [],
+ footers: []
+ },
+
+ property: 'HtmlTable',
+
+ initialize: function(){
+ var params = Array.link(arguments, {options: Object.type, table: Element.type});
+ this.setOptions(params.options);
+ this.element = params.table || new Element('table', this.options.properties);
+ if (this.occlude()) return this.occluded;
+ this.build();
+ },
+
+ build: function(){
+ this.element.store('HtmlTable', this);
+
+ this.body = document.id(this.element.tBodies[0]) || new Element('tbody').inject(this.element);
+ $$(this.body.rows);
+
+ if (this.options.headers.length) this.setHeaders(this.options.headers);
+ else this.thead = document.id(this.element.tHead);
+ if (this.thead) this.head = document.id(this.thead.rows[0]);
+
+ if (this.options.footers.length) this.setFooters(this.options.footers);
+ this.tfoot = document.id(this.element.tFoot);
+ if (this.tfoot) this.foot = document.id(this.thead.rows[0]);
+
+ this.options.rows.each(function(row){
+ this.push(row);
+ }, this);
+
+ ['adopt', 'inject', 'wraps', 'grab', 'replaces', 'dispose'].each(function(method){
+ this[method] = this.element[method].bind(this.element);
+ }, this);
+ },
+
+ toElement: function(){
+ return this.element;
+ },
+
+ empty: function(){
+ this.body.empty();
+ return this;
+ },
+
+ set: function(what, items) {
+ var target = (what == 'headers') ? 'tHead' : 'tFoot';
+ this[target.toLowerCase()] = (document.id(this.element[target]) || new Element(target.toLowerCase()).inject(this.element, 'top')).empty();
+ var data = this.push(items, {}, this[target.toLowerCase()], what == 'headers' ? 'th' : 'td');
+ if (what == 'headers') this.head = document.id(this.thead.rows[0]);
+ else this.foot = document.id(this.thead.rows[0]);
+ return data;
+ },
+
+ setHeaders: function(headers){
+ this.set('headers', headers);
+ return this;
+ },
+
+ setFooters: function(footers){
+ this.set('footers', footers);
+ return this;
+ },
+
+ push: function(row, rowProperties, target, tag){
+ var tds = row.map(function(data){
+ var td = new Element(tag || 'td', data.properties),
+ type = data.content || data || '',
+ element = document.id(type);
+ if($type(type) != 'string' && element) td.adopt(element);
+ else td.set('html', type);
+
+ return td;
+ });
+
+ return {
+ tr: new Element('tr', rowProperties).inject(target || this.body).adopt(tds),
+ tds: tds
+ };
+ }
+
+});
+/*
+---
+
+script: HtmlTable.Zebra.js
+
+description: Builds a stripy table with methods to add rows.
+
+license: MIT-style license
+
+authors:
+- Harald Kirschner
+- Aaron Newton
+
+requires:
+- /HtmlTable
+- /Class.refactor
+
+provides: [HtmlTable.Zebra]
+
+...
+*/
+
+HtmlTable = Class.refactor(HtmlTable, {
+
+ options: {
+ classZebra: 'table-tr-odd',
+ zebra: true
+ },
+
+ initialize: function(){
+ this.previous.apply(this, arguments);
+ if (this.occluded) return this.occluded;
+ if (this.options.zebra) this.updateZebras();
+ },
+
+ updateZebras: function(){
+ Array.each(this.body.rows, this.zebra, this);
+ },
+
+ zebra: function(row, i){
+ return row[((i % 2) ? 'remove' : 'add')+'Class'](this.options.classZebra);
+ },
+
+ push: function(){
+ var pushed = this.previous.apply(this, arguments);
+ if (this.options.zebra) this.updateZebras();
+ return pushed;
+ }
+
+});/*
+---
+
+script: HtmlTable.Sort.js
+
+description: Builds a stripy, sortable table with methods to add rows.
+
+license: MIT-style license
+
+authors:
+- Harald Kirschner
+- Aaron Newton
+
+requires:
+- core:1.2.4/Hash
+- /HtmlTable
+- /Class.refactor
+- /Element.Delegation
+- /Date
+
+provides: [HtmlTable.Sort]
+
+...
+*/
+
+HtmlTable = Class.refactor(HtmlTable, {
+
+ options: {/*
+ onSort: $empty, */
+ sortIndex: 0,
+ sortReverse: false,
+ parsers: [],
+ defaultParser: 'string',
+ classSortable: 'table-sortable',
+ classHeadSort: 'table-th-sort',
+ classHeadSortRev: 'table-th-sort-rev',
+ classNoSort: 'table-th-nosort',
+ classGroupHead: 'table-tr-group-head',
+ classGroup: 'table-tr-group',
+ classCellSort: 'table-td-sort',
+ classSortSpan: 'table-th-sort-span',
+ sortable: false
+ },
+
+ initialize: function () {
+ this.previous.apply(this, arguments);
+ if (this.occluded) return this.occluded;
+ this.sorted = {index: null, dir: 1};
+ this.bound = {
+ headClick: this.headClick.bind(this)
+ };
+ this.sortSpans = new Elements();
+ if (this.options.sortable) {
+ this.enableSort();
+ if (this.options.sortIndex != null) this.sort(this.options.sortIndex, this.options.sortReverse);
+ }
+ },
+
+ attachSorts: function(attach){
+ this.element.removeEvents('click:relay(th)');
+ this.element[$pick(attach, true) ? 'addEvent' : 'removeEvent']('click:relay(th)', this.bound.headClick);
+ },
+
+ setHeaders: function(){
+ this.previous.apply(this, arguments);
+ if (this.sortEnabled) this.detectParsers();
+ },
+
+ detectParsers: function(force){
+ if (!this.head) return;
+ var parsers = this.options.parsers,
+ rows = this.body.rows;
+
+ // auto-detect
+ this.parsers = $$(this.head.cells).map(function(cell, index) {
+ if (!force && (cell.hasClass(this.options.classNoSort) || cell.retrieve('htmltable-parser'))) return cell.retrieve('htmltable-parser');
+ var thDiv = new Element('div');
+ $each(cell.childNodes, function(node) {
+ thDiv.adopt(node);
+ });
+ thDiv.inject(cell);
+ var sortSpan = new Element('span', {'html': ' ', 'class': this.options.classSortSpan}).inject(thDiv, 'top');
+
+ this.sortSpans.push(sortSpan);
+
+ var parser = parsers[index],
+ cancel;
+ switch ($type(parser)) {
+ case 'function': parser = {convert: parser}; cancel = true; break;
+ case 'string': parser = parser; cancel = true; break;
+ }
+ if (!cancel) {
+ HtmlTable.Parsers.some(function(current) {
+ var match = current.match;
+ if (!match) return false;
+ for (var i = 0, j = rows.length; i < j; i++) {
+ var text = $(rows[i].cells[index]).get('html').clean();
+ if (text && match.test(text)) {
+ parser = current;
+ return true;
+ }
+ }
+ });
+ }
+
+ if (!parser) parser = this.options.defaultParser;
+ cell.store('htmltable-parser', parser);
+ return parser;
+ }, this);
+ },
+
+ headClick: function(event, el) {
+ console.log(el);
+ if (!this.head || el.hasClass(this.options.classNoSort)) return;
+ var index = Array.indexOf(this.head.cells, el);
+ this.sort(index);
+ return false;
+ },
+
+ sort: function(index, reverse, pre) {
+ if (!this.head) return;
+ pre = !!(pre);
+ var classCellSort = this.options.classCellSort;
+ var classGroup = this.options.classGroup,
+ classGroupHead = this.options.classGroupHead;
+
+ if (!pre) {
+ if (index != null) {
+ if (this.sorted.index == index) {
+ this.sorted.reverse = !(this.sorted.reverse);
+ } else {
+ if (this.sorted.index != null) {
+ this.sorted.reverse = false;
+ this.head.cells[this.sorted.index].removeClass(this.options.classHeadSort).removeClass(this.options.classHeadSortRev);
+ } else {
+ this.sorted.reverse = true;
+ }
+ this.sorted.index = index;
+ }
+ } else {
+ index = this.sorted.index;
+ }
+
+ if (reverse != null) this.sorted.reverse = reverse;
+
+ var head = document.id(this.head.cells[index]);
+ if (head) {
+ head.addClass(this.options.classHeadSort);
+ if (this.sorted.reverse) head.addClass(this.options.classHeadSortRev);
+ else head.removeClass(this.options.classHeadSortRev);
+ }
+
+ this.body.getElements('td').removeClass(this.options.classCellSort);
+ }
+
+ var parser = this.parsers[index];
+ if ($type(parser) == 'string') parser = HtmlTable.Parsers.get(parser);
+ if (!parser) return;
+
+ if (!Browser.Engine.trident) {
+ var rel = this.body.getParent();
+ this.body.dispose();
+ }
+
+ var data = Array.map(this.body.rows, function(row, i) {
+ var value = parser.convert.call(document.id(row.cells[index]));
+
+ return {
+ position: i,
+ value: value,
+ toString: function() {
+ return value.toString();
+ }
+ };
+ }, this);
+ data.reverse(true);
+
+ data.sort(function(a, b){
+ if (a.value === b.value) return 0;
+ return a.value > b.value ? 1 : -1;
+ });
+
+ if (!this.sorted.reverse) data.reverse(true);
+
+ var i = data.length, body = this.body;
+ var j, position, entry, group;
+
+ while (i) {
+ var item = data[--i];
+ position = item.position;
+ var row = body.rows[position];
+ if (row.disabled) continue;
+
+ if (!pre) {
+ if (group === item.value) {
+ row.removeClass(classGroupHead).addClass(classGroup);
+ } else {
+ group = item.value;
+ row.removeClass(classGroup).addClass(classGroupHead);
+ }
+ if (this.zebra) this.zebra(row, i);
+
+ row.cells[index].addClass(classCellSort);
+ }
+
+ body.appendChild(row);
+ for (j = 0; j < i; j++) {
+ if (data[j].position > position) data[j].position--;
+ }
+ };
+ data = null;
+ if (rel) rel.grab(body);
+
+ return this.fireEvent('sort', [body, index]);
+ },
+
+ reSort: function(){
+ if (this.sortEnabled) this.sort.call(this, this.sorted.index, this.sorted.reverse);
+ return this;
+ },
+
+ enableSort: function(){
+ this.element.addClass(this.options.classSortable);
+ this.attachSorts(true);
+ this.detectParsers();
+ this.sortEnabled = true;
+ return this;
+ },
+
+ disableSort: function(){
+ this.element.removeClass(this.options.classSortable);
+ this.attachSorts(false);
+ this.sortSpans.each(function(span) { span.destroy(); });
+ this.sortSpans.empty();
+ this.sortEnabled = false;
+ return this;
+ }
+
+});
+
+HtmlTable.Parsers = new Hash({
+
+ 'date': {
+ match: /^\d{2}[-\/ ]\d{2}[-\/ ]\d{2,4}$/,
+ convert: function() {
+ return Date.parse(this.get('text')).format('db');
+ },
+ type: 'date'
+ },
+ 'input-checked': {
+ match: / type="(radio|checkbox)" /,
+ convert: function() {
+ return this.getElement('input').checked;
+ }
+ },
+ 'input-value': {
+ match: /<input/,
+ convert: function() {
+ return this.getElement('input').value;
+ }
+ },
+ 'number': {
+ match: /^\d+[^\d.,]*$/,
+ convert: function() {
+ return this.get('text').toInt();
+ },
+ number: true
+ },
+ 'numberLax': {
+ match: /^[^\d]+\d+$/,
+ convert: function() {
+ return this.get('text').replace(/[^-?^0-9]/, '').toInt();
+ },
+ number: true
+ },
+ 'float': {
+ match: /^[\d]+\.[\d]+/,
+ convert: function() {
+ return this.get('text').replace(/[^-?^\d.]/, '').toFloat();
+ },
+ number: true
+ },
+ 'floatLax': {
+ match: /^[^\d]+[\d]+\.[\d]+$/,
+ convert: function() {
+ return this.get('text').replace(/[^-?^\d.]/, '');
+ },
+ number: true
+ },
+ 'string': {
+ match: null,
+ convert: function() {
+ return this.get('text');
+ }
+ },
+ 'title': {
+ match: null,
+ convert: function() {
+ return this.title;
+ }
+ }
+
+});
+
+/*
+---
+
+script: Keyboard.js
+
+description: KeyboardEvents used to intercept events on a class for keyboard and format modifiers in a specific order so as to make alt+shift+c the same as shift+alt+c.
+
+license: MIT-style license
+
+authors:
+- Perrin Westrich
+- Aaron Newton
+- Scott Kyle
+
+requires:
+- core:1.2.4/Events
+- core:1.2.4/Options
+- core:1.2.4/Element.Event
+- /Log
+
+provides: [Keyboard]
+
+...
+*/
+
+(function(){
+
+ var Keyboard = this.Keyboard = new Class({
+
+ Extends: Events,
+
+ Implements: [Options, Log],
+
+ options: {
+ /*
+ onActivate: $empty,
+ onDeactivate: $empty,
+ */
+ defaultEventType: 'keydown',
+ active: false,
+ events: {},
+ nonParsedEvents: ['activate', 'deactivate', 'onactivate', 'ondeactivate', 'changed', 'onchanged']
+ },
+
+ initialize: function(options){
+ this.setOptions(options);
+ this.setup();
+ },
+ setup: function(){
+ this.addEvents(this.options.events);
+ //if this is the root manager, nothing manages it
+ if (Keyboard.manager && !this.manager) Keyboard.manager.manage(this);
+ if (this.options.active) this.activate();
+ },
+
+ handle: function(event, type){
+ //Keyboard.stop(event) prevents key propagation
+ if (event.preventKeyboardPropagation) return;
+
+ var bubbles = !!this.manager;
+ if (bubbles && this.activeKB){
+ this.activeKB.handle(event, type);
+ if (event.preventKeyboardPropagation) return;
+ }
+ this.fireEvent(type, event);
+
+ if (!bubbles && this.activeKB) this.activeKB.handle(event, type);
+ },
+
+ addEvent: function(type, fn, internal){
+ return this.parent(Keyboard.parse(type, this.options.defaultEventType, this.options.nonParsedEvents), fn, internal);
+ },
+
+ removeEvent: function(type, fn){
+ return this.parent(Keyboard.parse(type, this.options.defaultEventType, this.options.nonParsedEvents), fn);
+ },
+
+ toggleActive: function(){
+ return this[this.active ? 'deactivate' : 'activate']();
+ },
+
+ activate: function(instance){
+ if (instance) {
+ //if we're stealing focus, store the last keyboard to have it so the relenquish command works
+ if (instance != this.activeKB) this.previous = this.activeKB;
+ //if we're enabling a child, assign it so that events are now passed to it
+ this.activeKB = instance.fireEvent('activate');
+ Keyboard.manager.fireEvent('changed');
+ } else if (this.manager) {
+ //else we're enabling ourselves, we must ask our parent to do it for us
+ this.manager.activate(this);
+ }
+ return this;
+ },
+
+ deactivate: function(instance){
+ if (instance) {
+ if(instance === this.activeKB) {
+ this.activeKB = null;
+ instance.fireEvent('deactivate');
+ Keyboard.manager.fireEvent('changed');
+ }
+ }
+ else if (this.manager) {
+ this.manager.deactivate(this);
+ }
+ return this;
+ },
+
+ relenquish: function(){
+ if (this.previous) this.activate(this.previous);
+ },
+
+ //management logic
+ manage: function(instance){
+ if (instance.manager) instance.manager.drop(instance);
+ this.instances.push(instance);
+ instance.manager = this;
+ if (!this.activeKB) this.activate(instance);
+ else this._disable(instance);
+ },
+
+ _disable: function(instance){
+ if (this.activeKB == instance) this.activeKB = null;
+ },
+
+ drop: function(instance){
+ this._disable(instance);
+ this.instances.erase(instance);
+ },
+
+ instances: [],
+
+ trace: function(){
+ Keyboard.trace(this);
+ },
+
+ each: function(fn){
+ Keyboard.each(this, fn);
+ }
+
+ });
+
+ var parsed = {};
+ var modifiers = ['shift', 'control', 'alt', 'meta'];
+ var regex = /^(?:shift|control|ctrl|alt|meta)$/;
+
+ Keyboard.parse = function(type, eventType, ignore){
+ if (ignore && ignore.contains(type.toLowerCase())) return type;
+
+ type = type.toLowerCase().replace(/^(keyup|keydown):/, function($0, $1){
+ eventType = $1;
+ return '';
+ });
+
+ if (!parsed[type]){
+ var key, mods = {};
+ type.split('+').each(function(part){
+ if (regex.test(part)) mods[part] = true;
+ else key = part;
+ });
+
+ mods.control = mods.control || mods.ctrl; // allow both control and ctrl
+
+ var keys = [];
+ modifiers.each(function(mod){
+ if (mods[mod]) keys.push(mod);
+ });
+
+ if (key) keys.push(key);
+ parsed[type] = keys.join('+');
+ }
+
+ return eventType + ':' + parsed[type];
+ };
+
+ Keyboard.each = function(keyboard, fn){
+ var current = keyboard || Keyboard.manager;
+ while (current){
+ fn.run(current);
+ current = current.activeKB;
+ }
+ };
+
+ Keyboard.stop = function(event){
+ event.preventKeyboardPropagation = true;
+ };
+
+ Keyboard.manager = new Keyboard({
+ active: true
+ });
+
+ Keyboard.trace = function(keyboard){
+ keyboard = keyboard || Keyboard.manager;
+ keyboard.enableLog();
+ keyboard.log('the following items have focus: ');
+ Keyboard.each(keyboard, function(current){
+ keyboard.log(document.id(current.widget) || current.wiget || current);
+ });
+ };
+
+ var handler = function(event){
+ var keys = [];
+ modifiers.each(function(mod){
+ if (event[mod]) keys.push(mod);
+ });
+
+ if (!regex.test(event.key)) keys.push(event.key);
+ Keyboard.manager.handle(event, event.type + ':' + keys.join('+'));
+ };
+
+ document.addEvents({
+ 'keyup': handler,
+ 'keydown': handler
+ });
+
+ Event.Keys.extend({
+ 'shift': 16,
+ 'control': 17,
+ 'alt': 18,
+ 'capslock': 20,
+ 'pageup': 33,
+ 'pagedown': 34,
+ 'end': 35,
+ 'home': 36,
+ 'numlock': 144,
+ 'scrolllock': 145,
+ ';': 186,
+ '=': 187,
+ ',': 188,
+ '-': Browser.Engine.Gecko ? 109 : 189,
+ '.': 190,
+ '/': 191,
+ '`': 192,
+ '[': 219,
+ '\\': 220,
+ ']': 221,
+ "'": 222
+ });
+
+})();
+/*
+---
+
+script: HtmlTable.Select.js
+
+description: Builds a stripy, sortable table with methods to add rows. Rows can be selected with the mouse or keyboard navigation.
+
+license: MIT-style license
+
+authors:
+- Harald Kirschner
+- Aaron Newton
+
+requires:
+- /Keyboard
+- /HtmlTable
+- /Class.refactor
+- /Element.Delegation
+
+provides: [HtmlTable.Select]
+
+...
+*/
+
+HtmlTable = Class.refactor(HtmlTable, {
+
+ options: {
+ /*onRowFocus: $empty,
+ onRowUnfocus: $empty,*/
+ useKeyboard: true,
+ classRowSelected: 'table-tr-selected',
+ classRowHovered: 'table-tr-hovered',
+ classSelectable: 'table-selectable',
+ allowMultiSelect: true,
+ selectable: false
+ },
+
+ initialize: function(){
+ this.previous.apply(this, arguments);
+ if (this.occluded) return this.occluded;
+ this.selectedRows = new Elements();
+ this.bound = {
+ mouseleave: this.mouseleave.bind(this),
+ focusRow: this.focusRow.bind(this)
+ };
+ if (this.options.selectable) this.enableSelect();
+ },
+
+ enableSelect: function(){
+ this.selectEnabled = true;
+ this.attachSelects();
+ this.element.addClass(this.options.classSelectable);
+ },
+
+ disableSelect: function(){
+ this.selectEnabled = false;
+ this.attach(false);
+ this.element.removeClass(this.options.classSelectable);
+ },
+
+ attachSelects: function(attach){
+ attach = $pick(attach, true);
+ var method = attach ? 'addEvents' : 'removeEvents';
+ this.element[method]({
+ mouseleave: this.bound.mouseleave
+ });
+ this.body[method]({
+ 'click:relay(tr)': this.bound.focusRow
+ });
+ if (this.options.useKeyboard || this.keyboard){
+ if (!this.keyboard) this.keyboard = new Keyboard({
+ events: {
+ down: function(e) {
+ e.preventDefault();
+ this.shiftFocus(1);
+ }.bind(this),
+ up: function(e) {
+ e.preventDefault();
+ this.shiftFocus(-1);
+ }.bind(this),
+ enter: function(e) {
+ e.preventDefault();
+ if (this.hover) this.focusRow(this.hover);
+ }.bind(this)
+ },
+ active: true
+ });
+ this.keyboard[attach ? 'activate' : 'deactivate']();
+ }
+ this.updateSelects();
+ },
+
+ mouseleave: function(){
+ if (this.hover) this.leaveRow(this.hover);
+ },
+
+ focus: function(){
+ if (this.keyboard) this.keyboard.activate();
+ },
+
+ blur: function(){
+ if (this.keyboard) this.keyboard.deactivate();
+ },
+
+ push: function(){
+ var ret = this.previous.apply(this, arguments);
+ this.updateSelects();
+ return ret;
+ },
+
+ updateSelects: function(){
+ Array.each(this.body.rows, function(row){
+ var binders = row.retrieve('binders');
+ if ((binders && this.selectEnabled) || (!binders && !this.selectEnabled)) return;
+ if (!binders){
+ binders = {
+ mouseenter: this.enterRow.bind(this, [row]),
+ mouseleave: this.leaveRow.bind(this, [row])
+ };
+ row.store('binders', binders).addEvents(binders);
+ } else {
+ row.removeEvents(binders);
+ }
+ }, this);
+ },
+
+ enterRow: function(row){
+ if (this.hover) this.hover = this.leaveRow(this.hover);
+ this.hover = row.addClass(this.options.classRowHovered);
+ },
+
+ shiftFocus: function(offset){
+ if (!this.hover) return this.enterRow(this.body.rows[0]);
+ var to = Array.indexOf(this.body.rows, this.hover) + offset;
+ if (to < 0) to = 0;
+ if (to >= this.body.rows.length) to = this.body.rows.length - 1;
+ if (this.hover == this.body.rows[to]) return this;
+ this.enterRow(this.body.rows[to]);
+ },
+
+ leaveRow: function(row){
+ row.removeClass(this.options.classRowHovered);
+ },
+
+ focusRow: function(){
+ var row = arguments[1] || arguments[0]; //delegation passes the event first
+ if (!this.body.getChildren().contains(row)) return;
+ var unfocus = function(row){
+ this.selectedRows.erase(row);
+ row.removeClass(this.options.classRowSelected);
+ this.fireEvent('rowUnfocus', [row, this.selectedRows]);
+ }.bind(this);
+ if (!this.options.allowMultiSelect) this.selectedRows.each(unfocus);
+ if (!this.selectedRows.contains(row)) {
+ this.selectedRows.push(row);
+ row.addClass(this.options.classRowSelected);
+ this.fireEvent('rowFocus', [row, this.selectedRows]);
+ } else {
+ unfocus(row);
+ }
+ return false;
+ },
+
+ selectAll: function(status){
+ status = $pick(status, true);
+ if (!this.options.allowMultiSelect && status) return;
+ if (!status) this.selectedRows.removeClass(this.options.classRowSelected).empty();
+ else this.selectedRows.combine(this.body.rows).addClass(this.options.classRowSelected);
+ return this;
+ },
+
+ selectNone: function(){
+ return this.selectAll(false);
+ }
+
+});
+/*
+---
+
+script: Keyboard.js
+
+description: Enhances Keyboard by adding the ability to name and describe keyboard shortcuts, and the ability to grab shortcuts by name and bind the shortcut to different keys.
+
+license: MIT-style license
+
+authors:
+- Perrin Westrich
+
+requires:
+- core:1.2.4/Function
+- /Keyboard.Extras
+
+provides: [Keyboard.Extras]
+
+...
+*/
+Keyboard.prototype.options.nonParsedEvents.combine(['rebound', 'onrebound']);
+
+Keyboard.implement({
+
+ /*
+ shortcut should be in the format of:
+ {
+ 'keys': 'shift+s', // the default to add as an event.
+ 'description': 'blah blah blah', // a brief description of the functionality.
+ 'handler': function(){} // the event handler to run when keys are pressed.
+ }
+ */
+ addShortcut: function(name, shortcut) {
+ this.shortcuts = this.shortcuts || [];
+ this.shortcutIndex = this.shortcutIndex || {};
+
+ shortcut.getKeyboard = $lambda(this);
+ shortcut.name = name;
+ this.shortcutIndex[name] = shortcut;
+ this.shortcuts.push(shortcut);
+ if(shortcut.keys) this.addEvent(shortcut.keys, shortcut.handler);
+ return this;
+ },
+
+ addShortcuts: function(obj){
+ for(var name in obj) this.addShortcut(name, obj[name]);
+ return this;
+ },
+
+ getShortcuts: function(){
+ return this.shortcuts || [];
+ },
+
+ getShortcut: function(name){
+ return (this.shortcutIndex || {})[name];
+ }
+
+});
+
+Keyboard.rebind = function(newKeys, shortcuts){
+ $splat(shortcuts).each(function(shortcut){
+ shortcut.getKeyboard().removeEvent(shortcut.keys, shortcut.handler);
+ shortcut.getKeyboard().addEvent(newKeys, shortcut.handler);
+ shortcut.keys = newKeys;
+ shortcut.getKeyboard().fireEvent('rebound');
+ });
+};
+
+
+Keyboard.getActiveShortcuts = function(keyboard) {
+ var activeKBS = [], activeSCS = [];
+ Keyboard.each(keyboard, [].push.bind(activeKBS));
+ activeKBS.each(function(kb){ activeSCS.extend(kb.getShortcuts()); });
+ return activeSCS;
+};
+
+Keyboard.getShortcut = function(name, keyboard, opts){
+ opts = opts || {};
+ var shortcuts = opts.many ? [] : null,
+ set = opts.many ? function(kb){
+ var shortcut = kb.getShortcut(name);
+ if(shortcut) shortcuts.push(shortcut);
+ } : function(kb) {
+ if(!shortcuts) shortcuts = kb.getShortcut(name);
+ };
+ Keyboard.each(keyboard, set);
+ return shortcuts;
+};
+
+Keyboard.getShortcuts = function(name, keyboard) {
+ return Keyboard.getShortcut(name, keyboard, { many: true });
+};
+/*
+---
+
+script: Scroller.js
+
+description: Class which scrolls the contents of any Element (including the window) when the mouse reaches the Element's boundaries.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+
+requires:
+- core:1.2.4/Events
+- core:1.2.4/Options
+- core:1.2.4/Element.Event
+- core:1.2.4/Element.Dimensions
+
+provides: [Scroller]
+
+...
+*/
+
+var Scroller = new Class({
+
+ Implements: [Events, Options],
+
+ options: {
+ area: 20,
+ velocity: 1,
+ onChange: function(x, y){
+ this.element.scrollTo(x, y);
+ },
+ fps: 50
+ },
+
+ initialize: function(element, options){
+ this.setOptions(options);
+ this.element = document.id(element);
+ this.docBody = document.id(this.element.getDocument().body);
+ this.listener = ($type(this.element) != 'element') ? this.docBody : this.element;
+ this.timer = null;
+ this.bound = {
+ attach: this.attach.bind(this),
+ detach: this.detach.bind(this),
+ getCoords: this.getCoords.bind(this)
+ };
+ },
+
+ start: function(){
+ this.listener.addEvents({
+ mouseover: this.bound.attach,
+ mouseout: this.bound.detach
+ });
+ },
+
+ stop: function(){
+ this.listener.removeEvents({
+ mouseover: this.bound.attach,
+ mouseout: this.bound.detach
+ });
+ this.detach();
+ this.timer = $clear(this.timer);
+ },
+
+ attach: function(){
+ this.listener.addEvent('mousemove', this.bound.getCoords);
+ },
+
+ detach: function(){
+ this.listener.removeEvent('mousemove', this.bound.getCoords);
+ 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(Math.round(1000 / this.options.fps), this);
+ },
+
+ scroll: function(){
+ var size = this.element.getSize(),
+ scroll = this.element.getScroll(),
+ pos = this.element != this.docBody ? this.element.getOffsets() : {x: 0, y:0},
+ scrollSize = this.element.getScrollSize(),
+ 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]) && scroll[z] + size[z] != scrollSize[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: Tips.js
+
+description: Class for creating nice tips that follow the mouse cursor when hovering an element.
+
+license: MIT-style license
+
+authors:
+- Valerio Proietti
+- Christoph Pojer
+
+requires:
+- core:1.2.4/Options
+- core:1.2.4/Events
+- core:1.2.4/Element.Event
+- core:1.2.4/Element.Style
+- core:1.2.4/Element.Dimensions
+- /MooTools.More
+
+provides: [Tips]
+
+...
+*/
+
+(function(){
+
+var read = function(option, element){
+ return (option) ? ($type(option) == 'function' ? option(element) : element.get(option)) : '';
+};
+
+this.Tips = new Class({
+
+ Implements: [Events, Options],
+
+ options: {
+ /*
+ onAttach: $empty(element),
+ onDetach: $empty(element),
+ */
+ onShow: function(){
+ this.tip.setStyle('display', 'block');
+ },
+ onHide: function(){
+ this.tip.setStyle('display', 'none');
+ },
+ title: 'title',
+ text: function(element){
+ return element.get('rel') || element.get('href');
+ },
+ showDelay: 100,
+ hideDelay: 100,
+ className: 'tip-wrap',
+ offset: {x: 16, y: 16},
+ windowPadding: {x:0, y:0},
+ fixed: false
+ },
+
+ initialize: function(){
+ var params = Array.link(arguments, {options: Object.type, elements: $defined});
+ this.setOptions(params.options);
+ if (params.elements) this.attach(params.elements);
+ this.container = new Element('div', {'class': 'tip'});
+ },
+
+ toElement: function(){
+ if (this.tip) return this.tip;
+
+ return this.tip = new Element('div', {
+ 'class': this.options.className,
+ styles: {
+ position: 'absolute',
+ top: 0,
+ left: 0
+ }
+ }).adopt(
+ new Element('div', {'class': 'tip-top'}),
+ this.container,
+ new Element('div', {'class': 'tip-bottom'})
+ ).inject(document.body);
+ },
+
+ attach: function(elements){
+ $$(elements).each(function(element){
+ var title = read(this.options.title, element),
+ text = read(this.options.text, element);
+
+ element.erase('title').store('tip:native', title).retrieve('tip:title', title);
+ element.retrieve('tip:text', text);
+ this.fireEvent('attach', [element]);
+
+ var events = ['enter', 'leave'];
+ if (!this.options.fixed) events.push('move');
+
+ events.each(function(value){
+ var event = element.retrieve('tip:' + value);
+ if (!event) event = this['element' + value.capitalize()].bindWithEvent(this, element);
+
+ element.store('tip:' + value, event).addEvent('mouse' + value, event);
+ }, this);
+ }, this);
+
+ return this;
+ },
+
+ detach: function(elements){
+ $$(elements).each(function(element){
+ ['enter', 'leave', 'move'].each(function(value){
+ element.removeEvent('mouse' + value, element.retrieve('tip:' + value)).eliminate('tip:' + value);
+ });
+
+ this.fireEvent('detach', [element]);
+
+ if (this.options.title == 'title'){ // This is necessary to check if we can revert the title
+ var original = element.retrieve('tip:native');
+ if (original) element.set('title', original);
+ }
+ }, this);
+
+ return this;
+ },
+
+ elementEnter: function(event, element){
+ this.container.empty();
+
+ ['title', 'text'].each(function(value){
+ var content = element.retrieve('tip:' + value);
+ if (content) this.fill(new Element('div', {'class': 'tip-' + value}).inject(this.container), content);
+ }, this);
+
+ $clear(this.timer);
+ this.timer = (function(){
+ this.show(this, element);
+ this.position((this.options.fixed) ? {page: element.getPosition()} : event);
+ }).delay(this.options.showDelay, this);
+ },
+
+ elementLeave: function(event, element){
+ $clear(this.timer);
+ this.timer = this.hide.delay(this.options.hideDelay, this, element);
+ this.fireForParent(event, element);
+ },
+
+ fireForParent: function(event, element){
+ element = element.getParent();
+ if (!element || element == document.body) return;
+ if (element.retrieve('tip:enter')) element.fireEvent('mouseenter', event);
+ else this.fireForParent(event, element);
+ },
+
+ elementMove: function(event, element){
+ this.position(event);
+ },
+
+ position: function(event){
+ if (!this.tip) document.id(this);
+
+ var size = window.getSize(), scroll = window.getScroll(),
+ tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight},
+ props = {x: 'left', y: 'top'},
+ obj = {};
+
+ for (var z in props){
+ obj[props[z]] = event.page[z] + this.options.offset[z];
+ if ((obj[props[z]] + tip[z] - scroll[z]) > size[z] - this.options.windowPadding[z]) obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
+ }
+
+ this.tip.setStyles(obj);
+ },
+
+ fill: function(element, contents){
+ if(typeof contents == 'string') element.set('html', contents);
+ else element.adopt(contents);
+ },
+
+ show: function(element){
+ if (!this.tip) document.id(this);
+ this.fireEvent('show', [this.tip, element]);
+ },
+
+ hide: function(element){
+ if (!this.tip) document.id(this);
+ this.fireEvent('hide', [this.tip, element]);
+ }
+
+});
+
+})();/*
+---
+
+script: Date.Catalan.js
+
+description: Date messages for Catalan.
+
+license: MIT-style license
+
+authors:
+- Alfons Sanchez
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Catalan]
+
+...
+*/
+
+MooTools.lang.set('ca-CA', 'Date', {
+
+ months: ['Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juli', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre'],
+ days: ['Diumenge', 'Dilluns', 'Dimarts', 'Dimecres', 'Dijous', 'Divendres', 'Dissabte'],
+ //culture's date order: MM/DD/YYYY
+ dateOrder: ['date', 'month', 'year'],
+
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H:%M',
+
+ AM: 'AM',
+ PM: 'PM',
+
+ /* Date.Extras */
+ ordinal: '',
+
+ lessThanMinuteAgo: 'fa menys d`un minut',
+ minuteAgo: 'fa un minut',
+ minutesAgo: 'fa {delta} minuts',
+ hourAgo: 'fa un hora',
+ hoursAgo: 'fa unes {delta} hores',
+ dayAgo: 'fa un dia',
+ daysAgo: 'fa {delta} dies',
+ lessThanMinuteUntil: 'menys d`un minut des d`ara',
+ minuteUntil: 'un minut des d`ara',
+ minutesUntil: '{delta} minuts des d`ara',
+ hourUntil: 'un hora des d`ara',
+ hoursUntil: 'unes {delta} hores des d`ara',
+ dayUntil: '1 dia des d`ara',
+ daysUntil: '{delta} dies des d`ara'
+
+});/*
+---
+
+script: Date.Czech.js
+
+description: Date messages for Czech.
+
+license: MIT-style license
+
+authors:
+- Jan Äerný chemiX
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Czech]
+
+...
+*/
+
+MooTools.lang.set('cs-CZ', 'Date', {
+
+ months: ['Leden', 'Ãnor', 'BÅezen', 'Duben', 'KvÄten', 'Äerven', 'Äervenec', 'Srpen', 'ZáÅÃ', 'ÅÃjen', 'Listopad', 'Prosinec'],
+ days: ['NedÄle', 'PondÄlÃ', 'Ãterý', 'StÅeda', 'Ätvrtek', 'Pátek', 'Sobota'],
+ //culture's date order: MM/DD/YYYY
+ dateOrder: ['date', 'month', 'year'],
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H:%M',
+ AM: 'dop.',
+ PM: 'odp.',
+
+ /* Date.Extras */
+ ordinal: function(dayOfMonth){
+ return '.';
+ },
+
+ // TODO : in examples use and fix it
+ lessThanMinuteAgo: 'ménÄ než minutou',
+ minuteAgo: 'pÅibližnÄ pÅed minutou',
+ minutesAgo: 'pÅed {delta} minutami',
+ hourAgo: 'pÅibližnÄ pÅed hodinou',
+ hoursAgo: 'pÅed {delta} hodinami',
+ dayAgo: 'pÅed dnem',
+ daysAgo: 'pÅed {delta} dni',
+ lessThanMinuteUntil: 'pÅed ménÄ než minutou',
+ minuteUntil: 'asi pÅed minutou',
+ minutesUntil: ' asi pÅed {delta} minutami',
+ hourUntil: 'asi pÅed hodinou',
+ hoursUntil: 'pÅed {delta} hodinami',
+ dayUntil: 'pÅed dnem',
+ daysUntil: 'pÅed {delta} dni',
+ weekUntil: 'pÅed týdnem',
+ weeksUntil: 'pÅed {delta} týdny',
+ monthUntil: 'pÅed mÄsÃcem',
+ monthsUntil: 'pÅed {delta} mÄsÃci',
+ yearUntil: 'pÅed rokem',
+ yearsUntil: 'pÅed {delta} lety'
+
+});
+/*
+---
+
+script: Date.Danish.js
+
+description: Date messages for Danish.
+
+license: MIT-style license
+
+authors:
+- Martin Overgaard
+- Henrik Hansen
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Danish]
+
+...
+*/
+
+MooTools.lang.set('da-DK', 'Date', {
+
+ months: ['Januar', 'Februa', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December'],
+ days: ['Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'],
+ //culture's date order: DD/MM/YYYY
+ dateOrder: ['date', 'month', 'year'],
+
+ AM: 'AM',
+ PM: 'PM',
+
+ shortDate: '%d-%m-%Y',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ ordinal: function(dayOfMonth){
+ //1st, 2nd, 3rd, etc.
+ return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)];
+ },
+
+ lessThanMinuteAgo: 'mindre end et minut siden',
+ minuteAgo: 'omkring et minut siden',
+ minutesAgo: '{delta} minutter siden',
+ hourAgo: 'omkring en time siden',
+ hoursAgo: 'omkring {delta} timer siden',
+ dayAgo: '1 dag siden',
+ daysAgo: '{delta} dage siden',
+ weekAgo: '1 uge siden',
+ weeksAgo: '{delta} uger siden',
+ monthAgo: '1 måned siden',
+ monthsAgo: '{delta} måneder siden',
+ yearthAgo: '1 år siden',
+ yearsAgo: '{delta} år siden',
+ lessThanMinuteUntil: 'mindre end et minut fra nu',
+ minuteUntil: 'omkring et minut fra nu',
+ minutesUntil: '{delta} minutter fra nu',
+ hourUntil: 'omkring en time fra nu',
+ hoursUntil: 'omkring {delta} timer fra nu',
+ dayUntil: '1 dag fra nu',
+ daysUntil: '{delta} dage fra nu',
+ weekUntil: '1 uge fra nu',
+ weeksUntil: '{delta} uger fra nu',
+ monthUntil: '1 måned fra nu',
+ monthsUntil: '{delta} måneder fra nu',
+ yearUntil: '1 år fra nu',
+ yearsUntil: '{delta} år fra nu'
+
+});
+/*
+---
+
+script: Date.Dutch.js
+
+description: Date messages in Dutch.
+
+license: MIT-style license
+
+authors:
+- Lennart Pilon
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Dutch]
+
+...
+*/
+
+MooTools.lang.set('nl-NL', 'Date', {
+
+ months: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
+ days: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag'],
+ //culture's date order: DD/MM/YYYY
+ dateOrder: ['date', 'month', 'year'],
+
+ AM: 'AM',
+ PM: 'PM',
+
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ ordinal: 'e',
+
+ lessThanMinuteAgo: 'minder dan een minuut geleden',
+ minuteAgo: 'ongeveer een minuut geleden',
+ minutesAgo: 'minuten geleden',
+ hourAgo: 'ongeveer een uur geleden',
+ hoursAgo: 'ongeveer {delta} uur geleden',
+ dayAgo: '{delta} dag geleden',
+ daysAgo: 'dagen geleden',
+ weekAgo: 'een week geleden',
+ weeksAgo: '{delta} weken geleden',
+ monthAgo: 'een maand geleden',
+ monthsAgo: '{delta} maanden geleden',
+ yearAgo: 'een jaar geleden',
+ yearsAgo: '{delta} jaar geleden',
+ lessThanMinuteUntil: 'minder dan een minuut vanaf nu',
+ minuteUntil: 'ongeveer een minuut vanaf nu',
+ minutesUntil: '{delta} minuten vanaf nu',
+ hourUntil: 'ongeveer een uur vanaf nu',
+ hoursUntil: 'ongeveer {delta} uur vanaf nu',
+ dayUntil: '1 dag vanaf nu',
+ daysUntil: '{delta} dagen vanaf nu',
+ weekAgo: 'een week geleden',
+ weeksAgo: '{delta} weken geleden',
+ monthAgo: 'een maand geleden',
+ monthsAgo: '{delta} maanden geleden',
+ yearthAgo: 'een jaar geleden',
+ yearsAgo: '{delta} jaar geleden',
+
+ weekUntil: 'over een week',
+ weeksUntil: 'over {delta} weken',
+ monthUntil: 'over een maand',
+ monthsUntil: 'over {delta} maanden',
+ yearUntil: 'over een jaar',
+ yearsUntil: 'over {delta} jaar'
+
+});/*
+---
+
+script: Date.English.GB.js
+
+description: Date messages for British English.
+
+license: MIT-style license
+
+authors:
+- Aaron Newton
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.English.GB]
+
+...
+*/
+
+MooTools.lang.set('en-GB', 'Date', {
+
+ dateOrder: ['date', 'month', 'year'],
+
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H:%M'
+
+}).set('cascade', ['en-US']);/*
+---
+
+script: Date.Estonian.js
+
+description: Date messages for Estonian.
+
+license: MIT-style license
+
+authors:
+- Kevin Valdek
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Estonian]
+
+...
+*/
+
+MooTools.lang.set('et-EE', 'Date', {
+
+ months: ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli', 'august', 'september', 'oktoober', 'november', 'detsember'],
+ days: ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev', 'neljapäev', 'reede', 'laupäev'],
+ //culture's date order: MM.DD.YYYY
+ dateOrder: ['month', 'date', 'year'],
+
+ AM: 'AM',
+ PM: 'PM',
+
+ shortDate: '%m.%d.%Y',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ ordinal: '',
+
+ lessThanMinuteAgo: 'vähem kui minut aega tagasi',
+ minuteAgo: 'umbes minut aega tagasi',
+ minutesAgo: '{delta} minutit tagasi',
+ hourAgo: 'umbes tund aega tagasi',
+ hoursAgo: 'umbes {delta} tundi tagasi',
+ dayAgo: '1 päev tagasi',
+ daysAgo: '{delta} päeva tagasi',
+ weekAgo: '1 nädal tagasi',
+ weeksAgo: '{delta} nädalat tagasi',
+ monthAgo: '1 kuu tagasi',
+ monthsAgo: '{delta} kuud tagasi',
+ yearAgo: '1 aasta tagasi',
+ yearsAgo: '{delta} aastat tagasi',
+ lessThanMinuteUntil: 'vähem kui minuti aja pärast',
+ minuteUntil: 'umbes minuti aja pärast',
+ minutesUntil: '{delta} minuti pärast',
+ hourUntil: 'umbes tunni aja pärast',
+ hoursUntil: 'umbes {delta} tunni pärast',
+ dayUntil: '1 päeva pärast',
+ daysUntil: '{delta} päeva pärast',
+ weekUntil: '1 nädala pärast',
+ weeksUntil: '{delta} nädala pärast',
+ monthUntil: '1 kuu pärast',
+ monthsUntil: '{delta} kuu pärast',
+ yearUntil: '1 aasta pärast',
+ yearsUntil: '{delta} aasta pärast'
+
+});/*
+---
+
+script: Date.German.js
+
+description: Date messages for German.
+
+license: MIT-style license
+
+authors:
+- Christoph Pojer
+- Frank Rossi
+- Ulrich Petri
+- Fabian Beiner
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.German]
+
+...
+*/
+
+MooTools.lang.set('de-DE', 'Date', {
+
+ months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
+ days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
+ //culture's date order: MM/DD/YYYY
+ dateOrder: [ 'date', 'month', 'year', '.'],
+
+ AM: 'vormittags',
+ PM: 'nachmittags',
+
+ shortDate: '%d.%m.%Y',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ ordinal: '.',
+
+ lessThanMinuteAgo: 'Vor weniger als einer Minute',
+ minuteAgo: 'Vor einer Minute',
+ minutesAgo: 'Vor {delta} Minuten',
+ hourAgo: 'Vor einer Stunde',
+ hoursAgo: 'Vor {delta} Stunden',
+ dayAgo: 'Vor einem Tag',
+ daysAgo: 'Vor {delta} Tagen',
+ weekAgo: 'Vor einer Woche',
+ weeksAgo: 'Vor {delta} Wochen',
+ monthAgo: 'Vor einem Monat',
+ monthsAgo: 'Vor {delta} Monaten',
+ yearAgo: 'Vor einem Jahr',
+ yearsAgo: 'Vor {delta} Jahren',
+ lessThanMinuteUntil: 'In weniger als einer Minute',
+ minuteUntil: 'In einer Minute',
+ minutesUntil: 'In {delta} Minuten',
+ hourUntil: 'In ca. einer Stunde',
+ hoursUntil: 'In ca. {delta} Stunden',
+ dayUntil: 'In einem Tag',
+ daysUntil: 'In {delta} Tagen',
+ weekUntil: 'In einer Woche',
+ weeksUntil: 'In {delta} Wochen',
+ monthUntil: 'In einem Monat',
+ monthsUntil: 'In {delta} Monaten',
+ yearUntil: 'In einem Jahr',
+ yearsUntil: 'In {delta} Jahren'
+});/*
+---
+
+script: Date.German.CH.js
+
+description: Date messages for German (Switzerland).
+
+license: MIT-style license
+
+authors:
+- Michael van der Weg
+
+requires:
+- /Lang
+- /Date.German
+
+provides: [Date.German.CH]
+
+...
+*/
+
+MooTools.lang.set('de-CH', 'cascade', ['de-DE']);/*
+---
+
+script: Date.French.js
+
+description: Date messages in French.
+
+license: MIT-style license
+
+authors:
+- Nicolas Sorosac
+- Antoine Abt
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.French]
+
+...
+*/
+
+MooTools.lang.set('fr-FR', 'Date', {
+
+ months: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
+ days: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
+ dateOrder: ['date', 'month', 'year'],
+
+ AM: 'AM',
+ PM: 'PM',
+
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ getOrdinal: function(dayOfMonth){
+ return (dayOfMonth > 1) ? '' : 'er';
+ },
+
+ lessThanMinuteAgo: 'il y a moins d\'une minute',
+ minuteAgo: 'il y a une minute',
+ minutesAgo: 'il y a {delta} minutes',
+ hourAgo: 'il y a une heure',
+ hoursAgo: 'il y a {delta} heures',
+ dayAgo: 'il y a un jour',
+ daysAgo: 'il y a {delta} jours',
+ weekAgo: 'il y a une semaine',
+ weeksAgo: 'il y a {delta} semaines',
+ monthAgo: 'il y a 1 mois',
+ monthsAgo: 'il y a {delta} mois',
+ yearthAgo: 'il y a 1 an',
+ yearsAgo: 'il y a {delta} ans',
+ lessThanMinuteUntil: 'dans moins d\'une minute',
+ minuteUntil: 'dans une minute',
+ minutesUntil: 'dans {delta} minutes',
+ hourUntil: 'dans une heure',
+ hoursUntil: 'dans {delta} heures',
+ dayUntil: 'dans un jour',
+ daysUntil: 'dans {delta} jours',
+ weekUntil: 'dans 1 semaine',
+ weeksUntil: 'dans {delta} semaines',
+ monthUntil: 'dans 1 mois',
+ monthsUntil: 'dans {delta} mois',
+ yearUntil: 'dans 1 an',
+ yearsUntil: 'dans {delta} ans'
+
+});
+/*
+---
+
+script: Date.Italian.js
+
+description: Date messages for Italian.
+
+license: MIT-style license.
+
+authors:
+- Andrea Novero
+- Valerio Proietti
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Italian]
+
+...
+*/
+
+MooTools.lang.set('it-IT', 'Date', {
+
+ months: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'],
+ days: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'],
+ //culture's date order: DD/MM/YYYY
+ dateOrder: ['date', 'month', 'year'],
+
+ AM: 'AM',
+ PM: 'PM',
+
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H.%M',
+
+ /* Date.Extras */
+ ordinal: 'º',
+
+ lessThanMinuteAgo: 'meno di un minuto fa',
+ minuteAgo: 'circa un minuto fa',
+ minutesAgo: 'circa {delta} minuti fa',
+ hourAgo: 'circa un\'ora fa',
+ hoursAgo: 'circa {delta} ore fa',
+ dayAgo: 'circa 1 giorno fa',
+ daysAgo: 'circa {delta} giorni fa',
+ lessThanMinuteUntil: 'tra meno di un minuto',
+ minuteUntil: 'tra circa un minuto',
+ minutesUntil: 'tra circa {delta} minuti',
+ hourUntil: 'tra circa un\'ora',
+ hoursUntil: 'tra circa {delta} ore',
+ dayUntil: 'tra circa un giorno',
+ daysUntil: 'tra circa {delta} giorni'
+
+});/*
+---
+
+script: Date.Norwegian.js
+
+description: Date messages in Norwegian.
+
+license: MIT-style license
+
+authors:
+- Espen 'Rexxars' Hovlandsdal
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Norwegian]
+
+...
+*/
+
+MooTools.lang.set('no-NO', 'Date', {
+
+ dateOrder: ['date', 'month', 'year'],
+
+ shortDate: '%d.%m.%Y',
+ shortTime: '%H:%M',
+
+ lessThanMinuteAgo: 'kortere enn et minutt siden',
+ minuteAgo: 'omtrent et minutt siden',
+ minutesAgo: '{delta} minutter siden',
+ hourAgo: 'omtrent en time siden',
+ hoursAgo: 'omtrent {delta} timer siden',
+ dayAgo: '{delta} dag siden',
+ daysAgo: '{delta} dager siden'
+
+});/*
+---
+
+script: Date.Polish.js
+
+description: Date messages for Polish.
+
+license: MIT-style license
+
+authors:
+- Oskar Krawczyk
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Polish]
+
+...
+*/
+
+MooTools.lang.set('pl-PL', 'Date', {
+ months: ['StyczeÅ', 'Luty', 'Marzec', 'KwiecieÅ', 'Maj', 'Czerwiec', 'Lipiec', 'SierpieÅ', 'WrzesieÅ', 'Październik', 'Listopad', 'GrudzieÅ'],
+ days: ['Niedziela', 'PoniedziaÅek', 'Wtorek', 'Åroda', 'Czwartek', 'PiÄ
tek', 'Sobota'],
+ dateOrder: ['year', 'month', 'date'],
+ AM: 'nad ranem',
+ PM: 'po poÅudniu',
+
+ shortDate: '%Y-%m-%d',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ ordinal: function(dayOfMonth){
+ return (dayOfMonth > 3 && dayOfMonth < 21) ? 'ty' : ['ty', 'szy', 'gi', 'ci', 'ty'][Math.min(dayOfMonth % 10, 4)];
+ },
+
+ lessThanMinuteAgo: 'mniej niż minute temu',
+ minuteAgo: 'okoÅo minutÄ temu',
+ minutesAgo: '{delta} minut temu',
+ hourAgo: 'okoÅo godzinÄ temu',
+ hoursAgo: 'okoÅo {delta} godzin temu',
+ dayAgo: 'Wczoraj',
+ daysAgo: '{delta} dni temu',
+ lessThanMinuteUntil: 'za niecaÅÄ
minutÄ',
+ minuteUntil: 'za okoÅo minutÄ',
+ minutesUntil: 'za {delta} minut',
+ hourUntil: 'za okoÅo godzinÄ',
+ hoursUntil: 'za okoÅo {delta} godzin',
+ dayUntil: 'za 1 dzieÅ',
+ daysUntil: 'za {delta} dni'
+});/*
+---
+
+script: Date.Portuguese.BR.js
+
+description: Date messages in Portuguese-BR (Brazil).
+
+license: MIT-style license
+
+authors:
+- Fabio Miranda Costa
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Portuguese.BR]
+
+...
+*/
+
+MooTools.lang.set('pt-BR', 'Date', {
+
+ months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
+ days: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'],
+ //culture's date order: DD/MM/YYYY
+ dateOrder: ['date', 'month', 'year'],
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ ordinal: function(dayOfMonth){
+ //1º, 2º, 3º, etc.
+ return 'º';
+ },
+
+ lessThanMinuteAgo: 'há menos de um minuto',
+ minuteAgo: 'há cerca de um minuto',
+ minutesAgo: 'há {delta} minutos',
+ hourAgo: 'há cerca de uma hora',
+ hoursAgo: 'há cerca de {delta} horas',
+ dayAgo: 'há um dia',
+ daysAgo: 'há {delta} dias',
+ weekAgo: 'há uma semana',
+ weeksAgo: 'há {delta} semanas',
+ monthAgo: 'há um mês',
+ monthsAgo: 'há {delta} meses',
+ yearAgo: 'há um ano',
+ yearsAgo: 'há {delta} anos',
+ lessThanMinuteUntil: 'em menos de um minuto',
+ minuteUntil: 'em um minuto',
+ minutesUntil: 'em {delta} minutos',
+ hourUntil: 'em uma hora',
+ hoursUntil: 'em {delta} horas',
+ dayUntil: 'em um dia',
+ daysUntil: 'em {delta} dias',
+ weekUntil: 'em uma semana',
+ weeksUntil: 'em {delta} semanas',
+ monthUntil: 'em um mês',
+ monthsUntil: 'em {delta} meses',
+ yearUntil: 'em um ano',
+ yearsUntil: 'em {delta} anos'
+
+});/*
+Script: Date.Russian.js
+ Date messages for Russian.
+
+ License:
+ MIT-style license.
+
+ Authors:
+ Evstigneev Pavel
+*/
+
+MooTools.lang.set('ru-RU-unicode', 'Date', {
+
+ months: ['ЯнваÑÑ', 'ФевÑалÑ', 'ÐаÑÑ', 'Ð?пÑелÑ', 'Ðай', 'ÐÑнÑ', 'ÐÑлÑ', 'Ð?вгÑÑ?Ñ', 'СенÑÑ?бÑÑ', 'ÐкÑÑ?бÑÑ', 'Ð?оÑ?бÑÑ', 'ÐекабÑÑ'],
+ days: ['ÐоÑ?кÑеÑ?енÑе', 'ÐонеделÑник', 'ÐÑоÑник', 'СÑеда', 'ЧеÑвеÑг', 'ÐÑ?ÑниÑа', 'СÑббоÑа'],
+ //culture's date order: MM/DD/YYYY
+ dateOrder: ['date', 'month', 'year'],
+ AM: 'AM',
+ PM: 'PM',
+
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H:%M',
+
+
+ /*
+ * Russian language pluralization rules, taken from CLDR project, http://unicode.org/cldr/
+ *
+ * one -> n mod 10 is 1 and n mod 100 is not 11;
+ * few -> n mod 10 in 2..4 and n mod 100 not in 12..14;
+ * many -> n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14;
+ * other -> everything else (example 3.14)
+ */
+
+ pluralize: function (n, one, few, many, other) {
+ var modulo10 = n % 10
+ var modulo100 = n % 100
+
+ if (modulo10 == 1 && modulo100 != 11) {
+ return one;
+ } else if ((modulo10 == 2 || modulo10 == 3 || modulo10 == 4) && !(modulo100 == 12 || modulo100 == 13 || modulo100 == 14)) {
+ return few;
+ } else if (modulo10 == 0 || (modulo10 == 5 || modulo10 == 6 || modulo10 == 7 || modulo10 == 8 || modulo10 == 9) || (modulo100 == 11 || modulo100 == 12 || modulo100 == 13 || modulo100 == 14)) {
+ return many;
+ } else {
+ return other;
+ }
+ },
+
+ /* Date.Extras */
+ ordinal: '',
+ lessThanMinuteAgo: 'менÑÑе минÑÑÑ Ð½Ð°Ð·Ð°Ð´',
+ minuteAgo: 'минÑÑа назад',
+ minutesAgo: function (delta) { return '{delta} ' + this.pluralize(delta, 'минÑÑа', 'минÑÑÑ', 'минÑÑ') + ' назад'},
+ hourAgo: 'ÑаÑ? назад',
+ hoursAgo: function (delta) { return '{delta} ' + this.pluralize(delta, 'ÑаÑ?', 'ÑаÑ?а', 'ÑаÑ?ов') + ' назад'},
+ dayAgo: 'вÑеÑа',
+ daysAgo: function (delta) { return '{delta} ' + this.pluralize(delta, 'денÑ', 'днÑ?', 'дней') + ' назад' },
+ lessThanMinuteUntil: 'менÑÑе минÑÑÑ Ð½Ð°Ð·Ð°Ð´',
+ minuteUntil: 'ÑеÑез минÑÑÑ',
+ minutesUntil: function (delta) { return 'ÑеÑез {delta} ' + this.pluralize(delta, 'ÑаÑ?', 'ÑаÑ?а', 'ÑаÑ?ов') + ''},
+ hourUntil: 'ÑеÑез ÑаÑ?',
+ hoursUntil: function (delta) { return 'ÑеÑез {delta} ' + this.pluralize(delta, 'ÑаÑ?', 'ÑаÑ?а', 'ÑаÑ?ов') + ''},
+ dayUntil: 'завÑÑа',
+ daysUntil: function (delta) { return 'ÑеÑез {delta} ' + this.pluralize(delta, 'денÑ', 'днÑ?', 'дней') + '' }
+
+});/*
+---
+
+script: Date.Spanish.US.js
+
+description: Date messages for Spanish.
+
+license: MIT-style license
+
+authors:
+- Ãlfons Sanchez
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Spanish]
+
+...
+*/
+
+MooTools.lang.set('es-ES', 'Date', {
+
+ months: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
+ days: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
+ //culture's date order: MM/DD/YYYY
+ dateOrder: ['date', 'month', 'year'],
+ AM: 'AM',
+ PM: 'PM',
+
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ ordinal: '',
+
+ lessThanMinuteAgo: 'hace menos de un minuto',
+ minuteAgo: 'hace un minuto',
+ minutesAgo: 'hace {delta} minutos',
+ hourAgo: 'hace una hora',
+ hoursAgo: 'hace unas {delta} horas',
+ dayAgo: 'hace un dÃa',
+ daysAgo: 'hace {delta} dÃas',
+ weekAgo: 'hace una semana',
+ weeksAgo: 'hace unas {delta} semanas',
+ monthAgo: 'hace un mes',
+ monthsAgo: 'hace {delta} meses',
+ yearAgo: 'hace un año',
+ yearsAgo: 'hace {delta} años',
+ lessThanMinuteUntil: 'menos de un minuto desde ahora',
+ minuteUntil: 'un minuto desde ahora',
+ minutesUntil: '{delta} minutos desde ahora',
+ hourUntil: 'una hora desde ahora',
+ hoursUntil: 'unas {delta} horas desde ahora',
+ dayUntil: 'un dÃa desde ahora',
+ daysUntil: '{delta} dÃas desde ahora',
+ weekUntil: 'una semana desde ahora',
+ weeksUntil: 'unas {delta} semanas desde ahora',
+ monthUntil: 'un mes desde ahora',
+ monthsUntil: '{delta} meses desde ahora',
+ yearUntil: 'un año desde ahora',
+ yearsUntil: '{delta} años desde ahora'
+
+});/*
+---
+
+script: Date.Swedish.js
+
+description: Date messages for Swedish (SE).
+
+license: MIT-style license
+
+authors:
+- Martin Lundgren
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Swedish]
+
+...
+*/
+
+MooTools.lang.set('sv-SE', 'Date', {
+
+ months: ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december'],
+ days: ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lördag'],
+ // culture's date order: YYYY-MM-DD
+ dateOrder: ['year', 'month', 'date'],
+ AM: '',
+ PM: '',
+
+ shortDate: '%Y-%m-%d',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ ordinal: function(dayOfMonth){
+ // Not used in Swedish
+ return '';
+ },
+
+ lessThanMinuteAgo: 'mindre än en minut sedan',
+ minuteAgo: 'ungefär en minut sedan',
+ minutesAgo: '{delta} minuter sedan',
+ hourAgo: 'ungefär en timme sedan',
+ hoursAgo: 'ungefär {delta} timmar sedan',
+ dayAgo: '1 dag sedan',
+ daysAgo: '{delta} dagar sedan',
+ lessThanMinuteUntil: 'mindre än en minut sedan',
+ minuteUntil: 'ungefär en minut sedan',
+ minutesUntil: '{delta} minuter sedan',
+ hourUntil: 'ungefär en timme sedan',
+ hoursUntil: 'ungefär {delta} timmar sedan',
+ dayUntil: '1 dag sedan',
+ daysUntil: '{delta} dagar sedan'
+
+});/*
+---
+
+script: Date.Ukrainian.js
+
+description: Date messages for Ukrainian.
+
+license: MIT-style license
+
+authors:
+- Slik
+
+requires:
+- /Lang
+- /Date
+
+provides: [Date.Ukrainian]
+
+...
+*/
+
+(function(){
+ var pluralize = function(n, one, few, many, other){
+ var d = (n / 10).toInt();
+ var z = n % 10;
+ var s = (n / 100).toInt();
+
+ if(d == 1 && n > 10) return many;
+ if(z == 1) return one;
+ if(z > 0 && z < 5) return few;
+ return many;
+ };
+
+ MooTools.lang.set('uk-UA', 'Date', {
+ months: ['СÑÑенÑ', 'ÐÑÑий', 'ÐеÑезенÑ', 'ÐвÑÑенÑ', 'ТÑавенÑ', 'ЧеÑвенÑ', 'ÐипенÑ', 'СеÑпенÑ', 'ÐеÑеÑ?енÑ', 'ÐовÑенÑ', 'ÐиÑ?Ñопад', 'ÐÑÑденÑ'],
+ days: ['Ð?едÑлÑ?', 'ÐонедÑлок', 'ÐÑвÑоÑок', 'СеÑеда', 'ЧеÑвеÑ', 'Ð\'Ñ?ÑниÑÑ?', 'СÑбоÑа'],
+ //culture's date order: DD/MM/YYYY
+ dateOrder: ['date', 'month', 'year'],
+ AM: 'до полÑднÑ?',
+ PM: 'по полÑднÑ',
+
+ shortDate: '%d/%m/%Y',
+ shortTime: '%H:%M',
+
+ /* Date.Extras */
+ ordinal: '',
+ lessThanMinuteAgo: 'менÑÑе Ñ
вилини ÑомÑ',
+ minuteAgo: 'Ñ
Ð²Ð¸Ð»Ð¸Ð½Ñ ÑомÑ',
+ minutesAgo: function (delta){
+ return '{delta} ' + pluralize(delta, 'Ñ
вилинÑ', 'Ñ
вилини', 'Ñ
вилин') + ' ÑомÑ';
+ },
+ hourAgo: 'Ð³Ð¾Ð´Ð¸Ð½Ñ ÑомÑ',
+ hoursAgo: function (delta){
+ return '{delta} ' + pluralize(delta, 'годинÑ', 'години', 'годин') + ' ÑомÑ';
+ },
+ dayAgo: 'вÑоÑа',
+ daysAgo: function (delta){
+ return '{delta} ' + pluralize(delta, 'денÑ', 'днÑ?', 'днÑв') + ' ÑомÑ';
+ },
+ weekAgo: 'ÑÐ¸Ð¶Ð´ÐµÐ½Ñ ÑомÑ',
+ weeksAgo: function (delta){
+ return '{delta} ' + pluralize(delta, 'ÑижденÑ', 'ÑижнÑ', 'ÑижнÑв') + ' ÑомÑ';
+ },
+ monthAgo: 'мÑÑ?Ñ?ÑÑ ÑомÑ',
+ monthsAgo: function (delta){
+ return '{delta} ' + pluralize(delta, 'мÑÑ?Ñ?ÑÑ', 'мÑÑ?Ñ?ÑÑ', 'мÑÑ?Ñ?ÑÑв') + ' ÑомÑ';
+ },
+ yearAgo: 'ÑÑк ÑомÑ',
+ yearsAgo: function (delta){
+ return '{delta} ' + pluralize(delta, 'ÑÑк', 'Ñоки', 'ÑокÑв') + ' ÑомÑ';
+ },
+ lessThanMinuteUntil: 'за миÑÑ',
+ minuteUntil: 'ÑеÑез Ñ
вилинÑ',
+ minutesUntil: function (delta){
+ return 'ÑеÑез {delta} ' + pluralize(delta, 'Ñ
вилинÑ', 'Ñ
вилини', 'Ñ
вилин');
+ },
+ hourUntil: 'ÑеÑез годинÑ',
+ hoursUntil: function (delta){
+ return 'ÑеÑез {delta} ' + pluralize(delta, 'годинÑ', 'години', 'годин');
+ },
+ dayUntil: 'завÑÑа',
+ daysUntil: function (delta){
+ return 'ÑеÑез {delta} ' + pluralize(delta, 'денÑ', 'днÑ?', 'днÑв');
+ },
+ weekUntil: 'ÑеÑез ÑижденÑ',
+ weeksUntil: function (delta){
+ return 'ÑеÑез {delta} ' + pluralize(delta, 'ÑижденÑ', 'ÑижнÑ', 'ÑижнÑв');
+ },
+ monthUntil: 'ÑеÑез мÑÑ?Ñ?ÑÑ',
+ monthesUntil: function (delta){
+ return 'ÑеÑез {delta} ' + pluralize(delta, 'мÑÑ?Ñ?ÑÑ', 'мÑÑ?Ñ?ÑÑ', 'мÑÑ?Ñ?ÑÑв');
+ },
+ yearUntil: 'ÑеÑез ÑÑк',
+ yearsUntil: function (delta){
+ return 'ÑеÑез {delta} ' + pluralize(delta, 'ÑÑк', 'Ñоки', 'ÑокÑв');
+ }
+ });
+
+})();/*
+---
+
+script: Form.Validator.Arabic.js
+
+description: Form.Validator messages in Arabic.
+
+license: MIT-style license
+
+authors:
+- Chafik Barbar
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Arabic]
+
+...
+*/
+
+MooTools.lang.set('ar', 'Form.Validator', {
+ required:'Ùذا اÙØÙÙ Ù
Ø·ÙÙب.',
+ minLength:'رجاء٠إدخا٠{minLength} Ø£ØرÙ? عÙ٠اÙØ£ÙÙ (تÙ
إدخا٠{length} Ø£ØرÙ?).',
+ maxLength:'اÙرجاء عدÙ
إدخا٠أÙثر Ù
Ù {maxLength} Ø£ØرÙ? (تÙ
إدخا٠{length} Ø£ØرÙ?).',
+ integer:'اÙرجاء إدخا٠عدد صØÙØ Ù?Ù Ùذا اÙØÙÙ. أ٠رÙÙ
Ø°Ù Ùسر عشر٠أ٠Ù
ئÙÙ (Ù
ثا٠1.25 ) غÙر Ù
سÙ
ÙØ.',
+ numeric:'اÙرجاء إدخا٠ÙÙÙ
رÙÙ
ÙØ© Ù?Ù Ùذا اÙØÙÙ (Ù
ثا٠"1" أ٠"1.1" أ٠"-1" أ٠"-1.1").',
+ digits:'اÙرجاء أستخداÙ
ÙÙÙ
رÙÙ
ÙØ© ÙعÙاÙ
ات ترÙÙÙ
ÙØ© Ù?ÙØ· Ù?Ù Ùذا اÙØÙÙ (Ù
ثاÙ, رÙÙ
ÙاتÙ? Ù
ع ÙÙطة Ø£Ù Ø´Øطة)',
+ alpha:'اÙرجاء أستخداÙ
Ø£ØرÙ? Ù?ÙØ· (ا-Ù) Ù?Ù Ùذا اÙØÙÙ. Ø£Ù Ù?راغات أ٠عÙاÙ
ات غÙر Ù
سÙ
ÙØØ©.',
+ alphanum:'اÙرجاء أستخداÙ
Ø£ØرÙ? Ù?ÙØ· (ا-Ù) أ٠أرÙاÙ
(0-9) Ù?ÙØ· Ù?Ù Ùذا اÙØÙÙ. Ø£Ù Ù?راغات أ٠عÙاÙ
ات غÙر Ù
سÙ
ÙØØ©.',
+ dateSuchAs:'اÙرجاء إدخا٠تارÙØ® صØÙØ ÙاÙتاÙÙ {date}',
+ dateInFormatMDY:'اÙرجاء إدخا٠تارÙØ® صØÙØ (Ù
ثاÙ, 31-12-1999)',
+ email:'اÙرجاء إدخا٠برÙد Ø¥ÙÙترÙÙ٠صØÙØ.',
+ url:'اÙرجاء إدخا٠عÙÙا٠إÙÙترÙÙ٠صØÙØ Ù
Ø«Ù http://www.google.com',
+ currencyDollar:'اÙرجاء إدخا٠ÙÙÙ
Ø© $ صØÙØØ©. Ù
ثاÙ, 100.00$',
+ oneRequired:'اÙرجاء إدخا٠ÙÙÙ
Ø© Ù?٠أØد Ùذ٠اÙØÙÙ٠عÙ٠اÙØ£ÙÙ.',
+ errorPrefix: 'خطأ: ',
+ warningPrefix: 'تØØ°Ùر: '
+}).set('ar', 'Date', {
+ dateOrder: ['date', 'month', 'year', '/']
+});/*
+---
+
+script: Form.Validator.Catalan.js
+
+description: Date messages for Catalan.
+
+license: MIT-style license
+
+authors:
+- Miquel Hudin
+- Alfons Sanchez
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Catalan]
+
+...
+*/
+
+MooTools.lang.set('ca-CA', 'Form.Validator', {
+
+ required:'Aquest camp es obligatori.',
+ minLength:'Per favor introdueix al menys {minLength} caracters (has introduit {length} caracters).',
+ maxLength:'Per favor introdueix no mes de {maxLength} caracters (has introduit {length} caracters).',
+ integer:'Per favor introdueix un nombre enter en aquest camp. Nombres amb decimals (p.e. 1,25) no estan permesos.',
+ numeric:'Per favor introdueix sols valors numerics en aquest camp (p.e. "1" o "1,1" o "-1" o "-1,1").',
+ digits:'Per favor usa sols numeros i puntuacio en aquest camp (per exemple, un nombre de telefon amb guions i punts no esta permes).',
+ alpha:'Per favor utilitza lletres nomes (a-z) en aquest camp. No s´admiteixen espais ni altres caracters.',
+ alphanum:'Per favor, utilitza nomes lletres (a-z) o numeros (0-9) en aquest camp. No s´admiteixen espais ni altres caracters.',
+ dateSuchAs:'Per favor introdueix una data valida com {date}',
+ dateInFormatMDY:'Per favor introdueix una data valida com DD/MM/YYYY (p.e. "31/12/1999")',
+ email:'Per favor, introdueix una adreça de correu electronic valida. Per exemple, "fred at domain.com".',
+ url:'Per favor introdueix una URL valida com http://www.google.com.',
+ currencyDollar:'Per favor introdueix una quantitat valida de â¬. Per exemple â¬100,00 .',
+ oneRequired:'Per favor introdueix alguna cosa per al menys una d´aquestes entrades.',
+ errorPrefix: 'Error: ',
+ warningPrefix: 'Avis: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'No poden haver espais en aquesta entrada.',
+ reqChkByNode: 'No hi han elements seleccionats.',
+ requiredChk: 'Aquest camp es obligatori.',
+ reqChkByName: 'Per favor selecciona una {label}.',
+ match: 'Aquest camp necessita coincidir amb el camp {matchName}',
+ startDate: 'la data de inici',
+ endDate: 'la data de fi',
+ currendDate: 'la data actual',
+ afterDate: 'La data deu ser igual o posterior a {label}.',
+ beforeDate: 'La data deu ser igual o anterior a {label}.',
+ startMonth: 'Per favor selecciona un mes d´orige',
+ sameMonth: 'Aquestes dos dates deuen estar dins del mateix mes - deus canviar una o altra.'
+
+});/*
+---
+
+script: Form.Validator.Czech.js
+
+description: Form Validator messages for Czech.
+
+license: MIT-style license
+
+authors:
+- Jan Äerný chemiX
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Czech]
+
+...
+*/
+
+MooTools.lang.set('cs-CZ', 'Form.Validator', {
+
+ required:'Tato položka je povinná.',
+ minLength:'Zadejte prosÃm alespoÅ {minLength} znaků (napsáno {length} znaků).',
+ maxLength:'Zadejte prosÃm ménÄ než {maxLength} znaků (nápsáno {length} znaků).',
+ integer:'Zadejte prosÃm celé Ä?Ãslo. Desetinná Ä?Ãsla (napÅ. 1.25) nejsou povolena.',
+ numeric:'Zadejte jen Ä?Ãselné hodnoty (tj. "1" nebo "1.1" nebo "-1" nebo "-1.1").',
+ digits:'Zadejte prosÃm pouze Ä?Ãsla a interpunkÄ?nà znaménka(napÅÃklad telefonnà Ä?Ãslo s pomlÄ?kami nebo teÄ?kami je povoleno).',
+ alpha:'Zadejte prosÃm pouze pÃsmena (a-z). Mezery nebo jiné znaky nejsou povoleny.',
+ alphanum:'Zadejte prosÃm pouze pÃsmena (a-z) nebo Ä?Ãslice (0-9). Mezery nebo jiné znaky nejsou povoleny.',
+ dateSuchAs:'Zadejte prosÃm platné datum jako {date}',
+ dateInFormatMDY:'Zadejte prosÃm platné datum jako MM / DD / RRRR (tj. "12/31/1999")',
+ email:'Zadejte prosÃm platnou e-mailovou adresu. NapÅÃklad "fred at domain.com".',
+ url:'Zadejte prosÃm platnou URL adresu jako http://www.google.com.',
+ currencyDollar:'Zadejte prosÃm platnou Ä?ástku. NapÅÃklad $100.00.',
+ oneRequired:'Zadejte prosÃm alespoÅ jednu hodnotu pro tyto položky.',
+ errorPrefix: 'Chyba: ',
+ warningPrefix: 'UpozornÄnÃ: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'V této položce nejsou povoleny mezery',
+ reqChkByNode: 'Nejsou vybrány žádné položky.',
+ requiredChk: 'Tato položka je vyžadována.',
+ reqChkByName: 'ProsÃm vyberte {label}.',
+ match: 'Tato položka se musà shodovat s položkou {matchName}',
+ startDate: 'datum zahájenÃ',
+ endDate: 'datum ukonÄ?enÃ',
+ currendDate: 'aktuálnà datum',
+ afterDate: 'Datum by mÄlo být stejné nebo vÄtÅ¡Ã než {label}.',
+ beforeDate: 'Datum by mÄlo být stejné nebo menÅ¡Ã než {label}.',
+ startMonth: 'Vyberte poÄ?áteÄ?nà mÄsÃc.',
+ sameMonth: 'Tyto dva datumy musà být ve stejném mÄsÃci - zmÄÅte jeden z nich.',
+ creditcard: 'Zadané Ä?Ãslo kreditnà karty je neplatné. ProsÃm opravte ho. Bylo zadáno {length} Ä?Ãsel.'
+
+});
+/*
+---
+
+script: Form.Validator.Chinese.js
+
+description: Form.Validator messages in chinese (both simplified and traditional).
+
+license: MIT-style license
+
+authors:
+- éæ¡å - guidy <at> ixuer [dot] net
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Chinese]
+
+...
+*/
+
+/*
+In Chinese:
+------------
+éè¦?æåºçæ¯ï¼
+ç®ä½ä¸æéç¨äºä¸å½å¤§éï¼
+ç¹?ä½ä¸æéç¨äºé¦æ¸¯ã?æ¾³é¨åå?°æ¹¾ç?ã
+ç®ä½ä¸æåç¹?ä½ä¸æå¨åä½åè¯æ³ä¸æå¾å¤çä¸?å?ä¹å¤ã
+
+æå?¯ä»¥ç¡®ä¿?ç®ä½ä¸æè¯è¨å
çåç¡®æ§ï¼
+ä½å¯¹äºç¹?ä½ä¸æï¼æå?¯ä»¥ä¿?è¯?ç¨æ·å?¯ä»¥åç¡®çç?解ï¼ä½æ æ³ä¿?è¯?è¯å?¥ç¬¦å?ä»ä»¬çé
è¯»ä¹ æ¯ã
+å¦ææ¨ä¸?è½ç¡®è®¤çè¯?ï¼å?¯ä»¥å?ªä½¿ç¨ç®ä½ä¸æè¯è¨å
ï¼å 为å®æ¯æéç¨çã
+
+In English:
+------------
+It should be noted that:
+Simplified Chinese apply to mainland Chinese,
+Traditional Chinese apply to Hong Kong, Macao and Taiwan Province.
+There are a lot of different from Simplified Chinese and Traditional Chinese , Contains font and syntax .
+
+I can assure Simplified Chinese language pack accuracy .
+For Traditional Chinese, I can only guarantee that users can understand, but not necessarily in line with their reading habits.
+If you are unsure, you can only use the simplified Chinese language pack, as it is the most common.
+
+*/
+
+// Simplified Chinese
+MooTools.lang.set('zhs-CN', 'Form.Validator', {
+ required:'è¿æ¯å¿
填项ã',
+ minLength:'请è³å°è¾å
¥ {minLength} 个å符 (å·²è¾å
¥ {length} 个)ã',
+ maxLength:'æå¤å?ªè½è¾å
¥ {maxLength} 个å符 (å·²è¾å
¥ {length} 个)ã',
+ integer:'请è¾å
¥ä¸ä¸ªæ´æ°ï¼ä¸?è½å
å?«å°?æ°ç¹ãä¾å¦ï¼"1", "200"ã',
+ numeric:'请è¾å
¥ä¸ä¸ªæ°åï¼ä¾å¦ï¼"1", "1.1", "-1", "-1.1"ã',
+ digits:'è¿éå?ªè½æ¥å?æ°ååæ ç¹çè¾å
¥ï¼æ ç¹å?¯ä»¥æ¯ï¼"(", ")", ".", ":", "-", "+", "#"åç©ºæ ¼ã',
+ alpha:'请è¾å
¥ A-Z ç 26 个åæ¯?ï¼ä¸?è½å
å?«ç©ºæ ¼æä»»ä½å
¶ä»å符ã',
+ alphanum:'请è¾å
¥ A-Z ç 26 个åæ¯?æ 0-9 ç 10 个æ°åï¼ä¸?è½å
å?«ç©ºæ ¼æä»»ä½å
¶ä»å符ã',
+ dateSuchAs:'请è¾å
¥å?æ³çæ¥ææ ¼å¼?ï¼å¦ï¼{date}ã',
+ dateInFormatMDY:'请è¾å
¥å?æ³çæ¥ææ ¼å¼?ï¼ä¾å¦ï¼MM/DD/YYYY ("12/31/1999")ã',
+ email:'请è¾å
¥å?æ³ççµå?ä¿¡ç®±å°å?ï¼ä¾å¦ï¼"fred at domain.com"ã',
+ url:'请è¾å
¥å?æ³ç Url å°å?ï¼ä¾å¦ï¼http://www.google.comã',
+ currencyDollar:'请è¾å
¥å?æ³çè´§å¸?符å?·ï¼ä¾å¦ï¼ï¿¥',
+ oneRequired:'请è³å°éæ©ä¸é¡¹ã',
+ errorPrefix: 'é误ï¼',
+ warningPrefix: 'è¦åï¼'
+});
+
+// Traditional Chinese
+MooTools.lang.set('zht-CN', 'Form.Validator', {
+ required:'éæ¯å¿
å¡«é
ã',
+ minLength:'è«è³å°é?µå
¥ {minLength} åå符(å·²é?µå
¥ {length} å)ã',
+ maxLength:'æå¤å?ªè½é?µå
¥ {maxLength} åå符(å·²é?µå
¥ {length} å)ã',
+ integer:'è«é?µå
¥ä¸åæ´æ¸ï¼ä¸?è½å
å?«å°?æ¸é»ãä¾å¦ï¼"1", "200"ã',
+ numeric:'è«é?µå
¥ä¸åæ¸åï¼ä¾å¦ï¼"1", "1.1", "-1", "-1.1"ã',
+ digits:'é裡å?ªè½æ¥å?æ¸ååæ¨é»çé?µå
¥ï¼æ¨é»å?¯ä»¥æ¯ï¼"(", ")", ".", ":", "-", "+", "#"åç©ºæ ¼ã',
+ alpha:'è«é?µå
¥ A-Z ç 26 ååæ¯?ï¼ä¸?è½å
å?«ç©ºæ ¼æä»»ä½å
¶ä»å符ã',
+ alphanum:'è«é?µå
¥ A-Z ç 26 ååæ¯?æ 0-9 ç 10 åæ¸åï¼ä¸?è½å
å?«ç©ºæ ¼æä»»ä½å
¶ä»å符ã',
+ dateSuchAs:'è«é?µå
¥å?æ³çæ¥ææ ¼å¼?ï¼å¦ï¼{date}ã',
+ dateInFormatMDY:'è«é?µå
¥å?æ³çæ¥ææ ¼å¼?ï¼ä¾å¦ï¼MM/DD/YYYY ("12/31/1999")ã',
+ email:'è«é?µå
¥å?æ³çé»å?ä¿¡ç®±å°å?ï¼ä¾å¦ï¼"fred at domain.com"ã',
+ url:'è«é?µå
¥å?æ³ç Url å°å?ï¼ä¾å¦ï¼http://www.google.comã',
+ currencyYuan:'è«é?µå
¥å?æ³ç貨幣符èï¼ä¾å¦ï¼ï¿¥',
+ oneRequired:'è«è³å°é?¸æä¸é
ã',
+ errorPrefix: 'é¯èª¤ï¼',
+ warningPrefix: 'è¦åï¼'
+});
+
+Form.Validator.add('validate-currency-yuan', {
+ errorMsg: function(){
+ return Form.Validator.getMsg('currencyYuan');
+ },
+ test: function(element) {
+ // [ï¿¥]1[##][,###]+[.##]
+ // [ï¿¥]1###+[.##]
+ // [ï¿¥]0.##
+ // [ï¿¥].##
+ return Form.Validator.getValidator('IsEmpty').test(element) || (/^ï¿¥?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/).test(element.get('value'));
+ }
+});
+/*
+---
+
+script: Form.Validator.Dutch.js
+
+description: Form.Validator messages in Dutch.
+
+license: MIT-style license
+
+authors:
+- Lennart Pilon
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Dutch]
+
+...
+*/
+
+MooTools.lang.set('nl-NL', 'Form.Validator', {
+ required:'Dit veld is verplicht.',
+ minLength:'Vul minimaal {minLength} karakters in (je hebt {length} karakters ingevoerd).',
+ maxLength:'Vul niet meer dan {maxLength} karakters in (je hebt {length} karakters ingevoerd).',
+ integer:'Vul een getal in. Getallen met decimalen (bijvoorbeeld 1,25) zijn niet toegestaan.',
+ numeric:'Vul alleen numerieke waarden in (bijvoorbeeld. "1" of "1.1" of "-1" of "-1.1").',
+ digits:'Vul alleen nummers en leestekens in (bijvoorbeeld een telefoonnummer met een streepje).',
+ alpha:'Vul alleen letters in (a-z). Spaties en andere karakters zijn niet toegestaan.',
+ alphanum:'Vul alleen letters in (a-z) of nummers (0-9). Spaties en andere karakters zijn niet toegestaan.',
+ dateSuchAs:'Vul een geldige datum in, zoals {date}',
+ dateInFormatMDY:'Vul een geldige datum, in het formaat MM/DD/YYYY (bijvoorbeeld "12/31/1999")',
+ email:'Vul een geldig e-mailadres in. Bijvoorbeeld "fred at domein.nl".',
+ url:'Vul een geldige URL in, zoals http://www.google.nl.',
+ currencyDollar:'Vul een geldig $ bedrag in. Bijvoorbeeld $100.00 .',
+ oneRequired:'Vul iets in bij minimaal een van de invoervelden.',
+ warningPrefix: 'Waarschuwing: ',
+ errorPrefix: 'Fout: '
+});/*
+---
+
+script: Form.Validator.Estonian.js
+
+description: Date messages for Estonian.
+
+license: MIT-style license
+
+authors:
+- Kevin Valdek
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Estonian]
+
+...
+*/
+
+MooTools.lang.set('et-EE', 'Form.Validator', {
+
+ required:'Väli peab olema täidetud.',
+ minLength:'Palun sisestage vähemalt {minLength} tähte (te sisestasite {length} tähte).',
+ maxLength:'Palun ärge sisestage rohkem kui {maxLength} tähte (te sisestasite {length} tähte).',
+ integer:'Palun sisestage väljale täisarv. Kümnendarvud (näiteks 1.25) ei ole lubatud.',
+ numeric:'Palun sisestage ainult numbreid väljale (näiteks "1", "1.1", "-1" või "-1.1").',
+ digits:'Palun kasutage ainult numbreid ja kirjavahemärke (telefoninumbri sisestamisel on lubatud kasutada kriipse ja punkte).',
+ alpha:'Palun kasutage ainult tähti (a-z). Tühikud ja teised sümbolid on keelatud.',
+ alphanum:'Palun kasutage ainult tähti (a-z) või numbreid (0-9). Tühikud ja teised sümbolid on keelatud.',
+ dateSuchAs:'Palun sisestage kehtiv kuupäev kujul {date}',
+ dateInFormatMDY:'Palun sisestage kehtiv kuupäev kujul MM.DD.YYYY (näiteks: "12.31.1999").',
+ email:'Palun sisestage kehtiv e-maili aadress (näiteks: "fred at domain.com").',
+ url:'Palun sisestage kehtiv URL (näiteks: http://www.google.com).',
+ currencyDollar:'Palun sisestage kehtiv $ summa (näiteks: $100.00).',
+ oneRequired:'Palun sisestage midagi vähemalt ühele antud väljadest.',
+ errorPrefix: 'Viga: ',
+ warningPrefix: 'Hoiatus: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'Väli ei tohi sisaldada tühikuid.',
+ reqChkByNode: 'Ãkski väljadest pole valitud.',
+ requiredChk: 'Välja täitmine on vajalik.',
+ reqChkByName: 'Palun valige üks {label}.',
+ match: 'Väli peab sobima {matchName} väljaga',
+ startDate: 'algkuupäev',
+ endDate: 'lõppkuupäev',
+ currendDate: 'praegune kuupäev',
+ afterDate: 'Kuupäev peab olema võrdne või pärast {label}.',
+ beforeDate: 'Kuupäev peab olema võrdne või enne {label}.',
+ startMonth: 'Palun valige algkuupäev.',
+ sameMonth: 'Antud kaks kuupäeva peavad olema samas kuus - peate muutma ühte kuupäeva.'
+
+});/*
+---
+
+script: Form.Validator.German.js
+
+description: Date messages for German.
+
+license: MIT-style license
+
+authors:
+- Frank Rossi
+- Ulrich Petri
+- Fabian Beiner
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.German]
+
+...
+*/
+
+MooTools.lang.set('de-DE', 'Form.Validator', {
+
+ required: 'Dieses Eingabefeld muss ausgefüllt werden.',
+ minLength: 'Geben Sie bitte mindestens {minLength} Zeichen ein (Sie haben nur {length} Zeichen eingegeben).',
+ maxLength: 'Geben Sie bitte nicht mehr als {maxLength} Zeichen ein (Sie haben {length} Zeichen eingegeben).',
+ integer: 'Geben Sie in diesem Eingabefeld bitte eine ganze Zahl ein. Dezimalzahlen (z.B. "1.25") sind nicht erlaubt.',
+ numeric: 'Geben Sie in diesem Eingabefeld bitte nur Zahlenwerte (z.B. "1", "1.1", "-1" oder "-1.1") ein.',
+ digits: 'Geben Sie in diesem Eingabefeld bitte nur Zahlen und Satzzeichen ein (z.B. eine Telefonnummer mit Bindestrichen und Punkten ist erlaubt).',
+ alpha: 'Geben Sie in diesem Eingabefeld bitte nur Buchstaben (a-z) ein. Leerzeichen und andere Zeichen sind nicht erlaubt.',
+ alphanum: 'Geben Sie in diesem Eingabefeld bitte nur Buchstaben (a-z) und Zahlen (0-9) ein. Leerzeichen oder andere Zeichen sind nicht erlaubt.',
+ dateSuchAs: 'Geben Sie bitte ein gültiges Datum ein (z.B. "{date}").',
+ dateInFormatMDY: 'Geben Sie bitte ein gültiges Datum im Format TT.MM.JJJJ ein (z.B. "31.12.1999").',
+ email: 'Geben Sie bitte eine gültige E-Mail-Adresse ein (z.B. "max at mustermann.de").',
+ url: 'Geben Sie bitte eine gültige URL ein (z.B. "http://www.google.de").',
+ currencyDollar: 'Geben Sie bitte einen gültigen Betrag in EURO ein (z.B. 100.00€).',
+ oneRequired: 'Bitte füllen Sie mindestens ein Eingabefeld aus.',
+ errorPrefix: 'Fehler: ',
+ warningPrefix: 'Warnung: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'Es darf kein Leerzeichen in diesem Eingabefeld sein.',
+ reqChkByNode: 'Es wurden keine Elemente gewählt.',
+ requiredChk: 'Dieses Feld muss ausgefüllt werden.',
+ reqChkByName: 'Bitte wählen Sie ein {label}.',
+ match: 'Dieses Eingabefeld muss mit dem {matchName} Eingabefeld übereinstimmen.',
+ startDate: 'Das Anfangsdatum',
+ endDate: 'Das Enddatum',
+ currendDate: 'Das aktuelle Datum',
+ afterDate: 'Das Datum sollte zur gleichen Zeit oder später sein als {label}.',
+ beforeDate: 'Das Datum sollte zur gleichen Zeit oder früher sein als {label}.',
+ startMonth: 'Wählen Sie bitte einen Anfangsmonat',
+ sameMonth: 'Diese zwei Datumsangaben müssen im selben Monat sein - Sie müssen eines von beiden verändern.',
+ creditcard: 'Die eingegebene Kreditkartennummer ist ungültig. Bitte überprüfen Sie diese und versuchen Sie es erneut. {length} Zahlen eingegeben.'
+});
+/*
+---
+
+script: Form.Validator.German.CH.js
+
+description: Date messages for German (Switzerland).
+
+license: MIT-style license
+
+authors:
+- Michael van der Weg
+
+requires:
+- /Lang
+- /Form.Validator.German
+
+provides: [Form.Validator.German.CH]
+
+...
+*/
+
+MooTools.lang.set('de-CH', 'Form.Validator', {
+
+ required:'Dieses Feld ist obligatorisch.',
+ minLength:'Geben Sie bitte mindestens {minLength} Zeichen ein (Sie haben {length} Zeichen eingegeben).',
+ maxLength:'Bitte geben Sie nicht mehr als {maxLength} Zeichen ein (Sie haben {length} Zeichen eingegeben).',
+ integer:'Geben Sie bitte eine ganze Zahl ein. Dezimalzahlen (z.B. 1.25) sind nicht erlaubt.',
+ numeric:'Geben Sie bitte nur Zahlenwerte in dieses Eingabefeld ein (z.B. "1", "1.1", "-1" oder "-1.1").',
+ digits:'Benutzen Sie bitte nur Zahlen und Satzzeichen in diesem Eingabefeld (erlaubt ist z.B. eine Telefonnummer mit Bindestrichen und Punkten).',
+ alpha:'Benutzen Sie bitte nur Buchstaben (a-z) in diesem Feld. Leerzeichen und andere Zeichen sind nicht erlaubt.',
+ alphanum:'Benutzen Sie bitte nur Buchstaben (a-z) und Zahlen (0-9) in diesem Eingabefeld. Leerzeichen und andere Zeichen sind nicht erlaubt.',
+ dateSuchAs:'Geben Sie bitte ein gültiges Datum ein. Wie zum Beispiel {date}',
+ dateInFormatMDY:'Geben Sie bitte ein gültiges Datum ein. Wie zum Beispiel TT.MM.JJJJ (z.B. "31.12.1999")',
+ email:'Geben Sie bitte eine gültige E-Mail Adresse ein. Wie zum Beispiel "maria at bernasconi.ch".',
+ url:'Geben Sie bitte eine gültige URL ein. Wie zum Beispiel http://www.google.ch.',
+ currencyDollar:'Geben Sie bitte einen gültigen Betrag in Schweizer Franken ein. Wie zum Beispiel 100.00 CHF .',
+ oneRequired:'Machen Sie für mindestens eines der Eingabefelder einen Eintrag.',
+ errorPrefix: 'Fehler: ',
+ warningPrefix: 'Warnung: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'In diesem Eingabefeld darf kein Leerzeichen sein.',
+ reqChkByNode: 'Es wurden keine Elemente gewählt.',
+ requiredChk: 'Dieses Feld ist obligatorisch.',
+ reqChkByName: 'Bitte wählen Sie ein {label}.',
+ match: 'Dieses Eingabefeld muss mit dem Feld {matchName} übereinstimmen.',
+ startDate: 'Das Anfangsdatum',
+ endDate: 'Das Enddatum',
+ currendDate: 'Das aktuelle Datum',
+ afterDate: 'Das Datum sollte zur gleichen Zeit oder später sein {label}.',
+ beforeDate: 'Das Datum sollte zur gleichen Zeit oder früher sein {label}.',
+ startMonth: 'Wählen Sie bitte einen Anfangsmonat',
+ sameMonth: 'Diese zwei Datumsangaben müssen im selben Monat sein - Sie müssen eine von beiden verändern.'
+
+});/*
+---
+
+script: Form.Validator.French.js
+
+description: Form.Validator messages in French.
+
+license: MIT-style license
+
+authors:
+- Miquel Hudin
+- Nicolas Sorosac <nicolas <dot> sorosac <at> gmail <dot> com>
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.French]
+
+...
+*/
+
+MooTools.lang.set('fr-FR', 'Form.Validator', {
+ required:'Ce champ est obligatoire.',
+ minLength:'Veuillez saisir un minimum de {minLength} caractère(s) (vous avez saisi {length} caractère(s)).',
+ maxLength:'Veuillez saisir un maximum de {maxLength} caractère(s) (vous avez saisi {length} caractère(s)).',
+ integer:'Veuillez saisir un nombre entier dans ce champ. Les nombres décimaux (ex : "1,25") ne sont pas autorisés.',
+ numeric:'Veuillez saisir uniquement des chiffres dans ce champ (ex : "1" ou "1,1" ou "-1" ou "-1,1").',
+ digits:'Veuillez saisir uniquement des chiffres et des signes de ponctuation dans ce champ (ex : un numéro de téléphone avec des traits d\'union est autorisé).',
+ alpha:'Veuillez saisir uniquement des lettres (a-z) dans ce champ. Les espaces ou autres caractères ne sont pas autorisés.',
+ alphanum:'Veuillez saisir uniquement des lettres (a-z) ou des chiffres (0-9) dans ce champ. Les espaces ou autres caractères ne sont pas autorisés.',
+ dateSuchAs:'Veuillez saisir une date correcte comme {date}',
+ dateInFormatMDY:'Veuillez saisir une date correcte, au format JJ/MM/AAAA (ex : "31/11/1999").',
+ email:'Veuillez saisir une adresse de courrier électronique. Par example "fred at domaine.com".',
+ url:'Veuillez saisir une URL, comme http://www.google.com.',
+ currencyDollar:'Veuillez saisir une quantité correcte. Par example 100,00€.',
+ oneRequired:'Veuillez sélectionner au moins une de ces options.',
+ errorPrefix: 'Erreur : ',
+ warningPrefix: 'Attention : ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'Ce champ n\'accepte pas les espaces.',
+ reqChkByNode: 'Aucun élément n\'est sélectionné.',
+ requiredChk: 'Ce champ est obligatoire.',
+ reqChkByName: 'Veuillez sélectionner un(e) {label}.',
+ match: 'Ce champ doit correspondre avec le champ {matchName}.',
+ startDate: 'date de début',
+ endDate: 'date de fin',
+ currendDate: 'date actuelle',
+ afterDate: 'La date doit être identique ou postérieure à {label}.',
+ beforeDate: 'La date doit être identique ou antérieure à {label}.',
+ startMonth: 'Veuillez sélectionner un mois de début.',
+ sameMonth: 'Ces deux dates doivent être dans le même mois - vous devez en modifier une.'
+
+});/*
+---
+
+script: Form.Validator.Italian.js
+
+description: Form.Validator messages in Italian.
+
+license: MIT-style license
+
+authors:
+- Leonardo Laureti
+- Andrea Novero
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Italian]
+
+...
+*/
+
+MooTools.lang.set('it-IT', 'Form.Validator', {
+
+ required:'Il campo è obbligatorio.',
+ minLength:'Inserire almeno {minLength} caratteri (ne sono stati inseriti {length}).',
+ maxLength:'Inserire al massimo {maxLength} caratteri (ne sono stati inseriti {length}).',
+ integer:'Inserire un numero intero. Non sono consentiti decimali (es.: 1.25).',
+ numeric:'Inserire solo valori numerici (es.: "1" oppure "1.1" oppure "-1" oppure "-1.1").',
+ digits:'Inserire solo numeri e caratteri di punteggiatura. Per esempio è consentito un numero telefonico con trattini o punti.',
+ alpha:'Inserire solo lettere (a-z). Non sono consentiti spazi o altri caratteri.',
+ alphanum:'Inserire solo lettere (a-z) o numeri (0-9). Non sono consentiti spazi o altri caratteri.',
+ dateSuchAs:'Inserire una data valida del tipo {date}',
+ dateInFormatMDY:'Inserire una data valida nel formato MM/GG/AAAA (es.: "12/31/1999")',
+ email:'Inserire un indirizzo email valido. Per esempio "nome at dominio.com".',
+ url:'Inserire un indirizzo valido. Per esempio "http://www.dominio.com".',
+ currencyDollar:'Inserire un importo valido. Per esempio "$100.00".',
+ oneRequired:'Completare almeno uno dei campi richiesti.',
+ errorPrefix: 'Errore: ',
+ warningPrefix: 'Attenzione: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'Non sono consentiti spazi.',
+ reqChkByNode: 'Nessuna voce selezionata.',
+ requiredChk: 'Il campo è obbligatorio.',
+ reqChkByName: 'Selezionare un(a) {label}.',
+ match: 'Il valore deve corrispondere al campo {matchName}',
+ startDate: 'data d\'inizio',
+ endDate: 'data di fine',
+ currendDate: 'data attuale',
+ afterDate: 'La data deve corrispondere o essere successiva al {label}.',
+ beforeDate: 'La data deve corrispondere o essere precedente al {label}.',
+ startMonth: 'Selezionare un mese d\'inizio',
+ sameMonth: 'Le due date devono essere dello stesso mese - occorre modificarne una.'
+
+});/*
+---
+
+script: Form.Validator.Norwegian.js
+
+description: Form.Validator messages in Norwegian.
+
+license: MIT-style license
+
+authors:
+- Espen 'Rexxars' Hovlandsdal
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Norwegian]
+
+...
+*/
+
+MooTools.lang.set('no-NO', 'Form.Validator', {
+ required:'Dette feltet er pÃÂ¥krevd.',
+ minLength:'Vennligst skriv inn minst {minLength} tegn (du skrev {length} tegn).',
+ maxLength:'Vennligst skriv inn maksimalt {maxLength} tegn (du skrev {length} tegn).',
+ integer:'Vennligst skriv inn et tall i dette feltet. Tall med desimaler (for eksempel 1,25) er ikke tillat.',
+ numeric:'Vennligst skriv inn kun numeriske verdier i dette feltet (for eksempel "1", "1.1", "-1" eller "-1.1").',
+ digits:'Vennligst bruk kun nummer og skilletegn i dette feltet.',
+ alpha:'Vennligst bruk kun bokstaver (a-z) i dette feltet. Ingen mellomrom eller andre tegn er tillat.',
+ alphanum:'Vennligst bruk kun bokstaver (a-z) eller nummer (0-9) i dette feltet. Ingen mellomrom eller andre tegn er tillat.',
+ dateSuchAs:'Vennligst skriv inn en gyldig dato, som {date}',
+ dateInFormatMDY:'Vennligst skriv inn en gyldig dato, i formatet MM/DD/YYYY (for eksempel "12/31/1999")',
+ email:'Vennligst skriv inn en gyldig epost-adresse. For eksempel "espen at domene.no".',
+ url:'Vennligst skriv inn en gyldig URL, for eksempel http://www.google.no.',
+ currencyDollar:'Vennligst fyll ut et gyldig $ beløp. For eksempel $100.00 .',
+ oneRequired:'Vennligst fyll ut noe i minst ett av disse feltene.',
+ errorPrefix: 'Feil: ',
+ warningPrefix: 'Advarsel: '
+});/*
+---
+
+script: Form.Validator.Polish.js
+
+description: Date messages for Polish.
+
+license: MIT-style license
+
+authors:
+- Oskar Krawczyk
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Polish]
+
+...
+*/
+
+MooTools.lang.set('pl-PL', 'Form.Validator', {
+
+ required:'To pole jest wymagane.',
+ minLength:'Wymagane jest przynajmniej {minLength} znaków (wpisanych zostaÅo tylko {length}).',
+ maxLength:'Dozwolone jest nie wiÄcej niż {maxLength} znaków (wpisanych zostaÅo {length})',
+ integer:'To pole wymaga liczb caÅych. Liczby dziesiÄtne (np. 1.25) sÄ
niedozwolone.',
+ numeric:'Prosimy używaÄ tylko numerycznych wartoÅci w tym polu (np. "1", "1.1", "-1" lub "-1.1").',
+ digits:'Prosimy używaÄ liczb oraz zankow punktuacyjnych w typ polu (dla przykÅadu, przy numerze telefonu myÅlniki i kropki sÄ
dozwolone).',
+ alpha:'Prosimy używaÄ tylko liter (a-z) w tym polu. Spacje oraz inne znaki sÄ
niedozwolone.',
+ alphanum:'Prosimy używaÄ tylko liter (a-z) lub liczb (0-9) w tym polu. Spacje oraz inne znaki sÄ
niedozwolone.',
+ dateSuchAs:'Prosimy podaÄ prawidÅowÄ
datÄ w formacie: {date}',
+ dateInFormatMDY:'Prosimy podaÄ poprawnÄ
date w formacie DD.MM.RRRR (i.e. "12.01.2009")',
+ email:'Prosimy podaÄ prawidÅowy adres e-mail, np. "jan at domena.pl".',
+ url:'Prosimy podaÄ prawidÅowy adres URL, np. http://www.google.pl.',
+ currencyDollar:'Prosimy podaÄ prawidÅowÄ
sumÄ w PLN. Dla przykÅadu: 100.00 PLN.',
+ oneRequired:'Prosimy wypeÅniÄ chociaż jedno z pól.',
+ errorPrefix: 'BÅÄ
d: ',
+ warningPrefix: 'Uwaga: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'W tym polu nie mogÄ
znajdowaÄ siÄ spacje.',
+ reqChkByNode: 'Brak zaznaczonych elementów.',
+ requiredChk: 'To pole jest wymagane.',
+ reqChkByName: 'Prosimy wybraÄ z {label}.',
+ match: 'To pole musi byÄ takie samo jak {matchName}',
+ startDate: 'data poczÄ
tkowa',
+ endDate: 'data koÅcowa',
+ currendDate: 'aktualna data',
+ afterDate: 'Podana data poinna byÄ taka sama lub po {label}.',
+ beforeDate: 'Podana data poinna byÄ taka sama lub przed {label}.',
+ startMonth: 'Prosimy wybraÄ poczÄ
tkowy miesiÄ
c.',
+ sameMonth: 'Te dwie daty muszÄ
byÄ w zakresie tego samego miesiÄ
ca - wymagana jest zmiana któregoŠz pól.'
+
+});/*
+---
+
+script: Form.Validator.Portuguese.js
+
+description: Form.Validator messages in Portuguese.
+
+license: MIT-style license
+
+authors:
+- Miquel Hudin
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Portuguese]
+
+...
+*/
+
+MooTools.lang.set('pt-PT', 'Form.Validator', {
+ required:'Este campo é necessário.',
+ minLength:'Digite pelo menos{minLength} caracteres (comprimento {length} caracteres).',
+ maxLength:'Não insira mais de {maxLength} caracteres (comprimento {length} caracteres).',
+ integer:'Digite um número inteiro neste domÃnio. Com números decimais (por exemplo, 1,25), não são permitidas.',
+ numeric:'Digite apenas valores numéricos neste domÃnio (p.ex., "1" ou "1.1" ou "-1" ou "-1,1").',
+ digits:'Por favor, use números e pontuação apenas neste campo (p.ex., um número de telefone com traços ou pontos é permitida).',
+ alpha:'Por favor use somente letras (a-z), com nesta área. Não utilize espaços nem outros caracteres são permitidos.',
+ alphanum:'Use somente letras (a-z) ou números (0-9) neste campo. Não utilize espaços nem outros caracteres são permitidos.',
+ dateSuchAs:'Digite uma data válida, como {date}',
+ dateInFormatMDY:'Digite uma data válida, como DD/MM/YYYY (p.ex. "31/12/1999")',
+ email:'Digite um endereço de email válido. Por exemplo "fred at domain.com".',
+ url:'Digite uma URL válida, como http://www.google.com.',
+ currencyDollar:'Digite um valor válido $. Por exemplo $ 100,00. ',
+ oneRequired:'Digite algo para pelo menos um desses insumos.',
+ errorPrefix: 'Erro: ',
+ warningPrefix: 'Aviso: '
+
+}).set('pt-PT', 'Date', {
+ dateOrder: ['date', 'month', 'year', '/']
+});/*
+---
+
+script: Form.Validator.Portuguese.BR.js
+
+description: Form.Validator messages in Portuguese-BR.
+
+license: MIT-style license
+
+authors:
+- Fábio Miranda Costa
+
+requires:
+- /Lang
+- /Form.Validator.Portuguese
+
+provides: [Form.Validator.Portuguese.BR]
+
+...
+*/
+
+MooTools.lang.set('pt-BR', 'Form.Validator', {
+
+ required: 'Este campo é obrigatório.',
+ minLength: 'Digite pelo menos {minLength} caracteres (tamanho atual: {length}).',
+ maxLength: 'Não digite mais de {maxLength} caracteres (tamanho atual: {length}).',
+ integer: 'Por favor digite apenas um número inteiro neste campo. Não são permitidos números decimais (por exemplo, 1,25).',
+ numeric: 'Por favor digite apenas valores numéricos neste campo (por exemplo, "1" ou "1.1" ou "-1" ou "-1,1").',
+ digits: 'Por favor use apenas números e pontuação neste campo (por exemplo, um número de telefone com traços ou pontos é permitido).',
+ alpha: 'Por favor use somente letras (a-z). Espaço e outros caracteres não são permitidos.',
+ alphanum: 'Use somente letras (a-z) ou números (0-9) neste campo. Espaço e outros caracteres não são permitidos.',
+ dateSuchAs: 'Digite uma data válida, como {date}',
+ dateInFormatMDY: 'Digite uma data válida, como DD/MM/YYYY (por exemplo, "31/12/1999")',
+ email: 'Digite um endereço de email válido. Por exemplo "nome at dominio.com".',
+ url: 'Digite uma URL válida. Exemplo: http://www.google.com.',
+ currencyDollar: 'Digite um valor em dinheiro válido. Exemplo: R$100,00 .',
+ oneRequired: 'Digite algo para pelo menos um desses campos.',
+ errorPrefix: 'Erro: ',
+ warningPrefix: 'Aviso: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'Não é possÃvel digitar espaços neste campo.',
+ reqChkByNode: 'Não foi selecionado nenhum item.',
+ requiredChk: 'Este campo é obrigatório.',
+ reqChkByName: 'Por favor digite um {label}.',
+ match: 'Este campo deve ser igual ao campo {matchName}.',
+ startDate: 'a data inicial',
+ endDate: 'a data final',
+ currendDate: 'a data atual',
+ afterDate: 'A data deve ser igual ou posterior a {label}.',
+ beforeDate: 'A data deve ser igual ou anterior a {label}.',
+ startMonth: 'Por favor selecione uma data inicial.',
+ sameMonth: 'Estas duas datas devem ter o mesmo mês - você deve modificar uma das duas.',
+ creditcard: 'O número do cartão de crédito informado é inválido. Por favor verifique o valor e tente novamente. {length} números informados.'
+
+});/*
+---
+
+script: Form.Validator.Russian.js
+
+description: Form.Validator messages in Russian (utf-8 and cp1251).
+
+license: MIT-style license
+
+authors:
+- Chernodarov Egor
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Russian]
+
+...
+*/
+
+MooTools.lang.set('ru-RU-unicode', 'Form.Validator', {
+ required:'ÐÑо поле обÑ?заÑелÑно к заполнениÑ.',
+ minLength:'ÐожалÑйÑ?Ñа, введиÑе Ñ
оÑÑ? Ð±Ñ {minLength} Ñ?имволов (ÐÑ Ð²Ð²ÐµÐ»Ð¸ {length}).',
+ maxLength:'ÐожалÑйÑ?Ñа, введиÑе не болÑÑе {maxLength} Ñ?имволов (ÐÑ Ð²Ð²ÐµÐ»Ð¸ {length}).',
+ integer:'ÐожалÑйÑ?Ñа, введиÑе в Ñ?Ñо поле ÑиÑ?ло. ÐÑобнÑе ÑиÑ?ла (напÑÐ¸Ð¼ÐµÑ 1.25) ÑÑÑ Ð½Ðµ ÑазÑеÑенÑ.',
+ numeric:'ÐожалÑйÑ?Ñа, введиÑе в Ñ?Ñо поле ÑиÑ?ло (напÑÐ¸Ð¼ÐµÑ "1" или "1.1", или "-1", или "-1.1").',
+ digits:'Ð Ñ?Ñом поле ÐÑ Ð¼Ð¾Ð¶ÐµÑе иÑ?полÑзоваÑÑ ÑолÑко ÑиÑÑÑ Ð¸ знаки пÑнкÑÑаÑии (напÑимеÑ, ÑелеÑоннÑй Ð½Ð¾Ð¼ÐµÑ Ñ?о знаками деÑиÑ?а или Ñ? ÑоÑками).',
+ alpha:'Ð Ñ?Ñом поле можно иÑ?полÑзоваÑÑ ÑолÑко лаÑинÑ?кие бÑÐºÐ²Ñ (a-z). ÐÑÐ¾Ð±ÐµÐ»Ñ Ð¸ дÑÑгие Ñ?Ð¸Ð¼Ð²Ð¾Ð»Ñ Ð·Ð°Ð¿ÑеÑенÑ.',
+ alphanum:'Ð Ñ?Ñом поле можно иÑ?полÑзоваÑÑ ÑолÑко лаÑинÑ?кие бÑÐºÐ²Ñ (a-z) и ÑиÑÑÑ (0-9). ÐÑÐ¾Ð±ÐµÐ»Ñ Ð¸ дÑÑгие Ñ?Ð¸Ð¼Ð²Ð¾Ð»Ñ Ð·Ð°Ð¿ÑеÑенÑ.',
+ dateSuchAs:'ÐожалÑйÑ?Ñа, введиÑе коÑÑекÑнÑÑ Ð´Ð°ÑÑ {date}',
+ dateInFormatMDY:'ÐожалÑйÑ?Ñа, введиÑе даÑÑ Ð² ÑоÑмаÑе ÐÐ/ÐÐ/ÐÐÐÐ (напÑÐ¸Ð¼ÐµÑ "12/31/1999")',
+ email:'ÐожалÑйÑ?Ñа, введиÑе коÑÑекÑнÑй емейл-адÑеÑ?. ÐлÑ? пÑимеÑа "fred at domain.com".',
+ url:'ÐожалÑйÑ?Ñа, введиÑе пÑавилÑнÑÑ Ñ?Ñ?ÑÐ»ÐºÑ Ð²Ð¸Ð´Ð° http://www.google.com.',
+ currencyDollar:'ÐожалÑйÑ?Ñа, введиÑе Ñ?ÑÐ¼Ð¼Ñ Ð² доллаÑаÑ
. Ð?апÑимеÑ: $100.00 .',
+ oneRequired:'ÐожалÑйÑ?Ñа, вÑбеÑиÑе Ñ
оÑÑ ÑÑо-нибÑÐ´Ñ Ð² одном из Ñ?ÑиÑ
полей.',
+ errorPrefix: 'ÐÑибка: ',
+ warningPrefix: 'Ðнимание: '
+});
+
+//translation in windows-1251 codepage
+MooTools.lang.set('ru-RU', 'Form.Validator', {
+ required:'Ã?òî ïîëå îáÿçà òåëüÃî ê çà ïîëÃÃ¥Ãèþ.',
+ minLength:'Ã?îæà ëóéñòà , ââåäèòå õîòÿ áû {minLength} ñèìâîëîâ (Ãû ââåëè {length}).',
+ maxLength:'Ã?îæà ëóéñòà , ââåäèòå ÃÃ¥ áîëüøå {maxLength} ñèìâîëîâ (Ãû ââåëè {length}).',
+ integer:'Ã?îæà ëóéñòà , ââåäèòå â ýòî ïîëå ÷èñëî. ÃðîáÃûå ÷èñëà (Ãà ïðèìåð 1.25) òóò ÃÃ¥ ðà çðåøåÃû.',
+ numeric:'Ã?îæà ëóéñòà , ââåäèòå â ýòî ïîëå ÷èñëî (Ãà ïðèìåð "1" èëè "1.1", èëè "-1", èëè "-1.1").',
+ digits:'à ýòîì ïîëå Ãû ìîæåòå èñïîëüçîâà òü òîëüêî öèôðû è çÃà êè ïóÃêòóà öèè (Ãà ïðèìåð, òåëåôîÃÃûé Ãîìåð ñî çÃà êà ìè äåôèñà èëè ñ òî÷êà ìè).',
+ alpha:'à ýòîì ïîëå ìîæÃî èñïîëüçîâà òü òîëüêî ëà òèÃñêèå áóêâû (a-z). Ã?ðîáåëû è äðóãèå ñèìâîëû çà ïðåùåÃû.',
+ alphanum:'à ýòîì ïîëå ìîæÃî èñïîëüçîâà òü òîëüêî ëà òèÃñêèå áóêâû (a-z) è öèôðû (0-9). Ã?ðîáåëû è äðóãèå ñèìâîëû çà ïðåùåÃû.',
+ dateSuchAs:'Ã?îæà ëóéñòà , ââåäèòå êîððåêòÃóþ äà òó {date}',
+ dateInFormatMDY:'Ã?îæà ëóéñòà , ââåäèòå äà òó â ôîðìà òå ÃÃ/ÃÃ/ÃÃÃà (Ãà ïðèìåð "12/31/1999")',
+ email:'Ã?îæà ëóéñòà , ââåäèòå êîððåêòÃûé åìåéë-à äðåñ. Ãëÿ ïðèìåðà "fred at domain.com".',
+ url:'Ã?îæà ëóéñòà , ââåäèòå ïðà âèëüÃóþ ññûëêó âèäà http://www.google.com.',
+ currencyDollar:'�îæà ëóéñòà , ââåäèòå ñóììó â äîëëà ðà õ. �à ïðèìåð: $100.00 .',
+ oneRequired:'Ã?îæà ëóéñòà , âûáåðèòå õîòü ÷òî-Ãèáóäü â îäÃîì èç ýòèõ ïîëåé.',
+ errorPrefix: 'Ãøèáêà : ',
+ warningPrefix: 'ÃÃèìà Ãèå: '
+});/*
+---
+
+script: Form.Validator.Spanish.js
+
+description: Date messages for Spanish.
+
+license: MIT-style license
+
+authors:
+- Ãlfons Sanchez
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Spanish]
+
+...
+*/
+
+MooTools.lang.set('es-ES', 'Form.Validator', {
+
+ required:'Este campo es obligatorio.',
+ minLength:'Por favor introduce al menos {minLength} caracteres (has introducido {length} caracteres).',
+ maxLength:'Por favor introduce no más de {maxLength} caracteres (has introducido {length} caracteres).',
+ integer:'Por favor introduce un número entero en este campo. Números con decimales (p.e. 1,25) no se permiten.',
+ numeric:'Por favor introduce solo valores numéricos en este campo (p.e. "1" o "1,1" o "-1" o "-1,1").',
+ digits:'Por favor usa solo números y puntuación en este campo (por ejemplo, un número de teléfono con guiones y puntos no esta permitido).',
+ alpha:'Por favor usa letras solo (a-z) en este campo. No se admiten espacios ni otros caracteres.',
+ alphanum:'Por favor, usa solo letras (a-z) o números (0-9) en este campo. No se admiten espacios ni otros caracteres.',
+ dateSuchAs:'Por favor introduce una fecha válida como {date}',
+ dateInFormatMDY:'Por favor introduce una fecha válida como DD/MM/YYYY (p.e. "31/12/1999")',
+ email:'Por favor, introduce una dirección de email válida. Por ejemplo, "fred at domain.com".',
+ url:'Por favor introduce una URL válida como http://www.google.com.',
+ currencyDollar:'Por favor introduce una cantidad válida de â¬. Por ejemplo â¬100,00 .',
+ oneRequired:'Por favor introduce algo para por lo menos una de estas entradas.',
+ errorPrefix: 'Error: ',
+ warningPrefix: 'Aviso: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'No pueden haber espacios en esta entrada.',
+ reqChkByNode: 'No hay elementos seleccionados.',
+ requiredChk: 'Este campo es obligatorio.',
+ reqChkByName: 'Por favor selecciona una {label}.',
+ match: 'Este campo necesita coincidir con el campo {matchName}',
+ startDate: 'la fecha de inicio',
+ endDate: 'la fecha de fin',
+ currendDate: 'la fecha actual',
+ afterDate: 'La fecha debe ser igual o posterior a {label}.',
+ beforeDate: 'La fecha debe ser igual o anterior a {label}.',
+ startMonth: 'Por favor selecciona un mes de origen',
+ sameMonth: 'Estas dos fechas deben estar en el mismo mes - debes cambiar una u otra.'
+
+});
+/*
+---
+
+script: Form.Validator.Swedish.js
+
+description: Date messages for Swedish.
+
+license: MIT-style license
+
+authors:
+- Martin Lundgren
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Swedish]
+
+...
+*/
+
+MooTools.lang.set('sv-SE', 'Form.Validator', {
+
+ required:'Fältet är obligatoriskt.',
+ minLength:'Ange minst {minLength} tecken (du angav {length} tecken).',
+ maxLength:'Ange högst {maxLength} tecken (du angav {length} tecken). ',
+ integer:'Ange ett heltal i fältet. Tal med decimaler (t.ex. 1,25) är inte tillåtna.',
+ numeric:'Ange endast numeriska värden i detta fält (t.ex. "1" eller "1.1" eller "-1" eller "-1,1").',
+ digits:'Använd endast siffror och skiljetecken i detta fält (till exempel ett telefonnummer med bindestreck tillåtet).',
+ alpha:'Använd endast bokstäver (a-ö) i detta fält. Inga mellanslag eller andra tecken är tillåtna.',
+ alphanum:'Använd endast bokstäver (a-ö) och siffror (0-9) i detta fält. Inga mellanslag eller andra tecken är tillåtna.',
+ dateSuchAs:'Ange ett giltigt datum som t.ex. {date}',
+ dateInFormatMDY:'Ange ett giltigt datum som t.ex. YYYY-MM-DD (i.e. "1999-12-31")',
+ email:'Ange en giltig e-postadress. Till exempel "erik at domain.com".',
+ url:'Ange en giltig webbadress som http://www.google.com.',
+ currencyDollar:'Ange en giltig belopp. Exempelvis 100,00.',
+ oneRequired:'Vänligen ange minst ett av dessa alternativ.',
+ errorPrefix: 'Fel: ',
+ warningPrefix: 'Varning: ',
+
+ //Form.Validator.Extras
+
+ noSpace: 'Det får inte finnas några mellanslag i detta fält.',
+ reqChkByNode: 'Inga objekt är valda.',
+ requiredChk: 'Detta är ett obligatoriskt fält.',
+ reqChkByName: 'Välj en {label}.',
+ match: 'Detta fält måste matcha {matchName}',
+ startDate: 'startdatumet',
+ endDate: 'slutdatum',
+ currendDate: 'dagens datum',
+ afterDate: 'Datumet bör vara samma eller senare än {label}.',
+ beforeDate: 'Datumet bör vara samma eller tidigare än {label}.',
+ startMonth: 'Välj en start månad',
+ sameMonth: 'Dessa två datum måste vara i samma månad - du måste ändra det ena eller det andra.'
+
+});/*
+---
+
+script: Form.Validator.Ukrainian.js
+
+description: Form.Validator messages in Ukrainian (utf-8).
+
+license: MIT-style license
+
+authors:
+- Slik
+
+requires:
+- /Lang
+- /Form.Validator
+
+provides: [Form.Validator.Ukrainian]
+
+...
+*/
+
+MooTools.lang.set('uk-UA', 'Form.Validator', {
+ required:'Це поле повинне бÑÑи заповненим.',
+ minLength:'ÐведÑÑÑ Ñ
оÑа б {minLength} Ñ?имволÑв (Ðи ввели {length}).',
+ maxLength:'ÐÑлÑкÑÑ?ÑÑ Ñ?имволÑв не може бÑÑи бÑлÑÑе {maxLength} (Ðи ввели {length}).',
+ integer:'ÐведÑÑÑ Ð² Ñе поле ÑиÑ?ло. ÐÑÐ¾Ð±Ð¾Ð²Ñ ÑиÑ?ла (напÑиклад 1.25) не дозволенÑ.',
+ numeric:'ÐведÑÑÑ Ð² Ñе поле ÑиÑ?ло (напÑиклад "1" або "1.1", або "-1", або "-1.1").',
+ digits:'Ð ÑÑÐ¾Ð¼Ñ Ð¿Ð¾Ð»Ñ Ð²Ð¸ можеÑе викоÑиÑ?ÑовÑваÑи лиÑе ÑиÑÑи Ñ Ð·Ð½Ð°ÐºÐ¸ пÑнкÑÑаÑÑÑ (напÑиклад, ÑелеÑонний Ð½Ð¾Ð¼ÐµÑ Ð· знаками деÑÑÐ·Ñ Ð°Ð±Ð¾ з кÑапками).',
+ alpha:'Ð ÑÑÐ¾Ð¼Ñ Ð¿Ð¾Ð»Ñ Ð¼Ð¾Ð¶Ð½Ð° викоÑиÑ?ÑовÑваÑи лиÑе лаÑинÑ?ÑÐºÑ Ð»ÑÑеÑи (a-z). ÐÑобÑли Ñ ÑнÑÑ Ñ?имволи забоÑоненÑ.',
+ alphanum:'Ð ÑÑÐ¾Ð¼Ñ Ð¿Ð¾Ð»Ñ Ð¼Ð¾Ð¶Ð½Ð° викоÑиÑ?ÑовÑваÑи лиÑе лаÑинÑ?ÑÐºÑ Ð»ÑÑеÑи (a-z) Ñ ÑиÑÑи (0-9). ÐÑобÑли Ñ ÑнÑÑ Ñ?имволи забоÑоненÑ.',
+ dateSuchAs:'ÐведÑÑÑ ÐºÐ¾ÑекÑÐ½Ñ Ð´Ð°ÑÑ {date}.',
+ dateInFormatMDY:'ÐведÑÑÑ Ð´Ð°ÑÑ Ð² ÑоÑмаÑÑ ÐÐ/ÐÐ/Ð Ð Ð Ð (напÑиклад "12/31/2009").',
+ email:'ÐведÑÑÑ ÐºÐ¾ÑекÑÐ½Ñ Ð°Ð´ÑеÑ?Ñ ÐµÐ»ÐµÐºÑÑÐ¾Ð½Ð½Ð¾Ñ Ð¿Ð¾ÑÑи (напÑиклад "name at domain.com").',
+ url:'ÐведÑÑÑ ÐºÐ¾ÑекÑне ÑнÑеÑнеÑ-поÑ?иланнÑ? (напÑиклад http://www.google.com).',
+ currencyDollar:'ÐведÑÑÑ Ñ?ÑÐ¼Ñ Ð² долаÑаÑ
(напÑиклад "$100.00").',
+ oneRequired:'ÐаповнÑÑÑ Ð¾Ð´Ð½Ðµ з полÑв.',
+ errorPrefix: 'Ðомилка: ',
+ warningPrefix: 'Увага: '
+});
+// $Id: common.js 746 2010-03-12 12:57:45Z pagameba $
/**
* Class: Jx
* Jx is a global singleton object that contains the entire Jx library
@@ -13860,7 +14595,7 @@
/* firebug console supressor for IE/Safari/Opera */
window.addEvent('load',
function() {
- if (! ("console" in window) || !("firebug" in window.console)) {
+ if (! ("console" in window)) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
"group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
@@ -13885,6 +14620,8 @@
}
};
+// this replaces the mootools $unlink method with our own version that
+// avoids infinite recursion on Jx objects.
function $unlink(object) {
if (object && object.jxFamily) {
return object;
@@ -13908,67 +14645,141 @@
return unlinked;
}
-/* Setup global namespace
- * If jxcore is loaded by jx.js, then the namespace and baseURL are
- * already established
+/* Setup global namespace. It is possible to set the global namespace
+ * prior to including jxlib. This would typically be required only if
+ * the auto-detection of the jxlib base URL would fail. For instance,
+ * if you combine jxlib with other javascript libraries into a single file
+ * build and call it something without jxlib in the file name, then the
+ * detection of baseURL would fail. If this happens to you, try adding
+ * Jx = { baseURL: '/path/to/jxlib/'; }
+ * where the path to jxlib contains a file called a_pixel.png (it doesn't
+ * have to include jxlib, just the a_pixel.png file).
*/
if (typeof Jx === 'undefined') {
- var Jx = {};
- (function() {
- var aScripts = document.getElementsByTagName('SCRIPT');
- for (var i = 0; i < aScripts.length; i++) {
- var s = aScripts[i].src;
- var matches = /(.*[jx|js|lib])\/jxlib(.*)/.exec(s);
- if (matches && matches[0]) {
- /**
- * APIProperty: {String} baseURL
- * This is the URL that Jx was loaded from, it is
- * automatically calculated from the script tag
- * src property that included Jx.
- *
- * Note that this assumes that you are loading Jx
- * from a js/ or lib/ folder in parallel to the
- * images/ folder that contains the various images
- * needed by Jx components. If you have a different
- * folder structure, you can define Jx's base
- * by including the following before including
- * the jxlib javascript file:
- *
- * (code)
- * Jx = {
- * baseURL: 'some/path'
- * }
- * (end)
- */
- Jx.aPixel = document.createElement('img', {
- alt: '',
- title: ''
- });
- Jx.aPixel.src = matches[1] + '/a_pixel.png';
- Jx.baseURL = Jx.aPixel.src.substring(0,
- Jx.aPixel.src.indexOf('a_pixel.png'));
-
- }
- }
-
- })();
+ var Jx = {};
}
- (function() {
- /**
- * Determine if we're running in Adobe AIR. Run this regardless of whether
- * the above runs or not.
- */
+/**
+ * APIProperty: {String} baseURL
+ * This is the URL that Jx was loaded from, it is
+ * automatically calculated from the script tag
+ * src property that included Jx.
+ *
+ * Note that this assumes that you are loading Jx
+ * from a js/ or lib/ folder in parallel to the
+ * images/ folder that contains the various images
+ * needed by Jx components. If you have a different
+ * folder structure, you can define Jx's base
+ * by including the following before including
+ * the jxlib javascript file:
+ *
+ * (code)
+ * Jx = {
+ * baseURL: 'some/path'
+ * }
+ * (end)
+ */
+if (!$defined(Jx.baseURL)) {
+ (function() {
var aScripts = document.getElementsByTagName('SCRIPT');
- var src = aScripts[0].src;
- if (src.contains('app:')) {
- Jx.isAir = true;
- } else {
- Jx.isAir = false;
+ for (var i = 0; i < aScripts.length; i++) {
+ var s = aScripts[i].src;
+ var n = s.lastIndexOf('/');
+ var file = s.slice(n+1,s.length-1);
+ if (file.contains('jxlib')) {
+ Jx.baseURL = s.slice(0,n);
+ break;
+ }
}
-})();
+ })();
+}
+/**
+ * APIProperty: {Image} aPixel
+ * aPixel is a single transparent pixel and is the only image we actually
+ * use directly in JxLib code. If you want to use your own transparent pixel
+ * image or use it from a different location than the install of jxlib
+ * javascript files, you can manually declare it before including jxlib code
+ * (code)
+ * Jx = {
+ * aPixel: new Element('img', {
+ * alt: '',
+ * title: '',
+ * width: 1,
+ * height: 1,
+ * src: 'path/to/a/transparent.png'
+ * });
+ * }
+ * (end)
+ */
+if (!$defined(Jx.aPixel)) {
+ Jx.aPixel = new Element('img', {
+ alt:'',
+ title:'',
+ src: Jx.baseURL +'/a_pixel.png'
+ });
+}
+/**
+ * APIProperty: {Boolean} isAir
+ * indicates if JxLib is running in an Adobe Air environment. This is
+ * normally auto-detected but you can manually set it by declaring the Jx
+ * namespace before including jxlib:
+ * (code)
+ * Jx = {
+ * isAir: true
+ * }
+ * (end)
+ */
+if (!$defined(Jx.isAir)) {
+ (function() {
+ /**
+ * Determine if we're running in Adobe AIR. Run this regardless of whether
+ * the above runs or not.
+ */
+ var aScripts = document.getElementsByTagName('SCRIPT');
+ var src = aScripts[0].src;
+ if (src.contains('app:')) {
+ Jx.isAir = true;
+ } else {
+ Jx.isAir = false;
+ }
+ })();
+}
+
/**
+ * APIMethod: setLanguage
+ * set the current language to be used by Jx widgets. This uses the MooTools
+ * lang module. If an invalid or missing language is requested, the default
+ * rules of MooTools.lang will be used (revert to en-US at time of writing).
+ *
+ * Parameters:
+ * {String} language identifier, the language to set.
+ */
+Jx.setLanguage = function(lang) {
+ Jx.lang = lang;
+ MooTools.lang.setLanguage(Jx.lang);
+};
+
+/**
+ * APIProperty: {String} lang
+ * Checks to see if Jx.lang is already set. If not, it sets it to the default
+ * 'en-US'. We will then set the Motools.lang language to this setting
+ * automatically.
+ *
+ * The language can be changed on the fly at anytime by calling
+ * Jx.setLanguage().
+ * By default all Jx.Widget subclasses will listen for the langChange event of
+ * the Mootools.lang class. It will then call a method, changeText(), if it
+ * exists on the particular widget. You will be able to disable listening for
+ * these changes by setting the Jx.Widget option useLang to false.
+ */
+if (!$defined(Jx.lang)) {
+ Jx.lang = 'en-US';
+}
+
+Jx.setLanguage(Jx.lang);
+
+/**
* APIMethod: applyPNGFilter
*
* Static method that applies the PNG Filter Hack for IE browsers
@@ -14060,26 +14871,6 @@
};
/**
- * APIMethod: createIframeShim
- * Creates a new iframe element that is intended to fill a container
- * to mask out other operating system controls (scrollbars, inputs,
- * buttons, etc) when HTML elements are supposed to be above them.
- *
- * Returns:
- * an HTML iframe element that can be inserted into the DOM.
- */
-/**
- * NOTE: This could be replaced by Mootools-more's IFrameShim class.
- */
-Jx.createIframeShim = function() {
- return new Element('iframe', {
- 'class': 'jxIframeShim',
- 'scrolling': 'no',
- 'frameborder': 0,
- 'src': Jx.baseURL + '/empty.html'
- });
-};
-/**
* APIMethod: getNumber
* safely parse a number and return its integer value. A NaN value
* returns 0. CSS size values are also parsed correctly.
@@ -14111,7 +14902,7 @@
};
/**
- * APIMethod: Jx.type
+ * APIMethod: type
* safely return the type of an object using the mootools type system
*
* Returns:
@@ -14125,27 +14916,26 @@
return obj.jxFamily || $type(obj);
};
-/**
- * Class: Element
- *
- * Element is a global object provided by the mootools library. The
- * functions documented here are extensions to the Element object provided
- * by Jx to make cross-browser compatibility easier to achieve. Most of the
- * methods are measurement related.
- *
- * While the code in these methods has been converted to use MooTools methods,
- * there may be better MooTools methods to use to accomplish these things.
- * Ultimately, it would be nice to eliminate most or all of these and find the
- * MooTools equivalent or convince MooTools to add them.
- *
- * NOTE: Many of these methods can be replaced with mootools-more's
- * Element.Measure
- */
-
-
(function($) {
// Wrapper for document.id
+ /**
+ * Class: Element
+ *
+ * Element is a global object provided by the mootools library. The
+ * functions documented here are extensions to the Element object provided
+ * by Jx to make cross-browser compatibility easier to achieve. Most of
+ * the methods are measurement related.
+ *
+ * While the code in these methods has been converted to use MooTools
+ * methods, there may be better MooTools methods to use to accomplish
+ * these things.
+ * Ultimately, it would be nice to eliminate most or all of these and find
+ * the MooTools equivalent or convince MooTools to add them.
+ *
+ * NOTE: Many of these methods can be replaced with mootools-more's
+ * Element.Measure
+ */
Element.implement({
/**
* APIMethod: getBoxSizing
@@ -14401,9 +15191,11 @@
return o.tagName == type ? o: false;
}
});
-
+ /**
+ * Class: Array
+ * Extensions to the javascript array object
+ */
Array.implement({
-
/**
* APIMethod: swap
* swaps 2 elements of an array
@@ -14413,14 +15205,11 @@
* b - the second position to swap
*/
'swap': function(a, b) {
- var temp;
- temp = this[a];
+ var temp = this[a];
this[a] = this[b];
this[b] = temp;
}
-
});
-
})(document.id || $);
// End Wrapper for document.id
/**
@@ -14452,14 +15241,14 @@
*/
Jx.Styles = new(new Class({
/**
- * dynamicStyleMap - <Hash> used to keep a reference to dynamically created
- * style sheets for quick access
+ * dynamicStyleMap - <Hash> used to keep a reference to dynamically
+ * created style sheets for quick access
*/
dynamicStyleMap: new Hash(),
/**
- * Method: getCssRule
- * retrieve a reference to a CSS rule in a specific style sheet based on its
- * selector. If the rule does not exist, create it.
+ * APIMethod: getCssRule
+ * retrieve a reference to a CSS rule in a specific style sheet based on
+ * its selector. If the rule does not exist, create it.
*
* Parameters:
* selector - <String> the CSS selector for the rule
@@ -14486,22 +15275,22 @@
return rule;
},
/**
- * Method: insertCssRule
+ * APIMethod: insertCssRule
* insert a new dynamic rule into the given stylesheet. If no name is
* given for the stylesheet then the default stylesheet is used.
*
* Parameters:
* selector - <String> the CSS selector for the rule
- * declaration - <String> CSS-formatted rules to include. May be empty, in
- * which case you may want to use the returned rule object to manipulate
- * styles
+ * declaration - <String> CSS-formatted rules to include. May be empty,
+ * in which case you may want to use the returned rule object to
+ * manipulate styles
* styleSheetName - <String> the name of the sheet to place the rules in,
* or empty to put them in a default sheet.
*
* Returns:
* <CSSRule> - a CSS Rule object with properties that are browser
- * dependent. In general, you can use rule.styles to set any CSS properties
- * in the same way that you would set them on a DOM object.
+ * dependent. In general, you can use rule.styles to set any CSS
+ * properties in the same way that you would set them on a DOM object.
*/
insertCssRule: function (selector, declaration, styleSheetName) {
var ss = this.getDynamicStyleSheet(styleSheetName);
@@ -14518,13 +15307,13 @@
return rule;
},
/**
- * Method: removeCssRule
+ * APIMethod: removeCssRule
* removes a CSS rule from the named stylesheet.
*
* Parameters:
* selector - <String> the CSS selector for the rule
- * styleSheetName - <String> the name of the sheet to remove the rule from,
- * or empty to remove them from the default sheet.
+ * styleSheetName - <String> the name of the sheet to remove the rule
+ * from, or empty to remove them from the default sheet.
*
* Returns:
* <Boolean> true if the rule was removed, false if it was not.
@@ -14543,7 +15332,7 @@
return false;
},
/**
- * Method: getDynamicStyleSheet
+ * APIMethod: getDynamicStyleSheet
* return a reference to a styleSheet based on its title. If the sheet
* does not already exist, it is created.
*
@@ -14556,13 +15345,14 @@
getDynamicStyleSheet: function (name) {
name = (name) ? name : 'default';
if (!this.dynamicStyleMap.has(name)) {
- var sheet = new Element('style').set('type', 'text/css').set('title', name).inject(document.head);
+ var sheet = new Element('style').set('type', 'text/css').inject(document.head);
sheet.indicies = [];
this.dynamicStyleMap.set(name, sheet);
}
return this.dynamicStyleMap.get(name);
},
- /* Method: enableStyleSheet
+ /**
+ * APIMethod: enableStyleSheet
* enable a style sheet
*
* Parameters:
@@ -14571,7 +15361,8 @@
enableStyleSheet: function (name) {
this.getDynamicStyleSheet(name).disabled = false;
},
- /* Method: disableStyleSheet
+ /**
+ * APIMethod: disableStyleSheet
* enable a style sheet
*
* Parameters:
@@ -14579,18 +15370,208 @@
*/
disableStyleSheet: function (name) {
this.getDynamicStyleSheet(name).disabled = true;
+ },
+ /**
+ * APIMethod: removeStyleSheet
+ * Removes a style sheet
+ *
+ * Parameters:
+ * name = <String> the title of the stylesheet to remove
+ */
+ removeStyleSheet: function (name) {
+ this.disableStyleSheet(name);
+ this.getDynamicStyleSheet(name).dispose();
+ this.dynamicStyleMap.erase(name);
+ },
+ /**
+ * APIMethod: isStyleSheetDefined
+ * Determined if the passed in name is a defined dynamic style sheet.
+ *
+ * Parameters:
+ * name = <String> the title of the stylesheet to remove
+ */
+ isStyleSheetDefined: function (name) {
+ return this.dynamicStyleMap.has(name);
}
-}))();// $Id: $
+}))();// $Id: object.js 777 2010-03-24 06:00:30Z jonlb at comcast.net $
/**
* Class: Jx.Object
* Base class for all other object in the JxLib framework. This class
* implements both mootools mixins Events and Options so the rest of the
* classes don't need to.
*
- * Example:
+ * The Initialization Pipeline:
+ * Jx.Object provides a default initialize method to construct new instances
+ * of objects that inherit from it. No sub-class should override initialize
+ * unless you know exactly what you're doing. Instead, the initialization
+ * pipeline provides an init() method that is intended to be overridden in
+ * sub-classes to provide class-specific initialization as part of the
+ * initialization pipeline.
+ *
+ * The basic initialization pipeline for a Jx.Object is to parse the
+ * parameters provided to initialize(), separate out options from other formal
+ * parameters based on the parameters property of the class, call init() and
+ * initialize plugins.
+ *
+ * Parsing Parameters:
+ * Because each sub-class no longer has an initialize method, it no longer has
+ * direct access to parameters passed to the constructor. Instead, a
+ * sub-class is expected to provide a parameters attribute with an array of
+ * parameter names in the order expected. Jx.Object will enumerate the
+ * attributes passed to its initialize method and automatically place them
+ * in the options object under the appropriate key (the value from the
+ * array). Parameters not found will not be present or will be null.
+ *
+ * The default parameters are a single options object which is merged with
+ * the options attribute of the class.
+ *
+ * Calling Init:
+ * Jx.Object fires the event 'preInit' before calling the init() method,
+ * calls the init() method, then fires the 'postInit' event. It is expected
+ * that most sub-class specific initialization will happen in the init()
+ * method. A sub-class may hook preInit and postInit events to perform tasks
+ * in one of two ways.
+ *
+ * First, simply send onPreInit and onPostInit functions via the options
+ * object as follows (they could be standalone functions or functions of
+ * another object setup using .bind())
+ *
* (code)
+ * var preInit = function () {}
+ * var postInit = function () {}
+ *
+ * var options = {
+ * onPreInit: preInit,
+ * onPostInit: postInit,
+ * ...other options...
+ * };
+ *
+ * var dialog = new Jx.Dialog(options);
* (end)
+ *
+ * The second method you can use is to override the initialize method
*
+ * (code)
+ * var MyClass = new Class({
+ * Family: 'MyClass',
+ * initialize: function() {
+ * this.addEvent('preInit', this.preInit.bind(this));
+ * this.addEvent('postInit', this.postInit.bind(this));
+ * this.parent.apply(this, arguments);
+ * },
+ * preInit: function() {
+ * // something just before init() is called
+ * },
+ * postInit: function() {
+ * // something just after init() is called
+ * },
+ * init: function() {
+ * this.parent();
+ * // initialization code here
+ * }
+ * });
+ * (end)
+ *
+ * When the object finishes initializing itself (including the plugin
+ * initialization) it will fire off the initializeDone event. You can hook
+ * into this event in the same way as the events mentioned above.
+ *
+ * Plugins:
+ * Plugins provide pieces of additional, optional, functionality. They are not
+ * necessary for the proper function of an object. All plugins should be
+ * located in the Jx.Plugin namespace and they should be further segregated by
+ * applicable object. While all objects can support plugins, not all of them
+ * have the automatic instantiation of applicable plugins turned on. In order
+ * to turn this feature on for an object you need to set the pluginNamespace
+ * property of the object. The following is an example of setting the
+ * property:
+ *
+ * (code)
+ * var MyClass = new Class({
+ * Extends: Jx.Object,
+ * pluginNamespace: 'MyClass'
+ * };
+ * (end)
+ *
+ * The absence of this property does not mean you cannot attach a plugin to an
+ * object. It simply means that you can't have Jx.Object create the
+ * plugin for you.
+ *
+ * There are four ways to attach a plugin to an object. First, simply
+ * instantiate the plugin yourself and call its attach() method (other class
+ * options left out for the sake of simplicity):
+ *
+ * (code)
+ * var MyGrid = new Jx.Grid();
+ * var APlugin = new Jx.Plugin.Grid.Selector();
+ * APlugin.attach(MyGrid);
+ * (end)
+ *
+ * Second, you can instantiate the plugin first and pass it to the object
+ * through the plugins array in the options object.
+ *
+ * (code)
+ * var APlugin = new Jx.Plugin.Grid.Selector();
+ * var MyGrid = new Jx.Grid({plugins: [APlugin]});
+ * (end)
+ *
+ * The third way is to pass the information needed to instantiate the plugin
+ * in the plugins array of the options object:
+ *
+ * (code)
+ * var MyGrid = new Jx.Grid({
+ * plugins: [{
+ * name: 'Selector',
+ * options: {} //options needed to create this plugin
+ * },{
+ * name: 'Sorter',
+ * options: {}
+ * }]
+ * });
+ * (end)
+ *
+ * The final way, if the plugin has no options, is to pass the name of the
+ * plugin as a simple string in the plugins array.
+ *
+ * (code)
+ * var MyGrid = new Jx.Grid({
+ * plugins: ['Selector','Sorter']
+ * });
+ * (end)
+ *
+ * Part of the process of initializing plugins is to call prePluginInit() and
+ * postPluginInit(). These events provide you access to the object just before
+ * and after the plugins are initialized and/or attached to the object using
+ * methods 2 and 3 above. You can hook into these in the same way that you
+ * hook into the preInit() and postInit() events.
+ *
+ * Destroying Jx.Object Instances:
+ * Jx.Object provides a destroy method that cleans up potential memory leaks
+ * when you no longer need an object. Sub-classes are expected to implement
+ * a cleanup() method that provides specific cleanup code for each
+ * sub-class. Remember to call this.parent() when providing a cleanup()
+ * method. Destroy will also fire off 2 events: preDestroy and postDestroy.
+ * You can hook into these methods in the same way as the init or plugin
+ * events.
+ *
+ * The Family Attribute:
+ * the Family attribute of a class is used internally by JxLib to identify Jx
+ * objects within mootools. The actual value of Family is unimportant to Jx.
+ * If you do not provide a Family, a class will inherit it's base class family
+ * up to Jx.Object. Family is useful when debugging as you will be able to
+ * identify the family in the firebug inspector, but is not as useful for
+ * coding purposes as it does not allow for inheritance.
+ *
+ * Events:
+ *
+ * preInit
+ * postInit
+ * prePluginInit
+ * postPluginInit
+ * initializeDone
+ * preDestroy
+ * postDestroy
+ *
* License:
* Copyright (c) 2009, Jon Bomgardner.
*
@@ -14599,9 +15580,33 @@
Jx.Object = new Class({
Family: "Jx.Object",
Implements: [Options, Events],
+ Binds: ['changeText'],
plugins: new Hash(),
pluginNamespace: 'Other',
+ /**
+ * Constructor: Jx.Object
+ * create a new instance of Jx.Object
+ *
+ * Parameters:
+ * options - {Object} optional parameters for creating an object.
+ */
parameters: ['options'],
+
+ options: {
+ /**
+ * Option: useLang
+ * Turns on this widget's ability to react to changes in
+ * the default language. Handy for changing text out on the fly.
+ *
+ * TODO: Should this be enabled or disabled by default?
+ */
+ useLang: true,
+ /**
+ * Option: plugins
+ * {Array} an array of plugins to add to the object.
+ */
+ plugins: null
+ },
initialize: function(){
//normalize arguments
@@ -14634,6 +15639,9 @@
}
this.setOptions(options);
+ if (this.options.useLang) {
+ MooTools.lang.addEvent('langChange', this.changeText)
+ }
this.fireEvent('preInit');
this.init();
this.fireEvent('postInit');
@@ -14643,8 +15651,13 @@
this.fireEvent('initializeDone');
},
+ /**
+ * Method: initPlugins
+ * internal function to initialize plugins on object creation
+ */
initPlugins: function () {
- //pluginNamespace must be defined in order to pass plugins to the object
+ // pluginNamespace must be defined in order to pass plugins to the
+ // object
if ($defined(this.pluginNamespace)) {
if ($defined(this.options.plugins)
&& Jx.type(this.options.plugins) === 'array') {
@@ -14653,24 +15666,52 @@
plugin.attach(this);
this.plugins.set(plugin.name, plugin);
} else if (Jx.type(plugin) === 'object') {
- //All plugin-enabled objects should define a pluginNamespace member variable
- //that is used for locating the plugins. The default namespace is 'Other' for
- //now until we come up with a better idea
- var p = new Jx.Plugin[this.pluginNamespace][plugin.name](plugin.options);
+ // All plugin-enabled objects should define a
+ // pluginNamespace member variable
+ // that is used for locating the plugins. The default
+ // namespace is 'Other' for
+ // now until we come up with a better idea
+ var p;
+ if ($defined(Jx.Plugin[this.pluginNamespace][plugin.name.capitalize()])) {
+ p = new Jx.Plugin[this.pluginNamespace][plugin.name.capitalize()](plugin.options);
+ } else {
+ p = new Jx.Adaptor[this.pluginNamespace][plugin.name.capitalize()](plugin.options);
+ }
p.attach(this);
- this.plugins.set(p.name, p);
+ } else if (Jx.type(plugin) === 'string') {
+ //this is a name for a plugin.
+ var p;
+ if ($defined(Jx.Plugin[this.pluginNamespace][plugin.capitalize()])) {
+ p = new Jx.Plugin[this.pluginNamespace][plugin.capitalize()]();
+ } else {
+ p = new Jx.Adaptor[this.pluginNamespace][plugin.capitalize()]();
+ }
+ p.attach(this);
}
}, this);
}
}
},
+ /**
+ * APIMethod: destroy
+ * destroy a Jx.Object, safely cleaning up any potential memory
+ * leaks along the way. Uses the cleanup method of an object to
+ * actually do the cleanup.
+ * Emits the preDestroy event before cleanup and the postDestroy event
+ * after cleanup.
+ */
destroy: function () {
this.fireEvent('preDestroy');
this.cleanup();
this.fireEvent('postDestroy');
},
+ /**
+ * Method: cleanup
+ * to be implemented by subclasses to do the actual work of destroying
+ * an object.
+ */
cleanup: function () {
//detach plugins
if (this.plugins.getLength > 0) {
@@ -14681,22 +15722,140 @@
}
},
+ /**
+ * Method: init
+ * virtual initialization method to be implemented by sub-classes
+ */
init: $empty,
-
+
+ /**
+ * APIMethod: registerPlugin
+ * This method is called by a plugin that has its attach method
+ * called.
+ *
+ * Parameters:
+ * plugin - the plugin to register with this object
+ */
registerPlugin: function (plugin) {
if (!this.plugins.has(plugin.name)) {
this.plugins.set(plugin.name, plugin);
}
},
-
+ /**
+ * APIMethod: deregisterPlugin
+ * his method is called by a plugin that has its detach method
+ * called.
+ *
+ * Parameters:
+ * plugin - the plugin to deregister.
+ */
deregisterPlugin: function (plugin) {
if (this.plugins.has(plugin.name)) {
this.plugins.erase(plugin.name);
}
- }
+ },
+
+ /**
+ * APIMethod: getPlugin
+ * Allows a developer to get a reference to a plugin with only the
+ * name of the plugin.
+ *
+ * Parameters:
+ * name - the name of the plugin as defined in the plugin's name property
+ */
+ getPlugin: function (name) {
+ if (this.plugins.has(name)) {
+ return this.plugins.get(name);
+ }
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: $empty
});
-// $Id: $
+
+MooTools.lang.set('en-US', 'Jx', {
+
+ 'widget': {
+ busyMessage: 'Working ...'
+ },
+ 'colorpalette': {
+ alphaLabel: 'alpha (%)'
+ },
+ notice: {
+ closeTip: 'close this notice'
+ },
+ progressbar: {
+ messageText: 'Loading...',
+ progressText: '{progress} of {total}'
+ },
+ field: {
+ requiredText: '*'
+ },
+ file: {
+ browseLabel: 'Browse...'
+ },
+ 'formatter.boolean': {
+ 'true': 'Yes',
+ 'false': 'No'
+ },
+ 'formatter.currency': {
+ sign: '$'
+ },
+ 'formatter.number': {
+ decimalSeparator: '.',
+ thousandsSeparator: ','
+ },
+ splitter: {
+ barToolTip: 'drag this bar to resize'
+ },
+ panel: {
+ collapseTooltip: 'Collapse/Expand Panel',
+ collapseLabel: 'Collapse',
+ expandLabel: 'Expand',
+ maximizeTooltip: 'Maximize Panel',
+ maximizeLabel: 'Maximize',
+ restoreTooltip: 'Restore Panel',
+ restoreLabel: 'Restore',
+ closeTooltip: 'Close Panel',
+ closeLabel: 'Close'
+ },
+ confirm: {
+ affirmitiveLabel: 'Yes',
+ negativeLabel: 'No'
+ },
+ dialog: {
+ resizeToolTip: 'Resize dialog'
+ },
+ message: {
+ okButton: 'Ok'
+ },
+ panelset: {
+ barTooltip: 'drag this bar to resize'
+ },
+ prompt: {
+ okButton: 'Ok',
+ cancelButton: 'Cancel'
+ },
+ upload: {
+ buttonText: 'Upload Files'
+ },
+ 'plugin.resize': {
+ tooltip: 'Drag to resize, double click to auto-size.'
+ },
+ 'plugin.editor': {
+ submitButton: 'Save',
+ cancelButton: 'Cancel'
+ }
+});// $Id: widget.js 781 2010-03-25 13:24:27Z zak4ms $
/**
* Class: Jx.Widget
* Base class for all widgets (visual classes) in the JxLib Framework. This
@@ -14719,10 +15878,10 @@
*
* Chrome:
*
- * Chrome is the extraneous visual element that provides the look and feel to some elements
- * i.e. dialogs. Chrome is added inside the element specified but may
- * bleed outside the element to provide drop shadows etc. This is done by
- * absolutely positioning the chrome objects in the container based on
+ * Chrome is the extraneous visual element that provides the look and feel to
+ * some elements i.e. dialogs. Chrome is added inside the element specified
+ * but may bleed outside the element to provide drop shadows etc. This is
+ * done by absolutely positioning the chrome objects in the container based on
* calculations using the margins, borders, and padding of the jxChrome
* class and the element it is added to.
*
@@ -14734,18 +15893,37 @@
* and height. The images are positioned and clipped such that the
* appropriate corners of the chrome image are displayed in those locations.
*
+ * Busy States:
+ *
+ * Any widget can be set as temporarily busy by calling the setBusy(true)
+ * method and then as idle by calling setBusy(false). By default, busy
+ * widgets display an event mask that prevents them from being clicked and
+ * a spinner image with a message. By default, there are two configurations
+ * for the spinner image and message, one for 'small' widgets like buttons
+ * and inputs, and one for larger widgets like panels and dialogs. The
+ * framework automatically chooses the most appropriate configuration so you
+ * don't need to worry about it unless you want to customize it.
*
+ * You can disable this behaviour entirely by setting busyMask: false in the
+ * widget options when creating the widget.
+ *
+ * The mask and spinner functionality is provided by the MooTools Spinner
+ * class. You can use any options documented for Spinner or Mask by setting
+ * the maskOptions option when creating a widget.
+ *
+ * MooTools.Lang Keys:
+ * widget.busyMessage - sets the message of the waiter component when used
*/
Jx.Widget = new Class({
Family: "Jx.Widget",
Extends: Jx.Object,
-
+
options: {
/**
* Option: content
* content may be an HTML element reference, the id of an HTML element
- * already in the DOM, or an HTML string that becomes the inner HTML of
- * the element.
+ * already in the DOM, or an HTML string that becomes the inner HTML
+ * of the element.
*/
content: null,
/**
@@ -14753,12 +15931,55 @@
* the URL to load content from
*/
contentURL: null,
- template: '<div class="jxWidget"></div>'
+ /**
+ * Option: template
+ * the default HTML structure of this widget. The default template
+ * is just a div with a class of jxWidget in the base class
+ */
+ template: '<div class="jxWidget"></div>',
+ /**
+ * Option: busyClass
+ * {String} a CSS class name to apply to busy mask when a widget is
+ * set as busy. The default is 'jxBusy'.
+ */
+ busyClass: 'jxBusy',
+ /**
+ * Option: busyMask
+ * {Object} an object of options to pass to the MooTools Spinner
+ * when masking a busy object. Set to false if you do not want
+ * to use the busy mask.
+ */
+ busyMask: {
+ 'class': 'jxSpinner jxSpinnerLarge',
+ img: {'class':'jxSpinnerImage'},
+ content: {'class':'jxSpinnerContent'},
+ messageContainer: {'class':'jxSpinnerMessage'},
+ useIframeShim: true,
+ iframeShimOptions: {
+ className: 'jxIframeShim'
+ },
+ fx: true
+ }
},
+ /**
+ * Property: classes
+ * {<Hash>} a hash of object properties to CSS class names used to
+ * automatically extract references to important DOM elements when
+ * processing a widget template. This allows developers to provide custom
+ * HTML structures without affecting the functionality of widgets.
+ */
classes: new Hash({
domObj: 'jxWidget'
}),
+
+ /**
+ * Property: busy
+ * {Boolean} is the widget currently busy? This should be considered
+ * an internal property, use the API methods <Jx.Widget::setBusy> and
+ * <Jx.Widget::isBusy> to manage the busy state of a widget.
+ */
+ busy: false,
/**
* Property: domObj
@@ -14768,8 +15989,7 @@
/**
* Property: contentIsLoaded
- *
- * tracks the load state of the content, specifically useful
+ * {Boolean} tracks the load state of the content, specifically useful
* in the case of remote content.
*/
contentIsLoaded: false,
@@ -14780,10 +16000,11 @@
*/
chrome: null,
-
/**
- * APIMethod: init
- * sets up the base widget code and runs the render function.
+ * Method: init
+ * sets up the base widget code and runs the render function. Called
+ * by the Jx.Object framework for object initialization, should not be
+ * called directly.
*/
init: function(){
if (!this.options.deferRender) {
@@ -14795,9 +16016,8 @@
}
},
-
/**
- * Method: loadContent
+ * APIMethod: loadContent
*
* triggers loading of content based on options set for the current
* object.
@@ -14874,28 +16094,8 @@
}
},
- processContent: function(element) {
- $A(element.childNodes).each(function(node){
- if (node.tagName == 'INPUT' || node.tagName == 'SELECT' || node.tagName == 'TEXTAREA') {
- if (node.type == 'button') {
- node.addEvent('click', function(){
- this.fireEvent('click', this, node);
- });
- } else {
- node.addEvent('change', function(){
- this.fireEvent('change',node);
- });
- }
- } else {
- if (node.childNodes) {
- this.processContent(node);
- }
- }
- }, this);
- },
-
/**
- * Method: position
+ * APIMethod: position
* positions an element relative to another element
* based on the provided options. Positioning rules are
* a string with two space-separated values. The first value
@@ -14946,8 +16146,8 @@
* vertical - the vertical positioning rule to use to position the
* element. Valid values are 'top', 'center', 'bottom', and a numeric
* value. The default value is 'center center'.
- * offsets - an object containing numeric pixel offset values for the object
- * being positioned as top, right, bottom and left properties.
+ * offsets - an object containing numeric pixel offset values for the
+ * object being positioned as top, right, bottom and left properties.
*/
position: function(element, relative, options) {
element = document.id(element);
@@ -14957,8 +16157,7 @@
var offsets = $merge({top:0,right:0,bottom:0,left:0}, options.offsets || {});
var coords = relative.getCoordinates(); //top, left, width, height
- var page;
- var scroll;
+ var page, scroll;
if (!document.id(element.parentNode) || element.parentNode == document.body) {
page = Jx.getPageDimensions();
scroll = document.id(document.body).getScroll();
@@ -14979,11 +16178,7 @@
coords.top = 0;
}
var size = element.getMarginBoxSize(); //width, height
- var left;
- var right;
- var top;
- var bottom;
- var n;
+ var left, right, top, bottom, n;
if (!hor.some(function(opt) {
var parts = opt.split(' ');
if (parts.length != 2) {
@@ -15054,73 +16249,73 @@
element.setStyle('left', left);
if (!ver.some(function(opt) {
- var parts = opt.split(' ');
- if (parts.length != 2) {
- return false;
- }
- if (!isNaN(parseInt(parts[0],10))) {
- top = parseInt(parts[0],10);
- } else {
- switch(parts[0]) {
- case 'bottom':
- top = coords.top + coords.height;
- break;
- case 'center':
- top = coords.top + Math.round(coords.height/2);
- break;
- case 'top':
- default:
- top = coords.top;
- break;
- }
- }
- if (!isNaN(parseInt(parts[1],10))) {
- var n = parseInt(parts[1],10);
- if (n>=0) {
- top += n;
- bottom = top + size.height;
- } else {
- bottom = top + n;
- top = bottom - size.height;
- }
- } else {
- switch(parts[1]) {
- case 'top':
- top -= offsets.top;
- bottom = top + size.height;
- break;
- case 'bottom':
- top += offsets.bottom;
- bottom = top;
- top = top - size.height;
- break;
- case 'center':
- default:
- top = top - Math.round(size.height/2);
- bottom = top + size.height;
- break;
- }
- }
- return (top >= scroll.y && bottom <= scroll.y + page.height);
- })) {
- // all failed, snap the last position onto the page as best
- // we can - can't do anything if the element is higher than the
- // space available.
- if (bottom > page.height) {
- top = scroll.y + page.height - size.height;
- }
- if (top < 0) {
- top = 0;
- }
+ var parts = opt.split(' ');
+ if (parts.length != 2) {
+ return false;
+ }
+ if (!isNaN(parseInt(parts[0],10))) {
+ top = parseInt(parts[0],10);
+ } else {
+ switch(parts[0]) {
+ case 'bottom':
+ top = coords.top + coords.height;
+ break;
+ case 'center':
+ top = coords.top + Math.round(coords.height/2);
+ break;
+ case 'top':
+ default:
+ top = coords.top;
+ break;
}
- element.setStyle('top', top);
+ }
+ if (!isNaN(parseInt(parts[1],10))) {
+ var n = parseInt(parts[1],10);
+ if (n>=0) {
+ top += n;
+ bottom = top + size.height;
+ } else {
+ bottom = top + n;
+ top = bottom - size.height;
+ }
+ } else {
+ switch(parts[1]) {
+ case 'top':
+ top -= offsets.top;
+ bottom = top + size.height;
+ break;
+ case 'bottom':
+ top += offsets.bottom;
+ bottom = top;
+ top = top - size.height;
+ break;
+ case 'center':
+ default:
+ top = top - Math.round(size.height/2);
+ bottom = top + size.height;
+ break;
+ }
+ }
+ return (top >= scroll.y && bottom <= scroll.y + page.height);
+ })) {
+ // all failed, snap the last position onto the page as best
+ // we can - can't do anything if the element is higher than the
+ // space available.
+ if (bottom > page.height) {
+ top = scroll.y + page.height - size.height;
+ }
+ if (top < 0) {
+ top = 0;
+ }
+ }
+ element.setStyle('top', top);
- /* update the jx layout if necessary */
- var jxl = element.retrieve('jxLayout');
- if (jxl) {
- jxl.options.left = left;
- jxl.options.top = top;
- }
+ /* update the jx layout if necessary */
+ var jxl = element.retrieve('jxLayout');
+ if (jxl) {
+ jxl.options.left = left;
+ jxl.options.top = top;
+ }
},
/**
@@ -15153,36 +16348,39 @@
/* get the chrome image from the background image of the element */
/* the app: protocol check is for adobe air support */
var src = c.getStyle('backgroundImage');
- if (!(src.contains('http://') || src.contains('https://') || src.contains('file://') || src.contains('app:/'))) {
- src = null;
- } else {
- src = src.slice(4,-1);
- /* this only seems to be IE and Opera, but they add quotes
- * around the url - yuck
- */
- if (src.charAt(0) == '"') {
- src = src.slice(1,-1);
- }
+ if (src != null) {
+ if (!(src.contains('http://') || src.contains('https://') || src.contains('file://') || src.contains('app:/'))) {
+ src = null;
+ } else {
+ src = src.slice(4,-1);
+ /* this only seems to be IE and Opera, but they add quotes
+ * around the url - yuck
+ */
+ if (src.charAt(0) == '"') {
+ src = src.slice(1,-1);
+ }
- /* and remove the background image */
- c.setStyle('backgroundImage', 'none');
+ /* and remove the background image */
+ c.setStyle('backgroundImage', 'none');
- /* make chrome */
- ['TR','TL','BL','BR'].each(function(s){
- c.adopt(
- new Element('div',{
- 'class':'jxChrome'+s
- }).adopt(
- new Element('img',{
- 'class':'png24',
- src:src,
- alt: '',
- title: ''
- })));
- }, this);
+ /* make chrome */
+ ['TR','TL','BL','BR'].each(function(s){
+ c.adopt(
+ new Element('div',{
+ 'class':'jxChrome'+s
+ }).adopt(
+ new Element('img',{
+ 'class':'png24',
+ src:src,
+ alt: '',
+ title: ''
+ })));
+ }, this);
+ }
}
- if (!window.opera) {
- c.adopt(Jx.createIframeShim());
+ /* create a shim so selects don't show through the chrome */
+ if ($defined(window.IframeShim)) {
+ this.shim = new IframeShim(c, {className: 'jxIframeShim'});
}
/* remove from DOM so the other resizing logic works as expected */
@@ -15191,7 +16389,7 @@
},
/**
- * Method: showChrome
+ * APIMethod: showChrome
* show the chrome on an element. This creates the chrome if necessary.
* If the chrome has been previously created and not removed, you can
* call this without an element and it will just resize the chrome within
@@ -15210,32 +16408,49 @@
element.addClass('jxHasChrome');
}
this.resizeChrome(element);
+ if (this.shim) {
+ this.shim.show();
+ }
if (element && this.chrome.parentNode !== element) {
element.adopt(this.chrome);
+ this.chrome.setStyle('z-index',-1);
}
}
},
/**
- * Method: hideChrome
+ * APIMethod: hideChrome
* removes the chrome from the DOM. If you do this, you can't
* call showChrome with no arguments.
*/
hideChrome: function() {
if (this.chrome) {
+ if (this.shim) {
+ this.shim.hide();
+ }
this.chrome.parentNode.removeClass('jxHasChrome');
this.chrome.dispose();
}
},
+ /**
+ * APIMethod: resizeChrome
+ * manually resize the chrome on an element.
+ *
+ * Parameters:
+ * element: {DOMElement} the element to resize the chrome for
+ */
resizeChrome: function(o) {
if (this.chrome && Browser.Engine.trident4) {
this.chrome.setContentBoxSize(document.id(o).getBorderBoxSize());
+ if (this.shim) {
+ this.shim.position();
+ }
}
},
/**
- * Method: addTo
+ * APIMethod: addTo
* adds the object to the DOM relative to another element. If you use
* 'top' or 'bottom' then the element is added to the relative
* element (becomes a child node). If you use 'before' or 'after'
@@ -15254,13 +16469,29 @@
addTo: function(reference, where) {
var el = document.id(this.addable) || document.id(this.domObj);
if (el) {
- ref = document.id(reference);
- el.inject(ref,where);
+ if (reference instanceof Jx.Widget && $defined(reference.add)) {
+ reference.add(el);
+ } else {
+ ref = document.id(reference);
+ el.inject(ref,where);
+ }
this.fireEvent('addTo',this);
}
return this;
},
+ /**
+ * APIMethod: toElement
+ * return a DOM element reference for this widget, by default this
+ * returns the local domObj reference. This is used by the mootools
+ * framework with the document.id() or $() methods allowing you to
+ * manipulate a Jx.Widget sub class as if it were a DOM element.
+ *
+ * (code)
+ * var button = new Jx.Button({label: 'test'});
+ * $(button).inject('someElement');
+ * (end)
+ */
toElement: function() {
return this.domObj;
},
@@ -15275,10 +16506,10 @@
* container - the container to add the template into
*
* Returns:
- * a hash object containing the requested Elements keyed by the class names
+ * a hash object containing the requested Elements keyed by the class
+ * names
*/
processTemplate: function(template,classes,container){
-
var h = new Hash();
var element;
if ($defined(container)){
@@ -15292,9 +16523,7 @@
h.set(klass,el);
}
});
-
return h;
-
},
/**
@@ -15308,13 +16537,21 @@
return prefix + uid;
},
- remove: function(){
+ /**
+ * APIMethod: dispose
+ * remove the widget from the DOM
+ */
+ dispose: function(){
var el = document.id(this.addable) || document.id(this.domObj);
if (el) {
el.dispose();
}
},
+ /**
+ * Method: cleanup
+ * destroy the widget and clean up any potential memory leaks
+ */
cleanup: function(){
if ($defined(this.domObj)) {
this.domObj.destroy();
@@ -15328,13 +16565,27 @@
this.parent();
},
+ /**
+ * Method: render
+ * render the widget, internal function called by the framework.
+ */
render: function() {
this.elements = this.processElements(this.options.template,
this.classes);
},
+ /**
+ * Property: elements
+ * a hash of elements extracted by processing the widget template
+ */
elements: null,
+ /**
+ * Method: processElements
+ * process the template of the widget and populate the elements hash
+ * with any objects. Also set any object references based on the classes
+ * hash.
+ */
processElements: function(template, classes) {
var keys = classes.getValues();
elements = this.processTemplate(template, keys);
@@ -15344,6 +16595,118 @@
}
}, this);
return elements;
+ },
+
+ /**
+ * APIMethod: isBusy
+ * indicate if the widget is currently busy or not
+ *
+ * Returns:
+ * {Boolean} true if busy, false otherwise.
+ */
+ isBusy: function() {
+ return this.busy;
+ },
+
+ /**
+ * APIMethod: setBusy
+ * set the busy state of the widget
+ *
+ * Parameters:
+ * busy - {Boolean} true to set the widget as busy, false to set it as
+ * idle.
+ */
+ setBusy: function(state) {
+ if (this.busy == state) {
+ return;
+ }
+ this.busy = state;
+ this.fireEvent('busy', this.busy);
+ if (this.busy) {
+ if (this.options.busyClass) {
+ this.domObj.addClass(this.options.busyClass);
+ }
+ if (this.options.busyMask && this.domObj.spin) {
+ /* put the spinner above the element in the z-index */
+ var z = Jx.getNumber(this.domObj.getStyle('z-index'));
+ var opts = {
+ style: {
+ 'z-index': z+1
+ }
+ };
+ /* switch to the small size if the element is less than
+ * 60 pixels high
+ */
+ var size = this.domObj.getBorderBoxSize();
+ if (size.height < 60) {
+ opts['class'] = 'jxSpinner jxSpinnerSmall';
+ opts.img = null;
+ opts.message = new Element('p',{
+ 'class':'jxSpinnerMessage',
+ html: '<span class="jxSpinnerImage"></span>'+MooTools.lang.get('Jx','widget').busyMessage
+ });
+ }
+ opts = $merge(this.options.busyMask, opts);
+
+ this.domObj.get('spinner', opts).show(!this.options.busyMask.fx);
+
+ }
+ } else {
+ if (this.options.busyClass) {
+ this.domObj.removeClass(this.options.busyClass);
+ }
+ if (this.options.busyMask && this.domObj.unspin) {
+ this.domObj.get('spinner').hide(!this.options.busyMask.fx);
+
+ }
+ }
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ //if the mask is being used then recreate it. The code will pull
+ //the new text automatically
+ if (this.busy) {
+ this.setBusy(false);
+ this.setBusy(true);
+ }
+ },
+
+ /**
+ * APIMethod: stack
+ * stack this widget in the z-index of the DOM relative to other stacked
+ * objects.
+ *
+ * Parameters:
+ * el - {DOMElement} optional, the element to stack. By default, the
+ * element to stack is the one returned by the toElement method which
+ * is typically this.domObj unless the method has been overloaded.
+ */
+ stack: function(el) {
+ el = el || document.id(this);
+ Jx.Stack.stack(el);
+ },
+
+ /**
+ * APIMethod: unstack
+ * remove this widget from the stack.
+ *
+ * Parameters:
+ * el - {DOMElement} optional, the element to unstack. By default, the
+ * element to unstack is the one returned by the toElement method which
+ * is typically this.domObj unless the method has been overloaded.
+ */
+ unstack: function(el) {
+ el = el || document.id(this);
+ Jx.Stack.unstack(el);
}
});
@@ -15377,8 +16740,32 @@
}
}
});
-}
+}// $Id: selection.js 762 2010-03-16 13:48:29Z pagameba $
+/**
+ * Class: Jx.Selection
+ *
+ * Manage selection of objects.
+ *
+ * Example:
+ * (code)
+ * var selection = new Jx.Selection();
+ * (end)
+ *
+ * Events:
+ * select - fired when an item is added to the selection. This event may be
+ * changed by passing the eventToFire option when creating the selection
+ * object.
+ * unselect - fired when an item is removed from the selection. This event
+ * may be changed by passing the eventToFire option when creating the
+ * selection object.
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+
Jx.Selection = new Class({
Family: 'Jx.Selection',
Extends: Jx.Object,
@@ -15386,7 +16773,17 @@
/**
* Option: eventToFire
* Allows the developer to change the event that is fired in case one
- * object is using multiple selectionManager instances.
+ * object is using multiple selectionManager instances. The default
+ * is to use 'select' and 'unselect'. To modify the event names,
+ * pass different values:
+ * (code)
+ * new Jx.Selection({
+ * eventToFire: {
+ * select: 'newSelect',
+ * unselect: 'newUnselect'
+ * }
+ * });
+ * (end)
*/
eventToFire: {
select: 'select',
@@ -15394,14 +16791,15 @@
},
/**
* APIProperty: selectClass
- * the CSS class name to add to the wrapper element when it is selected
+ * the CSS class name to add to the wrapper element when it is
+ * selected
*/
selectClass: 'jxSelected',
/**
* Option: selectMode
- * {string} default single. May be single or multiple. In single mode
- * only one item may be selected. Selecting a new item will implicitly
- * unselect the currently selected item.
+ * {string} default single. May be single or multiple. In single
+ * mode only one item may be selected. Selecting a new item will
+ * implicitly unselect the currently selected item.
*/
selectMode: 'single',
/**
@@ -15415,25 +16813,51 @@
* {Integer} Default 0. The minimum number of items that must be
* selected. If set to a number higher than 0, items added to a list
* are automatically selected until this minimum is met. The user may
- * not unselect items if unselecting them will drop the total number of
- * items selected below the minimum.
+ * not unselect items if unselecting them will drop the total number
+ * of items selected below the minimum.
*/
minimumSelection: 0
},
+ /**
+ * Property: selection
+ * {Array} an array holding the current selection
+ */
selection: null,
+ /**
+ * Constructor: Jx.Selection
+ * create a new instance of Jx.Selection
+ *
+ * Parameters:
+ * options - {Object} options for the new instance
+ */
init: function () {
this.selection = [];
},
+ /**
+ * APIMethod: defaultSelect
+ * select an item if the selection does not yet contain the minimum
+ * number of selected items. Uses <Jx.Selection::select> to select
+ * the item, so the same criteria is applied to the item if it is
+ * to be selected.
+ */
defaultSelect: function(item) {
if (this.selection.length < this.options.minimumSelection) {
this.select(item);
}
},
+ /**
+ * APIMethod: select
+ * select an item.
+ *
+ * Parameters:
+ * item - {DOMElement} a DOM element or an element ID.
+ */
select: function (item) {
+ item = document.id(item);
if (this.options.selectMode === 'multiple') {
if (this.selection.contains(item)) {
this.unselect(item);
@@ -15456,6 +16880,14 @@
}
},
+ /**
+ * APIMethod: unselect
+ * remove an item from the selection. The item must already be in the
+ * selection.
+ *
+ * Parameters:
+ * item - {DOMElement} a DOM element or an element ID.
+ */
unselect: function (item) {
if (this.selection.contains(item) &&
this.selection.length > this.options.minimumSelection) {
@@ -15465,15 +16897,32 @@
}
},
+ /**
+ * APIMethod: selected
+ * returns the items in the current selection.
+ *
+ * Returns:
+ * {Array} an array of DOM elements in the current selection
+ */
selected: function () {
return this.selection;
},
+ /**
+ * APIMethod: isSelected
+ * test if an item is in the current selection.
+ *
+ * Parameters:
+ * item - {DOMElement} a DOM element or an element ID.
+ *
+ * Returns:
+ * {Boolean} true if the current selection contains the item, false
+ * otherwise
+ */
isSelected: function(item) {
return this.selection.contains(item);
}
-
-});// $Id: $
+});// $Id: list.js 762 2010-03-16 13:48:29Z pagameba $
/**
* Class: Jx.List
*
@@ -15488,6 +16937,17 @@
*
* Example:
* (code)
+ * var list = new Jx.List('container',{
+ * hover: true,
+ * select: true,
+ * onSelect: function(el) {
+ * alert(el.get('html'));
+ * }
+ * });
+ * list.add(new Element('li', {html:'1'}));
+ * list.add(new Element('li', {html:'2'}));
+ * list.add(new Element('li', {html:'3'}));
+ *
* (end)
*
* Events:
@@ -15506,11 +16966,24 @@
Jx.List = new Class({
Family: 'Jx.List',
Extends: Jx.Object,
+ /**
+ * Constructor: Jx.List
+ * create a new instance of Jx.List
+ *
+ * Parameters:
+ * container - {Mixed} an element reference or id of an element that will
+ * contain the items in the list
+ * options - {Object} an object containing optional parameters
+ * selection - {<Jx.Selection>} null or a Jx.Selection object. If the
+ * select option is set to true, then list will use this selection object
+ * to track selections or create its own if no selection object is
+ * supplied.
+ */
parameters: ['container', 'options', 'selection'],
/* does this object own the selection object (and should clean it up) */
ownsSelection: false,
/**
- * APIProperty: itemContainer
+ * APIProperty: container
* the element that will contain items as they are added
*/
container: null,
@@ -15527,7 +17000,7 @@
items: null,
/**
* Option: hover
- * {Boolean} default true. If set to true, the wrapper element will
+ * {Boolean} default false. If set to true, the wrapper element will
* obtain the defined hoverClass if set and mouseenter/mouseleave
* events will be emitted when the user hovers over and out of elements
*/
@@ -15541,7 +17014,7 @@
/**
* Option: press
- * {Boolean} default true. If set to true, the wrapper element will
+ * {Boolean} default false. If set to true, the wrapper element will
* obtain the defined pressClass if set and mousedown/mouseup
* events will be emitted when the user clicks on elements
*/
@@ -15555,7 +17028,7 @@
/**
* Option: select
- * {Boolean} default true. If set to true, the wrapper element will
+ * {Boolean} default false. If set to true, the wrapper element will
* obtain the defined selectClass if set and select/unselect events
* will be emitted when items are selected and unselected. For other
* selection objects, see <Jx.Selection>
@@ -15643,6 +17116,8 @@
this.selection = new Jx.Selection(this.options);
this.ownsSelection = true;
}
+
+ this.setSelection(this.selection);
if ($defined(this.options.items)) {
this.add(this.options.items);
@@ -15705,9 +17180,9 @@
});
}
if ($defined(position)) {
- if ($type(position) == 'integer') {
+ if ($type(position) == 'number') {
if (position < this.container.childNodes.length) {
- el.inject(this.container.childNodes[position],' before');
+ el.inject(this.container.childNodes[position],'before');
} else {
el.inject(this.container, 'bottom');
}
@@ -15801,9 +17276,11 @@
* Parameters:
* func - {function} the function to apply, it will receive the item and
* index of the item as parameters
+ * context - {object} the context to execute the function in, null by
+ * default.
*/
- each: function(f) {
- $A(this.container.childNodes).each(f);
+ each: function(f, context) {
+ $A(this.container.childNodes).each(f, context);
},
/**
* APIMethod: select
@@ -15880,7 +17357,162 @@
}
}
-});// $Id: $
+});/**
+ * Class: Jx.Stack
+ * Manage the zIndex of widgets
+ *
+ * This is a singleton and should be called directly, like so:
+ *
+ * (code)
+ * (end)
+ *
+ * License:
+ * Copyright (c) 2010 Paul Spencer
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Stack = new(new Class({
+ /**
+ * Property: els
+ * {Array} the elements in the stack
+ */
+ els: [],
+
+ /**
+ * Property: base
+ * {Integer} the base z-index value of the first element in the stack
+ */
+ base: 1000,
+
+ /**
+ * Property: increment
+ * {Integer} the amount to increment the z-index between elements of the
+ * stack
+ */
+ increment: 100,
+
+ /**
+ * APIMethod: stack
+ * push an element onto the stack and set its z-index appropriately
+ *
+ * Parameters:
+ * el - {DOMElement} a DOM element to push on the stack
+ */
+ stack: function(el) {
+ this.unstack(el);
+ this.els.push(el);
+ this.setZIndex(el, this.els.length-1);
+ },
+
+ /**
+ * APIMethod: unstack
+ * pull an element off the stack and reflow the z-index of the remaining
+ * elements in the stack if necessary
+ *
+ * Parameters:
+ * el - {DOMElement} the DOM element to pull off the stack
+ */
+ unstack: function(el) {
+ if (this.els.contains(el)) {
+ el.setStyle('z-index', '');
+ var idx = this.els.indexOf(el);
+ this.els.erase(el);
+ for (var i=idx; i<this.els.length; i++) {
+ this.setZIndex(this.els[i], i);
+ }
+ }
+ },
+
+ /**
+ * Method: setZIndex
+ * set the z-index of an element based on its position in the stack
+ *
+ * Parameters:
+ * el - {DOMElement} the element to set the z-index for
+ * idx - {Integer} optional, the index to assume for this object
+ */
+ setZIndex: function(obj, idx) {
+ idx = idx || this.els.indexOf(obj);
+ if (idx !== false) {
+ document.id(obj).setStyle('z-index', this.base + (idx*this.increment));
+ }
+ }
+
+}))();
+MooTools.lang.set('de-DE', 'Jx', {
+
+ 'widget': {
+ busyMessage: 'Arbeite ...'
+ },
+ 'colorpalette': {
+ alphaLabel: 'alpha (%)'
+ },
+ notice: {
+ closeTip: 'Notiz schlieÃen'
+ },
+ progressbar: {
+ messageText: 'Lade...',
+ progressText: '{progress} von {total}'
+ },
+ field: {
+ requiredText: '*'
+ },
+ file: {
+ browseLabel: 'Durchsuchen...'
+ },
+ 'formatter.boolean': {
+ 'true': 'Ja',
+ 'false': 'Nein'
+ },
+ 'formatter.currency': {
+ sign: 'â¬'
+ },
+ 'formatter.number': {
+ decimalSeparator: '.',
+ thousandsSeparator: ','
+ },
+ splitter: {
+ barToolTip: 'Ziehen Sie diese Leiste um die GröÃe zu verändern'
+ },
+ panel: {
+ collapseTooltip: 'Panel ein-/ausklappen', //colB
+ collapseLabel: 'Einklappen', //colM
+ expandLabel: 'Ausklappen', //colM
+ maximizeTooltip: 'Panel maximieren',
+ maximizeLabel: 'maximieren',
+ restoreTooltip: 'Panel wieder herstellen', //maxB
+ restoreLabel: 'wieder herstellen', //maxM
+ closeTooltip: 'Panel schlieÃen', //closeB
+ closeLabel: 'SchlieÃen' //closeM
+ },
+ confirm: {
+ affirmitiveLabel: 'Ja',
+ negativeLabel: 'Nein'
+ },
+ dialog: {
+ label: 'Neues Fenster'
+ },
+ message: {
+ okButton: 'Ok'
+ },
+ panelset: {
+ barTooltip: 'Ziehen Sie diese Leiste um die GröÃe zu verändern'
+ },
+ prompt: {
+ okButton: 'Ok',
+ cancelButton: 'Abbrechen'
+ },
+ upload: {
+ buttonText: 'Dateien hochladen'
+ },
+ 'plugin.resize': {
+ tooltip: 'Klicken um GröÃe zu verändern. Doppelklick für automatische GröÃe.'
+ },
+ 'plugin.editor': {
+ submitButton: 'Speichern',
+ cancelButton: 'Abbrechen'
+ }
+});// $Id: record.js 686 2010-02-01 05:45:28Z jonlb at comcast.net $
/**
* Class: Jx.record
*
@@ -16008,7 +17640,8 @@
var oldValue = this.get(column);
this.data.set(column.name, data);
this.state = Jx.Record.UPDATE;
- this.store.fireEvent('storeColumnChanged', [this, column.name, oldValue, data]);
+ return [column.name, oldValue, data];
+ //this.store.fireEvent('storeColumnChanged', [this, column.name, oldValue, data]);
},
/**
@@ -16023,7 +17656,11 @@
* True | False depending on the outcome of the comparison.
*/
equals: function (column, value) {
- var column = this.resolveCol(column);
+ if (column === 'primaryKey') {
+ column = this.resolveCol(this.options.primaryKey);
+ } else {
+ column = this.resolveCol(column);
+ }
if (!this.data.has(column.name)) {
return null;
} else {
@@ -16084,7 +17721,7 @@
Jx.Record.UPDATE = 1;
Jx.Record.DELETE = 2;
-Jx.Record.INSERT = 3;// $Id: $
+Jx.Record.INSERT = 3;// $Id: store.js 797 2010-03-26 20:23:32Z jonlb at comcast.net $
/**
* Class: Jx.Store
*
@@ -16188,6 +17825,10 @@
*/
ready: false,
+ /**
+ * Method: init
+ * initialize the store, should be called by sub-classes
+ */
init: function () {
this.parent();
@@ -16222,6 +17863,11 @@
},
+ /**
+ * Method: cleanup
+ * avoid memory leaks when a store is destroyed, should be called
+ * by sub-classes if overridden
+ */
cleanup: function () {
this.strategies.each(function(strategy){
strategy.destroy();
@@ -16259,12 +17905,12 @@
},
/**
* APIMethod: load
- * used to load the store. It simply fires an event that the strategies are
- * listening for.
+ * used to load the store. It simply fires an event that the strategies
+ * are listening for.
*
* Parameters:
- * params - a hash of parameters passed to the strategy for determining what records
- * to load.
+ * params - a hash of parameters passed to the strategy for determining
+ * what records to load.
*/
load: function (params) {
this.fireEvent('storeLoad', params);
@@ -16288,14 +17934,9 @@
*/
hasNext : function () {
if ($defined(this.data)) {
- if (this.index < this.data.length - 1) {
- return true;
- } else {
- return false;
- }
- } else {
- return null;
+ return this.index < this.data.length - 1;
}
+ return null;
},
/**
@@ -16307,14 +17948,9 @@
*/
hasPrevious : function () {
if ($defined(this.data)) {
- if (this.index > 0) {
- return true;
- } else {
- return false;
- }
- } else {
- return null;
+ return this.index > 0;
}
+ return null;
},
/**
@@ -16410,9 +18046,8 @@
count : function () {
if ($defined(this.data)) {
return this.data.length;
- } else {
- return null;
}
+ return null;
},
/**
@@ -16425,9 +18060,8 @@
getPosition : function () {
if ($defined(this.data)) {
return this.index;
- } else {
- return null;
}
+ return null;
},
/**
@@ -16452,7 +18086,8 @@
},
/**
* APIMethod: each
- * allows iteration through the store's records.
+ * allows iteration through the store's records.
+ * NOTE: this function is untested
*
* Parameters:
* fn - the function to execute for each record
@@ -16506,7 +18141,12 @@
if (!$defined(index)) {
index = this.index;
}
- return this.data[index].set(column, data);
+ var ret = this.data[index].set(column, data);
+ ret.reverse();
+ ret.push(index);
+ ret.reverse();
+ //fire event with array [index, column, oldvalue, newValue]
+ this.fireEvent('storeColumnChanged', ret);
},
/**
* APIMethod: refresh
@@ -16522,12 +18162,17 @@
* Parameters:
* data - The data to use in creating a record. This should be in whatever
* form Jx.Store.Record, or the current subclass, needs it in.
+ * position - whether the record is added to the 'top' or 'bottom' of the
+ * store.
* insert - flag whether this is an "insert"
*/
- addRecord: function (data, insert) {
+ addRecord: function (data, position, insert) {
if (!$defined(this.data)) {
this.data = [];
}
+
+ position = $defined(position)? position : 'bottom';
+
var record;
if (data instanceof Jx.Record) {
record = data;
@@ -16537,8 +18182,16 @@
if (insert) {
record.state = Jx.Record.INSERT;
}
- this.data.push(record);
- this.fireEvent('storeRecordAdded', [record, this]);
+ if (position === 'top') {
+ //some literature claims that .shift() and .unshift() don't work reliably in IE
+ //so we do it this way.
+ this.data.reverse();
+ this.data.push(record);
+ this.data.reverse();
+ } else {
+ this.data.push(record);
+ }
+ this.fireEvent('storeRecordAdded', [this, record, position]);
},
/**
* APIMethod: addRecords
@@ -16546,14 +18199,21 @@
*
* Parameters:
* data - an array of data to add.
+ * position - 'top' or 'bottom'. Indicates whether to add at the top or
+ * the bottom of the store
*/
- addRecords: function (data) {
+ addRecords: function (data, position) {
var def = $defined(data);
var type = Jx.type(data);
if (def && type === 'array') {
this.fireEvent('storeBeginAddRecords', this);
+ //if position is top, reverse the array or we'll add them in the
+ // wrong order.
+ if (position === 'top') {
+ data.reverse();
+ }
data.each(function(d){
- this.addRecord(d);
+ this.addRecord(d, position);
},this);
this.fireEvent('storeEndAddRecords', this);
return true;
@@ -16566,8 +18226,8 @@
* Returns the record at the given index or the current store index
*
* Parameters:
- * index - the index from which to return the record. Optional. Defaults to
- * the current store index
+ * index - the index from which to return the record. Optional. Defaults
+ * to the current store index
*/
getRecord: function (index) {
if (!$defined(index)) {
@@ -16579,6 +18239,9 @@
return this.data[index];
}
} else {
+ //Not sure what the point of this part is. It compares the
+ //record to the index directly as if we passed in the record which
+ //means we already have the record... huh???
var r;
this.data.each(function(record){
if (record === index) {
@@ -16629,7 +18292,8 @@
var record = this.data[index];
record.state = Jx.Record.DELETE;
// Set to Null or slice it out and compact the array???
- this.data[index] = null;
+ //this.data[index] = null;
+ this.data.splice(index,1);
if (!$defined(this.deleted)) {
this.deleted = [];
}
@@ -16640,12 +18304,14 @@
* APIMethod: insertRecord
* Shortcut to addRecord which facilitates marking a record as inserted.
*
- * Paremeters:
+ * Parameters:
* data - the data to use in creating this inserted record. Should be in
* whatever form the current implementation of Jx.Record needs
+ * position - where to place the record. Should be either 'top' or
+ * 'bottom'.
*/
- insertRecord: function (data) {
- this.addRecord(data, true);
+ insertRecord: function (data, position) {
+ this.addRecord(data, position, true);
},
/**
@@ -16659,8 +18325,8 @@
/**
* APIMethod: findByColumn
* Used to find a specific record by the value in a specific column. This
- * is particularly useful for finding records by a unique id column. The search
- * will stop on the first instance of the value
+ * is particularly useful for finding records by a unique id column. The
+ * search will stop on the first instance of the value
*
* Parameters:
* column - the name (or index) of the column to search by
@@ -16686,8 +18352,82 @@
return index;
}
return null;
- }
-});// $Id: $
+ },
+ /**
+ * APIMethod: removeRecord
+ * removes (but does not mark for deletion) a record at the given index
+ * or the current store index if none is passed in.
+ *
+ * Parameters:
+ * index - Optional. The store index of the record to remove.
+ */
+ removeRecord: function (index) {
+ if (!$defined(index)) {
+ index = this.index;
+ }
+ this.data.splice(index,1);
+ this.fireEvent('storeRecordRemoved', [this, index])
+ },
+ /**
+ * APIMethod: removeRecords
+ * Used to remove multiple contiguous records from a store.
+ *
+ * Parameters:
+ * first - where to start removing records (zero-based)
+ * last - where to stop removing records (zero-based, inclusive)
+ */
+ removeRecords: function (first, last) {
+ for (var i = first; i <= last; i++) {
+ this.removeRecord(first);
+ }
+ this.fireEvent('storeMultipleRecordsRemoved', [this, first, last]);
+ },
+
+ /**
+ * APIMethod: parseTemplate
+ * parses the provided template to determine which store columns are
+ * required to complete it.
+ *
+ * Parameters:
+ * template - the template to parse
+ */
+ parseTemplate: function (template) {
+ //we parse the template based on the columns in the data store looking
+ //for the pattern {column-name}. If it's in there we add it to the
+ //array of ones to look fo
+ var arr = [];
+ this.options.columns.each(function (col) {
+ var s = '{' + col.name + '}';
+ if (template.contains(s)) {
+ arr.push(col.name);
+ }
+ }, this);
+ return arr;
+ },
+
+ /**
+ * APIMethod: fillTemplate
+ * Actually does the work of getting the data from the store
+ * and creating a single item based on the provided template
+ *
+ * Parameters:
+ * index - the index of the data in the store to use in populating the
+ * template.
+ * template - the template to fill
+ * columnsNeeded - the array of columns needed by this template. should be
+ * obtained by calling parseTemplate().
+ */
+ fillTemplate: function (index, template, columnsNeeded) {
+ index = $defined(index)? index : this.index;
+
+ //create the item
+ var itemObj = {};
+ columnsNeeded.each(function (col) {
+ itemObj[col] = this.get(col, index);
+ }, this);
+ return template.substitute(itemObj);
+ }
+});// $Id: compare.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Compare
*
@@ -16809,7 +18549,7 @@
return (a === true && b === false) ? -1 : (a === b) ? 0 : 1;
}
-});// $Id: $
+});// $Id: sort.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Sort Base class for all of the sorting algorithm classes.
*
@@ -16947,7 +18687,7 @@
this.comparator = fn;
}
});
-// $Id: $
+// $Id: mergesort.js 649 2009-11-30 22:19:48Z pagameba $
/**
* class: Jx.Sort.Mergesort
*
@@ -17044,7 +18784,7 @@
}
});
-// $Id: $
+// $Id: heapsort.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Sort.Heapsort
*
@@ -17146,7 +18886,7 @@
}
});
-// $Id: $
+// $Id: quicksort.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Sort.Quicksort
*
@@ -17300,7 +19040,7 @@
return k;
}
});
-// $Id: $
+// $Id: nativesort.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Sort.Nativesort
*
@@ -17345,7 +19085,7 @@
}
});
-// $Id: $
+// $Id: response.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Store.Response
*
@@ -17407,7 +19147,7 @@
Jx.Store.Response.WAITING = 2;
Jx.Store.Response.SUCCESS = 1;
Jx.Store.Response.FAILURE = 0;
-// $Id: $
+// $Id: protocol.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Store.Protocol
*
@@ -17490,7 +19230,7 @@
* that subclasses should implement.
*/
abort: $empty
-});// $Id: $
+});// $Id: protocol.local.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Store.Protocol.Local
*
@@ -17575,7 +19315,7 @@
* - commit
* - abort
*/
-});// $Id: $
+});// $Id: protocol.ajax.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Store.Protocol.Ajax
*
@@ -17785,7 +19525,7 @@
return resp;
}
-});// $Id: $
+});// $Id: strategy.js 776 2010-03-22 14:35:16Z pagameba $
/**
* Class: Jx.Store.Strategy
*
@@ -17813,6 +19553,10 @@
*/
active: null,
+ /**
+ * Method: init
+ * initialize the strategy, should be called by subclasses
+ */
init: function () {
this.parent();
this.active = false;
@@ -17851,10 +19595,7 @@
}
return false;
}
-
-
-
-});// $Id: $
+});// $Id: strategy.full.js 776 2010-03-22 14:35:16Z pagameba $
/**
* Class: Jx.Store.Strategy.Full
*
@@ -17875,7 +19616,10 @@
name: 'full',
options:{},
-
+ /**
+ * Method: init
+ * initialize this strategy
+ */
init: function () {
this.parent();
this.bound = {
@@ -17884,19 +19628,27 @@
}
},
+ /**
+ * APIMethod: activate
+ * activates the strategy if it isn't already active.
+ */
activate: function () {
this.parent();
this.store.addEvent('storeLoad', this.bound.load);
},
+ /**
+ * APIMethod: deactivate
+ * deactivates the strategy if it is already active.
+ */
deactivate: function () {
this.parent();
this.store.removeEvent('storeLoad', this.bound.load);
},
/**
- * Method: load
+ * APIMethod: load
* Called as the eventhandler for the store load method. Can also
* be called independently to load data into the current store.
*
@@ -17916,6 +19668,7 @@
opts.data.itemsPerPage = -1;
this.store.protocol.read(opts);
},
+
/**
* Method: loadStore
* Called as the event hanlder for the protocol's dataLoaded event. Checks
@@ -17955,9 +19708,9 @@
this.store.options.recordOptions.primaryKey = meta.primaryKey;
}
}
-});// $Id: $
+});// $Id: strategy.paginate.js 776 2010-03-22 14:35:16Z pagameba $
/**
- * Class: Jx.Store.Strategy.Paginat
+ * Class: Jx.Store.Strategy.Paginate
*
* Extends: <Jx.Store.Strategy>
*
@@ -17984,7 +19737,7 @@
return {
page: this.page,
itemsPerPage: this.itemsPerPage
- }
+ };
},
/**
* Option: startingItemsPerPage
@@ -18000,15 +19753,16 @@
startingPage: 1,
/**
* Option: expirationInterval
- * The interval, in milliseconds (1000 = 1 sec), to hold a page of data
- * before it expires. If the page is expired, the next time the page
- * is accessed it must be retrieved again. Default is 5 minutes (1000 * 60 * 5)
+ * The interval, in milliseconds (1000 = 1 sec), to hold a page of
+ * data before it expires. If the page is expired, the next time the
+ * page is accessed it must be retrieved again. Default is 5 minutes
+ * (1000 * 60 * 5)
*/
expirationInterval: (1000 * 60 * 5),
/**
* Option: ignoreExpiration
- * Set to TRUE to ignore the expirationInterval setting and never expire
- * pages.
+ * Set to TRUE to ignore the expirationInterval setting and never
+ * expire pages.
*/
ignoreExpiration: false
},
@@ -18034,6 +19788,10 @@
*/
itemsPerPage: null,
+ /**
+ * Method: init
+ * initialize this strategy
+ */
init: function () {
this.parent();
//set up bindings that we need here
@@ -18045,11 +19803,19 @@
this.page = this.options.startingPage;
},
+ /**
+ * APIMethod: activate
+ * activates the strategy if it isn't already active.
+ */
activate: function () {
this.parent();
this.store.addEvent('storeLoad', this.bound.load);
},
+ /**
+ * APIMethod: deactivate
+ * deactivates the strategy if it is already active.
+ */
deactivate: function () {
this.parent();
this.store.removeEvent('storeLoad', this.bound.load);
@@ -18064,13 +19830,14 @@
load: function (params) {
this.store.fireEvent('storeBeginDataLoad', this.store);
this.store.protocol.addEvent('dataLoaded', this.bound.loadStore);
+ this.params = params;
var opts = {
data: $merge(params, this.options.getPaginationParams.apply(this))
};
this.store.protocol.read(opts);
},
/**
- * MethodL loadStore
+ * Method: loadStore
* Used to assist in the loading of data into the store. This is
* called as a response to the protocol finishing.
*
@@ -18091,9 +19858,9 @@
},
/**
* Method: loadData
- * This method does the actual work of loading data to the store. It is called
- * when either the protocol finishes or setPage() has the data and it's not
- * expired.
+ * This method does the actual work of loading data to the store. It is
+ * called when either the protocol finishes or setPage() has the data and
+ * it's not expired.
*
* Parameters:
* data - the data to load into the store.
@@ -18111,8 +19878,8 @@
},
/**
* Method: parseMetaData
- * Takes the metadata returned from the protocol and places it in the appropriate
- * places.
+ * Takes the metadata returned from the protocol and places it in the
+ * appropriate Vplaces.
*
* Parameters:
* meta - the meta data object returned from the protocol.
@@ -18230,9 +19997,139 @@
getTotalCount: function () {
return this.totalItems;
}
+});
+Jx.Store.Strategy.Progressive = new Class({
+ Extends: Jx.Store.Strategy.Paginate,
-});// $Id: $
+ name: 'progressive',
+
+ options: {
+ /**
+ * Option: maxRecords
+ * The maximum number of records we want in the store at any one time.
+ */
+ maxRecords: 1000,
+ /**
+ * Option: dropRecords
+ * Whether the strategy should drop records when the maxRecords limit
+ * is reached. if this is false then maxRecords is ignored and data is
+ * always added to the bottom of the store.
+ */
+ dropRecords: true
+ },
+ /**
+ * Property: startingPage
+ */
+ startingPage: 0,
+ /**
+ * Property: maxPages
+ */
+ maxPages: null,
+ /**
+ * Property: loadedPages
+ */
+ loadedPages: 0,
+ /**
+ * Property: loadAt
+ */
+ loadAt: 'bottom',
+
+ /**
+ * Method: init
+ * initialize this strategy
+ */
+ init: function () {
+ this.parent();
+ if (this.options.dropPages) {
+ this.maxPages = Math.ceil(this.options.maxRecords/this.itemsPerPage);
+ }
+ },
+
+ /**
+ * Method: loadStore
+ * Used to assist in the loading of data into the store. This is
+ * called as a response to the protocol finishing.
+ *
+ * Parameters:
+ * resp - the response object
+ */
+ loadStore: function (resp) {
+ this.store.protocol.removeEvent('dataLoaded', this.bound.loadStore);
+ if (resp.success()) {
+ if ($defined(resp.meta)) {
+ this.parseMetaData(resp.meta);
+ }
+ this.loadData(resp.data);
+ } else {
+ this.store.fireEvent('storeDataLoadFailed', this.store);
+ }
+ },
+
+ /**
+ * Method: loadData
+ * This method does the actual work of loading data to the store. It is
+ * called when either the protocol finishes or setPage() has the data and
+ * it's not expired.
+ *
+ * Parameters:
+ * data - the data to load into the store.
+ */
+ loadData: function (data) {
+ this.store.loaded = false;
+ this.store.addRecords(data, this.loadAt);
+ this.store.loaded = true;
+ this.loadedPages++;
+ this.store.fireEvent('storeDataLoaded',this.store);
+ },
+
+ /**
+ * APIMethod: nextPage
+ * Allows a caller (i.e. a paging toolbar) to load more data to the end of
+ * the store
+ *
+ * Parameters:
+ * end - which end to load to. Either 'top' or 'bottom'.
+ */
+ nextPage: function (params) {
+ if (!$defined(params)) {
+ params = {};
+ }
+ if (this.options.dropPages && this.totalPages > this.startingPage + this.loadedPages) {
+ this.loadAt = 'bottom';
+ if (this.loadedPages >= this.maxPages) {
+ //drop records before getting more
+ this.startingPage++;
+ this.store.removeRecords(0,this.itemsPerPage - 1);
+ this.loadedPages--;
+ }
+ }
+ this.page = this.startingPage + this.loadedPages + 1;
+ this.load($merge(this.params, params));
+ },
+
+ previousPage: function (params) {
+ //if we're not dropping pages there's nothing todo
+ if (!this.options.dropPages) {
+ return;
+ }
+
+ if (!$defined(params)) {
+ params = {};
+ }
+ if (this.startingPage > 0) {
+ this.loadAt = 'top';
+ if (this.loadedPages >= this.maxPages) {
+ //drop off end before loading previous pages
+ this.startingPage--;
+ this.store.removeRecords(this.options.maxRecords - this.itemsPerPage, this.options.maxRecords);
+ this.loadedPages--;
+ }
+ this.page = this.startingPage;
+ this.load($merge(this.params, params));
+ }
+ }
+});// $Id: strategy.save.js 776 2010-03-22 14:35:16Z pagameba $
/**
* Class: Jx.Store.Strategy.Save
*
@@ -18277,6 +20174,10 @@
*/
totalChanges: 0,
+ /**
+ * Method: init
+ * initialize this strategy
+ */
init: function () {
this.parent();
this.bound = {
@@ -18285,6 +20186,10 @@
};
},
+ /**
+ * APIMethod: activate
+ * activates the strategy if it isn't already active.
+ */
activate: function () {
this.parent();
if (Jx.type(this.options.autoSave) === 'number') {
@@ -18297,6 +20202,10 @@
},
+ /**
+ * APIMethod: deactivate
+ * deactivates the strategy if it is already active.
+ */
deactivate: function () {
this.parent();
if ($defined(this.periodicalId)) {
@@ -18311,8 +20220,8 @@
/**
* APIMethod: saveRecord
- * Called by event handlers when store data is changed, updated, or deleted.
- * If deleted, the record will be removed from the deleted array.
+ * Called by event handlers when store data is changed, updated, or
+ * deleted. If deleted, the record will be removed from the deleted array.
*
* Parameters:
* record - The Jx.Record instance that was changed
@@ -18348,21 +20257,23 @@
*/
save: function () {
//go through all of the data and figure out what needs to be acted on
- var records = [];
- records[Jx.Record.UPDATE] = [];
- records[Jx.Record.INSERT] = [];
+ if (this.store.loaded) {
+ var records = [];
+ records[Jx.Record.UPDATE] = [];
+ records[Jx.Record.INSERT] = [];
+
+ this.store.data.each(function (record) {
+ if ($defined(record) && $defined(record.state)) {
+ records[record.state].push(record);
+ }
+ }, this);
+ records[Jx.Record.DELETE] = this.store.deleted;
+
+ records.flatten().each(function (record) {
+ this.saveRecord(record);
+ }, this);
+ }
- this.store.data.each(function (record) {
- if ($defined(record) && $defined(record.state)) {
- records[record.state].push(record);
- }
- }, this);
- records[Jx.Record.DELETE] = this.store.deleted;
-
- records.flatten().each(function (record) {
- this.saveRecord(record);
- }, this);
-
},
/**
* Method: onComplete
@@ -18371,9 +20282,9 @@
* come back failed we will hold that response and send it to the caller
* via the fired event. This method is responsible for updating the status
* of each record as it returns and on inserts, it updates the primary key
- * of the record. If it was a delete it will remove it permanently from the
- * store's deleted array (provided it returns successful - based on the
- * success attribute of the meta object). When all changes have been
+ * of the record. If it was a delete it will remove it permanently from
+ * the store's deleted array (provided it returns successful - based on
+ * the success attribute of the meta object). When all changes have been
* accounted for the method fires a finished event and passes all of the
* failed responses to the caller so they can be handled appropriately.
*
@@ -18410,10 +20321,8 @@
failed: this.failedChanges
});
}
-
}
-
-});// $Id: $
+});// $Id: strategy.sort.js 776 2010-03-22 14:35:16Z pagameba $
/**
* Class: Jx.Store.Strategy.Sort
*
@@ -18442,8 +20351,8 @@
sortOnStoreEvents: ['storeColumnChanged','storeDataLoaded'],
/**
* Option: defaultSort
- * The default sorting type, currently set to merge but can be any of the
- * sorters available
+ * The default sorting type, currently set to merge but can be any of
+ * the sorters available
*/
defaultSort : 'merge',
/**
@@ -18471,6 +20380,10 @@
'native' : "Nativesort"
},
+ /**
+ * Method: init
+ * initialize this strategy
+ */
init: function () {
this.parent();
this.bound = {
@@ -18478,6 +20391,10 @@
};
},
+ /**
+ * APIMethod: activate
+ * activates the strategy if it isn't already active.
+ */
activate: function () {
if ($defined(this.options.sortOnStoreEvents)) {
this.options.sortOnStoreEvents.each(function (ev) {
@@ -18486,6 +20403,10 @@
}
},
+ /**
+ * APIMethod: deactivate
+ * deactivates the strategy if it is already active.
+ */
deactivate: function () {
if ($defined(this.options.sortOnStoreEvents)) {
this.options.sortOnStoreEvents.each(function (ev) {
@@ -18500,16 +20421,14 @@
*
* Parameters:
* cols - Optional. An array of columns to sort/group by
- * sort - the sort type (quick,heap,merge,native),defaults to options.defaultSort
+ * sort - the sort type (quick,heap,merge,native),defaults to
+ * options.defaultSort
* dir - the direction to sort. Set to "desc" for descending,
* anything else implies ascending (even null).
*/
sort : function (cols, sort, dir) {
-
if (this.store.count()) {
-
this.store.fireEvent('sortStart', this);
-
var c;
if ($defined(cols) && Jx.type(cols) === 'array') {
c = this.options.sortCols = cols;
@@ -18668,7 +20587,7 @@
}
return col;
}
-});// $Id: $
+});// $Id: parser.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Store.Parser
*
@@ -18705,7 +20624,7 @@
* object - an object to encode
*/
encode: $empty
-});// $Id: $
+});// $Id: parser.json.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Store.Parser.JSON
*
@@ -18765,7 +20684,7 @@
return JSON.encode(data);
}
-});// $Id: button.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: button.js 808 2010-03-27 18:07:49Z pagameba $
/**
* Class: Jx.Button
*
@@ -18774,41 +20693,11 @@
* Jx.Button creates a clickable element that can be added to a web page.
* When the button is clicked, it fires a 'click' event.
*
- * The CSS styling for a button is controlled by several classes related
- * to the various objects in the button's HTML structure:
- *
- * (code)
- * <div class="jxButtonContainer">
- * <a class="jxButton">
- * <span class="jxButtonContent">
- * <img class="jxButtonIcon" src="image_url">
- * <span class="jxButtonLabel">button label</span>
- * </span>
- * </a>
- * </div>
- * (end)
- *
- * The CSS classes will change depending on the type option passed to the
- * constructor of the button. The default type is Button. Passing another
- * value such as Tab will cause all the CSS classes to change from jxButton
- * to jxTab. For example:
- *
- * (code)
- * <div class="jxTabContainer">
- * <a class="jxTab">
- * <span class="jxTabContent">
- * <img class="jxTabIcon" src="image_url">
- * <span class="jxTabLabel">tab label</span>
- * </span>
- * </a>
- * </div>
- * (end)
- *
* When you construct a new instance of Jx.Button, the button does not
* automatically get inserted into the web page. Typically a button
* is used as part of building another capability such as a Jx.Toolbar.
* However, if you want to manually insert the button into your application,
- * you may use the addTo method to append or insert the button into the
+ * you may use the <Jx.Button::addTo> method to append or insert the button into the
* page.
*
* There are two modes for a button, normal and toggle. A toggle button
@@ -18862,13 +20751,6 @@
Family: 'Jx.Button',
Extends: Jx.Widget,
- /**
- * the HTML element that is inserted into the DOM for this button. You
- * may reference this object to append it to the DOM or remove it from
- * the DOM if necessary.
- */
- domObj: null,
-
options: {
/* Option: id
* optional. A string value to use as the ID of the button
@@ -18897,9 +20779,20 @@
* default true, whether the button is a toggle button or not.
*/
toggle: false,
-
+ /* Option: toggleClass
+ * A class to apply to the button if it is a toggle button,
+ * 'jxButtonToggle' by default.
+ */
toggleClass: 'jxButtonToggle',
+ /* Option: pressedClass
+ * A class to apply to the button when it is pressed,
+ * 'jxButtonPressed' by default.
+ */
pressedClass: 'jxButtonPressed',
+ /* Option: activeClass
+ * A class to apply to the buttonwhen it is active,
+ * 'jxButtonActive' by default.
+ */
activeClass: 'jxButtonActive',
/* Option: active
@@ -18911,15 +20804,26 @@
* whether the button is enabled or not.
*/
enabled: true,
+ /* Option: href
+ * set an href on the button's action object, typically an <a> tag.
+ * Default is javascript:void(0) and use onClick.
+ */
+ href: 'javascript:void(0);',
/* Option: template
* the HTML structure of the button. As a minimum, there must be a
- * containing element with a class of jxButtonContainer and an internal
- * element with a class of jxButton. jxButtonIcon and jxButtonLabel are
- * used if present to put the image and label into the button.
+ * containing element with a class of jxButtonContainer and an
+ * internal element with a class of jxButton. jxButtonIcon and
+ * jxButtonLabel are used if present to put the image and label into
+ * the button.
*/
template: '<span class="jxButtonContainer"><a class="jxButton"><span class="jxButtonContent"><img class="jxButtonIcon" src="'+Jx.aPixel.src+'"><span class="jxButtonLabel"></span></span></a></span>'
},
+ /**
+ * Property: classes
+ * used to auto-populate this object with element references when
+ * processing templates
+ */
classes: new Hash({
domObj: 'jxButtonContainer',
domA: 'jxButton',
@@ -18928,7 +20832,7 @@
}),
/**
- * APIMethod: render
+ * Method: render
* create a new button.
*/
render: function() {
@@ -18944,7 +20848,7 @@
var hasFocus;
var mouseDown;
this.domA.set({
- href: 'javascript:void(0)',
+ href: this.options.href,
title: this.options.tooltip,
alt: this.options.tooltip
});
@@ -18995,7 +20899,7 @@
title: this.options.tooltip,
alt: this.options.tooltip
});
- if (this.options.image && this.options.image.indexOf('a_pixel.png') == -1) {
+ if (this.options.image && this.options.image.indexOf(Jx.aPixel.src) == -1) {
this.domImg.setStyle('backgroundImage',"url("+this.options.image+")");
}
if (this.options.imageClass) {
@@ -19031,7 +20935,7 @@
},
/**
- * Method: clicked
+ * APIMethod: clicked
* triggered when the user clicks the button, processes the
* actionPerformed event
*
@@ -19039,7 +20943,7 @@
* evt - {Event} the user click event
*/
clicked : function(evt) {
- if (this.options.enabled) {
+ if (this.options.enabled && !this.isBusy()) {
if (this.options.toggle) {
this.setActive(!this.options.active);
} else {
@@ -19049,7 +20953,7 @@
//return false;
},
/**
- * Method: isEnabled
+ * APIMethod: isEnabled
* This returns true if the button is enabled, false otherwise
*
* Returns:
@@ -19060,7 +20964,7 @@
},
/**
- * Method: setEnabled
+ * APIMethod: setEnabled
* enable or disable the button.
*
* Parameters:
@@ -19075,7 +20979,7 @@
}
},
/**
- * Method: isActive
+ * APIMethod: isActive
* For toggle buttons, this returns true if the toggle button is
* currently active and false otherwise.
*
@@ -19086,28 +20990,30 @@
return this.options.active;
},
/**
- * Method: setActive
+ * APIMethod: setActive
* Set the active state of the button
*
* Parameters:
* active - {Boolean} the new active state of the button
*/
setActive: function(active) {
- if (this.options.active == active) {
- return;
+ if (this.options.enabled && !this.isBusy()) {
+ if (this.options.active == active) {
+ return;
+ }
+ this.options.active = active;
+ if (this.domA) {
+ if (this.options.active) {
+ this.domA.addClass(this.options.activeClass);
+ } else {
+ this.domA.removeClass(this.options.activeClass);
+ }
+ }
+ this.fireEvent(active ? 'down':'up', this);
}
- this.options.active = active;
- if (this.domA) {
- if (this.options.active) {
- this.domA.addClass(this.options.activeClass);
- } else {
- this.domA.removeClass(this.options.activeClass);
- }
- }
- this.fireEvent(active ? 'down':'up', this);
},
/**
- * Method: setImage
+ * APIMethod: setImage
* set the image of this button to a new image URL
*
* Parameters:
@@ -19122,12 +21028,10 @@
}
},
/**
- * Method: setLabel
- *
+ * APIMethod: setLabel
* sets the text of the button.
*
* Parameters:
- *
* label - {String} the new label for the button
*/
setLabel: function(label) {
@@ -19138,15 +21042,14 @@
}
},
/**
- * Method: getLabel
- *
+ * APIMethod: getLabel
* returns the text of the button.
*/
getLabel: function() {
return this.options.label;
},
/**
- * Method: setTooltip
+ * APIMethod: setTooltip
* sets the tooltip displayed by the button
*
* Parameters:
@@ -19159,9 +21062,21 @@
'alt':tooltip
});
}
+ //need to account for the tooltip on the image as well
+ if (this.domImg) {
+ //check if title and alt are set...
+ var t = this.domImg.get('title');
+ if ($defined(t)) {
+ //change it...
+ this.domImg.set({
+ 'title':tooltip,
+ 'alt':tooltip
+ });
+ }
+ }
},
/**
- * Method: focus
+ * APIMethod: focus
* capture the keyboard focus on this button
*/
focus: function() {
@@ -19170,7 +21085,7 @@
}
},
/**
- * Method: blur
+ * APIMethod: blur
* remove the keyboard focus from this button
*/
blur: function() {
@@ -19179,14 +21094,12 @@
}
}
});
-// $Id: flyout.js 602 2009-11-10 19:41:36Z pagameba $
+// $Id: flyout.js 768 2010-03-18 16:22:50Z fred.warnock $
/**
* Class: Jx.Button.Flyout
*
* Extends: <Jx.Button>
*
- * Implements: <Jx.ContentLoader>, <Jx.AutoPosition>, <Jx.Chrome>
- *
* Flyout buttons expose a panel when the user clicks the button. The
* panel can have arbitrary content. You must provide any necessary
* code to hook up elements in the panel to your application.
@@ -19213,9 +21126,6 @@
* flyout buttons inside the content area of another flyout button. In this
* case, opening the inner flyout will not close the outer flyout but it will
* close any other flyouts that are siblings.
- *
- * The options argument takes a combination of options that apply to <Jx.Button>,
- * <Jx.ContentLoader>, and <Jx.AutoPosition>.
*
* Example:
* (code)
@@ -19243,12 +21153,22 @@
Jx.Button.Flyout = new Class({
Family: 'Jx.Button.Flyout',
Extends: Jx.Button,
-
+ Binds: ['keypressHandler', 'clickHandler'],
options: {
+ /* Option: template
+ * the HTML structure of the flyout button
+ */
template: '<span class="jxButtonContainer"><a class="jxButton jxButtonFlyout jxDiscloser"><span class="jxButtonContent"><img class="jxButtonIcon" src="'+Jx.aPixel.src+'"><span class="jxButtonLabel "></span></a></span>',
+ /* Option: contentTemplate
+ * the HTML structure of the flyout content area
+ */
contentTemplate: '<div class="jxFlyout"><div class="jxFlyoutContent"></div></div>'
},
+ /**
+ * Property: contentClasses
+ * the classes array for processing the contentTemplate
+ */
contentClasses: new Hash({
contentContainer: 'jxFlyout',
content: 'jxFlyoutContent'
@@ -19260,7 +21180,7 @@
*/
content: null,
/**
- * APIMethod: render
+ * Method: render
* construct a new instance of a flyout button.
*/
render: function() {
@@ -19276,11 +21196,9 @@
this.content.store('jxFlyout', this);
this.loadContent(this.content);
- this.keypressWatcher = this.keypressHandler.bindWithEvent(this);
- this.hideWatcher = this.clickHandler.bindWithEvent(this);
},
/**
- * Method: clicked
+ * APIMethod: clicked
* Override <Jx.Button::clicked> to hide/show the content area of the
* flyout.
*
@@ -19331,6 +21249,7 @@
}
// now we go on the stack.
Jx.Button.Flyout.Stack.push(this);
+ this.fireEvent('beforeOpen');
this.options.active = true;
this.domA.addClass(this.options.activeClass);
@@ -19354,14 +21273,15 @@
*/
this.contentContainer.setContentBoxSize(document.id(this.content).getMarginBoxSize());
+ this.stack(this.contentContainer);
this.contentContainer.setStyle('visibility','');
- document.addEvent('keydown', this.keypressWatcher);
- document.addEvent('click', this.hideWatcher);
+ document.addEvent('keydown', this.keypressHandler);
+ document.addEvent('click', this.clickHandler);
this.fireEvent('open', this);
},
/**
- * Method: hide
+ * APIMethod: hide
* Closes the flyout if open
*/
hide: function() {
@@ -19371,11 +21291,15 @@
Jx.Button.Flyout.Stack.pop();
this.setActive(false);
this.contentContainer.dispose();
- document.removeEvent('keydown', this.keypressWatcher);
- document.removeEvent('click', this.hideWatcher);
+ this.unstack(this.contentContainer);
+ document.removeEvent('keydown', this.keypressHandler);
+ document.removeEvent('click', this.clickHandler);
this.fireEvent('close', this);
},
- /* hide flyout if the user clicks outside of the flyout */
+ /**
+ * Method: clickHandler
+ * hide flyout if the user clicks outside of the flyout
+ */
clickHandler: function(e) {
e = new Event(e);
var elm = document.id(e.target);
@@ -19385,14 +21309,17 @@
flyout.hide();
}
},
- /* hide flyout if the user presses the ESC key */
+ /**
+ * Method: keypressHandler
+ * hide flyout if the user presses the ESC key
+ */
keypressHandler: function(e) {
e = new Event(e);
if (e.key == 'esc') {
Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1].hide();
}
}
-});// $Id: layout.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: layout.js 718 2010-03-02 16:22:06Z pagameba $
/**
* Class: Jx.Layout
*
@@ -19426,6 +21353,12 @@
Extends: Jx.Object,
options: {
+ /* Option: resizeWithWindow
+ * boolean, automatically resize this layout when the window size
+ * changes, even if the element is not a direct descendant of the
+ * BODY. False by default.
+ */
+ resizeWithWindow: false,
/* Option: propagate
* boolean, controls propogation of resize to child nodes.
* True by default. If set to false, changes in size will not be
@@ -19520,7 +21453,7 @@
this.domObj.setStyle('position', this.options.position);
this.domObj.store('jxLayout', this);
- if (document.body == this.domObj.parentNode) {
+ if (this.options.resizeWithWindow || document.body == this.domObj.parentNode) {
window.addEvent('resize', this.windowResize.bindWithEvent(this));
window.addEvent('load', this.windowResize.bind(this));
}
@@ -19818,7 +21751,7 @@
this.fireEvent('sizeChange',this);
}
-});// $Id: tab.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: tab.js 762 2010-03-16 13:48:29Z pagameba $
/**
* Class: Jx.Button.Tab
*
@@ -19866,18 +21799,69 @@
Extends: Jx.Button,
/**
* Property: content
- * {HTMLElement} The content area that is displayed when the tab is active.
+ * {HTMLElement} The content area that is displayed when the tab is
+ * active.
*/
content: null,
options: {
+ /* Option: toggleClass
+ * the CSS class to use for the button, 'jxTabToggle' by default
+ */
toggleClass: 'jxTabToggle',
+ /* Option: pressedClass
+ * the CSS class to use when the tab is pressed, 'jxTabPressed' by
+ * default
+ */
pressedClass: 'jxTabPressed',
+ /* Option: activeClass
+ * the CSS class to use when the tab is active, 'jxTabActive' by
+ * default.
+ */
activeClass: 'jxTabActive',
+ /* Option: activeTabClass
+ * the CSS class to use on the content area of the active tab,
+ * 'tabContentActive' by default.
+ */
activeTabClass: 'tabContentActive',
+ /* Option: template
+ * the HTML template for a tab
+ */
template: '<span class="jxTabContainer"><a class="jxTab"><span class="jxTabContent"><img class="jxTabIcon"><span class="jxTabLabel"></span></span></a><a class="jxTabClose"></span>',
- contentTemplate: '<div class="tabContent"></div>'
+ /* Option: contentTemplate
+ * the HTML template for a tab's content area
+ */
+ contentTemplate: '<div class="tabContent"></div>',
+ /* Option: close
+ * {Boolean} can the tab be closed by the user? False by default.
+ */
+ close: false,
+ /* Option: shouldClose
+ * {Mixed} when a tab is closeable, the shouldClose option is checked
+ * first to see if the tab should close. You can provide a function
+ * for this option that can be used to return a boolean value. This
+ * is useful if your tab contains something the user can edit and you
+ * want to see if they want to discard the changes before closing.
+ * The default value is true, meaning the tab will close immediately.
+ * (code)
+ * new Jx.Tab({
+ * label: 'test close',
+ * close: true,
+ * shouldClose: function() {
+ * return window.confirm('Are you sure?');
+ * }
+ * });
+ * (end)
+ */
+ shouldClose: true
},
+ /**
+ * Property: classes
+ * {<Hash>} a hash of object properties to CSS class names used to
+ * automatically extract references to important DOM elements when
+ * processing a widget template. This allows developers to provide custom
+ * HTML structures without affecting the functionality of widgets.
+ */
classes: new Hash({
domObj: 'jxTabContainer',
domA: 'jxTab',
@@ -19888,7 +21872,7 @@
}),
/**
- * APIMethod: render
+ * Method: render
* Create a new instance of Jx.Button.Tab. Any layout options passed are used
* to create a <Jx.Layout> for the tab content area.
*/
@@ -19911,7 +21895,17 @@
if (this.options.close) {
this.domObj.addClass('jxTabClose');
this.domClose.addEvent('click', (function(){
+ var shouldClose = true;
+ if ($defined(this.options.shouldClose)) {
+ if (typeof this.options.shouldClose == 'function') {
+ shouldClose = this.options.shouldClose();
+ } else {
+ shouldClose = this.options.shouldClose;
+ }
+ }
+ if (shouldClose) {
this.fireEvent('close');
+ }
}).bind(this));
} else {
this.domClose.dispose();
@@ -19919,7 +21913,7 @@
}
},
/**
- * Method: clicked
+ * APIMethod: clicked
* triggered when the user clicks the button, processes the
* actionPerformed event
*/
@@ -19928,7 +21922,7 @@
this.setActive(true);
}
}
-});// $Id: colorpalette.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: colorpalette.js 776 2010-03-22 14:35:16Z pagameba $
/**
* Class: Jx.ColorPalette
*
@@ -19939,8 +21933,9 @@
* palette of web-safe colours. The user can also enter an opacity value.
*
* A Jx.ColorPalette can be embedded anywhere in a web page using its addTo
- * method. However, a <Jx.Button> suJx.Tooltipbclass is provided (<Jx.Button.Color>)
- * that embeds a colour panel inside a button for easy use in toolbars.
+ * method. However, a <Jx.Button> suJx.Tooltipbclass is provided
+ * (<Jx.Button.Color>) that embeds a colour panel inside a button for easy use
+ * in toolbars.
*
* Colour changes are propogated via a change event. To be notified
* of changes in a Jx.ColorPalette, use the addEvent method.
@@ -19953,6 +21948,10 @@
* change - triggered when the color changes.
* click - the user clicked on a color swatch (emitted after a change event)
*
+ * MooTools.lang keys:
+ * - colorpalette.alphaLabel
+ *
+ *
* License:
* Copyright (c) 2008, DM Solutions Group Inc.
*
@@ -19983,14 +21982,10 @@
* an array of hex colors for creating the palette, defaults to a
* set of web safe colors.
*/
- hexColors: ['00', '33', '66', '99', 'CC', 'FF'],
- /* Option: alphaLabel
- * the text to display next to the alpha input for i18n.
- */
- alphaLabel: 'alpha (%)'
+ hexColors: ['00', '33', '66', '99', 'CC', 'FF']
},
/**
- * APIMethod: render
+ * Method: render
* initialize a new instance of Jx.ColorPalette
*/
render: function() {
@@ -20009,7 +22004,10 @@
top.adopt(d);
- this.colorInputLabel = new Element('label', {'class':'jxColorLabel', html:'#'});
+ this.colorInputLabel = new Element('label', {
+ 'class':'jxColorLabel',
+ html:'#'
+ });
top.adopt(this.colorInputLabel);
var cc = this.changed.bind(this);
@@ -20026,7 +22024,7 @@
top.adopt(this.colorInput);
- this.alphaLabel = new Element('label', {'class':'jxAlphaLabel', 'html':this.options.alphaLabel});
+ this.alphaLabel = new Element('label', {'class':'jxAlphaLabel', 'html':MooTools.lang.get('Jx','colorpalette').alphaLabel});
top.adopt(this.alphaLabel);
this.alphaInput = new Element('input', {
@@ -20088,7 +22086,9 @@
g = j%6;
b = i%6;
}
- var bgColor = '#'+this.options.hexColors[r]+this.options.hexColors[g]+this.options.hexColors[b];
+ var bgColor = '#'+this.options.hexColors[r]+
+ this.options.hexColors[g]+
+ this.options.hexColors[b];
var td = new Element('td');
if (!bSkip) {
@@ -20180,7 +22180,7 @@
},
/**
- * Method: setColor
+ * APIMethod: setColor
* set the colour represented by this colour panel
*
* Parameters:
@@ -20192,7 +22192,7 @@
},
/**
- * Method: setAlpha
+ * APIMethod: setAlpha
* set the alpha represented by this colour panel
*
* Parameters:
@@ -20217,17 +22217,39 @@
if (this.options.alpha < 1) {
styles.opacity = this.options.alpha;
styles.filter = 'Alpha(opacity='+(this.options.alpha*100)+')';
+
} else {
- styles.opacity = '';
- styles.filter = '';
+ styles.opacity = 1;
+ //not sure what the proper way to remove the filter would be since
+ // I don't have IE to test against.
+ styles.filter = '';
}
this.selectedSwatch.setStyles(styles);
this.previewSwatch.setStyles(styles);
+
this.fireEvent('change', this);
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the
+ * widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ this.parent();
+
+ if ($defined(this.alphaLabel)) {
+ this.alphaLabel.set('html', MooTools.lang.get('Jx','colorpalette').alphaLabel);
+ }
}
});
-// $Id: color.js 626 2009-11-20 13:22:22Z pagameba $
+// $Id: color.js 762 2010-03-16 13:48:29Z pagameba $
/**
* Class: Jx.Button.Color
*
@@ -20265,6 +22287,11 @@
Family: 'Jx.Button.Color',
Extends: Jx.Button.Flyout,
+ /**
+ * Property: swatch
+ * the color swatch element used to portray the currently selected
+ * color
+ */
swatch: null,
options: {
@@ -20281,9 +22308,20 @@
*
*/
alpha: 100,
+ /*
+ * Option: template
+ * the HTML template for the color button
+ */
template: '<span class="jxButtonContainer"><a class="jxButton jxButtonFlyout jxDiscloser"><span class="jxButtonContent"><span class="jxButtonSwatch"><span class="jxButtonSwatchColor"></span></span><span class="jxButtonLabel"></span></span></a></span>'
},
+ /**
+ * Property: classes
+ * {<Hash>} a hash of object properties to CSS class names used to
+ * automatically extract references to important DOM elements when
+ * processing a widget template. This allows developers to provide custom
+ * HTML structures without affecting the functionality of widgets.
+ */
classes: new Hash({
domObj: 'jxButtonContainer',
domA: 'jxButton',
@@ -20292,7 +22330,7 @@
}),
/**
- * APIMethod: render
+ * Method: render
* creates a new color button.
*/
render: function() {
@@ -20315,7 +22353,7 @@
},
/**
- * Method: clicked
+ * APIMethod: clicked
* override <Jx.Button.Flyout> to use a singleton color palette.
*/
clicked: function() {
@@ -20339,7 +22377,7 @@
},
/**
- * Method: hide
+ * APIMethod: hide
* hide the color panel
*/
hide: function() {
@@ -20351,7 +22389,7 @@
},
/**
- * Method: setColor
+ * APIMethod: setColor
* set the color represented by this color panel
*
* Parameters:
@@ -20363,7 +22401,7 @@
},
/**
- * Method: setAlpha
+ * APIMethod: setAlpha
* set the alpha represented by this color panel
*
* Parameters:
@@ -20409,13 +22447,13 @@
styles.opacity = this.options.alpha / 100;
} else {
- styles.opacity = '';
+ styles.opacity = 1;
styles.filter = '';
}
this.swatch.setStyles(styles);
}
});
-// $Id: menu.js 626 2009-11-20 13:22:22Z pagameba $
+// $Id: menu.js 817 2010-03-30 12:13:04Z pagameba $
/**
* Class: Jx.Menu
*
@@ -20521,9 +22559,9 @@
*
* Parameters:
* item - {<Jx.MenuItem>} the menu item to add. Multiple menu items
- * can be added by passing multiple arguments to this function.
- * position -
- * owner -
+ * can be added by passing an array of menu items.
+ * position - the index to add the item at, defaults to the end of the
+ * menu
*/
add: function(item, position, owner) {
if (Jx.type(item) == 'array') {
@@ -20560,6 +22598,18 @@
return this;
},
/**
+ * APIMethod: empty
+ * Empty the menu of items
+ */
+ empty: function() {
+ this.list.each(function(item){
+ if (item.empty) {
+ item.empty();
+ }
+ }, this);
+ this.list.empty();
+ },
+ /**
* Method: deactivate
* Deactivate the menu by hiding it.
*/
@@ -20652,6 +22702,7 @@
this.list.each(function(item){item.retrieve('jxMenuItem').hide(e);});
document.removeEvent('mousedown', this.bound.mousedown);
document.removeEvent('keydown', this.bound.keypress);
+ this.unstack(this.contentContainer);
this.contentContainer.dispose();
this.visibleItem = null;
this.fireEvent('hide', this);
@@ -20694,7 +22745,7 @@
this.position(this.contentContainer, this.domObj, $merge({
offsets: this.chromeOffsets
}, this.options.position));
-
+ this.stack(this.contentContainer);
this.contentContainer.setStyle('visibility','visible');
if (this.button && this.button.domA) {
@@ -20828,25 +22879,25 @@
});
-// $Id: set.js 626 2009-11-20 13:22:22Z pagameba $
+// $Id: set.js 762 2010-03-16 13:48:29Z pagameba $
/**
* Class: Jx.ButtonSet
*
* Extends: <Jx.Object>
*
- * A ButtonSet manages a set of <Jx.Button> instances by ensuring that only one
- * of the buttons is active. All the buttons need to have been created with
- * the toggle option set to true for this to work.
+ * A ButtonSet manages a set of <Jx.Button> instances by ensuring that only
+ * one of the buttons is active. All the buttons need to have been created
+ * with the toggle option set to true for this to work.
*
* Example:
* (code)
* var toolbar = new Jx.Toolbar('bar');
* var buttonSet = new Jx.ButtonSet();
*
- * var tab1 = new Jx.Button({label: 'b1', toggle:true, contentID: 'content1'});
- * var tab2 = new Jx.Button({label: 'b2', toggle:true, contentID: 'content2'});
- * var tab3 = new Jx.Button({label: 'b3', toggle:true, contentID: 'content3'});
- * var tab4 = new Jx.Button({label: 'b4', toggle:true, contentURL: 'test_content.html'});
+ * var b1 = new Jx.Button({label: 'b1', toggle:true, contentID: 'content1'});
+ * var b2 = new Jx.Button({label: 'b2', toggle:true, contentID: 'content2'});
+ * var b3 = new Jx.Button({label: 'b3', toggle:true, contentID: 'content3'});
+ * var b4 = new Jx.Button({label: 'b4', toggle:true, contentID: 'content4'});
*
* buttonSet.add(b1,b2,b3,b4);
* (end)
@@ -20862,27 +22913,21 @@
Jx.ButtonSet = new Class({
Family: 'Jx.ButtonSet',
Extends: Jx.Object,
+ Binds: ['buttonChanged'],
/**
* Property: buttons
* {Array} array of buttons that are managed by this button set
*/
- buttons: null,
- /**
- * APIMethod: init
- * initializes the button set.
- */
- init : function() {
- this.buttons = [];
- this.buttonChangedHandler = this.buttonChanged.bind(this);
- },
+ buttons: [],
/**
- * Method: add
+ * APIMethod: add
* Add one or more <Jx.Button>s to the ButtonSet.
*
* Parameters:
- * button - {<Jx.Button>} an instance of <Jx.Button> to add to the button set. More
- * than one button can be added by passing extra parameters to this method.
+ * button - {<Jx.Button>} an instance of <Jx.Button> to add to the button
+ * set. More than one button can be added by passing extra parameters to
+ * this method.
*/
add : function() {
$A(arguments).each(function(button) {
@@ -20890,7 +22935,7 @@
button.domObj.removeClass(button.options.toggleClass);
button.domObj.addClass(button.options.toggleClass+'Set');
}
- button.addEvent('down',this.buttonChangedHandler);
+ button.addEvent('down',this.buttonChanged);
button.setActive = function(active) {
if (button.options.active && this.activeButton == button) {
return;
@@ -20907,7 +22952,7 @@
return this;
},
/**
- * Method: remove
+ * APIMethod: remove
* Remove a button from this Button.
*
* Parameters:
@@ -20919,12 +22964,20 @@
if (this.buttons.length) {
this.buttons[0].setActive(true);
}
- button.removeEvent('down',this.buttonChangedHandler);
+ button.removeEvent('down',this.buttonChanged);
button.setActive = Jx.Button.prototype.setActive;
}
},
/**
- * Method: setActiveButton
+ * APIMethod: empty
+ * empty the button set and clear the active button
+ */
+ empty: function() {
+ this.buttons = [];
+ this.activeButton = null;
+ },
+ /**
+ * APIMethod: setActiveButton
* Set the active button to the one passed to this method
*
* Parameters:
@@ -20938,7 +22991,7 @@
}
},
/**
- * Method: selectionChanged
+ * Method: buttonChanged
* Handle selection changing on the buttons themselves and activate the
* appropriate button in response.
*
@@ -20949,7 +23002,7 @@
this.setActiveButton(button);
this.fireEvent('change', this);
}
-});// $Id: multi.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: multi.js 762 2010-03-16 13:48:29Z pagameba $
/**
* Class: Jx.Button.Multi
*
@@ -21008,13 +23061,14 @@
*/
Jx.Button.Multi = new Class({
Family: 'Jx.Button.Multi',
+ Extends: Jx.Button,
- Extends: Jx.Button,
/**
* Property: {<Jx.Button>} activeButton
* the currently selected button
*/
activeButton: null,
+
/**
* Property: buttons
* {Array} the buttons added to this multi button
@@ -21022,8 +23076,19 @@
buttons: null,
options: {
+ /* Option: template
+ * the button template for a multi button
+ */
template: '<span class="jxButtonContainer"><a class="jxButton jxButtonMulti jxDiscloser"><span class="jxButtonContent"><img src="'+Jx.aPixel.src+'" class="jxButtonIcon"><span class="jxButtonLabel"></span></span></a><a class="jxButtonDisclose" href="javascript:void(0)"><img src="'+Jx.aPixel.src+'"></a></span>'
},
+
+ /**
+ * Property: classes
+ * {<Hash>} a hash of object properties to CSS class names used to
+ * automatically extract references to important DOM elements when
+ * processing a widget template. This allows developers to provide custom
+ * HTML structures without affecting the functionality of widgets.
+ */
classes: new Hash({
domObj: 'jxButtonContainer',
domA: 'jxButton',
@@ -21032,9 +23097,8 @@
domDisclose: 'jxButtonDisclose'
}),
-
/**
- * APIMethod: render
+ * Method: render
* construct a new instance of Jx.Button.Multi.
*/
render: function() {
@@ -21079,8 +23143,8 @@
this.contentContainer.setStyle('visibility','');
- document.addEvent('mousedown', this.hideWatcher);
- document.addEvent('keyup', this.keypressWatcher);
+ document.addEvent('mousedown', this.bound.mousedown);
+ document.addEvent('keyup', this.bound.keypress);
this.fireEvent('show', this);
}).bindWithEvent(this.menu),
@@ -21137,7 +23201,7 @@
}
},
/**
- * Method: add
+ * APIMethod: add
* adds one or more buttons to the Multi button. The first button
* added becomes the active button initialize. This function
* takes a variable number of arguments, each of which is expected
@@ -21179,7 +23243,7 @@
}, this);
},
/**
- * Method: remove
+ * APIMethod: remove
* remove a button from a multi button
*
* Parameters:
@@ -21212,7 +23276,14 @@
}
},
/**
- * Method: setActiveButton
+ * APIMethod: empty
+ * remove all buttons from the multi button
+ */
+ empty: function() {
+ this.buttons.each(function(b){this.remove(b);}, this);
+ },
+ /**
+ * APIMethod: setActiveButton
* update the menu item to be the requested button.
*
* Parameters:
@@ -21366,7 +23437,7 @@
}
});
-// $Id: combo.js 647 2009-11-26 16:23:24Z pagameba $
+// $Id: combo.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Button.Combo
*
@@ -21465,7 +23536,7 @@
}
this.contentContainer.setStyle('visibility','hidden');
this.contentContainer.setStyle('display','block');
- $(document.body).adopt(this.contentContainer);
+ document.id(document.body).adopt(this.contentContainer);
/* we have to size the container for IE to render the chrome correctly
* but just in the menu/sub menu case - there is some horrible peekaboo
* bug in IE related to ULs that we just couldn't figure out
@@ -21515,8 +23586,12 @@
return this.options.label;
},
- setValue: function() {
-
+ setValue: function(value) {
+ this.buttonSet.buttons.each(function(button){
+ if (button.options.label === value) {
+ button.setActive(true);
+ }
+ },this);
},
/**
@@ -21561,8 +23636,19 @@
*/
remove: function(idx) {
//TODO: implement remove?
+ },
+
+ /**
+ * APIMethod: empty
+ * remove all items from the combo
+ */
+ empty: function() {
+ this.menu.empty();
+ this.buttonSet.empty();
+ this.setLabel('');
+ this.setImage(Jx.aPixel.src);
}
-});// $Id: toolbar.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: toolbar.js 801 2010-03-27 15:04:05Z pagameba $
/**
* Class: Jx.Toolbar
*
@@ -21739,6 +23825,10 @@
}
this.list.add(item);
}, this);
+
+ //Update the size of the toolbar container.
+ this.update();
+
return this;
},
/**
@@ -21759,9 +23849,17 @@
}
var li = item.findElement('LI');
this.list.remove(li);
+ this.update();
return this;
},
/**
+ * APIMethod: empty
+ * remove all items from the toolbar
+ */
+ empty: function() {
+ this.list.each(function(item){this.remove(item);},this);
+ },
+ /**
* Method: deactivate
* Deactivate the Toolbar (when it is acting as a menu bar).
*/
@@ -21814,11 +23912,36 @@
this.visibleItem.show();
}
},
+
showItem: function(item) {
this.fireEvent('show', item);
+ },
+ /**
+ * Method: update
+ * Updates the size of the UL so that the size is always consistently the
+ * exact size of the size of the sum of the buttons. This will keep all of
+ * the buttons on one line.
+ */
+ update: function () {
+ // if (['top','bottom'].contains(this.options.position)) {
+ // (function(){
+ // var s = 0;
+ // var children = this.domObj.getChildren();
+ // children.each(function(button){
+ // var size = button.getMarginBoxSize();
+ // s += size.width +0.5;
+ // },this);
+ // if (s !== 0) {
+ // this.domObj.setStyle('width', Math.round(s));
+ // } else {
+ // this.domObj.setStyle('width','auto');
+ // }
+ // }).delay(1,this);
+ // }
+ this.fireEvent('update');
}
});
-// $Id: container.js 626 2009-11-20 13:22:22Z pagameba $
+// $Id: container.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Toolbar.Container
*
@@ -21842,14 +23965,18 @@
*
* This file is licensed under an MIT style license
*/
+
Jx.Toolbar.Container = new Class({
+
Family: 'Jx.Toolbar.Container',
Extends: Jx.Widget,
+ Binds: ['update'],
+ pluginNamespace: 'ToolbarContainer',
/**
* Property: domObj
* {HTMLElement} the HTML element that the container lives in
*/
- domObj : null,
+ domObj: null,
options: {
/* Option: parent
* a DOM element to add this to
@@ -21871,32 +23998,42 @@
* Default is true.
*/
scroll: true,
- template: "<div class='jxBarContainer'></div>",
- scrollerTemplate: "<div class='jxBarScroller'></div>"
+ template: "<div class='jxBarContainer'><div class='jxBarControls'></div></div>",
+ scrollerTemplate: "<div class='jxBarScroller'><div class='jxBarWrapper'></div></div>"
},
classes: new Hash({
domObj: 'jxBarContainer',
- scroller: 'jxBarScroller'
+ scroller: 'jxBarScroller',
+ //used to hide the overflow of the wrapper
+ wrapper: 'jxBarWrapper',
+ controls: 'jxBarControls'
+ //used to allow multiple toolbars to float next to each other
}),
+
+ updating: false,
+
/**
* APIMethod: render
* Create a new instance of Jx.Toolbar.Container
*/
- render : function() {
+ render: function() {
this.parent();
/* if a container was passed in, use it instead of the one from the
* template
*/
if (document.id(this.options.parent)) {
this.domObj = document.id(this.options.parent);
- this.elements = new Hash({'jxBarContainer':this.domObj});
+ this.elements = new Hash({
+ 'jxBarContainer': this.domObj
+ });
this.domObj.addClass('jxBarContainer');
- this.domObj.adopt(this.scroller);
+ this.domObj.grab(this.controls);
+ this.domObj.addEvent('sizeChange', this.update);
}
if (this.options.scroll) {
this.processElements(this.options.scrollerTemplate, this.classes);
- this.domObj.adopt(this.scroller);
+ this.domObj.grab(this.scroller, 'top');
}
/* this allows toolbars to add themselves to this bar container
@@ -21905,149 +24042,135 @@
*/
this.domObj.store('jxBarContainer', this);
- if (['top','right','bottom','left'].contains(this.options.position)) {
+ if (['top', 'right', 'bottom', 'left'].contains(this.options.position)) {
this.domObj.addClass('jxBar' +
- this.options.position.capitalize());
+ this.options.position.capitalize());
} else {
this.domObj.addClass('jxBarTop');
this.options.position = 'top';
}
- if (this.options.scroll && ['top','bottom'].contains(this.options.position)) {
+ if (this.options.scroll && ['top', 'bottom'].contains(this.options.position)) {
// make sure we update our size when we get added to the DOM
- this.addEvent('addTo', this.update.bind(this));
+ this.addEvent('addTo', function(){
+ this.domObj.getParent().addEvent('sizeChange', this.update);
+ this.update();
+ });
- //making Fx.Tween optional
- if (typeof Fx != 'undefined' && typeof Fx.Tween != 'undefined'){
- this.scrollFx = scrollFx = new Fx.Tween(this.scroller, {
- link: 'chain'
- });
- }
-
this.scrollLeft = new Jx.Button({
image: Jx.aPixel.src
- }).addTo(this.domObj);
- this.scrollLeft.domObj.addClass('jxBarScrollLeft');
+ }).addTo(this.controls, 'bottom');
+ document.id(this.scrollLeft).addClass('jxBarScrollLeft');
this.scrollLeft.addEvents({
- click: (function(){
- var from = this.scroller.getStyle('left').toInt();
- if (isNaN(from)) { from = 0; }
- var to = Math.min(from+100, 0);
- if (to >= 0) {
- this.scrollLeft.domObj.setStyle('visibility', 'hidden');
- }
- this.scrollRight.domObj.setStyle('visibility', '');
- if ($defined(this.scrollFx)){
- this.scrollFx.start('left', from, to);
- } else {
- this.scroller.setStyle('left',to);
- }
- }).bind(this)
+ click: this.scroll.bind(this, 'left')
});
this.scrollRight = new Jx.Button({
image: Jx.aPixel.src
- }).addTo(this.domObj);
- this.scrollRight.domObj.addClass('jxBarScrollRight');
+ }).addTo(this.controls, 'bottom');
+ document.id(this.scrollRight).addClass('jxBarScrollRight');
this.scrollRight.addEvents({
- click: (function(){
- var from = this.scroller.getStyle('left').toInt();
- if (isNaN(from)) { from = 0; }
- var to = Math.max(from - 100, this.scrollWidth);
- if (to == this.scrollWidth) {
- this.scrollRight.domObj.setStyle('visibility', 'hidden');
- }
- this.scrollLeft.domObj.setStyle('visibility', '');
- if ($defined(this.scrollFx)){
- this.scrollFx.start('left', from, to);
- } else {
- this.scroller.setStyle('left',to);
- }
- }).bind(this)
+ click: this.scroll.bind(this, 'right')
});
+ } else if (this.options.scroll && ['left', 'right'].contains(this.options.position)) {
+ //do we do scrolling up and down?
+ //for now disable scroll in this case
+ this.options.scroll = false;
} else {
this.options.scroll = false;
}
+ this.addEvent('add', this.update);
if (this.options.toolbars) {
this.add(this.options.toolbars);
}
},
update: function() {
- if (this.options.autoSize) {
- /* delay the size update a very small amount so it happens
- * after the current thread of execution finishes. If the
- * current thread is part of a window load event handler,
- * rendering hasn't quite finished yet and the sizes are
- * all wrong
- */
- (function(){
- var x = 0;
- this.scroller.getChildren().each(function(child){
- x+= child.getSize().x;
- });
- this.domObj.setStyles({width:x});
- this.measure();
- }).delay(1,this);
- } else {
- this.measure();
- }
- },
+ if (this.options.scroll) {
+ if (['top', 'bottom'].contains(this.options.position)) {
+ var tbcSize = this.domObj.getContentBoxSize().width;
- measure: function() {
- if (!this.options.scroll) { return; }
+ var s = 0;
+ //next check to see if we need the scrollers or not.
+ var children = this.wrapper.getChildren();
+ if (children.length > 0) {
+ children.each(function(tb) {
+ s += tb.getMarginBoxSize().width;
+ },
+ this);
- if ((!this.scrollLeftSize || !this.scrollLeftSize.x) && this.domObj.parentNode) {
- this.scrollLeftSize = this.scrollLeft.domObj.getSize();
- this.scrollRightSize = this.scrollRight.domObj.getSize();
- }
- /* decide if we need to show the scroller buttons and
- * do some calculations that will make it faster
- */
- this.scrollWidth = this.domObj.getSize().x;
- this.scroller.getChildren().each(function(child){
- this.scrollWidth -= child.getSize().x;
- }, this);
- if (this.scrollWidth < 0) {
- /* we need to show scrollers on at least one side */
- var l = this.scroller.getStyle('left').toInt();
- if (l < 0) {
- this.scrollLeft.domObj.setStyle('visibility','');
- } else {
- this.scrollLeft.domObj.setStyle('visibility','hidden');
- }
- if (l <= this.scrollWidth) {
- this.scrollRight.domObj.setStyle('visibility', 'hidden');
- if (l < this.scrollWidth) {
- if ($defined(this.scrollFx)){
- this.scrollFx.start('left', l, this.scrollWidth);
+ var scrollerSize = tbcSize;
+
+ if (s === 0) {
+ this.scrollLeft.setEnabled(false);
+ this.scrollRight.setEnabled(false);
} else {
- this.scroller.setStyle('left',this.scrollWidth);
+
+
+ var leftMargin = this.wrapper.getStyle('margin-left').toInt();
+ scrollerSize -= this.controls.getMarginBoxSize().width;
+
+
+ if (leftMargin < 0) {
+ //has been scrolled left so activate the right scroller
+ this.scrollLeft.setEnabled(true);
+ } else {
+ //we don't need it
+ this.scrollLeft.setEnabled(false);
+ }
+
+ if (s + leftMargin > scrollerSize) {
+ //we need the right one
+ this.scrollRight.setEnabled(true);
+ } else {
+ //we don't need it
+ this.scrollRight.setEnabled(false);
+ }
}
- }
- } else {
- this.scrollRight.domObj.setStyle('visibility', '');
- }
- } else {
- /* don't need any scrollers but we might need to scroll
- * the toolbar into view
- */
- this.scrollLeft.domObj.setStyle('visibility','hidden');
- this.scrollRight.domObj.setStyle('visibility','hidden');
- var from = this.scroller.getStyle('left').toInt();
- if (!isNaN(from) && from !== 0) {
- if ($defined(this.scrollFx)) {
- this.scrollFx.start('left', 0);
} else {
- this.scroller.setStyle('left',0);
+ this.scrollRight.setEnabled(false);
+ this.scrollLeft.setEnabled(false);
}
+ this.scroller.setStyle('width', scrollerSize);
+
+ this.findFirstVisible();
+ this.updating = false;
}
}
},
+ /**
+ * Method: findFirstVisible
+ * Finds the first visible button on the toolbar and saves a reference in
+ * the scroller object
+ */
+ findFirstVisible: function() {
+ if ($defined(this.scroller.retrieve('buttonPointer'))) {
+ return;
+ };
+ var children = this.wrapper.getChildren();
+
+ if (children.length > 0) {
+ children.each(function(toolbar) {
+ var buttons = toolbar.getChildren();
+ if (buttons.length > 1) {
+ buttons.each(function(button) {
+ var pos = button.getCoordinates(this.scroller);
+ if (pos.left >= 0 && !$defined(this.scroller.retrieve('buttonPointer'))) {
+ //this is the first visible button
+ this.scroller.store('buttonPointer', button);
+ }
+ },
+ this);
+ }
+ },
+ this);
+ }
+ },
+
/**
* Method: add
* Add a toolbar to the container.
@@ -22056,31 +24179,108 @@
* toolbar - {Object} the toolbar to add. More than one toolbar
* can be added by passing multiple arguments.
*/
- add: function( ) {
+ add: function() {
$A(arguments).flatten().each(function(thing) {
if (this.options.scroll) {
/* we potentially need to show or hide scroller buttons
* when the toolbar contents change
*/
- thing.addEvent('add', this.update.bind(this));
- thing.addEvent('remove', this.update.bind(this));
+ thing.addEvent('update', this.update.bind(this));
thing.addEvent('show', this.scrollIntoView.bind(this));
}
- if (this.scroller) {
- this.scroller.adopt(thing.domObj);
+ if (this.wrapper) {
+ this.wrapper.adopt(thing.domObj);
} else {
this.domObj.adopt(thing.domObj);
}
- this.domObj.addClass('jxBar'+this.options.position.capitalize());
- }, this);
- if (this.options.scroll) {
- this.update();
- }
+ this.domObj.addClass('jxBar' + this.options.position.capitalize());
+ },
+ this);
if (arguments.length > 0) {
this.fireEvent('add', this);
}
return this;
},
+
+ scroll: function(direction) {
+ if (this.updating) {
+ return
+ };
+ this.updating = true;
+
+ var currentButton = this.scroller.retrieve('buttonPointer');
+ if (direction === 'left') {
+ //need to tween the amount of the previous button
+ var previousButton = this.scroller.retrieve('previousPointer');
+ if (!previousButton) {
+ previousButton = this.getPreviousButton(currentButton);
+ }
+ if (previousButton) {
+ var w = previousButton.getMarginBoxSize().width;
+ var ml = this.wrapper.getStyle('margin-left').toInt();
+ ml += w;
+ if (typeof Fx != 'undefined' && typeof Fx.Tween != 'undefined') {
+ //scroll it
+ this.wrapper.get('tween', {
+ property: 'margin-left',
+ onComplete: this.afterTweenLeft.bind(this, previousButton)
+ }).start(ml);
+ } else {
+ //set it
+ this.wrapper.setStyle('margin-left', ml);
+ this.afterTweenLeft(previousButton);
+ }
+ } else {
+ this.update();
+ }
+ } else {
+ //must be right
+ var w = currentButton.getMarginBoxSize().width;
+
+ var ml = this.wrapper.getStyle('margin-left').toInt();
+ ml -= w;
+
+ //now, if Fx is defined tween the margin to the left to
+ //hide the current button
+ if (typeof Fx != 'undefined' && typeof Fx.Tween != 'undefined') {
+ //scroll it
+ this.wrapper.get('tween', {
+ property: 'margin-left',
+ onComplete: this.afterTweenRight.bind(this, currentButton)
+ }).start(ml);
+ } else {
+ //set it
+ this.wrapper.setStyle('margin-left', ml);
+ this.afterTweenRight(currentButton);
+ }
+
+ }
+ },
+
+ afterTweenRight: function(currentButton) {
+ var np = this.getNextButton(currentButton);
+ if (!np) {
+ np = currentButton;
+ }
+ this.scroller.store('buttonPointer', np);
+ if (np !== currentButton) {
+ this.scroller.store('previousPointer', currentButton);
+ }
+ this.update();
+ },
+
+ afterTweenLeft: function(previousButton) {
+ this.scroller.store('buttonPointer', previousButton);
+ var pp = this.getPreviousButton(previousButton);
+ if ($defined(pp)) {
+ this.scroller.store('previousPointer', pp);
+ } else {
+ this.scroller.eliminate('previousPointer');
+ }
+ this.update();
+ },
+
+
/**
* Method: remove
* remove an item from a toolbar. If the item is not in this toolbar
@@ -22094,7 +24294,12 @@
* removed.
*/
remove: function(item) {
-
+ if (item instanceof Jx.Widget) {
+ item.dispose();
+ } else {
+ document.id(item).dispose();
+ }
+ this.update();
},
/**
* Method: scrollIntoView
@@ -22105,62 +24310,98 @@
* item - the item to scroll.
*/
scrollIntoView: function(item) {
- var width = this.domObj.getSize().x;
- var coords = item.domObj.getCoordinates(this.scroller);
+ var currentButton = this.scroller.retrieve('buttonPointer');
+ // if (!$defined(currentButton)) return;
+ if (item instanceof Jx.Widget) {
+ item = item.domObj;
+ while (!item.hasClass('jxToolItem')) {
+ item = item.getParent();
+ }
+ }
+ var pos = item.getCoordinates(this.scroller);
+ var scrollerSize = this.scroller.getStyle('width').toInt();
- //left may be set to auto or even a zero length string.
- //In the previous version, in air, this would evaluate to
- //NaN which would cause the right hand scroller to show when
- //the component was first created.
+ if (pos.right > 0 && pos.right <= scrollerSize && pos.left > 0 && pos.left <= scrollerSize) {
+ //we are completely on screen
+ return;
+ };
- //So, get the left value first
- var l = this.scroller.getStyle('left');
- //then check to see if it's auto or a zero length string
- if (l === 'auto' || l.length <= 0) {
- //If so, set to 0.
- l = 0;
+ if (pos.right > scrollerSize) {
+ //it's right of the scroller
+ var diff = pos.right - scrollerSize;
+
+ //loop through toolbar items until we have enough width to
+ //make the item visible
+ var ml = this.wrapper.getStyle('margin-left').toInt();
+ var w = currentButton.getMarginBoxSize().width;
+ var np;
+ while (w < diff && $defined(currentButton)) {
+ np = this.getNextButton(currentButton);
+ if (np) {
+ w += np.getMarginBoxSize().width;
+ } else {
+ break;
+ }
+ currentButton = np;
+ }
+
+ ml -= w;
+
+ if (typeof Fx != 'undefined' && typeof Fx.Tween != 'undefined') {
+ //scroll it
+ this.wrapper.get('tween', {
+ property: 'margin-left',
+ onComplete: this.afterTweenRight.bind(this, currentButton)
+ }).start(ml);
+ } else {
+ //set it
+ this.wrapper.setStyle('margin-left', ml);
+ this.afterTweenRight(currentButton);
+ }
} else {
- //otherwise, convert to int
- l = l.toInt();
+ //it's left of the scroller
+ var ml = this.wrapper.getStyle('margin-left').toInt();
+ ml -= pos.left;
+
+ if (typeof Fx != 'undefined' && typeof Fx.Tween != 'undefined') {
+ //scroll it
+ this.wrapper.get('tween', {
+ property: 'margin-left',
+ onComplete: this.afterTweenLeft.bind(this, item)
+ }).start(ml);
+ } else {
+ //set it
+ this.wrapper.setStyle('margin-left', ml);
+ this.afterTweenLeft(item);
+ }
}
- var slSize = this.scrollLeftSize ? this.scrollLeftSize.x : 0;
- var srSize = this.scrollRightSize ? this.scrollRightSize.x : 0;
- var left = l;
- if (l < -coords.left + slSize) {
- /* the left edge of the item is not visible */
- left = -coords.left + slSize;
- if (left >= 0) {
- left = 0;
+ },
+
+ getPreviousButton: function(currentButton) {
+ pp = currentButton.getPrevious();
+ if (!$defined(pp)) {
+ //check for a new toolbar
+ pp = currentButton.getParent().getPrevious();
+ if (pp) {
+ pp = pp.getLast();
}
- } else if (width - coords.right - srSize< l) {
- /* the right edge of the item is not visible */
- left = width - coords.right - srSize;
- if (left < this.scrollWidth) {
- left = this.scrollWidth;
- }
}
+ return pp;
+ },
- if (left < 0) {
- this.scrollLeft.domObj.setStyle('visibility','');
- } else {
- this.scrollLeft.domObj.setStyle('visibility','hidden');
- }
- if (left <= this.scrollWidth) {
- this.scrollRight.domObj.setStyle('visibility', 'hidden');
- } else {
- this.scrollRight.domObj.setStyle('visibility', '');
- }
- if (left != l) {
- if ($defined(this.scrollFx)) {
- this.scrollFx.start('left', left);
- } else {
- this.scroller.setStyle('left',left);
+ getNextButton: function(currentButton) {
+ np = currentButton.getNext();
+ if (!np) {
+ np = currentButton.getParent().getNext();
+ if (np) {
+ np = np.getFirst();
}
}
+ return np;
}
-});
-// $Id: toolbar.item.js 626 2009-11-20 13:22:22Z pagameba $
+
+});// $Id: toolbar.item.js 626 2009-11-20 13:22:22Z pagameba $
/**
* Class: Jx.Toolbar.Item
*
@@ -22203,7 +24444,7 @@
this.domObj.adopt(el);
}
}
-});// $Id: panel.js 633 2009-11-20 17:54:21Z zak4ms $
+});// $Id: panel.js 770 2010-03-18 21:12:28Z jonlb at comcast.net $
/**
* Class: Jx.Panel
*
@@ -22223,6 +24464,17 @@
* close - fired when the panel is closed
* collapse - fired when the panel is collapsed
* expand - fired when the panel is opened
+ *
+ * MooTools.lang Keys:
+ * - panel.collapseTooltip
+ * - panel.collapseLabel
+ * - panel.expandlabel
+ * - panel.maximizeTooltip
+ * - panel.maximizeLabel
+ * - panel.restoreTooltip
+ * - panel.restoreLabel
+ * - panel.closeTooltip
+ * - panel.closeLabel
*
* License:
* Copyright (c) 2008, DM Solutions Group Inc.
@@ -22267,26 +24519,6 @@
* to control the state of the panel.
*/
collapse: true,
- /* Option: collapseTooltip
- * the tooltip to display over the collapse button
- */
- collapseTooltip: 'Collapse/Expand Panel',
- /* Option: collapseLabel
- * the label to use for the collapse menu item
- */
- collapseLabel: 'Collapse',
- /* Option: expandLabel
- * the label to use for the expand menu item
- */
- expandLabel: 'Expand',
- /* Option: maximizeTooltip
- * the tooltip to display over the maximize button
- */
- maximizeTooltip: 'Maximize Panel',
- /* Option: maximizeLabel
- * the label to use for the maximize menu item
- */
- maximizeLabel: 'Maximize',
/* Option: close
* boolean, determine if the panel can be closed (hidden) by the user.
* The application needs to provide a way to re-open the panel after
@@ -22295,14 +24527,6 @@
* the panel.
*/
close: false,
- /* Option: closeTooltip
- * the tooltip to display over the close button
- */
- closeTooltip: 'Close Panel',
- /* Option: closeLabel
- * the label to use for the close menu item
- */
- closeLabel: 'Close',
/* Option: closed
* boolean, initial state of the panel (true to start the panel
* closed), default is false
@@ -22317,7 +24541,9 @@
* of each toolbar is used to position the toolbar within the panel.
*/
toolbars: [],
- template: '<div class="jxPanel"><div class="jxPanelTitle"><img class="jxPanelIcon" src="'+Jx.aPixel.src+'" alt="" title=""/><span class="jxPanelLabel"></span><div class="jxPanelControls"></div></div><div class="jxPanelContentContainer"><div class="jxPanelContent"></div></div></div>'
+ type: 'panel',
+ template: '<div class="jxPanel"><div class="jxPanelTitle"><img class="jxPanelIcon" src="'+Jx.aPixel.src+'" alt="" title=""/><span class="jxPanelLabel"></span><div class="jxPanelControls"></div></div><div class="jxPanelContentContainer"><div class="jxPanelContent"></div></div></div>',
+ controlButtonTemplate: '<a class="jxButtonContainer jxButton"><img class="jxButtonIcon" src="'+Jx.aPixel.src+'"></a>'
},
classes: new Hash({
domObj: 'jxPanel',
@@ -22352,76 +24578,106 @@
this.toolbar = new Jx.Toolbar({parent:tbDiv, scroll: false});
var that = this;
-
if (this.options.menu) {
this.menu = new Jx.Menu({
image: Jx.aPixel.src
+ }, {
+ buttonTemplate: this.options.controlButtonTemplate
});
this.menu.domObj.addClass(this.options.menuClass);
this.menu.domObj.addClass('jxButtonContentLeft');
this.toolbar.add(this.menu);
}
- var b, item;
+ //var b, item;
if (this.options.collapse) {
- b = new Jx.Button({
+ this.colB = new Jx.Button({
+ template: this.options.controlButtonTemplate,
image: Jx.aPixel.src,
- tooltip: this.options.collapseTooltip,
+ tooltip: MooTools.lang.get('Jx','panel').collapseTooltip,
onClick: function() {
that.toggleCollapse();
}
});
- b.domObj.addClass(this.options.collapseClass);
- this.toolbar.add(b);
+ this.colB.domObj.addClass(this.options.collapseClass);
+ this.addEvents({
+ collapse: function() {
+ this.colB.setTooltip(MooTools.lang.get('Jx','panel').expandTooltip);
+ }.bind(this),
+ expand: function() {
+ this.colB.setTooltip(MooTools.lang.get('Jx','panel').collapseTooltip);
+ }.bind(this)
+ });
+ this.toolbar.add(this.colB);
if (this.menu) {
- item = new Jx.Menu.Item({
+ this.colM = new Jx.Menu.Item({
label: this.options.collapseLabel,
onClick: function() { that.toggleCollapse(); }
});
+ var item = this.colM
this.addEvents({
collapse: function() {
- item.setLabel(this.options.expandLabel);
- },
+ this.colM.setLabel(MooTools.lang.get('Jx','panel').expandLabel);
+ }.bind(this),
expand: function() {
- item.setLabel(this.options.collapseLabel);
- }
+ this.colM.setLabel(MooTools.lang.get('Jx','panel').collapseLabel);
+ }.bind(this)
});
this.menu.add(item);
}
}
if (this.options.maximize) {
- b = new Jx.Button({
+ this.maxB = new Jx.Button({
+ template: this.options.controlButtonTemplate,
image: Jx.aPixel.src,
- tooltip: this.options.maximizeTooltip,
+ tooltip: MooTools.lang.get('Jx','panel').maximizeTooltip,
onClick: function() {
that.maximize();
}
});
- b.domObj.addClass(this.options.maximizeClass);
- this.toolbar.add(b);
+ this.maxB.domObj.addClass(this.options.maximizeClass);
+ this.addEvents({
+ maximize: function() {
+ this.maxB.setTooltip(MooTools.lang.get('Jx','panel').restoreTooltip);
+ }.bind(this),
+ restore: function() {
+ this.maxB.setTooltip(MooTools.lang.get('Jx','panel').maximizeTooltip);
+ }.bind(this)
+ });
+ this.toolbar.add(this.maxB);
if (this.menu) {
- item = new Jx.Menu.Item({
+ this.maxM = new Jx.Menu.Item({
label: this.options.maximizeLabel,
onClick: function() { that.maximize(); }
});
- this.menu.add(item);
+
+ this.addEvents({
+ maximize: function() {
+ this.maxM.setLabel(MooTools.lang.get('Jx','panel').restoreLabel);
+ }.bind(this),
+ restore: function() {
+ this.maxM.setLabel(MooTools.lang.get('Jx','panel').maximizeLabel);
+ }.bind(this)
+ });
+ this.menu.add(this.maxM);
}
}
if (this.options.close) {
- b = new Jx.Button({
+ this.closeB = new Jx.Button({
+ template: this.options.controlButtonTemplate,
image: Jx.aPixel.src,
- tooltip: this.options.closeTooltip,
+ tooltip: MooTools.lang.get('Jx','panel').closeTooltip,
onClick: function() {
that.close();
}
});
- b.domObj.addClass(this.options.closeClass);
- this.toolbar.add(b);
+ this.closeB.domObj.addClass(this.options.closeClass);
+ this.toolbar.add(this.closeB);
if (this.menu) {
- item = new Jx.Menu.Item({
- label: this.options.closeLabel,
+ this.closeM = new Jx.Menu.Item({
+ label: MooTools.lang.get('Jx','panel').closeLabel,
onClick: function() {
that.close();
}
@@ -22515,6 +24771,7 @@
}, this);
if (Jx.type(this.options.toolbars) == 'array') {
this.options.toolbars.each(function(tb){
+ tb.update();
position = tb.options.position;
tbc = this.toolbarContainers[position];
// IE 6 doesn't seem to want to measure the width of
@@ -22660,20 +24917,6 @@
window.setTimeout(this.onContentReady.bind(this),1);
}
},
- /**
- * Method: setBusy
- * Set the panel as busy or not busy, which displays a loading image
- * in the title bar.
- *
- * Parameters:
- * isBusy - {Boolean} the busy state
- */
- setBusy : function(isBusy) {
- this.busyCount += isBusy?1:-1;
- if (this.loadingObj){
- this.loadingObj.img.style.visibility = (this.busyCount>0)?'visible':'hidden';
- }
- },
/**
* Method: toggleCollapse
@@ -22722,9 +24965,32 @@
close: function() {
this.domObj.dispose();
this.fireEvent('close', this);
+ },
+
+ changeText: function (lang) {
+ this.parent(); //TODO: change this class so that we can access these properties without too much voodoo...
+ if($defined(this.closeB)) {
+ this.closeB.setTooltip(MooTools.lang.get('Jx','panel').closeTooltip);
+ }
+ if ($defined(this.closeM)) {
+ this.closeM.setLabel(MooTools.lang.get('Jx','panel').closeLabel);
+ }
+ if ($defined(this.maxB)) {
+ this.maxB.setTooltip(MooTools.lang.get('Jx','panel').maximizeTooltip);
+ }
+ if ($defined(this.colB)) {
+ this.colB.setTooltip(MooTools.lang.get('Jx','panel').collapseTooltip);
+ }
+ if ($defined(this.colM)) {
+ if (this.options.closed == true) {
+ this.colM.setLabel(MooTools.lang.get('Jx','panel').expandLabel);
+ } else {
+ this.colM.setLabel(MooTools.lang.get('Jx','panel').collapseLabel);
+ }
+ }
}
-});// $Id: dialog.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: dialog.js 816 2010-03-30 11:57:09Z pagameba $
/**
* Class: Jx.Dialog
*
@@ -22760,6 +25026,9 @@
*
* Extends:
* Jx.Dialog extends <Jx.Panel>, please go there for more details.
+ *
+ * MooTools.lang Keys:
+ * - dialog.resizeToolTip
*
* License:
* Copyright (c) 2008, DM Solutions Group Inc.
@@ -22769,22 +25038,30 @@
Jx.Dialog = new Class({
Family: 'Jx.Dialog',
Extends: Jx.Panel,
- //Implements: [Jx.AutoPosition, Jx.Chrome],
- /**
- * Property: {HTMLElement} blanket
- * modal dialogs prevent interaction with the rest of the application
- * while they are open, this element is displayed just under the
- * dialog to prevent the user from clicking anything.
- */
- blanket: null,
-
options: {
/* Option: modal
* (optional) {Boolean} controls whether the dialog will be modal
* or not. The default is to create modal dialogs.
*/
modal: true,
+ /**
+ * Option: maskOptions
+ */
+ maskOptions: {
+ 'class':'jxModalMask',
+ maskMargins: true,
+ useIframeShim: true,
+ iframeShimOptions: {
+ className: 'jxIframeShim'
+ }
+ },
+ eventMaskOptions: {
+ 'class':'jxEventMask',
+ maskMargins: false,
+ useIframeShim: false,
+ destroyOnHide: true
+ },
/* just overrides default position of panel, don't document this */
position: 'absolute',
/* Option: width
@@ -22810,10 +25087,9 @@
*/
vertical: 'center center',
/* Option: label
- * (optional) {String} the title of the dialog box. "New Dialog"
- * is the default value.
+ * (optional) {String} the title of the dialog box.
*/
- label: 'New Dialog',
+ label: '',
/* Option: id
* (optional) {String} an HTML ID to assign to the dialog, primarily
* used for applying CSS styles to specific dialogs
@@ -22830,10 +25106,7 @@
* resizeable by the user or not. Default is false.
*/
resize: false,
- /* Option: resizeTooltip
- * the tooltip to display for the resize handle, empty by default.
- */
- resizeTooltip: '',
+
/* Option: move
* (optional) {Boolean} determines whether the dialog is
* moveable by the user or not. Default is true.
@@ -22849,7 +25122,7 @@
menuClass: 'jxDialogMenu',
maximizeClass: 'jxDialogMaximize',
closeClass: 'jxDialogClose',
-
+ type: 'dialog',
template: '<div class="jxDialog"><div class="jxDialogTitle"><img class="jxDialogIcon" src="'+Jx.aPixel.src+'" alt="" title=""/><span class="jxDialogLabel"></span><div class="jxDialogControls"></div></div><div class="jxDialogContentContainer"><div class="jxDialogContent"></div></div></div>'
},
classes: new Hash({
@@ -22880,26 +25153,6 @@
this.openOnLoaded = this.open.bind(this);
this.options.parent = document.id(this.options.parent);
- if (this.options.modal) {
- this.blanket = new Element('div',{
- 'class':'jxDialogModal',
- styles:{
- display:'none',
- zIndex: -1
- }
- });
- this.blanket.resize = (function() {
- var ss = document.id(document.body).getScrollSize();
- this.setStyles({
- width: ss.x,
- height: ss.y
- });
- }).bind(this.blanket);
- this.options.parent.adopt(this.blanket);
- window.addEvent('resize', this.blanket.resize);
-
- }
-
this.domObj.setStyle('display','none');
this.options.parent.adopt(this.domObj);
@@ -22909,13 +25162,19 @@
new Drag(this.domObj, {
handle: this.title,
onBeforeStart: (function(){
- Jx.Dialog.orderDialogs(this);
+ this.stack();
}).bind(this),
onStart: (function() {
+ if (!this.options.modal && this.options.parent.mask) {
+ this.options.parent.mask(this.options.eventMaskOptions);
+ }
this.contentContainer.setStyle('visibility','hidden');
this.chrome.addClass('jxChromeDrag');
}).bind(this),
onComplete: (function() {
+ if (!this.options.modal && this.options.parent.unmask) {
+ this.options.parent.unmask();
+ }
this.chrome.removeClass('jxChromeDrag');
this.contentContainer.setStyle('visibility','');
var left = Math.max(this.chromeOffsets.left, parseInt(this.domObj.style.left,10));
@@ -22936,7 +25195,7 @@
if (this.options.resize && typeof Drag != 'undefined') {
this.resizeHandle = new Element('div', {
'class':'jxDialogResize',
- title: this.options.resizeTooltip,
+ title: MooTools.lang.get('Jx','panel').resizeTooltip,
styles: {
'display':this.options.closed?'none':'block'
}
@@ -22951,6 +25210,9 @@
this.domObj.makeResizable({
handle:this.resizeHandle,
onStart: (function() {
+ if (!this.options.modal && this.options.parent.mask) {
+ this.options.parent.mask(this.options.eventMaskOptions);
+ }
this.contentContainer.setStyle('visibility','hidden');
this.chrome.addClass('jxChromeDrag');
}).bind(this),
@@ -22958,6 +25220,9 @@
this.resizeChrome(this.domObj);
}).bind(this),
onComplete: (function() {
+ if (!this.options.modal && this.options.parent.unmask) {
+ this.options.parent.unmask();
+ }
this.chrome.removeClass('jxChromeDrag');
var size = this.domObj.getMarginBoxSize();
this.options.width = size.width;
@@ -22973,7 +25238,7 @@
}
/* this adjusts the zIndex of the dialogs when activated */
this.domObj.addEvent('mousedown', (function(){
- Jx.Dialog.orderDialogs(this);
+ this.stack();
}).bind(this));
},
@@ -23062,6 +25327,60 @@
}
this.showChrome(this.domObj);
},
+
+ /**
+ * Method: maximize
+ * Called when the maximize button of a dialog is clicked. It will maximize
+ * the dialog to match the size of its parent.
+ */
+ maximize: function () {
+
+ if (!this.maximized) {
+ //get size of parent
+ var p = this.options.parent;
+ var size;
+
+ if (p === document.body) {
+ size = Jx.getPageDimensions();
+ } else {
+ size = p.getBorderBoxSize();
+ }
+ this.previousSettings = {
+ width: this.options.width,
+ height: this.options.height,
+ horizontal: this.options.horizontal,
+ vertical: this.options.vertical,
+ left: this.options.left,
+ right: this.options.right,
+ top: this.options.top,
+ bottom: this.options.bottom
+ };
+ this.options.width = size.width;
+ this.options.height = size.height;
+ this.options.vertical = '0 top';
+ this.options.horizontal = '0 left';
+ this.options.right = 0;
+ this.options.left = 0;
+ this.options.top = 0;
+ this.options.bottom = 0;
+ this.domObj.resize(this.options);
+ this.fireEvent('resize');
+ this.resizeChrome(this.domObj);
+ this.maximized = true;
+ this.domObj.addClass('jxDialogMaximized');
+ this.fireEvent('maximize');
+ } else {
+ this.options = $merge(this.options, this.previousSettings);
+ this.domObj.resize(this.options);
+ this.fireEvent('resize');
+ this.resizeChrome(this.domObj);
+ this.maximized = false;
+ if (this.domObj.hasClass('jxDialogMaximized')) {
+ this.domObj.removeClass('jxDialogMaximized');
+ }
+ this.fireEvent('restore');
+ }
+ },
/**
* Method: show
@@ -23074,20 +25393,20 @@
'display': 'block',
'visibility': 'hidden'
});
-
- if (this.blanket) {
- this.blanket.resize();
- }
-
- Jx.Dialog.orderDialogs(this);
-
+ this.toolbar.update();
+
/* do the modal thing */
- if (this.blanket) {
- this.blanket.setStyles({
- visibility: 'visible',
- display: 'block'
- });
+ if (this.options.modal && this.options.parent.mask) {
+ var opts = $merge(this.options.maskOptions || {}, {
+ style: {
+ 'z-index': Jx.getNumber(this.domObj.getStyle('z-index')) - 1
+ }
+ });
+ this.options.parent.mask(opts);
+ Jx.Stack.stack(this.options.parent.get('mask').element);
}
+ /* stack the dialog */
+ this.stack();
if (this.options.closed) {
var m = this.domObj.measure(function(){
@@ -23098,6 +25417,7 @@
} else {
this.domObj.resize(this.options);
}
+
if (this.firstShow) {
this.contentContainer.resize({forceResize: true});
this.layoutContent();
@@ -23115,7 +25435,7 @@
this.showChrome(this.domObj);
/* put it in the right place using auto-positioning */
this.position(this.domObj, this.options.parent, this.options);
- this.domObj.setStyle('visibility', '');
+ this.domObj.setStyle('visibility', 'visible');
},
/**
* Method: hide
@@ -23123,12 +25443,11 @@
* method to hide the dialog.
*/
hide : function() {
- Jx.Dialog.Stack.erase(this);
- Jx.Dialog.ZIndex--;
this.domObj.setStyle('display','none');
- if (this.blanket) {
- this.blanket.setStyle('visibility', 'hidden');
- Jx.Dialog.ZIndex--;
+ this.unstack();
+ if (this.options.modal && this.options.parent.unmask) {
+ Jx.Stack.unstack(this.options.parent.get('mask').element);
+ this.options.parent.unmask();
}
},
@@ -23146,8 +25465,7 @@
this.options.content = null; //force Url loading
this.loadContent(this.content);
this.addEvent('contentLoaded', this.openOnLoaded);
- }
- else {
+ } else {
this.open();
}
},
@@ -23183,28 +25501,33 @@
this.fireEvent('close');
},
- cleanup: function() {
- this.blanket.destroy();
+ cleanup: function() { },
+
+ /**
+ * APIMethod: isOpen
+ * returns true if the dialog is currently open, false otherwise
+ */
+ isOpen: function () {
+ //check to see if we're visible
+ return !((this.domObj.getStyle('display') === 'none') || (this.domObj.getStyle('visibility') === 'hidden'));
+ },
+
+ createText: function (lang) {
+ this.parent();
+ if ($defined(this.maxM)) {
+ if (this.maximize) {
+ this.maxM.setLabel(MooTools.lang.get('Jx','panel').restoreLabel);
+ } else {
+ this.maxM.setLabel(MooTools.lang.get('Jx','panel').maximizeLabel);
+ }
+ }
+ if ($defined(this.resizeHandle)) {
+ this.resizeHandle.set('title', MooTools.lang.get('Jx','dialog').resizeTooltip);
+ }
}
});
-Jx.Dialog.Stack = [];
-Jx.Dialog.BaseZIndex = null;
-Jx.Dialog.orderDialogs = function(d) {
- Jx.Dialog.Stack.erase(d).push(d);
- if (Jx.Dialog.BaseZIndex === null) {
- Jx.Dialog.BaseZIndex = Math.max(Jx.Dialog.Stack[0].domObj.getStyle('zIndex').toInt(), 1);
- }
- Jx.Dialog.Stack.each(function(d, i) {
- var z = Jx.Dialog.BaseZIndex+i;
- if (d.blanket) {
- d.blanket.setStyle('zIndex',z);
- }
- d.domObj.setStyle('zIndex',z);
- });
-
-};
-// $Id: splitter.js 626 2009-11-20 13:22:22Z pagameba $
+// $Id: splitter.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Splitter
*
@@ -23221,6 +25544,9 @@
* Example:
* (code)
* (end)
+ *
+ * MooTools.lang Keys:
+ * - splitter.barToolTip
*
* License:
* Copyright (c) 2008, DM Solutions Group Inc.
@@ -23300,11 +25626,6 @@
* elements open or closed.
*/
snaps: [],
- /* Option: barTooltip
- * the tooltip to display when the mouse hovers over a split bar,
- * used for i18n.
- */
- barTooltip: 'drag this bar to resize',
/* Option: onStart
* an optional function to call when a bar starts dragging
*/
@@ -23453,7 +25774,7 @@
prepareBar: function() {
var o = new Element('div', {
'class': 'jxSplitBar'+this.options.layout.capitalize(),
- 'title': this.options.barTitle
+ 'title': MooTools.lang.get('Jx','panel').barTooltip
});
return o;
},
@@ -23946,20 +26267,29 @@
currentPosition += rightBar.retrieve('size').height;
}
}
+ },
+
+ createText: function (lang) {
+ this.parent();
+ this.bars.each(function(bar){
+ document.id(bar).set('title', MooTools.lang.get('Jx','splitter').title);
+ },this);
+
}
-});// $Id: panelset.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: panelset.js 770 2010-03-18 21:12:28Z jonlb at comcast.net $
/**
* Class: Jx.PanelSet
*
* Extends: <Jx.Widget>
*
- * A panel set manages a set of panels within a DOM element. The PanelSet fills
- * its container by resizing the panels in the set to fill the width and then
- * distributing the height of the container across all the panels. Panels
- * can be resized by dragging their respective title bars to make them taller
- * or shorter. The maximize button on the panel title will cause all other
- * panels to be closed and the target panel to be expanded to fill the remaining
- * space. In this respect, PanelSet works like a traditional Accordion control.
+ * A panel set manages a set of panels within a DOM element. The PanelSet
+ * fills its container by resizing the panels in the set to fill the width and
+ * then distributing the height of the container across all the panels.
+ * Panels can be resized by dragging their respective title bars to make them
+ * taller or shorter. The maximize button on the panel title will cause all
+ * other panels to be closed and the target panel to be expanded to fill the
+ * remaining space. In this respect, PanelSet works like a traditional
+ * Accordion control.
*
* When creating panels for use within a panel set, it is important to use the
* proper options. You must override the collapse option and set it to false
@@ -23968,11 +26298,14 @@
*
* Example:
* (code)
- * var p1 = new Jx.Panel({collapse: false, maximize: true, content: 'content1'});
- * var p2 = new Jx.Panel({collapse: false, maximize: true, content: 'content2'});
- * var p3 = new Jx.Panel({collapse: false, maximize: true, content: 'content3'});
+ * var p1 = new Jx.Panel({collapse: false, maximize: true, content: 'c1'});
+ * var p2 = new Jx.Panel({collapse: false, maximize: true, content: 'c2'});
+ * var p3 = new Jx.Panel({collapse: false, maximize: true, content: 'c3'});
* var panelSet = new Jx.PanelSet('panels', [p1,p2,p3]);
* (end)
+ *
+ * MooTools.lang Keys:
+ * - panelset.barTooltip
*
* License:
* Copyright (c) 2008, DM Solutions Group Inc.
@@ -23991,11 +26324,7 @@
/* Option: panels
* an array of <Jx.Panel> objects that will be managed by the set.
*/
- panels: [],
- /* Option: barTooltip
- * the tooltip to place on the title bars of each panel
- */
- barTooltip: 'drag this bar to resize'
+ panels: []
},
/**
@@ -24045,7 +26374,7 @@
prepareBar: (function(i) {
var bar = new Element('div', {
'class': 'jxPanelBar',
- 'title': this.options.barTooltip
+ 'title': MooTools.lang.get('Jx','panelset').barTooltip
});
var panel = this.panels[i];
@@ -24174,15 +26503,24 @@
}
}
panel.domObj.resize({top: top, height:panelSize, bottom: null});
+ this.fireEvent('panelMaximize',panel);
+ },
+
+ createText: function (lang) {
+ this.parent();
+ //barTooltip is handled by the splitter's createText() function
}
-});// $Id:$
+});// $Id: message.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Dialog.Message
*
* Extends: <Jx.Dialog>
*
- * Jx.Dialog.Confirm is an extension of Jx.Dialog that allows the developer
+ * Jx.Dialog.Message is an extension of Jx.Dialog that allows the developer
* to display a message to the user. It only presents an OK button.
+ *
+ * MooTools.lang Keys:
+ * - message.okButton
*
* License:
* Copyright (c) 2009, Jonathan Bomgardner
@@ -24190,9 +26528,9 @@
* This file is licensed under an MIT style license
*/
Jx.Dialog.Message = new Class({
-
+ Family: 'Jx.Dialog.Message',
Extends: Jx.Dialog,
-
+ Binds: ['onOk'],
options: {
/**
* Option: message
@@ -24200,27 +26538,43 @@
*/
message: '',
/**
- * Jx.Dialog option defaults
+ * Option: width
+ * default width of message dialogs is 300px
*/
width: 300,
+ /**
+ * Option: height
+ * default height of message dialogs is 150px
+ */
height: 150,
+ /**
+ * Option: close
+ * by default, message dialogs are closable
+ */
close: true,
+ /**
+ * Option: resize
+ * by default, message dialogs are resizable
+ */
resize: true,
+ /**
+ * Option: collapse
+ * by default, message dialogs are not collapsible
+ */
collapse: false
},
/**
- * APIMethod: render
+ * Method: render
* constructs the dialog.
*/
render: function () {
//create content to be added
- this.buttons = new Jx.Toolbar({position: 'bottom'});
- this.buttons.add(
- new Jx.Button({
- label: 'Ok',
- onClick: this.onClick.bind(this, 'Ok')
- })
- );
+ this.buttons = new Jx.Toolbar({position: 'bottom',scroll:false});
+ this.ok = new Jx.Button({
+ label: MooTools.lang.get('Jx','message').okButton,
+ onClick: this.onOk
+ });
+ this.buttons.add(this.ok);
this.options.toolbars = [this.buttons];
if (Jx.type(this.options.message) === 'string') {
this.question = new Element('div', {
@@ -24229,22 +26583,46 @@
});
} else {
this.question = this.options.question;
- $(this.question).addClass('jxMessage');
+ document.id(this.question).addClass('jxMessage');
}
this.options.content = this.question;
this.parent();
},
/**
- * Method: onClick
+ * Method: onOk
* Called when the OK button is clicked. Closes the dialog.
*/
- onClick: function (value) {
+ onOk: function () {
this.close();
+ },
+
+ /**
+ * APIMethod: setMessage
+ * set the message of the dialog, useful for responding to language
+ * changes on the fly.
+ *
+ * Parameters
+ * message - {String} the new message
+ */
+ setMessage: function(message) {
+ this.options.message = message;
+ if ($defined(this.question)) {
+ this.question.set('html',message);
+ }
+ },
+
+ /**
+ * Method: createText
+ * handle change in language
+ */
+ createText: function (lang) {
+ this.parent();
+ if ($defined(this.ok)) {
+ this.ok.setLabel(MooTools.lang.get('Jx','message').okButton);
+ }
}
-
-
});
-// $Id:$
+// $Id: confirm.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Dialog.Confirm
*
@@ -24252,7 +26630,11 @@
*
* Jx.Dialog.Confirm is an extension of Jx.Dialog that allows the developer
* to prompt their user with e yes/no question.
- *
+ *
+ * MooTools.lang Keys:
+ * - confirm.affirmitiveLabel
+ * - confirm.negativeLabel
+ *
* License:
* Copyright (c) 2009, Jonathan Bomgardner
*
@@ -24269,17 +26651,6 @@
*/
question: '',
/**
- * Option: affirmitiveLabel
- * The text to use for the affirmitive button. Defaults to 'Yes'.
- */
- affirmitiveLabel: 'Yes',
- /**
- * Option: negativeLabel
- * The text to use for the negative button. Defaults to 'No'.
- */
- negativeLabel: 'No',
-
- /**
* Jx.Dialog option defaults
*/
width: 300,
@@ -24294,17 +26665,18 @@
*/
render: function () {
//create content to be added
- this.buttons = new Jx.Toolbar({position: 'bottom'});
- this.buttons.add(
- new Jx.Button({
- label: this.options.affirmitiveLabel,
- onClick: this.onClick.bind(this, this.options.affirmitiveLabel)
- }),
- new Jx.Button({
- label: this.options.negativeLabel,
- onClick: this.onClick.bind(this, this.options.negativeLabel)
- })
- );
+ //turn scrolling off as confirm only has 2 buttons.
+ this.buttons = new Jx.Toolbar({position: 'bottom',scroll: false});
+
+ this.ok = new Jx.Button({
+ label: MooTools.lang.get('Jx','confirm').affirmitiveLabel,
+ onClick: this.onClick.bind(this, MooTools.lang.get('Jx','confirm').affirmitiveLabel)
+ }),
+ this.cancel = new Jx.Button({
+ label: MooTools.lang.get('Jx','confirm').negativeLabel,
+ onClick: this.onClick.bind(this, MooTools.lang.get('Jx','confirm').negativeLabel)
+ })
+ this.buttons.add(this.ok, this.cancel);
this.options.toolbars = [this.buttons];
if (Jx.type(this.options.question) === 'string') {
this.question = new Element('div', {
@@ -24313,7 +26685,7 @@
});
} else {
this.question = this.options.question;
- $(this.question).addClass('jxConfirmQuestion');
+ document.id(this.question).addClass('jxConfirmQuestion');
}
this.options.content = this.question;
this.parent();
@@ -24327,451 +26699,30 @@
this.isOpening = false;
this.hide();
this.fireEvent('close', [this, value]);
- }
-
-
-});// $Id: $
-/**
- * Class: Jx.Panel.DataView
- *
- * Extends: <Jx.Panel>
- *
- * This panel extension takes a standard Jx.Store (or subclass) and displays
- * each record as an item using a provided template. It sorts the store as requested
- * before doing so. The class only creates the HTML and has no default CSS display. All
- * styling must be done by the developer using the control.
- *
- *
- * Events:
- * renderDone - fires when the panel completes creating all of the items.
- *
- * License:
- * Copyright (c) 2009, Jonathan Bomgardner.
- *
- * This file is licensed under an MIT style license
- */
-Jx.Panel.DataView = new Class({
-
- Extends: Jx.Panel,
-
- options: {
- /**
- * Option: data
- * The store containing the data
- */
- data: null,
- /**
- * Option: sortColumns
- * An array of columns to sort the store by.
- */
- sortColumns: null,
- /**
- * Option: itemTemplate
- * The template to use in rendering records
- */
- itemTemplate: null,
- /**
- * Option: emptyTemplate
- * the template that is displayed when there are no records in the
- * store.
- */
- emptyTemplate: null,
- /**
- * Option: containerClass
- * The class added to the container. It can be used to target the items
- * in the panel.
- */
- containerClass: null,
- /**
- * Option: itemClass
- * The class to add to each item. Used for styling purposes
- */
- itemClass: null,
- /**
- * Option: itemOptions
- * Options to pass to the list object
- */
- listOptions: {
- select: true,
- hover: true
- }
},
-
- /**
- * Property: bound
- * hold bound functions
- */
- bound: {},
-
- init: function () {
- this.domA = new Element('div');
- this.list = this.createList(this.domA, this.options.listOptions);
- this.parent();
- },
- /**
- * APIMethod: render
- * Renders the dataview. If the store already has data loaded it will be rendered
- * at the end of the method.
- */
- render: function () {
- if (!$defined(this.options.data)) {
- //we can't do anything without data
- return;
- }
-
- this.options.content = this.domA;
-
- //pass to parent
- this.parent();
-
- this.domA.addClass(this.options.containerClass);
-
- //parse templates so we know what values are needed in each
- this.itemCols = this.parseTemplate(this.options.itemTemplate);
-
- this.bound.update = this.update.bind(this);
- //listen for data updates
- this.options.data.addEvent('loadFinished', this.bound.update);
- this.options.data.addEvent('sortFinished', this.bound.update);
- this.options.data.addEvent('loadError', this.bound.update);
-
- if (this.options.data.loaded) {
- this.update();
- }
-
- },
-
- /**
- * Method: draw
- * begins the process of creating the items
- */
- draw: function () {
- var n = this.options.data.count();
- if ($defined(n) && n > 0) {
- for (var i = 0; i < n; i++) {
- this.options.data.moveTo(i);
-
- var item = this.createItem();
- this.list.add(item);
- }
- } else {
- var empty = new Element('div', {html: this.options.emptyTemplate});
- this.list.add(item);
- }
- this.fireEvent('renderDone', this);
- },
- /**
- * Method: createItem
- * Actually does the work of getting the data from the store
- * and creating a single item based on the provided template
- */
- createItem: function () {
- //create the item
- var itemObj = {};
- this.itemCols.each(function (col) {
- itemObj[col] = this.options.data.get(col);
- }, this);
- var itemTemp = this.options.itemTemplate.substitute(itemObj);
- var item = new Element('div', {
- 'class': this.options.itemClass,
- html: itemTemp
- });
- return item;
- },
- /**
- * APIMethod: update
- * This method begins the process of creating the items. It is called when
- * the store is loaded or can be called to manually recreate the view.
- */
- update: function () {
- if (!this.updating) {
- this.updating = true;
- this.list.empty();
- this.options.data.sort(this.options.sortColumns);
- this.draw();
- this.updating = false;
- }
- },
- /**
- * Method: parseTemplate
- * parses the provided template to determine which store columns are
- * required to complete it.
- *
- * Parameters:
- * template - the template to parse
- */
- parseTemplate: function (template) {
- //we parse the template based on the columns in the data store looking
- //for the pattern {column-name}. If it's in there we add it to the
- //array of ones to look for
- var columns = this.options.data.getColumns();
- var arr = [];
- columns.each(function (col) {
- var s = '{' + col.name + '}';
- if (template.contains(s)) {
- arr.push(col.name);
- }
- }, this);
- return arr;
- },
- /**
- * Method: enterItem
- * Fires mouseenter event
- *
- * Parameters:
- * item - the item that is the target of the event
- * list - the list this item is in.
- */
- enterItem: function(item, list){
- this.fireEvent('mouseenter', item, list);
- },
- /**
- * Method: leaveItem
- * Fires mouseleave event
- *
- * Parameters:
- * item - the item that is the target of the event
- * list - the list this item is in.
- */
- leaveItem: function(item, list){
- this.fireEvent('mouseleave', item, list);
- },
- /**
- * Method: selectItem
- * Fires select event
- *
- * Parameters:
- * item - the item that is the target of the event
- * list - the list this item is in.
- */
- selectItem: function(item, list){
- this.fireEvent('select', item, list);
- },
- /**
- * Method: unselectItem
- * Fires unselect event
- *
- * Parameters:
- * item - the item that is the target of the event
- * list - the list this item is in.
- */
- unselectItem: function(item, list){
- this.fireEvent('unselect', item, list);
- },
- /**
- * Method: addItem
- * Fires add event
- *
- * Parameters:
- * item - the item that is the target of the event
- * list - the list this item is in.
- */
- addItem: function(item, list) {
- this.fireEvent('add', item, list);
- },
- /**
- * Method: removeItem
- * Fires remove event
- *
- * Parameters:
- * item - the item that is the target of the event
- * list - the list this item is in.
- */
- removeItem: function(item, list) {
- this.fireEvent('remove', item, list);
- },
- /**
- * Method: createList
- * Creates the list object
- *
- * Parameters:
- * container - the container to use in the list
- * options - the options for the list
- */
- createList: function(container, options){
- return new Jx.List(container, $extend({
- onMouseenter: this.enterItem.bind(this),
- onMouseleave: this.leaveItem.bind(this),
- onSelect: this.selectItem.bind(this),
- onAdd: this.addItem.bind(this),
- onRemove: this.removeItem.bind(this),
- onUnselect: this.unselectItem.bind(this)
- }, options));
+
+ createText: function (lang) {
+ this.parent();
+ if ($defined(this.ok)) {
+ this.ok.setLabel(MooTools.lang.get('Jx','confirm').affirmitiveLabel);
+ }
+ if ($defined(this.cancel)) {
+ this.cancel.setLabel(MooTools.lang.get('Jx','confirm').negativeLabel);
+ }
+
}
-});
-// $Id: $
-/**
- * Class: Jx.Panel.DataView.Group
- *
- * Extends: <Jx.Panel.DataView>
- *
- * This extension of Jx.Panel.DataView that provides for grouping the items
- * by a particular column.
- *
- * License:
- * Copyright (c) 2009, Jonathan Bomgardner.
- *
- * This file is licensed under an MIT style license
- */
-Jx.Panel.DataView.Group = new Class({
- Extends: Jx.Panel.DataView,
- options: {
- /**
- * Option: groupTemplate
- * The template used to render the group heading
- */
- groupTemplate: null,
- /**
- * Option: groupContainerClass
- * The class added to the group container. All of the items and header
- * for a single grouping is contained by a div that has this class added.
- */
- groupContainerClass: null,
- /**
- * Option: groupHeaderClass
- * The class added to the heading. Used for styling.
- */
- groupHeaderClass: null,
- /**
- * Option: listOption
- * Options to pass to the main list
- */
- listOptions: {
- select: false,
- hover: false
- },
- /**
- * Option: itemOption
- * Options to pass to the item lists
- */
- itemOptions: {
- select: true,
- hover: true,
- hoverClass: 'jxItemHover',
- selectClass: 'jxItemSelect'
- }
- },
-
- init: function() {
- this.groupCols = this.parseTemplate(this.options.groupTemplate);
- this.itemManager = new Jx.Selection({
- eventToFire: {
- select: 'itemselect',
- unselect: 'itemunselect'
- },
- selectClass: 'jxItemSelected'
- });
- this.groupManager = new Jx.Selection({
- eventToFire: {
- select: 'groupselect',
- unselect: 'groupunselect'
- },
- selectClass: 'jxGroupSelected'
- });
- this.parent();
-
- },
- /**
- * APIMethod: render
- * sets up the list container and calls the parent class' render function.
- */
- render: function () {
- this.list = this.createList(this.domA, this.listOptions, this.groupManager);
- this.parent();
-
- },
- /**
- * Method: draw
- * actually does the work of creating the view
- */
- draw: function () {
- var d = this.options.data;
- var n = d.count();
-
- if ($defined(n) && n > 0) {
- var currentGroup = '';
- var itemList = null;
-
- for (var i = 0; i < n; i++) {
- d.moveTo(i);
- var group = d.get(this.options.sortColumns[0]);
-
- if (group !== currentGroup) {
- //we have a new grouping
-
- //group container
- var container = new Element('div', {
- 'class': this.options.groupContainerClass
- });
- var l = this.createList(container,{
- select: false,
- hover: false
- });
- this.list.add(l.container);
-
- //group header
- currentGroup = group;
- var obj = {};
- this.groupCols.each(function (col) {
- obj[col] = d.get(col);
- }, this);
- var temp = this.options.groupTemplate.substitute(obj);
- var g = new Element('div', {
- 'class': this.options.groupHeaderClass,
- 'html': temp,
- id: 'group-' + group.replace(" ","-","g")
- });
- l.add(g);
-
- //items container
- var currentItemContainer = new Element('div', {
- 'class': this.options.containerClass
- });
- itemList = this.createList(currentItemContainer, this.options.itemOptions, this.itemManager);
- l.add(itemList.container);
- }
-
- var item = this.createItem();
- itemList.add(item);
- }
- } else {
- var empty = new Element('div', {html: this.options.emptyTemplate});
- this.list.add(empty);
- }
- this.fireEvent('renderDone', this);
- },
-
- /**
- * Method: createList
- * Creates the list object
- *
- * Parameters:
- * container - the container to use in the list
- * options - the options for the list
- * manager - <Jx.Selection> which selection obj to connect to this list
- */
- createList: function(container, options, manager){
- return new Jx.List(container, $extend({
- onMouseenter: this.enterItem.bind(this),
- onMouseleave: this.leaveItem.bind(this),
- onAdd: this.addItem.bind(this),
- onRemove: this.removeItem.bind(this)
- }, options), manager);
- }
-
-});
-// $Id: $
+});// $Id: tooltip.js 776 2010-03-22 14:35:16Z pagameba $
/**
* Class: Jx.Tooltip
*
* Extends: <Jx.Widget>
*
* An implementation of tooltips. These are very simple tooltips that are
- * designed to be instantiated in javascript and directly attached to the object
- * that they are the tip for. We can only have one Tip per element so we use
- * element storage to store the tip object and check for it's presence
+ * designed to be instantiated in javascript and directly attached to the
+ * object that they are the tip for. We can only have one Tip per element so
+ * we use element storage to store the tip object and check for it's presence
* before creating a new tip. If one is there we remove it and create this new
* one.
*
@@ -24787,12 +26738,12 @@
Jx.Tooltip = new Class({
Family: 'Jx.Widget',
Extends : Jx.Widget,
-
+ Binds: ['enter', 'leave', 'move'],
options : {
/**
* Option: offsets
- * An object with x and y components for where to put the tip related to
- * the mouse cursor.
+ * An object with x and y components for where to put the tip related
+ * to the mouse cursor.
*/
offsets : {
x : 15,
@@ -24806,8 +26757,8 @@
showDelay : 100,
/**
* Option: cssClass
- * a class to be added to the tip's container. This can be used to style
- * the tip.
+ * a class to be added to the tip's container. This can be used to
+ * style the tip.
*/
cssClass : null
},
@@ -24822,10 +26773,9 @@
parameters: ['target','tip','options'],
/**
- * APIMethod: render
+ * Method: render
* Creates the tooltip
*
-
*/
render : function () {
this.parent();
@@ -24860,10 +26810,9 @@
this.options.target.store('Tip', this);
//add events
- this.options.target.addEvent('mouseenter', this.enter.bindWithEvent(this));
- this.options.target.addEvent('mouseleave', this.leave.bindWithEvent(this));
- this.options.target.addEvent('mousemove', this.move.bindWithEvent(this));
-
+ this.options.target.addEvent('mouseenter', this.enter);
+ this.options.target.addEvent('mouseleave', this.leave);
+ this.options.target.addEvent('mousemove', this.move);
},
/**
@@ -24872,9 +26821,8 @@
*
* Parameters:
* event - the event object
- * element - the element the cursor passed over
*/
- enter : function (event, element) {
+ enter : function (event) {
this.timer = $clear(this.timer);
this.timer = (function () {
this.domObj.setStyle('visibility', 'visible');
@@ -24887,9 +26835,8 @@
*
* Parameters:
* event - the event object
- * element - the element the cursor passed over
*/
- leave : function (event, element) {
+ leave : function (event) {
this.timer = $clear(this.timer);
this.timer = (function () {
this.domObj.setStyle('visibility', 'hidden');
@@ -24936,7 +26883,7 @@
this.domObj.setStyle('left', tipPlacement.x);
},
/**
- * Method: detach
+ * APIMethod: detach
* Called to manually remove a tooltip.
*/
detach : function () {
@@ -24944,7 +26891,7 @@
this.destroy();
}
});
-// $Id: $
+// $Id: field.js 823 2010-03-31 12:18:00Z pagameba $
/**
* Class: Jx.Field
*
@@ -24958,6 +26905,9 @@
* Example:
* (code)
* (end)
+ *
+ * MooTools.lang Keys:
+ * - field.requiredText
*
* License:
* Copyright (c) 2009, Jon Bomgardner.
@@ -24968,7 +26918,7 @@
Family: 'Jx.Field',
Extends : Jx.Widget,
pluginNamespace: 'Field',
-
+
options : {
/**
* Option: id
@@ -25042,12 +26992,6 @@
*/
required : false,
/**
- * Option: requiredText
- * Text to be displayed if a field is required. It is added as an
- * <em> element inside the <label>.
- */
- requiredText : '*',
- /**
* Option: readonly
* {True|False} defaults to false. Whether this field is readonly.
*/
@@ -25159,11 +27103,11 @@
this.label.set('for', this.id);
if (this.options.required) {
- var em = new Element('em', {
- 'html' : this.options.requiredText,
+ this.requiredText = new Element('em', {
+ 'html' : MooTools.lang.get('Jx','field').requiredText,
'class' : 'required'
});
- em.inject(this.label);
+ this.requiredText.inject(this.label);
}
}
@@ -25190,12 +27134,14 @@
this.field.set("disabled", "disabled");
this.field.addClass('jxFieldDisabled');
}
+
+ //add events
+ this.field.addEvents({
+ 'focus': this.onFocus.bind(this),
+ 'blur': this.onBlur.bind(this),
+ 'change': this.onChange.bind(this)
+ });
- // add validator classes
- if ($defined(this.options.validatorClasses)) {
- this.field.addClass(this.options.validatorClasses);
- }
-
this.field.store('field', this);
}
@@ -25217,13 +27163,16 @@
},
/**
- * APIMethod: setValue Sets the value property of the field
+ * APIMethod: setValue
+ * Sets the value property of the field
*
* Parameters:
* v - The value to set the field to.
*/
setValue : function (v) {
- this.field.set('value', v);
+ if (!this.options.readonly) {
+ this.field.set('value', v);
+ }
},
/**
@@ -25271,10 +27220,45 @@
this.parent(what);
}
return this;
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ this.parent();
+ if ($defined(this.requiredText)) {
+ this.requiredText.set('html',MooTools.lang.get('Jx','field').requiredText);
+ }
+ },
+
+ onFocus: function() {
+ this.fireEvent('focus', this);
+ },
+
+ onBlur: function () {
+ this.fireEvent('blur',this);
+ },
+
+ onChange: function () {
+ this.fireEvent('change', this);
+ },
+
+ setBusy: function(state, withoutMask) {
+ if (!withoutMask) {
+ this.parent(state);
+ }
+ this.field.set('readonly', state || this.options.readonly);
}
});
-// $Id: $
+// $Id: text.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Field.Text
*
@@ -25331,8 +27315,530 @@
}
-});// $Id: $
+});// $Id: prompt.js 785 2010-03-25 19:19:21Z jonlb at comcast.net $
/**
+ * Class: Jx.Dialog.Prompt
+ *
+ * Extends: <Jx.Dialog>
+ *
+ * Jx.Dialog.Prompt is an extension of Jx.Dialog that allows the developer
+ * to display a message to the user and ask for a text response.
+ *
+ * MooTools.lang Keys:
+ * - prompt.okButton
+ * - prompt.cancelButton
+ *
+ * License:
+ * Copyright (c) 2009, Jonathan Bomgardner
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Dialog.Prompt = new Class({
+
+ Extends: Jx.Dialog,
+
+ options: {
+ /**
+ * Option: prompt
+ * The message to display to the user
+ */
+ prompt: '',
+ /**
+ * Option: startingValue
+ * The startingvalue to place in the text box
+ */
+ startingValue: '',
+ /**
+ * Jx.Dialog option defaults
+ */
+ width: 400,
+ height: 200,
+ close: true,
+ resize: true,
+ collapse: false
+ },
+ /**
+ * APIMethod: render
+ * constructs the dialog.
+ */
+ render: function () {
+ //create content to be added
+ this.buttons = new Jx.Toolbar({position: 'bottom',scroll:false});
+ this.ok = new Jx.Button({
+ label: MooTools.lang.get('Jx','prompt').okButton,
+ onClick: this.onClick.bind(this, 'Ok')
+ });
+ this.cancel = new Jx.Button({
+ label: MooTools.lang.get('Jx','prompt').cancelButton,
+ onClick: this.onClick.bind(this,'Cancel')
+ });
+ this.buttons.add(this.ok, this.cancel);
+ this.options.toolbars = [this.buttons];
+
+ this.field = new Jx.Field.Text({
+ label: this.options.prompt,
+ value: this.options.startingValue,
+ containerClass: 'jxPrompt'
+ });
+ this.options.content = document.id(this.field);
+ this.parent();
+ },
+ /**
+ * Method: onClick
+ * Called when the OK button is clicked. Closes the dialog.
+ */
+ onClick: function (value) {
+ this.isOpening = false;
+ this.hide();
+ this.fireEvent('close', [this, value, this.field.getValue()]);
+ },
+
+ createText: function (lang) {
+ this.parent();
+ if ($defined(this.ok)) {
+ this.ok.setLabel(MooTools.lang.get('Jx','prompt').okButton);
+ }
+ if ($defined(this.cancel)) {
+ this.cancel.setLabel(MooTools.lang.get('Jx','prompt').cancelButton);
+ }
+ }
+
+
+});
+// $Id: dataview.js 686 2010-02-01 05:45:28Z jonlb at comcast.net $
+/**
+ * Class: Jx.Panel.DataView
+ *
+ * Extends: <Jx.Panel>
+ *
+ * This panel extension takes a standard Jx.Store (or subclass) and displays
+ * each record as an item using a provided template. It sorts the store as requested
+ * before doing so. The class only creates the HTML and has no default CSS display. All
+ * styling must be done by the developer using the control.
+ *
+ *
+ * Events:
+ * renderDone - fires when the panel completes creating all of the items.
+ *
+ * License:
+ * Copyright (c) 2009, Jonathan Bomgardner.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Panel.DataView = new Class({
+
+ Extends: Jx.Panel,
+
+ options: {
+ /**
+ * Option: data
+ * The store containing the data
+ */
+ data: null,
+ /**
+ * Option: sortColumns
+ * An array of columns to sort the store by.
+ */
+ sortColumns: null,
+ /**
+ * Option: itemTemplate
+ * The template to use in rendering records
+ */
+ itemTemplate: null,
+ /**
+ * Option: emptyTemplate
+ * the template that is displayed when there are no records in the
+ * store.
+ */
+ emptyTemplate: null,
+ /**
+ * Option: containerClass
+ * The class added to the container. It can be used to target the items
+ * in the panel.
+ */
+ containerClass: null,
+ /**
+ * Option: itemClass
+ * The class to add to each item. Used for styling purposes
+ */
+ itemClass: null,
+ /**
+ * Option: itemOptions
+ * Options to pass to the list object
+ */
+ listOptions: {
+ select: true,
+ hover: true
+ }
+ },
+
+ /**
+ * Property: bound
+ * hold bound functions
+ */
+ bound: {},
+
+ init: function () {
+ this.domA = new Element('div');
+ this.list = this.createList(this.domA, this.options.listOptions);
+ this.parent();
+ },
+ /**
+ * APIMethod: render
+ * Renders the dataview. If the store already has data loaded it will be rendered
+ * at the end of the method.
+ */
+ render: function () {
+ if (!$defined(this.options.data)) {
+ //we can't do anything without data
+ return;
+ }
+
+ this.options.content = this.domA;
+
+ //pass to parent
+ this.parent();
+
+ this.domA.addClass(this.options.containerClass);
+
+ //parse templates so we know what values are needed in each
+ this.itemCols = this.parseTemplate(this.options.itemTemplate);
+
+ this.bound.update = this.update.bind(this);
+ //listen for data updates
+ this.options.data.addEvent('loadFinished', this.bound.update);
+ this.options.data.addEvent('sortFinished', this.bound.update);
+ this.options.data.addEvent('loadError', this.bound.update);
+
+ if (this.options.data.loaded) {
+ this.update();
+ }
+
+ },
+
+ /**
+ * Method: draw
+ * begins the process of creating the items
+ */
+ draw: function () {
+ var n = this.options.data.count();
+ if ($defined(n) && n > 0) {
+ for (var i = 0; i < n; i++) {
+ this.options.data.moveTo(i);
+
+ var item = this.createItem();
+ this.list.add(item);
+ }
+ } else {
+ var empty = new Element('div', {html: this.options.emptyTemplate});
+ this.list.add(item);
+ }
+ this.fireEvent('renderDone', this);
+ },
+ /**
+ * Method: createItem
+ * Actually does the work of getting the data from the store
+ * and creating a single item based on the provided template
+ */
+ createItem: function () {
+ //create the item
+ var itemObj = {};
+ this.itemCols.each(function (col) {
+ itemObj[col] = this.options.data.get(col);
+ }, this);
+ var itemTemp = this.options.itemTemplate.substitute(itemObj);
+ var item = new Element('div', {
+ 'class': this.options.itemClass,
+ html: itemTemp
+ });
+ return item;
+ },
+ /**
+ * APIMethod: update
+ * This method begins the process of creating the items. It is called when
+ * the store is loaded or can be called to manually recreate the view.
+ */
+ update: function () {
+ if (!this.updating) {
+ this.updating = true;
+ this.list.empty();
+ this.options.data.sort(this.options.sortColumns);
+ this.draw();
+ this.updating = false;
+ }
+ },
+ /**
+ * Method: parseTemplate
+ * parses the provided template to determine which store columns are
+ * required to complete it.
+ *
+ * Parameters:
+ * template - the template to parse
+ */
+ parseTemplate: function (template) {
+ //we parse the template based on the columns in the data store looking
+ //for the pattern {column-name}. If it's in there we add it to the
+ //array of ones to look for
+ var columns = this.options.data.getColumns();
+ var arr = [];
+ columns.each(function (col) {
+ var s = '{' + col.name + '}';
+ if (template.contains(s)) {
+ arr.push(col.name);
+ }
+ }, this);
+ return arr;
+ },
+ /**
+ * Method: enterItem
+ * Fires mouseenter event
+ *
+ * Parameters:
+ * item - the item that is the target of the event
+ * list - the list this item is in.
+ */
+ enterItem: function(item, list){
+ this.fireEvent('mouseenter', item, list);
+ },
+ /**
+ * Method: leaveItem
+ * Fires mouseleave event
+ *
+ * Parameters:
+ * item - the item that is the target of the event
+ * list - the list this item is in.
+ */
+ leaveItem: function(item, list){
+ this.fireEvent('mouseleave', item, list);
+ },
+ /**
+ * Method: selectItem
+ * Fires select event
+ *
+ * Parameters:
+ * item - the item that is the target of the event
+ * list - the list this item is in.
+ */
+ selectItem: function(item, list){
+ this.fireEvent('select', item, list);
+ },
+ /**
+ * Method: unselectItem
+ * Fires unselect event
+ *
+ * Parameters:
+ * item - the item that is the target of the event
+ * list - the list this item is in.
+ */
+ unselectItem: function(item, list){
+ this.fireEvent('unselect', item, list);
+ },
+ /**
+ * Method: addItem
+ * Fires add event
+ *
+ * Parameters:
+ * item - the item that is the target of the event
+ * list - the list this item is in.
+ */
+ addItem: function(item, list) {
+ this.fireEvent('add', item, list);
+ },
+ /**
+ * Method: removeItem
+ * Fires remove event
+ *
+ * Parameters:
+ * item - the item that is the target of the event
+ * list - the list this item is in.
+ */
+ removeItem: function(item, list) {
+ this.fireEvent('remove', item, list);
+ },
+ /**
+ * Method: createList
+ * Creates the list object
+ *
+ * Parameters:
+ * container - the container to use in the list
+ * options - the options for the list
+ */
+ createList: function(container, options){
+ return new Jx.List(container, $extend({
+ onMouseenter: this.enterItem.bind(this),
+ onMouseleave: this.leaveItem.bind(this),
+ onSelect: this.selectItem.bind(this),
+ onAdd: this.addItem.bind(this),
+ onRemove: this.removeItem.bind(this),
+ onUnselect: this.unselectItem.bind(this)
+ }, options));
+ }
+});
+// $Id: group.js 649 2009-11-30 22:19:48Z pagameba $
+/**
+ * Class: Jx.Panel.DataView.Group
+ *
+ * Extends: <Jx.Panel.DataView>
+ *
+ * This extension of Jx.Panel.DataView that provides for grouping the items
+ * by a particular column.
+ *
+ * License:
+ * Copyright (c) 2009, Jonathan Bomgardner.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Panel.DataView.Group = new Class({
+
+ Extends: Jx.Panel.DataView,
+
+ options: {
+ /**
+ * Option: groupTemplate
+ * The template used to render the group heading
+ */
+ groupTemplate: null,
+ /**
+ * Option: groupContainerClass
+ * The class added to the group container. All of the items and header
+ * for a single grouping is contained by a div that has this class added.
+ */
+ groupContainerClass: null,
+ /**
+ * Option: groupHeaderClass
+ * The class added to the heading. Used for styling.
+ */
+ groupHeaderClass: null,
+ /**
+ * Option: listOption
+ * Options to pass to the main list
+ */
+ listOptions: {
+ select: false,
+ hover: false
+ },
+ /**
+ * Option: itemOption
+ * Options to pass to the item lists
+ */
+ itemOptions: {
+ select: true,
+ hover: true,
+ hoverClass: 'jxItemHover',
+ selectClass: 'jxItemSelect'
+ }
+ },
+
+ init: function() {
+ this.groupCols = this.parseTemplate(this.options.groupTemplate);
+ this.itemManager = new Jx.Selection({
+ eventToFire: {
+ select: 'itemselect',
+ unselect: 'itemunselect'
+ },
+ selectClass: 'jxItemSelected'
+ });
+ this.groupManager = new Jx.Selection({
+ eventToFire: {
+ select: 'groupselect',
+ unselect: 'groupunselect'
+ },
+ selectClass: 'jxGroupSelected'
+ });
+ this.parent();
+
+ },
+ /**
+ * APIMethod: render
+ * sets up the list container and calls the parent class' render function.
+ */
+ render: function () {
+ this.list = this.createList(this.domA, this.listOptions, this.groupManager);
+ this.parent();
+
+ },
+ /**
+ * Method: draw
+ * actually does the work of creating the view
+ */
+ draw: function () {
+ var d = this.options.data;
+ var n = d.count();
+
+ if ($defined(n) && n > 0) {
+ var currentGroup = '';
+ var itemList = null;
+
+ for (var i = 0; i < n; i++) {
+ d.moveTo(i);
+ var group = d.get(this.options.sortColumns[0]);
+
+ if (group !== currentGroup) {
+ //we have a new grouping
+
+ //group container
+ var container = new Element('div', {
+ 'class': this.options.groupContainerClass
+ });
+ var l = this.createList(container,{
+ select: false,
+ hover: false
+ });
+ this.list.add(l.container);
+
+ //group header
+ currentGroup = group;
+ var obj = {};
+ this.groupCols.each(function (col) {
+ obj[col] = d.get(col);
+ }, this);
+ var temp = this.options.groupTemplate.substitute(obj);
+ var g = new Element('div', {
+ 'class': this.options.groupHeaderClass,
+ 'html': temp,
+ id: 'group-' + group.replace(" ","-","g")
+ });
+ l.add(g);
+
+ //items container
+ var currentItemContainer = new Element('div', {
+ 'class': this.options.containerClass
+ });
+ itemList = this.createList(currentItemContainer, this.options.itemOptions, this.itemManager);
+ l.add(itemList.container);
+ }
+
+ var item = this.createItem();
+ itemList.add(item);
+ }
+ } else {
+ var empty = new Element('div', {html: this.options.emptyTemplate});
+ this.list.add(empty);
+ }
+ this.fireEvent('renderDone', this);
+ },
+
+ /**
+ * Method: createList
+ * Creates the list object
+ *
+ * Parameters:
+ * container - the container to use in the list
+ * options - the options for the list
+ * manager - <Jx.Selection> which selection obj to connect to this list
+ */
+ createList: function(container, options, manager){
+ return new Jx.List(container, $extend({
+ onMouseenter: this.enterItem.bind(this),
+ onMouseleave: this.leaveItem.bind(this),
+ onAdd: this.addItem.bind(this),
+ onRemove: this.removeItem.bind(this)
+ }, options), manager);
+ }
+
+});
+// $Id: hidden.js 649 2009-11-30 22:19:48Z pagameba $
+/**
* Class: Jx.Field.Hidden
*
* Extends: <Jx.Field>
@@ -25370,7 +27876,7 @@
-// $Id: $
+// $Id: form.js 823 2010-03-31 12:18:00Z pagameba $
/**
* Class: Jx.Form
*
@@ -25422,7 +27928,12 @@
* Option: name
* the name property for the form
*/
- name: ''
+ name: '',
+ /**
+ * Option: acceptCharset
+ * the character encoding to be used. Defaults to utf-8.
+ */
+ acceptCharset: 'utf-8'
},
/**
@@ -25438,13 +27949,17 @@
* Property: fields
* An array of all of the single fields (not contained in a fieldset) for this form
*/
- fields : new Hash(),
+ fields : null,
/**
* Property: pluginNamespace
* required variable for plugins
*/
pluginNamespace: 'Form',
-
+
+ init: function() {
+ this.parent();
+ this.fields = new Hash();
+ },
/**
* APIMethod: render
* Constructs the form but does not add it to anything to be shown. The caller
@@ -25457,6 +27972,7 @@
'action' : this.options.action,
'class' : 'jxForm',
'name' : this.options.name,
+ 'accept-charset': this.options.acceptCharset,
events: {
keypress: function(e) {
if (e.key == 'enter' &&
@@ -25465,6 +27981,7 @@
this.defaultAction.click) {
document.id(this.defaultAction).focus();
this.defaultAction.click();
+ e.stop();
}
}.bind(this)
}
@@ -25500,7 +28017,7 @@
* Determines if the form passes validation
*
* Parameters:
- * evt - the Mootools event object
+ * evt - the MooTools event object
*/
isValid : function (evt) {
return true;
@@ -25519,7 +28036,7 @@
*/
getValues : function (asQueryString) {
var queryString = this.domObj.toQueryString();
- if ($defined(asQueryString)) {
+ if ($defined(asQueryString) && asQueryString) {
return queryString;
} else {
return queryString.parseQueryString();
@@ -25557,7 +28074,10 @@
if (field instanceof Jx.Field && !$defined(field.form)) {
field.form = this;
this.addField(field);
+ } else if (field instanceof Jx.Fieldset && !$defined(field.form)) {
+ field.form = this;
}
+
this.domObj.grab(field);
}
return this;
@@ -25582,6 +28102,23 @@
}
},this);
return fields;
+ },
+
+ getField: function (id) {
+ if (this.fields.has(id)) {
+ return this.fields.get(id);
+ }
+ return null;
+ },
+
+ setBusy: function(state) {
+ if (this.busy == state) {
+ return;
+ }
+ this.parent(state);
+ this.fields.each(function(field) {
+ field.setBusy(state, true);
+ });
}
});
/**
@@ -25601,6 +28138,9 @@
* call the Jx.Field.File.upload() method for each file input directly and
* then submit the rest of the form via ajax.
*
+ * MooTools.lang Keys:
+ * - file.browseLabel
+ *
* License:
* Copyright (c) 2009, Jon Bomgardner.
*
@@ -25698,7 +28238,7 @@
template : '<span class="jxInputContainer"><input class="jxInputText" type="text" /></span>'
});
this.browseButton = new Jx.Button({
- label : 'Browse...'
+ label: MooTools.lang.get('Jx','file').browseLabel
});
@@ -25764,14 +28304,14 @@
});
//iframeBody.grab(this.form);
- $(this.form).set('target', this.iframe.get('name')).setStyles({
+ document.id(this.form).set('target', this.iframe.get('name')).setStyles({
visibility: 'hidden',
display: 'none'
}).inject(document.body);
//move the form input into it (cloneNode)
- $(this.form).grab(this.field.cloneNode(true));
+ document.id(this.form).grab(this.field.cloneNode(true));
//if polling the server we need an APC_UPLOAD_PROGRESS id.
//get it from the server.
if (this.options.progress) {
@@ -25809,7 +28349,7 @@
//submit the form
- $(this.form).submit();
+ document.id(this.form).submit();
//begin polling if needed
if (this.options.progress && $defined(this.progressID)) {
this.pollUpload();
@@ -25908,6 +28448,22 @@
getExt: function () {
var fn = this.getFileName();
return fn.slice(fn.length - 3);
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ this.parent();
+ if ($defined(this.browseButton)) {
+ this.browseButton.setLabel( MooTools.lang.get('Jx','file').browseLabel);
+ }
}
});
/**
@@ -25936,6 +28492,10 @@
* onUpdate - Fired when the bar is updated
* onComplete - fires when the progress bar completes it's fill
*
+ * MooTools.lang keys:
+ * - progressbar.messageText
+ * - progressbar.progressText
+ *
*/
Jx.Progressbar = new Class({
Family: 'Jx.Progressbar',
@@ -25945,17 +28505,6 @@
onUpdate: $empty,
onComplete: $empty,
/**
- * Option: messageText
- * The text of a message displayed above the bar. Set to NULL to prevent any text from appearing
- */
- messageText: 'Loading...',
- /**
- * Option: progressText
- * The text displayed inside the bar. This defaults to "{progress} of {total}"
- * where {progress} and {total} are substituted for passed in values.
- */
- progressText: '{progress} of {total}',
- /**
* Option: bar
* an object that gives options for the bar itself. Specifically,
* the width and height of the bar. You can set either to 'auto' to
@@ -26007,9 +28556,11 @@
this.parent();
if ($defined(this.options.parent)) {
- this.domObj.inject($(this.options.parent));
+ this.domObj.inject(document.id(this.options.parent));
}
+ this.domObj.addClass('jxProgressStarting');
+
//determine width of progressbar
if (this.options.bar.width === 'auto') {
//get width of container
@@ -26017,14 +28568,16 @@
}
//determine height
+ /**
if (this.options.bar.height === 'auto') {
this.options.bar.height = this.domObj.getStyle('height').toInt() - 4;
}
+ **/
//Message
if (this.message) {
- if ($defined(this.options.messageText)) {
- this.message.set('html', this.options.messsageText);
+ if ($defined(MooTools.lang.get('Jx','progressbar').messageText)) {
+ this.message.set('html', MooTools.lang.get('Jx','progressbar').messageText);
} else {
this.message.destroy();
}
@@ -26034,39 +28587,40 @@
if (this.container) {
this.container.setStyles({
'position': 'relative',
- 'width': this.options.bar.width,
- 'height' : this.options.bar.height + 4
+ 'width': this.options.bar.width
+ //'height' : this.options.bar.height + 4
});
}
//Outline
if (this.outline) {
this.outline.setStyles({
- 'width': this.options.bar.width,
- 'height' : this.options.bar.height
+ 'width': this.options.bar.width
+ //'height' : this.options.bar.height
});
}
//Fill
if (this.fill) {
this.fill.setStyles({
- 'width': 0,
- 'height' : this.options.bar.height
+ 'width': 0
+ //'height' : this.options.bar.height
});
}
//TODO: check for {progress} and {total} in progressText
var obj = {};
- if (this.options.progressText.contains('{progress}')) {
+ var progressText = MooTools.lang.get('Jx','progressbar').progressText;
+ if (progressText.contains('{progress}')) {
obj.progress = 0;
}
- if (this.options.progressText.contains('{total}')) {
+ if (progressText.contains('{total}')) {
obj.total = 0;
}
//Progress text
if (this.text) {
- this.text.set('html', this.options.progressText.substitute(obj));
+ this.text.set('html', progressText.substitute(obj));
}
},
@@ -26080,19 +28634,25 @@
* equal to the total)
*/
update: function (total, progress) {
+
+ //check for starting class
+ if (this.domObj.hasClass('jxProgressStarting')) {
+ this.domObj.removeClass('jxProgressStarting').addClass('jxProgressWorking');
+ }
+
var newWidth = (progress * this.options.bar.width) / total;
//update bar width
- //TODO: animate this
this.text.get('tween', {property:'width', onComplete: function() {
var obj = {};
- if (this.options.progressText.contains('{progress}')) {
+ var progressText = MooTools.lang.get('Jx','progressbar').progressText
+ if (progressText.contains('{progress}')) {
obj.progress = progress;
}
- if (this.options.progressText.contains('{total}')) {
+ if (progressText.contains('{total}')) {
obj.total = total;
}
- var t = this.options.progressText.substitute(obj);
+ var t = progressText.substitute(obj);
this.text.set('text', t);
}.bind(this)}).start(newWidth);
@@ -26100,15 +28660,33 @@
if (total === progress) {
this.complete = true;
+ this.domObj.removeClass('jxProgressWorking').addClass('jxProgressFinished');
this.fireEvent('complete');
} else {
this.fireEvent('update');
}
}).bind(this)}).start(newWidth);
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ this.parent();
+ if (this.message) {
+ this.message.set('html',MooTools.lang.get('Jx','progressbar').messageText);
+ }
+ //progress text will update on next update.
}
-});
+});// $Id: upload.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Panel.FileUpload
*
@@ -26116,6 +28694,9 @@
*
* This class extends Jx.Panel to provide a consistent interface for uploading
* files in an application.
+ *
+ * MooTools.lang Keys:
+ * - upload.buttonText
*
* License:
* Copyright (c) 2009, Jon Bomgardner.
@@ -26139,7 +28720,7 @@
progressUrl: ''
},
/**
- * Option: onFileUploadComplete
+ * Option: onFileComplete
* An event handler that is called when a file has been uploaded
*/
onFileComplete: $empty,
@@ -26155,11 +28736,6 @@
*/
prompt: null,
/**
- * Option: buttonText
- * The text to place on the upload button
- */
- buttonText: 'Upload Files',
- /**
* Option: removeOnComplete
* Determines whether a file is removed from the queue after uploading
*/
@@ -26177,7 +28753,7 @@
*/
fileQueue: [],
/**
- * APIMethod: render
+ * Method: render
* Sets up the upload panel.
*/
render: function () {
@@ -26216,7 +28792,7 @@
});
this.queueDiv.inject(this.domObjA);
this.uploadBtn = new Jx.Button({
- label : this.options.buttonText,
+ label : MooTools.lang.get('Jx','upload').buttonText,
onClick: this.upload.bind(this)
});
var tlb = new Jx.Toolbar({position: 'bottom'}).add(this.uploadBtn);
@@ -26228,8 +28804,8 @@
},
/**
* Method: moveToQueue
- * Called by Jx.Field.File's fileSelected event. Moves the selected file into the
- * upload queue.
+ * Called by Jx.Field.File's fileSelected event. Moves the selected file
+ * into the upload queue.
*/
moveToQueue: function (file) {
var cf = this.currentFile;
@@ -26239,7 +28815,7 @@
this.currentFile = new Jx.Field.File(this.fileOpt);
this.currentFile.addEvent('fileSelected', this.moveToQueue.bind(this));
- $(this.currentFile).replaces($(cf));
+ document.id(this.currentFile).replaces(document.id(cf));
//add to queue div
@@ -26275,6 +28851,8 @@
file.addEvent('uploadProgress', this.fileUploadProgress.bind(this));
//progressbar
//setup options
+ // TODO: should (at least some of) these options be available to
+ // the developer?
var options = {
containerClass: 'progress-container',
messageText: null,
@@ -26392,14 +28970,25 @@
var name = file.getFileName();
//TODO: Should prompt the user to be sure - use Jx.Dialog.Confirm?
this.list.remove(file.queuedDiv);
- //$(name).destroy();
+ //document.id(name).destroy();
this.fileQueue = this.fileQueue.erase(file);
if (this.fileQueue.length === 0) {
this.uploadBtn.setEnabled(false);
}
+ },
+
+ /**
+ * Method: createText
+ * handle change in language
+ */
+ createText: function (lang) {
+ this.parent();
+ if ($defined(this.uploadBtn)) {
+ this.uploadBtn.setLabel(MooTools.lang.get('Jx','upload').buttonText);
+ }
}
});
-// $Id: $
+// $Id: listitem.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.ListItem
*
@@ -26439,7 +29028,7 @@
enable: function(state) {
}
-});// $Id: $
+});// $Id: listview.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.ListView
*
@@ -26512,7 +29101,7 @@
this.list.replace(item, withItem);
return this;
}
-});// $Id: $
+});// $Id: column.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Column
*
@@ -26531,24 +29120,31 @@
*/
Jx.Column = new Class({
- Extends: Jx.Object,
+ Family: 'Jx.Column',
+ Extends: Jx.Widget,
options: {
/**
- * Option: header
- * The text to be used as a header for this column
+ * Option: renderMode
+ * The mode to use in rendering this column to determine its width.
+ * Valid options include
+ *
+ * fit - auto calculates the width for the best fit to the text. This
+ * is the default.
+ * fixed - uses the value passed in the width option, doesn't
+ * auto calculate.
+ * expand - uses the value in the width option as a minimum width and
+ * allows this column to expand and take up any leftover space.
+ * NOTE: there can be only 1 expand column in a grid. The
+ * Jx.Columns object will only take the first column with this
+ * option as the expanding column. All remaining columns marked
+ * "expand" will be treated as "fixed".
*/
- header: null,
+ renderMode: 'fit',
/**
- * Option: modelField
- * The field of the model that this column is keyed to
- */
- modelField: null,
- /**
* Option: width
- * Determines the width of the column. Set to 'null' or 'auto'
- * to allow the column to autocalculate it's width based on its
- * contents
+ * Determines the width of the column when using 'fixed' rendering mode
+ * or acts as a minimum width when using 'expand' mode.
*/
width: null,
/**
@@ -26572,51 +29168,31 @@
*/
isHidden: false,
/**
- * Option: formatter
- * an instance of <Jx.Formatter> or one of its subclasses which
- * will be used to format the data in this column. It can also be
- * an object containing the name (This should be the part after
- * Jx.Formatter in the class name. For instance, to get a currency
- * formatter, specify 'Currency' as the name.) and options for the
- * needed formatter (see individual formatters for options).
- * (code)
- * {
- * name: 'formatter name',
- * options: {}
- * }
- * (end)
- */
- formatter: null,
- /**
* Option: name
* The name given to this column
*/
name: '',
/**
- * Option: dataType
- * The type of the data in this column, used for sorting. Can be
- * alphanumeric, numeric, currency, boolean, or date
+ * Option: template
*/
- dataType: 'alphanumeric',
+ template: null,
/**
- * Option: templates
- * objects used to determine the type of tag and css class to
- * assign to a header cell and a regular cell. The css class can
- * also be a function that returns a string to assign as the css
- * class. The function will be passed the text to be formatted.
+ * Option: renderer
+ * an instance of a Jx.Grid.Renderer to use in rendering the content
+ * of this column or a config object for creating one like so:
+ *
+ * (code)
+ * {
+ * name: 'Text',
+ * options: { ... renderer options ... }
+ * }
*/
- templates: {
- header: {
- tag: 'span',
- cssClass: null
- },
- cell: {
- tag: 'span',
- cssClass: null
- }
- }
-
+ renderer: null
},
+
+ classes: $H({
+ domObj: 'jxGridCellContent'
+ }),
/**
* Property: model
* holds a reference to the model (an instance of <Jx.Store> or subclass)
@@ -26630,127 +29206,157 @@
* initializes the column object
*/
init : function () {
+
+ this.name = this.options.name;
+
+ //adjust header for column
+ if (!$defined(this.options.template)) {
+ this.options.template = '<span class="jxGridCellContent">' + this.name.capitalize() + '</span>';
+ }
+
this.parent();
if ($defined(this.options.grid) && this.options.grid instanceof Jx.Grid) {
this.grid = this.options.grid;
}
- this.name = this.options.name;
- //we need to check the formatter
- if ($defined(this.options.formatter)
- && !(this.options.formatter instanceof Jx.Formatter)) {
- var t = Jx.type(this.options.formatter);
- if (t === 'object') {
- this.options.formatter = new Jx.Formatter[this.options.formatter.name](
- this.options.formatter.options);
+
+ //check renderer
+ if (!$defined(this.options.renderer)) {
+ //set a default renderer
+ this.options.renderer = new Jx.Grid.Renderer.Text({
+ textTemplate: '{' + this.name + '}'
+ });
+ } else {
+ if (!(this.options.renderer instanceof Jx.Grid.Renderer)) {
+ var t = Jx.type(this.options.renderer);
+ if (t === 'object') {
+ this.options.renderer = new Jx.Grid.Renderer[this.options.renderer.name.capitalize()](
+ this.options.renderer.options);
+ }
}
}
+
+ this.options.renderer.setColumn(this);
+
+ this.sortImg = new Element('img', {
+ src: Jx.aPixel.src
+ });
+
},
+
/**
* APIMethod: getHeaderHTML
- * Returns the header text wrapped in the tag specified in
- * options.templates.hedaer.tag
*/
getHeaderHTML : function () {
- var text = this.options.header ? this.options.header
- : this.options.modelField;
- var ht = this.options.templates.header;
- var el = new Element(ht.tag, {
- 'class' : 'jxGridCellContent',
- 'html' : text
- });
- if ($defined(ht.cssClass)) {
- if (Jx.type(ht.cssClass) === 'function') {
- el.addClass(ht.cssClass.run(text));
- } else {
- el.addClass(ht.cssClass);
- }
- }
- this.header = el;
- return el;
+ if (this.isSortable()) {
+ this.sortImg.inject(this.domObj);
+ }
+ return this.domObj;
},
setWidth: function(newWidth) {
- if (this.rule && parseInt(newWidth,10) >= 0) {
- this.width = parseInt(newWidth,10);
- this.rule.style.width = parseInt(newWidth,10) + "px";
- }
+ var delta = this.cellWidth - this.width;
+ this.width = parseInt(newWidth,10);
+ this.cellWidth = this.width + delta;
+ this.options.width = newWidth;
+ if (this.rule && parseInt(newWidth,10) >= 0) {
+ this.rule.style.width = parseInt(newWidth,10) + "px";
+ }
+ if (this.cellRule && parseInt(this.cellWidth,10) >= 0) {
+ this.cellRule.style.width = parseInt(this.cellWidth,10) + "px";
+ }
},
+
+ getWidth: function () {
+ return this.width;
+ },
+
+ getCellWidth: function() {
+ return this.cellWidth;
+ },
+
/**
- * APIMethod: getWidth
+ * APIMethod: calculateWidth
* returns the width of the column.
*
* Parameters:
- * recalculate - {boolean} determines if the width should be recalculated
- * if the column is set to autocalculate. Has no effect if the width is
- * preset
* rowHeader - flag to tell us if this calculation is for the row header
*/
- getWidth : function (recalculate, rowHeader) {
- rowHeader = $defined(rowHeader) ? rowHeader : false;
+ calculateWidth : function (rowHeader) {
+ //if this gets called then we assume that we want to calculate the width
+ rowHeader = $defined(rowHeader) ? rowHeader : false;
var maxWidth;
- //check for null width or for "auto" setting and measure all contents in this column
- //in the entire model as well as the header (really only way to do it).
- if (!$defined(this.width) || recalculate) {
- if (this.options.width !== null
- && this.options.width !== 'auto') {
- maxWidth = this.width = Jx.getNumber(this.options.width);
- } else {
- //calculate the width
- var model = this.grid.getModel();
- var oldPos = model.getPosition();
- maxWidth = 0;
- model.first();
- while (model.valid()) {
- //check size by placing text into a TD and measuring it.
- //TODO: this should add .jxGridRowHead/.jxGridColHead if
- // this is a header to get the correct measurement.
- var text = model.get(this.options.modelField);
- var klass = 'jxGridCell';
- if (this.grid.row.useHeaders()
- && this.options.modelField === this.grid.row
- .getRowHeaderField()) {
- klass = 'jxGridRowHead';
- }
- var s = this.measure(text, klass, rowHeader);
- if (s.width > maxWidth) {
- maxWidth = s.width;
- }
- if (model.hasNext()) {
- model.next();
- } else {
- break;
- }
+ var maxCellWidth;
+
+ var model = this.grid.getModel();
+ model.first();
+ if ((this.options.renderMode == 'fixed' ||
+ this.options.renderMode == 'expand') &&
+ model.valid) {
+ var t = new Element('span', {
+ 'class': 'jxGridCellContent',
+ html: 'a',
+ styles: {
+ width: this.options.width
+ }
+ });
+ var s = this.measure(t,'jxGridCell');
+ maxWidth = s.content.width;
+ maxCellWidth = s.cell.width;
+ } else {
+ //calculate the width
+ var oldPos = model.getPosition();
+ maxWidth = maxCellWidth = 0;
+ while (model.valid()) {
+ //check size by placing text into a TD and measuring it.
+ this.options.renderer.render();
+ var text = document.id(this.options.renderer);
+ var klass = 'jxGridCell';
+ if (this.grid.row.useHeaders()
+ && this.options.name === this.grid.row
+ .getRowHeaderColumn()) {
+ klass = 'jxGridRowHead';
}
+ var s = this.measure(text, klass, rowHeader, model.getPosition());
+ if (s.content.width > maxWidth) {
+ maxWidth = s.content.width;
+ }
+ if (s.cell.width > maxCellWidth) {
+ maxCellWidth = s.cell.width
+ }
+ if (model.hasNext()) {
+ model.next();
+ } else {
+ break;
+ }
+ }
- //check the column header as well (unless this is the row header)
- if (!(this.grid.row.useHeaders() && this.options.modelField === this.grid.row
- .getRowHeaderField())) {
- klass = 'jxGridColHead';
- if (this.isEditable()) {
- klass += ' jxColEditable';
- }
- if (this.isResizable()) {
- klass += ' jxColResizable';
- }
- if (this.isSortable()) {
- klass += ' jxColSortable';
- }
- s = this.measure(this.options.header, klass);
- if (s.width > maxWidth) {
- maxWidth = s.width;
- }
+ //check the column header as well (unless this is the row header)
+ if (!(this.grid.row.useHeaders() &&
+ this.options.name === this.grid.row.getRowHeaderColumn())) {
+ klass = 'jxGridColHead';
+ if (this.isEditable()) {
+ klass += ' jxColEditable';
}
- if (!rowHeader) {
- this.width = maxWidth;
+ if (this.isResizable()) {
+ klass += ' jxColResizable';
}
- model.moveTo(oldPos);
+ if (this.isSortable()) {
+ klass += ' jxColSortable';
+ }
+ s = this.measure(this.domObj.clone(), klass);
+ if (s.content.width > maxWidth) {
+ maxWidth = s.content.width;
+ }
+ if (s.cell.width > maxCellWidth) {
+ maxCellWidth = s.cell.width
+ }
}
}
- if (!rowHeader) {
- return this.width;
- } else {
- return maxWidth;
- }
+
+ this.width = maxWidth;
+ this.cellWidth = maxCellWidth;
+ model.moveTo(oldPos);
+ return this.width;
},
/**
* Method: measure
@@ -26760,32 +29366,33 @@
* text - the text to measure
* klass - a string indicating and extra classes to add so that
* css classes can be taken into account.
+ * rowHeader -
+ * row -
*/
- measure : function (text, klass, rowHeader) {
- if ($defined(this.options.formatter)
- && text !== this.options.header) {
- text = this.options.formatter.format(text);
- }
+ measure : function (text, klass, rowHeader, row) {
var d = new Element('span', {
'class' : klass
});
- var el = new Element('span', {
- 'html' : text,
- 'class': 'jxGridCellContent'
- }).inject(d);
- d.setStyle('height', this.grid.row.getHeight());
+ text.inject(d);
+ //d.setStyle('height', this.grid.row.getHeight(row));
d.setStyles({
'visibility' : 'hidden',
'width' : 'auto'
- //'font-family' : 'Arial' removed because CSS may impose different font(s)
});
+
d.inject(document.body, 'bottom');
var s = d.measure(function () {
- //if nogt rowHeader, get size of innner span
+ //if not rowHeader, get size of innner span
if (!rowHeader) {
- return this.getFirst().getContentBoxSize();
+ return {
+ content: this.getFirst().getContentBoxSize(),
+ cell: this.getFirst().getMarginBoxSize()
+ }
} else {
- return this.getMarginBoxSize();
+ return {
+ content: this.getMarginBoxSize(),
+ cell: this.getMarginBoxSize()
+ }
}
});
d.destroy();
@@ -26821,34 +29428,14 @@
},
/**
* APIMethod: getHTML
- * returns the content of the current model row wrapped in the tag
- * specified by options.templates.cell.tag and with the appropriate classes
- * added
+ * calls render method of the renderer object passed in.
*/
getHTML : function () {
- var text = this.grid.getModel().get(this.options.modelField);
- var ct = this.options.templates.cell;
- if ($defined(this.options.formatter)) {
- text = this.options.formatter.format(text);
- }
- var el = new Element(ct.tag, {
- 'html' : text,
- 'class' : 'jxGridCellContent',
- styles: {
- // width: this.getWidth()
- }
- });
- if ($defined(ct.cssClass)) {
- if (Jx.type(ct.cssClass) === 'function') {
- el.addClass(ct.cssClass.run(text));
- } else {
- el.addClass(ct.cssClass);
- }
- }
- return el;
+ this.options.renderer.render();
+ return document.id(this.options.renderer);
}
-});// $Id: $
+});// $Id: columns.js 818 2010-03-30 12:45:20Z pagameba $
/**
* Class: Jx.Columns
*
@@ -26865,6 +29452,7 @@
*/
Jx.Columns = new Class({
+ Family: 'Jx.Columns',
Extends : Jx.Object,
options : {
@@ -26907,14 +29495,13 @@
this.options.columns.each(function (col) {
//check the column to see if it's a Jx.Grid.Column or an object
- if (col instanceof Jx.Column) {
- this.columns.push(col);
- } else if (Jx.type(col) === "object") {
- col.grid = this.grid;
- this.columns.push(new Jx.Column(col));
- }
+ if (col instanceof Jx.Column) {
+ this.columns.push(col);
+ } else if (Jx.type(col) === "object") {
+ this.columns.push(new Jx.Column(col,this.grid));
+ }
- }, this);
+ }, this);
},
/**
* APIMethod: getHeaderHeight
@@ -26981,11 +29568,16 @@
* index - an integer denoting the placement of the column in the grid (zero-based)
*/
getByGridIndex : function (index) {
- var headers = this.grid.colTableBody.getFirst().getChildren();
+ var headers = this.options.useHeaders ?
+ this.grid.colTableBody.getFirst().getChildren() :
+ this.grid.gridTableBody.getFirst().getChildren();
var cell = headers[index];
- var hClasses = cell.get('class').split(' ').filter(function (cls) {
- return cls.test('jxColHead-');
- });
+ var hClasses = cell.get('class').split(' ').filter(function (cls) {
+ if(this.options.useHeaders)
+ return cls.test('jxColHead-')
+ else
+ return cls.test('jxCol-');
+ }.bind(this));
var parts = hClasses[0].split('-');
return this.getByName(parts[1]);
},
@@ -26999,17 +29591,17 @@
*/
getHeaders : function (list) {
var r = this.grid.row.useHeaders();
- var hf = this.grid.row.getRowHeaderField();
+ var hf = this.grid.row.getRowHeaderColumn();
this.columns.each(function (col, idx) {
- if (r && hf === col.options.modelField) {
+ if (r && hf === col.options.name) {
//do nothing
} else if (!col.isHidden()) {
- var th = new Element('td', {
+ var th = new Element('th', {
'class' : 'jxGridColHead jxGridCol'+idx
});
th.adopt(col.getHeaderHTML());
// th.setStyle('width', col.getWidth());
- th.addClass('jxColHead-' + col.options.modelField);
+ th.addClass('jxColHead-' + col.name);
//add other styles for different attributes
if (col.isEditable()) {
th.addClass('jxColEditable');
@@ -27039,15 +29631,16 @@
*/
getColumnCells : function (list) {
var r = this.grid.row;
- var f = r.getRowHeaderField();
+ var f = r.getRowHeaderColumn();
var h = r.useHeaders();
this.columns.each(function (col, idx) {
- if (h && col.options.modelField !== f && !col.isHidden()) {
+ if (h && col.name !== f && !col.isHidden()) {
list.add(this.getColumnCell(col, idx));
} else if (!h && !col.isHidden()) {
list.add(this.getColumnCell(col, idx));
}
}, this);
+ list.add(new Element('td'));
},
/**
* APIMethod: getColumnCell
@@ -27062,7 +29655,7 @@
'class' : 'jxGridCell'
});
td.adopt(col.getHTML());
- td.addClass('jxCol-' + col.options.modelField);
+ td.addClass('jxCol-' + col.name);
td.addClass('jxGridCol'+idx);
//add other styles for different attributes
if (col.isEditable()) {
@@ -27077,21 +29670,98 @@
td.store('jxCellData',{
col: col,
- index: idx,
+ index: idx, //This is the position of the column
row: this.grid.model.getPosition()
});
return td;
},
+
+ calculateWidths: function () {
+ //to calculate widths we loop through each column
+ var expand = null;
+ var totalWidth = 0;
+ var rowHeaderWidth = 0;
+ this.columns.each(function(col,idx){
+ //are we checking the rowheader?
+ var rowHeader = false;
+ if (col.name == this.grid.row.options.headerColumn) {
+ rowHeader = true;
+ }
+ //if it's fixed, set the width to the passed in width
+ if (col.options.renderMode == 'fixed') {
+ col.calculateWidth(); //col.setWidth(col.options.width);
+
+ } else if (col.options.renderMode == 'fit') {
+ col.calculateWidth(rowHeader);
+ } else if (col.options.renderMode == 'expand' && !$defined(expand)) {
+ expand = col;
+ } else {
+ //treat it as fixed if has width, otherwise as fit
+ if ($defined(col.options.width)) {
+ col.setWidth(col.options.width);
+ } else {
+ col.calculateWidth(rowHeader);
+ }
+ }
+ if (!col.isHidden() && !(col.name == this.grid.row.options.headerColumn)) {
+ totalWidth += Jx.getNumber(col.getWidth());
+ if (rowHeader) {
+ rowHeaderWidth = col.getWidth();
+ }
+ }
+ },this);
+
+ // width of the container
+ //var containerWidth = this.grid.gridObj.getContentBoxSize();
+ var gridSize = this.grid.gridObj.getContentBoxSize();
+ if (gridSize.width > totalWidth) {
+ //now figure the expand column
+ if ($defined(expand)) {
+ // var leftOverSpace = gridSize.width - totalWidth + rowHeaderWidth;
+ var leftOverSpace = gridSize.width - totalWidth;
+ if (leftOverSpace >= expand.options.width) {
+ expand.options.width = leftOverSpace;
+ expand.calculateWidth();
+ expand.setWidth(leftOverSpace);
+ totalWidth += leftOverSpace;
+ } else {
+ expand.setWidth(expand.options.width);
+ }
+ }
+ } //else {
+ this.grid.gridTable.setContentBoxSize({'width': totalWidth - rowHeaderWidth});
+ this.grid.colTable.setContentBoxSize({'width': totalWidth - rowHeaderWidth});
+ // }
+ },
createRules: function(styleSheet, scope) {
this.columns.each(function(col, idx) {
- var selector = scope+' .jxGridCol'+idx+', '+scope + " .jxGridCol" + idx + " .jxGridCellContent";
- col.rule = Jx.Styles.insertCssRule(selector, '', styleSheet);
+ var selector = scope+' .jxGridCol'+idx
+ var dec = '';
+ if (col.options.renderMode === 'fixed' || col.options.renderMode === 'expand') {
+ //set the white-space to 'normal !important'
+ dec = 'white-space: normal !important';
+ }
+ col.cellRule = Jx.Styles.insertCssRule(selector, dec, styleSheet);
+ col.cellRule.style.width = col.getCellWidth() + "px";
+
+ var selector = scope+" .jxGridCol" + idx + " .jxGridCellContent";
+ col.rule = Jx.Styles.insertCssRule(selector, dec, styleSheet);
col.rule.style.width = col.getWidth() + "px";
+
}, this);
},
+ updateRule: function(column) {
+ var col = this.getByName(column);
+ if (col.options.renderMode === 'fit') {
+ col.calculateWidth();
+ }
+ col.rule.style.width = col.getWidth() + "px";
+ col.cellRule.style.width = col.getCellWidth() + "px";
+ },
+
/**
* APIMethod: getColumnCount
* returns the number of columns in this model (including hidden).
@@ -27107,13 +29777,19 @@
* name - the name of the column to get an index for
*/
getIndexFromGrid : function (name) {
- var headers = this.grid.colTableBody.getFirst().getChildren();
+ var headers = this.options.useHeaders ?
+ this.grid.colTableBody.getFirst().getChildren() :
+ this.grid.gridTableBody.getFirst().getChildren();
var c;
var i = -1;
+ var self = this;
headers.each(function (h) {
i++;
var hClasses = h.get('class').split(' ').filter(function (cls) {
- return cls.test('jxColHead-');
+ if(self.options.useHeaders)
+ return cls.test('jxColHead-');
+ else
+ return cls.test('jxCol-');
});
hClasses.each(function (cls) {
if (cls.test(name)) {
@@ -27125,7 +29801,7 @@
}
});
-// $Id: $
+// $Id: row.js 809 2010-03-28 04:15:14Z jonlb at comcast.net $
/**
* Class: Jx.Row
*
@@ -27143,6 +29819,7 @@
*/
Jx.Row = new Class({
+ Family: 'Jx.Row',
Extends : Jx.Object,
options : {
@@ -27169,7 +29846,7 @@
},
/**
* Option: rowHeight
- * The height of the row. Make it null or 'auto' to auto-calculate
+ * The height of the row. Make it null or 'auto' to auto-calculate.
*/
rowHeight : 20,
/**
@@ -27178,30 +29855,26 @@
*/
headerWidth : 20,
/**
- * Option: headerField
- * The field in the model to use as the header
+ * Option: headerColumn
+ * The name of the column in the model to use as the header
*/
- headerField : 'id',
- /**
- * Option: templates
- * objects used to determine the type of tag and css class to
- * assign to a header cell. The css class can
- * also be a function that returns a string to assign as the css
- * class. The function will be passed the text to be formatted.
- */
- templates: {
- header: {
- tag: 'span',
- cssClass: null
- }
- }
-
+ headerColumn : 'id'
},
/**
* Property: grid
* A reference to the grid that this row model belongs to
*/
grid : null,
+ /**
+ * Property: heights
+ * This will hold the calculated height of each row in the grid.
+ */
+ heights: [],
+ /**
+ * Property: rules
+ * A hash that will hold all of the CSS rules for the rows.
+ */
+ rules: $H(),
parameters: ['options','grid'],
@@ -27220,16 +29893,18 @@
* APIMethod: getGridRowElement
* Used to create the TR for the main grid row
*/
- getGridRowElement : function () {
+ getGridRowElement : function (row) {
var tr = new Element('tr');
- tr.setStyle('height', this.getHeight());
+ //tr.setStyle('height', this.getHeight());
if (this.options.alternateRowColors) {
tr.className = (this.grid.getModel().getPosition() % 2) ? this.options.rowClasses.even
: this.options.rowClasses.odd;
} else {
tr.className = this.options.rowClasses.all;
}
+ tr.store('jxRowData', {row: row});
+ tr.addClass('jxGridRow'+row);
return tr;
},
/**
@@ -27239,24 +29914,16 @@
getRowHeaderCell : function () {
//get and set text for element
var model = this.grid.getModel();
- var th = new Element('td', {
+ var th = new Element('th', {
'class' : 'jxGridRowHead'
});
-
- var text = model.get(this.options.headerField);
- var ht = this.options.templates.header;
- var el = new Element(ht.tag, {
- 'class' : 'jxGridCellContent',
- 'html' : text
- }).inject(th);
- if ($defined(ht.cssClass)) {
- if (Jx.type(ht.cssClass) === 'function') {
- el.addClass(ht.cssClass.run(text));
- } else {
- el.addClass(ht.cssClass);
- }
- }
-
+ var col = this.grid.columns.getByName(this.options.headerColumn);
+ var el = col.getHTML();
+ el.inject(th);
+ th.store('jxCellData',{
+ row: model.getPosition(),
+ rowHeader: true
+ });
return th;
},
@@ -27267,20 +29934,65 @@
getRowHeaderWidth : function () {
//this can be drawn from the column for the
//header field
- var col = this.grid.columns.getByField(this.options.headerField);
- return col.getWidth(true, true);
+ var col = this.grid.columns.getByName(this.options.headerColumn);
+ if (!$defined(col.getWidth())) {
+ col.calculateWidth(true);
+ }
+ return col.getWidth();
},
/**
* APIMethod: getHeight
* determines and returns the height of a row
*/
- getHeight : function () {
+ getHeight : function (row) {
//this should eventually compute a height, however, we would need
//a fixed width to do so reliably. For right now, we use a fixed height
//for all rows.
- return this.options.rowHeight;
+ if ((!$defined(this.options.rowHeight) || this.options.rowHeight === 'auto') && $defined(this.heights[row])) {
+ return this.heights[row];
+ } else if (Jx.type(this.options.rowHeight === 'number')) {
+ return this.options.rowHeight;
+ }
},
+ calculateHeights : function () {
+ //grab all rows in the grid body
+ document.id(this.grid.gridTableBody).getChildren().each(function(row){
+ row = document.id(row);
+ var data = row.retrieve('jxRowData');
+ var s = row.getContentBoxSize();
+ this.heights[data.row] = s.height;
+ },this);
+ document.id(this.grid.rowTableHead).getChildren().each(function(row){
+ row = document.id(row);
+ var data = row.retrieve('jxRowData');
+ if (data) {
+ var s = row.getContentBoxSize();
+ this.heights[data.row] = Math.max(this.heights[data.row],s.height);
+ if (Browser.Engine.webkit) {
+ //for some reason webkit (Safari and Chrome)
+ this.heights[data.row] -= 1;
+ }
+ }
+ },this);
+
+ },
+
+ createRules: function(styleSheet, scope) {
+ this.grid.gridTableBody.getChildren().each(function(row, idx) {
+ var selector = scope+' .jxGridRow'+idx;
+ var rule = Jx.Styles.insertCssRule(selector, '', styleSheet);
+ this.rules.set('jxGridRow'+idx, rule);
+ rule.style.height = this.heights[idx] + "px";
+
+ if (Browser.Engine.webkit) {
+ selector += " th";
+ var thRule = Jx.Styles.insertCssRule(selector, '', styleSheet);
+ thRule.style.height = this.heights[idx] + "px";
+ }
+
+ }, this);
+ },
/**
* APIMethod: useHeaders
* determines and returns whether row headers should be used
@@ -27297,10 +30009,10 @@
*/
getRowHeader : function (list) {
var th = this.getRowHeaderCell();
- if (this.grid.model.getPosition() === 0) {
- var rowWidth = this.getRowHeaderWidth();
- th.setStyle("width", rowWidth);
- }
+ //if (this.grid.model.getPosition() === 0) {
+ // var rowWidth = this.getRowHeaderWidth();
+ // th.setStyle("width", rowWidth);
+ //}
th.store('jxCellData', {
rowHeader: true,
row: this.grid.model.getPosition()
@@ -27308,16 +30020,16 @@
list.add(th);
},
/**
- * APIMethod: getRowHeaderField
- * returns the name of the model field that is used for the header
+ * APIMethod: getRowHeaderColumn
+ * returns the name of the column that is used for the row header
*/
- getRowHeaderField : function () {
- return this.options.headerField;
+ getRowHeaderColumn : function () {
+ return this.options.headerColumn;
}
});
-// $Id: $
+// $Id: plugin.js 822 2010-03-31 11:28:31Z conrad.barthelmes $
/**
- * Class: Jx.Grid.Plugin
+ * Class: Jx.Plugin
*
* Extend: <Jx.Object>
*
@@ -27353,9 +30065,26 @@
*/
detach: function(obj){
obj.deregisterPlugin(this);
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ //if the mask is being used then recreate it. The code will pull
+ //the new text automatically
+ if (this.busy) {
+ this.setBusy(false);
+ this.setBusy(true);
+ }
}
-
-});// $Id: $
+});// $Id: plugin.grid.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Plugin.Grid
* Grid plugin namespace
@@ -27366,7 +30095,7 @@
*
* This file is licensed under an MIT style license
*/
-Jx.Plugin.Grid = {};// $Id: grid.js 637 2009-11-21 06:50:06Z jonlb at comcast.net $
+Jx.Plugin.Grid = {};// $Id: grid.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Grid
*
@@ -27391,8 +30120,7 @@
* Sorter - sorts rows by specific column
*
* Jx.Grid renders data that comes from an external source. This external
- * source, called the model, must be a Jx.Store or extended from it (such as
- * Jx.Store.Remote).
+ * source, called the model, must be a Jx.Store or extended from it.
*
* Events:
* gridCellEnter(cell, list) - called when the mouse enters a cell
@@ -27412,6 +30140,9 @@
Family : 'Jx.Grid',
Extends : Jx.Widget,
+ Binds: ['modelChanged','render','addRow','removeRow','removeRows',
+ 'onSelect', 'onUnselect','onMouseEnter','onMouseLeave'],
+
options : {
/**
* Option: parent
@@ -27446,7 +30177,7 @@
/**
* Option: model
- * An instance of Jx.Store or one of its descendants
+ * An instance of Jx.Store
*/
model : null,
@@ -27496,13 +30227,16 @@
*/
init : function () {
this.uniqueId = this.generateId('jxGrid_');
+
var opts;
if ($defined(this.options.model)
&& this.options.model instanceof Jx.Store) {
this.model = this.options.model;
- this.model.addEvent('storeColumnChanged', this.modelChanged
- .bind(this));
- this.model.addEvent('storeSortFinished', this.render.bind(this));
+ this.model.addEvent('storeColumnChanged', this.modelChanged);
+ this.model.addEvent('storeSortFinished', this.render);
+ this.model.addEvent('storeRecordAdded', this.addRow);
+ this.model.addEvent('storeRecordRemoved', this.removeRow);
+ this.model.addEvent('storeMultipleRecordsRemoved', this.removeRows);
}
if ($defined(this.options.columns)) {
@@ -27557,7 +30291,7 @@
this.colTable = new Element('table', {
'class' : 'jxGridTable jxGridHeader'
});
- this.colTableBody = new Element('tbody');
+ this.colTableBody = new Element('thead');
this.colTable.appendChild(this.colTableBody);
this.colObj.appendChild(this.colTable);
@@ -27580,7 +30314,7 @@
}
});
this.gridTable = new Element('table', {
- 'class' : 'jxGridTable'
+ 'class' : 'jxGridTable jxGridContent'
});
this.gridTableBody = new Element('tbody');
this.gridTable.appendChild(this.gridTableBody);
@@ -27595,19 +30329,11 @@
this.gridObj.addEvent('scroll', this.onScroll.bind(this));
- //bind events
- this.bound = {
- select: this.onSelect.bind(this),
- unselect: this.onUnselect.bind(this),
- mouseenter: this.onMouseEnter.bind(this),
- mouseleave: this.onMouseLeave.bind(this)
- };
-
//setup the selection
this.selection = new Jx.Selection();
this.selection.addEvents({
- select: this.bound.select,
- unselect: this.bound.unselect
+ select: this.onSelect,
+ unselect: this.onUnselect
});
this.parent();
@@ -27643,6 +30369,7 @@
var size = this.domObj.getContentBoxSize();
//sum all of the column widths except the hidden columns and the header column
+ /**
var w = size.width - rowWidth - 1;
var totalCols = 0;
this.columns.columns.each(function (col) {
@@ -27651,7 +30378,8 @@
totalCols += col.getWidth();
}
}, this);
-
+ **/
+
/* -1 because of the right/bottom borders */
this.rowColObj.setStyles({
width : rowWidth - 1,
@@ -27725,6 +30453,12 @@
this.gridTable.replaceChild(n, this.gridTableBody);
this.gridTableBody = n;
+ document.id(this.rowColObj).empty();
+
+ if (Jx.Styles.isStyleSheetDefined(this.styleSheet)) {
+ Jx.Styles.removeStyleSheet(this.styleSheet);
+ }
+
},
/**
@@ -27758,37 +30492,50 @@
this.columns.getHeaders(headerList);
/* one extra column at the end for filler */
- th = new Element('td', {
- 'class':'jxGridColHead'
+ th = new Element('th', {
+ 'class':'jxGridColHead',
+ styles: {
+ width: 1000,
+ height: colHeight - 1
+ }
}).inject(trBody);
- new Element('span',{
- 'class': 'jxGridCellContent',
- styles : {
- width : 1000,
- height : colHeight - 1
- }
- }).inject(th);
-
} else {
//hide the headers
this.colTableBody.setStyle('visibility', 'hidden');
}
- if (this.row.useHeaders()) {
- this.rowTableHead.setStyle('visibility', 'visible');
+ //This section actually adds the rows
+ this.model.first();
+ while (this.model.valid()) {
+ tr = this.row.getGridRowElement(this.model.getPosition());
+ var rl = this.makeList(tr);
+ this.gridTableBody.appendChild(tr);
+ //this.rowList.add(rl.container);
- var rowHeight = this.row.getHeight();
+ //Actually add the columns
+ this.columns.getColumnCells(rl);
+ if (this.model.hasNext()) {
+ this.model.next();
+ } else {
+ break;
+ }
+ }
+
+
+ //Moved rowheaders after other columns so we can figure the heights
+ //of each row (after render)
+ if (this.row.useHeaders()) {
+ this.rowTableHead.setStyle('visibility', 'visible');
//loop through all rows and add header
this.model.first();
while (this.model.valid()) {
- var tr = new Element('tr', {
- styles : {
- height : rowHeight
- }
+ var tr = new Element('tr',{
+ 'class': 'jxGridRow'+this.model.getPosition()
});
+ tr.store('jxRowData', {row:this.model.getPosition()});
var rowHeaderList = this.makeList(tr);
this.row.getRowHeader(rowHeaderList);
this.rowTableHead.appendChild(tr);
@@ -27800,7 +30547,7 @@
}
/* one extra row at the end for filler */
tr = new Element('tr').inject(this.rowTableHead);
- th = new Element('td', {
+ th = new Element('th', {
'class' : 'jxGridRowHead',
styles : {
width : this.row.getRowHeaderWidth(),
@@ -27811,35 +30558,15 @@
//hide row headers
this.rowTableHead.setStyle('visibility', 'hidden');
}
-
- colHeight = this.columns.getHeaderHeight();
-
-
- //This section actually adds the rows
- this.model.first();
- while (this.model.valid()) {
- tr = this.row.getGridRowElement();
- tr.store('jxRowData', {row: this.model.getPosition()});
-
-
- var rl = this.makeList(tr);
- this.gridTableBody.appendChild(tr);
- //this.rowList.add(rl.container);
-
- //Actually add the columns
- this.columns.getColumnCells(rl);
-
- if (this.model.hasNext()) {
- this.model.next();
- } else {
- break;
- }
-
- }
-
+
+ this.domObj.resize();
+ this.resize();
+ this.columns.calculateWidths();
Jx.Styles.enableStyleSheet(this.styleSheet);
this.columns.createRules(this.styleSheet, "."+this.uniqueId);
- this.domObj.resize();
+ this.row.calculateHeights();
+ this.row.createRules(this.styleSheet, "."+this.uniqueId);
+
this.fireEvent('doneCreateGrid', this);
} else {
this.model.load();
@@ -27853,21 +30580,88 @@
*/
modelChanged : function (row, col) {
//grab new TD
- var column = this.columns.getIndexFromGrid(col.name);
+ var column = this.columns.getIndexFromGrid(col);
var td = document.id(this.gridObj.childNodes[0].childNodes[0].childNodes[row].childNodes[column]);
var currentRow = this.model.getPosition();
this.model.moveTo(row);
-
- var newTD = this.columns.getColumnCell(this.columns.getByName(col.name));
+ // need to find out whether the header is used or not, to have the right reference back
+ var colIndex = this.options.row.useHeaders ? column+1 : column;
+ var newTD = this.columns.getColumnCell(this.columns.getByName(col),colIndex);
//get parent list
var list = td.getParent().retrieve('jxList');
list.replace(td, newTD);
- //newTD.replaces(td);
-
+ this.columns.updateRule(col);
this.model.moveTo(currentRow);
},
+
/**
+ * APIMethod: addRow
+ * Adds a row to the table. Can add to either the beginning or the end
+ * based on passed flag
+ */
+ addRow: function (store, record, position) {
+ if (this.model.loaded) {
+ if (position === 'bottom') {
+ this.model.last();
+ } else {
+ this.model.first();
+ this.renumberGrid(0, 1);
+ }
+
+ //row header
+ if (this.row.useHeaders()) {
+ var rowHeight = this.row.getHeight();
+ var tr = new Element('tr', {
+ styles : {
+ height : rowHeight
+ }
+ });
+ var rowHeaderList = this.makeList(tr);
+ this.row.getRowHeader(rowHeaderList);
+ if (position === 'top') {
+ tr.inject(this.rowTableHead, position);
+ } else {
+ var lastTr = this.rowTableHead.children[this.rowTableHead.children.length - 1];
+ tr.inject(lastTr, 'before');
+ }
+ }
+ tr = this.row.getGridRowElement();
+ tr.store('jxRowData', {row: this.model.getPosition()});
+ var rl = this.makeList(tr);
+ this.columns.getColumnCells(rl);
+ tr.inject(this.gridTableBody, position);
+ }
+ },
+
+ renumberGrid: function (offset, increment) {
+ var l = this.gridTable.rows.length;
+ for (var i = offset; i < l; i++) {
+ var r = document.id(this.gridTable.rows[i]);
+ var d = r.retrieve('jxRowData');
+ d.row += increment;
+ r.store('jxRowData', d);
+ $A(r.children).each(function(cell){
+ var d = cell.retrieve('jxCellData');
+ d.row += increment;
+ cell.store('jxCellData', d);
+ },this);
+ }
+ },
+
+ removeRow: function (store, index) {
+ this.gridTable.deleteRow(index);
+ this.rowTable.deleteRow(index);
+ this.renumberGrid(index, -1);
+ },
+
+ removeRows: function (store, first, last) {
+ for (var i = first; i <= last; i++) {
+ this.removeRow(first);
+ }
+ },
+
+ /**
* Method: makeList
* utility method used to make row lists
*
@@ -27881,8 +30675,8 @@
}, this.selection);
var target = this;
l.addEvents({
- mouseenter: this.bound.mouseenter,
- mouseleave: this.bound.mouseleave
+ mouseenter: this.onMouseEnter,
+ mouseleave: this.onMouseLeave
});
this.lists.push(l);
return l;
@@ -27905,8 +30699,272 @@
}
});
-// $Id: $
/**
+ * Class: Jx.Grid.Renderer
+ * This is the base class and namespace for all grid renderers.
+ *
+ * Extends: <Jx.Widget>
+ * We extended Jx.Widget to take advantage of templating support.
+ */
+Jx.Grid.Renderer = new Class({
+
+ Family: 'Jx.Grid.Renderer',
+ Extends: Jx.Widget,
+
+ parameters: ['options'],
+
+ options: {
+ deferRender: true,
+ /**
+ * Option: template
+ * The template for rendering this cell. Will be processed as per
+ * the Jx.Widget standard.
+ */
+ template: '<span class="jxGridCellContent"></span>'
+ },
+
+ classes: $H({
+ domObj: 'jxGridCellContent'
+ }),
+
+ column: null,
+
+ init: function () {
+ this.parent();
+ },
+
+ render: function () {
+ this.parent();
+ },
+
+ setColumn: function (column) {
+ if (column instanceof Jx.Column) {
+ this.column = column;
+ }
+ }
+
+});/**
+ * Class: Jx.Grid.Renderer.Text
+ * This is the default renderer for grid cells. It works the same as the
+ * original column implementation. It needs a store, a field name, and an
+ * optional formatter as well as other options.
+ *
+ * Extends: <Jx.Grid.Renderer>
+ *
+ */
+Jx.Grid.Renderer.Text = new Class({
+
+ Family: 'Jx.Grid.Renderer.Text',
+ Extends: Jx.Grid.Renderer,
+
+ options: {
+ /**
+ * Option: formatter
+ * an instance of <Jx.Formatter> or one of its subclasses which
+ * will be used to format the data in this column. It can also be
+ * an object containing the name (This should be the part after
+ * Jx.Formatter in the class name. For instance, to get a currency
+ * formatter, specify 'Currency' as the name.) and options for the
+ * needed formatter (see individual formatters for options).
+ * (code)
+ * {
+ * name: 'formatter name',
+ * options: {}
+ * }
+ * (end)
+ */
+ formatter: null,
+ /**
+ * Option: textTemplate
+ * Will be used for creating the text that goes iside the template. Use
+ * placeholders for indicating the field(s). You can add as much text
+ * as you want. for example, if you wanted to display someone's full
+ * name that is brokem up in the model with first and last names you
+ * can write a template like '{lastName}, {firstName}' and as long as
+ * the text between { and } are field names in the store they will be
+ * substituted properly.
+ */
+ textTemplate: null,
+ /**
+ * Option: css
+ * A string or function to use in adding classes to the text
+ */
+ css: null
+ },
+
+ store: null,
+
+ columnsNeeded: null,
+
+
+ init: function () {
+ this.parent();
+ //check the formatter
+ if ($defined(this.options.formatter)
+ && !(this.options.formatter instanceof Jx.Formatter)) {
+ var t = Jx.type(this.options.formatter);
+ if (t === 'object') {
+ this.options.formatter = new Jx.Formatter[this.options.formatter.name](
+ this.options.formatter.options);
+ }
+ }
+ },
+
+ setColumn: function (column) {
+ this.parent();
+
+ this.store = column.grid.getModel();
+
+ if ($defined(this.options.textTemplate)) {
+ this.columnsNeeded = this.store.parseTemplate(this.options.textTemplate);
+ }
+ },
+
+ render: function () {
+ this.parent();
+
+ var text = '';
+ if ($defined(this.options.textTemplate)) {
+ text = this.store.fillTemplate(null,this.options.textTemplate,this.columnsNeeded);
+ }
+
+ if ($defined(this.options.formatter)) {
+ text = this.options.formatter.format(text);
+ }
+
+ this.domObj.set('html',text);
+
+ if ($defined(this.options.css) && Jx.type(this.options.css) === 'function') {
+ this.domObj.addClass(this.options.css.run(text));
+ } else if ($defined(this.options.css) && Jx.type(this.options.css) === 'string'){
+ this.domObj.addClass(this.options.css);
+ }
+
+ }
+
+});/**
+ * Class: Jx.Grid.Renderer.CheckBox
+ * Renders a checkbox into the cell. Allows options for connecting the cell
+ * to a model field and propogating changes back to the store.
+ *
+ * Extends: <Jx.Grid.Renderer>
+ *
+ */
+Jx.Grid.Renderer.Checkbox = new Class({
+
+ Family: 'Jx.Grid.Renderer.Checkbox',
+ Extends: Jx.Grid.Renderer,
+
+ Binds: ['onBlur','onChange'],
+
+ options: {
+ useStore: false,
+ field: null,
+ updateStore: false,
+ checkboxOptions: {
+ template : '<input class="jxInputContainer jxInputCheck" type="checkbox" name="{name}"/>',
+ name: ''
+ }
+ },
+
+ init: function () {
+ this.parent();
+ },
+
+ render: function () {
+ this.parent();
+ var checkbox = new Jx.Field.Checkbox(this.options.checkboxOptions);
+ this.domObj.adopt(document.id(checkbox));
+
+ if (this.options.useStore) {
+ //set initial state
+ checkbox.setValue(this.store.get(this.options.field));
+ }
+
+ //hook up change and blur events to change store field
+ checkbox.addEvents({
+ 'blur': this.onBlur,
+ 'change': this.onChange
+ });
+ },
+
+ setColumn: function (column) {
+ this.column = column;
+
+ if (this.options.useStore) {
+ this.store = this.column.grid.getModel();
+ }
+ },
+
+ onBlur: function (field) {
+ if (this.options.updateStore) {
+ this.updateStore(field);
+ }
+ this.column.grid.fireEvent('checkBlur',[this.column, field]);
+ },
+
+ onChange: function (field) {
+ if (this.options.updateStore) {
+ this.updateStore(field);
+ }
+ this.column.grid.fireEvent('checkBlur',[this.column, field]);
+ },
+
+ updateStore: function (field) {
+ var newValue = field.getValue();
+
+ var data = document.id(field).getParent().retrieve('jxCellData');
+ var row = data.row;
+
+ if (this.store.get(this.options.field, row) !== newValue) {
+ this.store.set(this.options.field, newValue, row);
+ }
+ }
+
+
+});/**
+ * Class: Jx.Grid.Renderer.Button
+ * Renders a <Jx.Button> into the cell. You can add s many buttons as you'd like per column by passing button configs
+ * in as an array option to options.buttonOptions
+ *
+ * Extends: <Jx.Grid.Renderer>
+ *
+ */
+Jx.Grid.Renderer.Button = new Class({
+
+ Family: 'Jx.Grid.Renderer.Button',
+ Extends: Jx.Grid.Renderer,
+
+ Binds: [],
+
+ options: {
+ template: '<span class="buttons"></span>',
+ /**
+ * Option: buttonOptions
+ * an array of option configurations for <Jx.Button>
+ */
+ buttonOptions: null
+ },
+
+ classes: $H({
+ domObj: 'buttons'
+ }),
+
+ init: function () {
+ this.parent();
+ },
+
+ render: function () {
+ this.parent();
+
+ $A(this.options.buttonOptions).each(function(opts){
+ var button = new Jx.Button(opts);
+ this.domObj.grab(document.id(button));
+ },this);
+
+ }
+});// $Id: grid.selector.js 826 2010-03-31 18:46:16Z pagameba $
+/**
* Class: Jx.Plugin.Selector
*
* Extends: <Jx.Plugin>
@@ -27923,7 +30981,10 @@
*/
Jx.Plugin.Grid.Selector = new Class({
+ Family: 'Jx.Plugin.Grid.Selector',
Extends : Jx.Plugin,
+
+ Binds: ['select','checkSelection','checkAll','afterGridRender'],
options : {
/**
@@ -27940,13 +31001,30 @@
* Option: column
* determines if columns are selectable
*/
- column : false
+ column : false,
+ /**
+ * Option: multiple
+ * Allow multiple selections
+ */
+ multiple: false,
+ /**
+ * Option: useCheckColumn
+ * Whether to use a check box column as the row header or as the
+ * first column in the grid and use it for manipulating selections.
+ */
+ useCheckColumn: false,
+ /**
+ * Option: checkAsHeader
+ * Determines if the check column is the header of the rows
+ */
+ checkAsHeader: false
},
/**
- * Property: bound
- * storage for bound methods useful for working with events
+ * Property: selected
+ * Holds arrays of selected rows and/or columns and their headers
*/
- bound: {},
+ selected: null,
+
/**
* APIMethod: init
* construct a new instance of the plugin. The plugin must be attached
@@ -27954,7 +31032,12 @@
*/
init: function() {
this.parent();
- this.bound.select = this.select.bind(this);
+ this.selected = $H({
+ columns: [],
+ rows: [],
+ rowHeads: [],
+ columnHeads: []
+ });
},
/**
* APIMethod: attach
@@ -27969,22 +31052,85 @@
return;
}
this.grid = grid;
- this.grid.addEvent('gridCellSelect', this.bound.select);
+ this.grid.addEvent('gridCellSelect', this.select);
if (this.options.cell) {
this.oldSelectionClass = this.grid.selection.options.selectedClass;
this.grid.selection.options.selectClass = "jxGridCellSelected";
+ if (this.options.multiple) {
+ this.grid.selection.options.selectMode = 'multiple';
+ }
}
+
+ //setup check column if needed
+ if (this.options.useCheckColumn) {
+
+ var template = '<span class="jxGridCellContent">';
+
+ if (this.options.multiple) {
+ template += '<span class="jxInputContainer jxInputContainerCheck"><input class="jxInputCheck" type="checkbox" name="checkAll" id="checkAll"/></span>';
+ } else {
+ template += '</span>';
+ }
+
+ template += "</span>";
+
+ this.checkColumn = new Jx.Column({
+ template: template,
+ renderMode: 'fit',
+ renderer: new Jx.Grid.Renderer.Checkbox({
+ // onChange: this.checkSelection
+ }),
+ name: 'selection'
+ }, this.grid);
+ this.grid.columns.columns.reverse();
+ this.grid.columns.columns.push(this.checkColumn);
+ this.grid.columns.columns.reverse();
+
+ if (this.options.checkAsHeader) {
+ this.oldHeaderColumn = this.grid.row.options.headerColumn;
+ this.grid.row.options.headerColumn = 'selection';
+
+ if (this.options.multiple) {
+ this.grid.addEvent('doneCreateGrid', this.afterGridRender);
+ }
+ }
+ //attach event to header
+ if (this.options.multiple) {
+ var ch = document.id(this.checkColumn).getElement('input');
+ ch.addEvents({
+ 'change': this.checkAll
+ });
+ }
+
+ }
},
+
+ afterGridRender: function () {
+ if (this.options.checkAsHeader) {
+ var chkCol = document.id(this.checkColumn).clone();
+ chkCol.getElement('input').addEvent('change',this.checkAll);
+ this.grid.rowColObj.adopt(chkCol);
+ //document.id(this.checkColumn).inject(this.grid.rowColObj);
+ }
+ this.grid.removeEvent('doneCreateGrid',this.afterGridRender);
+ },
/**
* APIMethod: detach
*/
detach: function() {
if (this.grid) {
- this.grid.removeEvent('gridCellSelect', this.bound.select);
+ this.grid.removeEvent('gridCellSelect', this.select);
if (this.options.cell) {
this.grid.selection.options.selectedClass = this.oldSelectionClass;
}
}
+ if (this.options.useCheckColumn) {
+ var col = this.grid.columns.getByName('selection');
+ this.grid.columns.columns.erase(col);
+ if (this.options.checkAsHeader) {
+ this.grid.row.options.headerColumn = this.oldHeaderColumn;
+ }
+ }
this.grid = null;
},
/**
@@ -28017,19 +31163,29 @@
this.grid.selection.options.selectClass = this.oldSelectionClass;
} else if (opt === 'row') {
- this.selectedRow.removeClass('jxGridRowSelected');
- this.selectedRow = null;
- this.selectedRowHead.removeClass('jxGridRowHeaderSelected');
- this.selectedRowHead = null;
+
+ this.selected.get('rows').each(function(row){
+ row.removeClass('jxGridRowSelected');
+ },this);
+ this.selected.set('rows',[]);
+
+ this.selected.get('rowHeads').each(function(rowHead){
+ rowHead.removeClass('jxGridRowHeaderSelected');
+ },this);
+ this.selected.set('rowHeads',[]);
+
} else {
- if ($defined(this.selectedCol)) {
+ this.selected.get('columns').each(function(column){
for (var i = 0; i < this.grid.gridTable.rows.length; i++) {
- this.grid.gridTable.rows[i].cells[this.selectedCol].removeClass('jxGridColumnSelected');
+ this.grid.gridTable.rows[i].cells[column].removeClass('jxGridColumnSelected');
}
- }
- this.selectedColHead.removeClass('jxGridColumnHeaderSelected');
- this.selectedColHead = null;
- this.selectedCol = null;
+ },this);
+ this.selected.set('columns',[]);
+
+ this.selected.get('columnHeads').each(function(rowHead){
+ rowHead.removeClass('jxGridColumnHeaderSelected');
+ },this);
+ this.selected.set('columnHeads',[]);
}
},
/**
@@ -28038,16 +31194,20 @@
*/
select : function (cell) {
- console.log('select method');
+ // console.log('select method');
var data = cell.retrieve('jxCellData');
- console.log(data);
+ // console.log(data);
- if (this.options.row) {
+ if (this.options.row && $defined(data.row)) {
this.selectRow(data.row);
}
- if (this.options.column) {
- this.selectColumn(data.index - 1);
+ if (this.options.column && $defined(data.index)) {
+ if (this.grid.row.useHeaders()) {
+ this.selectColumn(data.index - 1);
+ } else {
+ this.selectColumn(data.index);
+ }
}
},
@@ -28062,23 +31222,58 @@
if (!this.options.row) { return; }
var tr = (row >= 0 && row < this.grid.gridTableBody.rows.length) ? this.grid.gridTableBody.rows[row] : null;
+ tr = document.id(tr);
+
+ var rows = this.selected.get('rows');
+ if (tr.hasClass('jxGridRowSelected')) {
+ tr.removeClass('jxGridRowSelected');
+ this.setCheckField(row, false);
- if (tr.hasClass('jxGridRowSelected')) {
- this.selectedRow.removeClass('jxGridRowSelected');
- this.selectedRow = null;
- } else {
- if (this.selectedRow) {
- this.selectedRow.removeClass('jxGridRowSelected');
+ if (this.options.multiple && this.options.useCheckColumn) {
+ if (this.options.checkAsHeader) {
+ document.id(this.grid.rowColObj).getElement('input').removeProperty('checked');
+ } else {
+ document.id(this.checkColumn).getElement('input').removeProperty('checked');
+ }
}
- this.selectedRow = $(tr);
- this.selectedRow.addClass('jxGridRowSelected');
+
+ //search array and remove this item
+ rows.erase(tr);
+ } else {
+ rows.push(tr);
+ tr.addClass('jxGridRowSelected');
+ this.setCheckField(row, true);
+ }
+
+ if (!this.options.multiple) {
+ rows.each(function(row){
+ if (row !== tr) {
+ row.removeClass('jxGridRowSelected');
+ this.setCheckField(row.retrieve('jxRowData').row,false);
+ rows.erase(row);
+ }
+ },this);
}
- this.selectRowHeader(row);
+
+ this.selectRowHeader(row);
},
+
+ setCheckField: function (row, checked) {
+ if (this.options.useCheckColumn) {
+ var check;
+ if (this.options.checkAsHeader) {
+ check = document.id(this.grid.rowTableHead.rows[row].cells[0]).getFirst().getFirst();
+ } else {
+ var col = this.grid.columns.getIndexFromGrid(this.checkColumn.name);
+ check = document.id(this.grid.gridTableBody.rows[row].cells[col]).getFirst().getFirst();
+ }
+ check.retrieve('field').setValue(checked);
+ }
+ },
/**
* Method: selectRowHeader
- * Apply the jxGridRowHea}derSelected style to the row header cell of a
+ * Apply the jxGridRowHeaderSelected style to the row header cell of a
* selected row.
*
* Parameters:
@@ -28088,20 +31283,31 @@
if (!this.grid.row.useHeaders()) {
return;
}
- var cell = (row >= 0 && row < this.grid.rowTableHead.rows.length) ? this.grid.rowTableHead.rows[row].cells[0] : null;
+ var cell = (row >= 0 && row < this.grid.rowTableHead.rows.length) ?
+ this.grid.rowTableHead.rows[row].cells[0] : null;
if (!cell) {
return;
}
- if (this.selectedRowHead) {
- this.selectedRowHead.removeClass('jxGridRowHeaderSelected');
+ cell = document.id(cell);
+ var cells = this.selected.get('rowHeads');
+ if (cells.contains(cell)) {
+ cell.removeClass('jxGridRowHeaderSelected');
+ cells.erase(cell);
+ } else {
+ cell.addClass('jxGridRowHeaderSelected');
+ cells.push(cell);
}
- if (this.selectedRowHead !== cell) {
- this.selectedRowHead = $(cell);
- cell.addClass('jxGridRowHeaderSelected');
- } else if (cell.hasClass('jxgridRowHeaderSelected')) {
- this.selectedRowHead = null;
+
+ if (!this.options.multiple) {
+ cells.each(function(c){
+ if (c !== cell) {
+ c.removeClass('jxGridRowHeaderSelected');
+ cells.erase(c);
+ }
+ },this);
}
+
},
/**
* Method: selectColumn
@@ -28113,19 +31319,33 @@
*/
selectColumn: function (col) {
if (col >= 0 && col < this.grid.gridTable.rows[0].cells.length) {
- if ($defined(this.selectedCol)) {
- for (var i = 0; i < this.grid.gridTable.rows.length; i++) {
- this.grid.gridTable.rows[i].cells[this.selectedCol].removeClass('jxGridColumnSelected');
- }
- }
- if (col !== this.selectedCol) {
- this.selectedCol = col;
- for (i = 0; i < this.grid.gridTable.rows.length; i++) {
- this.grid.gridTable.rows[i].cells[col].addClass('jxGridColumnSelected');
- }
+ var cols = this.selected.get('columns');
+
+ var m = '';
+ if (cols.contains(col)) {
+ //deselect
+ m = 'removeClass';
+ cols.erase(col);
} else {
- this.selectedCol = null;
+ //select
+ m = 'addClass';
+ cols.push(col);
}
+ for (var i = 0; i < this.grid.gridTable.rows.length; i++) {
+ this.grid.gridTable.rows[i].cells[col][m]('jxGridColumnSelected');
+ }
+
+ if (!this.options.multiple) {
+ cols.each(function(c){
+ if (c !== col) {
+ for (var i = 0; i < this.grid.gridTable.rows.length; i++) {
+ this.grid.gridTable.rows[i].cells[c].removeClass('jxGridColumnSelected');
+ }
+ cols.erase(c);
+ }
+ },this);
+ }
+
this.selectColumnHeader(col);
}
},
@@ -28144,25 +31364,79 @@
}
- var cell = (col >= 0 && col < this.grid.colTableBody.rows[0].cells.length) ? this.grid.colTableBody.rows[0].cells[col]
- : null;
+ var cell = (col >= 0 && col < this.grid.colTableBody.rows[0].cells.length) ?
+ this.grid.colTableBody.rows[0].cells[col] : null;
+
if (cell === null) {
return;
}
- if (this.selectedColHead) {
- this.selectedColHead.removeClass('jxGridColumnHeaderSelected');
+ cell = document.id(cell);
+ cells = this.selected.get('columnHeads');
+
+ if (cells.contains(cell)) {
+ cell.removeClass('jxGridColumnHeaderSelected');
+ cells.erase(cell);
+ } else {
+ cell.addClass('jxGridColumnHeaderSelected');
+ cells.push(cell);
}
- if (this.selectedColHead !== cell) {
- this.selectedColHead = $(cell);
- cell.addClass('jxGridColumnHeaderSelected');
+
+ if (!this.options.multiple) {
+ cells.each(function(c){
+ if (c !== cell) {
+ c.removeClass('jxGridColumnHeaderSelected');
+ cells.erase(c);
+ }
+ },this);
+ }
+
+ },
+ /**
+ * Method: checkSelection
+ * Checks whether a row's check box is/isn't checked and modifies the
+ * selection appropriately.
+ *
+ * Parameters:
+ * column - <Jx.Column> that created the checkbox
+ * field - <Jx.Field.Checkbox> instance that was checked/unchecked
+ */
+ checkSelection: function (column, field) {
+ var data = document.id(field).getParent().retrieve('jxCellData');
+ this.selectRow(data.row);
+ },
+ /**
+ * Method: checkAll
+ * Checks all checkboxes in the column the selector inserted.
+ */
+ checkAll: function () {
+ var col;
+ var rows;
+ var checked;
+
+ checked = this.options.checkAsHeader ? this.grid.rowColObj.getElement('input').get('checked') :
+ this.checkColumn.domObj.getElement('input').get('checked');
+
+ if (this.options.checkAsHeader) {
+ col = 0;
+ rows = this.grid.rowTableHead.rows;
} else {
- this.selectedColHead = null;
+ col = this.grid.columns.getIndexFromGrid(this.checkColumn.name);
+ rows = this.grid.gridTableBody.rows;
}
+ $A(rows).each(function(row, idx) {
+ var check = row.cells[col].getElement('input');
+ if ($defined(check)) {
+ var rowChecked = check.get('checked');
+ if (rowChecked !== checked) {
+ this.selectRow(idx);
+ }
+ }
+ }, this);
}
});
-// $Id: $
+// $Id: grid.prelighter.js 662 2009-12-08 06:56:43Z jonlb at comcast.net $
/**
* Class: Jx.Plugin.Prelighter
*
@@ -28302,7 +31576,11 @@
this.prelightRow(data.row, on);
}
if (this.options.column) {
- this.prelightColumn(data.index - 1, on);
+ if (this.grid.row.useHeaders()) {
+ this.prelightColumn(data.index - 1, on);
+ } else {
+ this.prelightColumn(data.index, on);
+ }
}
if (this.options.rowHeader) {
this.prelightRowHeader(data.row, on);
@@ -28439,7 +31717,7 @@
}
}
});
-// $Id: $
+// $Id: grid.sorter.js 809 2010-03-28 04:15:14Z jonlb at comcast.net $
/**
* Class: Jx.Plugin.Sorter
*
@@ -28447,8 +31725,6 @@
*
* Grid plugin to sort the grid by a single column.
*
- * Original selection code from Jx.Grid's original class
- *
* License:
* Copyright (c) 2009, Jon Bomgardner.
*
@@ -28456,9 +31732,10 @@
*/
Jx.Plugin.Grid.Sorter = new Class({
+ Family: 'Jx.Plugin.Grid.Sorter',
Extends : Jx.Plugin,
+ Binds: ['sort', 'addHeaderClass'],
- options : {},
/**
* Property: current
* refernce to the currently sorted column
@@ -28475,21 +31752,6 @@
*/
currentGridIndex : null,
/**
- * Property: bound
- * storage for bound methods useful for working with events
- */
- bound: {},
- /**
- * APIMethod: init
- * construct a new instance of the plugin. The plugin must be attached
- * to a Jx.Grid instance to be useful though.
- */
- init: function() {
- this.parent();
- this.bound.sort = this.sort.bind(this);
- this.bound.addHeaderClass = this.addHeaderClass.bind(this);
- },
- /**
* APIMethod: attach
* Sets up the plugin and attaches the plugin to the grid events it
* will be monitoring
@@ -28501,15 +31763,14 @@
this.grid = grid;
- this.grid.addEvent('gridCellSelect', this.bound.sort);
- this.boundAddHeader = this.addHeaderClass.bind(this);
+ this.grid.addEvent('gridCellSelect', this.sort);
},
/**
* APIMethod: detach
*/
detach: function() {
if (this.grid) {
- this.grid.removeEvent('gridCellSelect', this.bound.sort);
+ this.grid.removeEvent('gridCellSelect', this.sort);
}
this.grid = null;
},
@@ -28534,12 +31795,15 @@
this.currentGridIndex = data.index - 1;
}
- //The grid should be listening for the sortFinished event and will re-render the grid
- //we will listen for the grid's doneCreateGrid event to add the header
- this.grid.addEvent('doneCreateGrid', this.bound.addHeaderClass);
+ // The grid should be listening for the sortFinished event and
+ // will re-render the grid we will listen for the grid's
+ // doneCreateGrid event to add the header
+ this.grid.addEvent('doneCreateGrid', this.addHeaderClass);
//sort the store
var strategy = this.grid.getModel().getStrategy('sort');
- strategy.sort(this.current.name, null, this.direction);
+ if (strategy) {
+ strategy.sort(this.current.name, null, this.direction);
+ }
}
}
@@ -28550,14 +31814,14 @@
* column we sorted by so that the sort arrow shows
*/
addHeaderClass : function () {
- this.grid.removeEvent('doneCreateGrid', this.bound.addHeaderClass);
+ this.grid.removeEvent('doneCreateGrid', this.addHeaderClass);
//get header TD
var th = this.grid.colTable.rows[0].cells[this.currentGridIndex];
th.addClass('jxGridColumnSorted' + this.direction.capitalize());
}
});
-// $Id: $
+// $Id: grid.resize.js 796 2010-03-26 19:56:43Z pagameba $
/**
* Class: Jx.Plugin.Resize
*
@@ -28574,53 +31838,44 @@
Jx.Plugin.Grid.Resize = new Class({
Extends : Jx.Plugin,
-
+ Binds: ['createHandles','removeHandles'],
options: {
/**
- * Option: columns
+ * Option: column
* set to true to make column widths resizeable
*/
- columns: false,
+ column: false,
/**
- * Option: rows
+ * Option: row
* set to true to make row heights resizeable
*/
- rows: false,
+ row: false,
/**
* Option: tooltip
* the tooltip to display for the draggable portion of the
* cell header
*/
- tooltip: 'Drag to resize, double click to auto-size.'
+ tooltip: MooTools.lang.get('Jx','plugin.resize').tooltip
},
/**
* Property: els
* the DOM elements by which the rows/columns are resized.
*/
- els: [],
+ els: {
+ column: [],
+ row: []
+ },
/**
* Property: drags
* the Drag instances
*/
- drags: [],
+ drags: {
+ column: [],
+ row: []
+ },
/**
- * Property: bound
- * storage for bound methods useful for working with events
- */
- bound: {},
- /**
- * APIMethod: init
- * construct a new instance of the plugin. The plugin must be attached
- * to a Jx.Grid instance to be useful though.
- */
- init: function() {
- this.parent();
- this.bound.createResizeHandles = this.createResizeHandles.bind(this);
- this.bound.removeResizeHandles = this.removeResizeHandles.bind(this);
- },
- /**
* APIMethod: attach
* Sets up the plugin and connects it to the grid
*/
@@ -28629,64 +31884,1247 @@
return;
}
this.grid = grid;
- this.grid.addEvent('doneCreateGrid', this.bound.createResizeHandles);
- this.grid.addEvent('beginCreateGrid', this.bound.removeResizeHandles);
- this.createResizeHandles();
+ this.grid.addEvent('doneCreateGrid', this.createHandles);
+ this.grid.addEvent('beginCreateGrid', this.removeHandles);
+ this.createHandles();
},
/**
* APIMethod: detach
*/
detach: function() {
if (this.grid) {
- this.grid.removeEvent('doneCreateGrid', this.bound.createResizeHandles);
- this.grid.removeEvent('beginCreateGrid', this.bound.removeResizeHandles);
+ this.grid.removeEvent('doneCreateGrid', this.createHandles);
+ this.grid.removeEvent('beginCreateGrid', this.removeHandles);
}
this.grid = null;
},
- removeResizeHandles: function() {
- this.els.each(function(el) { el.dispose(); } );
- this.els = [];
- this.drags.each(function(drag){ drag.detach(); });
- this.drags = [];
+ activate: function(option) {
+ if ($defined(this.options[option])) {
+ this.options[option] = true;
+ }
+ this.createHandles();
},
-
- createResizeHandles: function() {
- if (this.options.columns && this.grid.columns.useHeaders()) {
+
+ deactivate: function(option) {
+ if ($defined(this.options[option])) {
+ this.options[option] = false;
+ }
+ this.createHandles();
+ },
+ /**
+ * Method: removeHandles
+ * clean up any handles we created
+ */
+ removeHandles: function() {
+ ['column','row'].each(function(option) {
+ this.els[option].each(function(el) { el.dispose(); } );
+ this.els[option] = [];
+ this.drags[option].each(function(drag){ drag.detach(); });
+ this.drags[option] = [];
+ }, this);
+ },
+ /**
+ * Method: createHandles
+ * create handles that let the user drag to resize columns and rows
+ */
+ createHandles: function() {
+ this.removeHandles();
+ if (this.options.column && this.grid.columns.useHeaders()) {
+ var hf = this.grid.row.getRowHeaderColumn();
this.grid.columns.columns.each(function(col, idx) {
- if (col.header) {
+ if (col.options.name != hf &&
+ col.isResizable() &&
+ col.domObj) {
var el = new Element('div', {
'class':'jxGridColumnResize',
title: this.options.tooltip,
events: {
dblclick: function() {
+ col.options.renderMode = 'fixed';
col.options.width = 'auto';
col.setWidth(col.getWidth(true));
}
}
- }).inject(col.header);
- this.els.push(el);
- this.drags.push(new Drag(el, {
+ }).inject(col.domObj);
+ el.store('col', col);
+ this.els.column.push(el);
+ this.drags.column.push(new Drag(el, {
limit: {y:[0,0]},
+ snap: 2,
+ onBeforeStart: function(el) {
+ var l = el.getPosition(el.parentNode).x.toInt();
+ el.setStyles({
+ left: l,
+ right: null
+ });
+
+ },
+ onStart: function(el) {
+ var l = el.getPosition(el.parentNode).x.toInt();
+ el.setStyles({
+ left: l,
+ right: null
+ });
+ },
onDrag: function(el) {
+ var col = el.retrieve('col');
+ col.options.renderMode = 'fixed';
var w = el.getPosition(el.parentNode).x.toInt();
col.setWidth(w);
+ },
+ onComplete: function(el) {
+ el.setStyle('left', null);
}
}));
}
}, this);
}
- // if (this.options.rows && this.grid.row.useHeaders()) {
- //
- // }
+ //if (this.options.row && this.grid.row.useHeaders()) {}
+ },
+ /**
+ * Method: createText
+ * respond to a language change by updating the tooltip
+ */
+ createText: function (lang) {
+ this.parent();
+ var txt = MooTools.lang.get('Jx','plugin.resize').tooltip;
+ ['column','row'].each(function(option) {
+ this.els[option].each(function(el) { el.set('title',txt); } );
+ }, this);
}
});
+// $Id: grid.editor.js 822 2010-03-31 11:28:31Z conrad.barthelmes $
/**
+ * Class: Jx.Plugin.Editor
+ *
+ * Extends: <Jx.Plugin>
+ *
+ * Grid plugin to enable inline editing within a cell
+ *
+ * Original selection code from Jx.Grid's original class
+ *
+ * License:
+ * Original Copyright (c) 2008, DM Solutions Group Inc.
+ * This version Copyright (c) 2009, Conrad Barthelmes.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Plugin.Grid.Editor = new Class({
+
+ Extends : Jx.Plugin,
+ Binds: ['activate','deactivate','changeText'],
+
+ options : {
+ /**
+ * Option: enabled
+ * Determines if inline editing is avaiable
+ */
+ enabled : true,
+ /**
+ * Option: blurDelay
+ * Set the time in miliseconds when the inputfield/popup shall hide. When
+ * the user refocuses the input/popup within this time, the timeout will be cleared
+ *
+ * set to 'false' if no hiding on blur is wanted
+ */
+ blurDelay : 500,
+ /**
+ * Option: popup
+ *
+ * Definitions for a PopUp to use.
+ * - use - determines whether to use a PopUp or simply the input
+ * - useLabel - determines whether to use labels on top of the input.
+ * Text will be the column header
+ * - useButtons - determines whether to use Submit and Cancel Buttons
+ * - buttonLabel.submit - Text for Submit Button, uses MooTools.lang.get('Jx', 'plugin.editor').submitButton for default
+ * - buttonLabel.cancel - Text for Cancel Button, uses MooTools.lang.get('Jx', 'plugin.editor').cancelButton for default
+ */
+ popup : {
+ use : true,
+ useLabels : false,
+ useButtons : true,
+ button : {
+ submit : {
+ label : '',
+ image : 'images/accept.png'
+ },
+ cancel : {
+ label : '',
+ image : 'images/cancel.png'
+ }
+ },
+ template: '<div class="jxGridEditorPopup"><div class="jxGridEditorPopupInnerWrapper"></div></div>'
+ },
+ /**
+ * Option {boolean} validate
+ * - set to true to have all editable input fields as mandatory field
+ * if they don't have 'mandatory:true' in their colOptions
+ */
+ validate : true,
+ /**
+ * Option: {Array} fieldOptions with objects
+ * Contains objects with options for the Jx.Field instances to show up.
+ * Default options will be added automatically if custom options are entered.
+ *
+ * Preferences:
+ * field - Default * for all types or the name of the column in the model (Jx.Store)
+ * type - Input type to show (Text, Password, Textarea, Select, Checkbox)
+ * options - All Jx.Field options for this column. More options depend on what type you are using.
+ * See Jx.Form.[yourField] for details
+ * validatorOptions: - See Jx.Plugin.Field.Validator Options for details
+ * will only be used if this.options.validate is set to true
+ */
+ fieldOptions : [
+ {
+ field : '*',
+ type : 'Text',
+ options : {},
+ validatorOptions: {
+ validators : [],
+ validateOnBlur: true,
+ validateOnChange : false
+ }
+ }
+ ],
+ /**
+ * Option: {Boolean} fieldFormatted
+ * Displays the cell value also inside the input field as formatted
+ */
+ fieldFormatted : true,
+ /**
+ * Option cellChangeFx
+ * set use to false if no highlighting effect is wanted.
+ *
+ * this is just an idea how successfully changing could be highlighed for the user
+ */
+ cellChangeFx : {
+ use : true,
+ success : '#090',
+ error : '#F00'
+ },
+ /**
+ * Option cellOutline
+ * shows an outline style to the currently active cell to make it easier to see
+ * which cell is active
+ */
+ cellOutline : {
+ use : true,
+ style : '2px solid #88c3e7'
+ },
+ /**
+ * Option: useKeyboard
+ * Set to false if no keyboard support is needed
+ */
+ useKeyboard : true,
+ /**
+ * Option: keys
+ * Contains the event codes for several commands that can be used when
+ * a field is active. Syntax is the same like for the Mootools Keyboard Class
+ * http://mootools.net/docs/more/Interface/Keyboard
+ */
+ keys : {
+ 'ctrl+shift+enter' : 'saveNGoUp',
+ 'tab' : 'saveNGoRight',
+ 'ctrl+enter' : 'saveNGoDown',
+ 'shift+tab' : 'saveNGoLeft',
+ 'enter' : 'saveNClose',
+ 'ctrl+up' : 'cancelNGoUp',
+ 'ctrl+right' : 'cancelNGoRight',
+ 'ctrl+down' : 'cancelNGoDown',
+ 'ctrl+left' : 'cancelNGoLeft',
+ 'esc' : 'cancelNClose',
+ 'up' : 'valueIncrement',
+ 'down' : 'valueDecrement'
+ },
+ /**
+ * Option: keyboardMethods
+ *
+ * can be used to overwrite existing keyboard methods that are used inside
+ * this.options.keys - also possible to add new ones.
+ * Functions are bound to the editor plugin when using 'this'
+ *
+ * example:
+ * keys : {
+ * 'ctrl+u' : 'cancelNGoRightNDown'
+ * },
+ * keyboardMethods: {
+ * 'cancelNGoRightNDown' : function(ev){
+ * ev.preventDefault();
+ * this.getNextCellInRow(false);
+ * this.getNextCellInCol(false);
+ * }
+ * }
+ */
+ keyboardMethods : {},
+ /**
+ * Option: linkClickListener
+ * disables all click events on links that are formatted with Jx.Formatter.Uri
+ * - otherwise the link will open directly instead of open the input editor)
+ * - hold [ctrl] to open the link in a new tab
+ */
+ linkClickListener : true
+ },
+ classes: ['jxGridEditorPopup', 'jxGridEditorPopupInnerWrapper'],
+ /**
+ * Property: activeCell
+ *
+ * Containing Objects:
+ * field : Reference to the Jx.Field instance that will be created
+ * cell : Reference to the cell inside the table
+ * span : Reference to the Dom Element inside the selected cell of the grid
+ * oldValue : Old value of the cell from the grid's model
+ * newValue : Object with <data> and <error> for better validation possibilites
+ * timeoutId : TimeoutId if the focus blurs the input.
+ * coords : Coordinates of the selected cell
+ * colOptions : Reference to the column's option in which the cell is
+ * fieldOptions : Reference to the field options of this column
+ */
+ activeCell : {
+ field : null,
+ cell : null,
+ span : null,
+ oldValue : null,
+ newValue : { data: null, error: false },
+ timeoutId : null,
+ coords : {},
+ colOptions : {},
+ fieldOptions: {}
+ },
+ /**
+ * Property : popup
+ *
+ * References to all contents within a popup (only 1 popup for 1 grid initialization)
+ *
+ * COMMENT: I don't know how deep we need to go into that.. innerWrapper and closeLink probably don't need
+ * own references.. I just made them here in case they are needed at some time..
+ *
+ * Containing Objects:
+ * domObj : Reference to the Dom Element of the popup (absolutely positioned)
+ * innerWrapper : Reference to the inner Wrapper inside the popup to provide relative positioning
+ * closeIcon : Reference to the Dom Element of a little [x] in the upper right to close it (not saving)
+ * buttons : References to all Jx.Buttons used inside the popup
+ * buttons.submit : Reference to the Submit Button
+ * buttons.cancel : Reference to the Cancel Button
+ */
+ popup : {
+ domObj : null,
+ innerWarpper : null,
+ closeIcon : null,
+ button : {
+ submit : null,
+ cancel : null
+ }
+ },
+ /**
+ * Property: keyboard
+ * Instance of a Mootols Keyboard Class
+ */
+ keyboard : null,
+ /**
+ * Property keyboardMethods
+ * Editing and grid functions for keyboard functionality.
+ * Methods are defined and implemented inside this.attach() because of referencing troubles
+ */
+ keyboardMethods : {},
+ /**
+ * APIMethod: init
+ * construct a new instance of the plugin. The plugin must be attached
+ * to a Jx.Grid instance to be useful though.
+ */
+ init: function() {
+ this.parent();
+ },
+ /**
+ * APIMethod: attach
+ * Sets up the plugin and attaches the plugin to the grid events it
+ * will be monitoring
+ *
+ * @var {Object} grid - Instance of Class Jx.Grid
+ */
+ attach: function (grid) {
+ if (!$defined(grid) && !(grid instanceof Jx.Grid)) {
+ return;
+ }
+ this.grid = grid;
+
+ this.grid.addEvent('gridCellSelect', this.activate);
+ this.grid.addEvent('gridCellUnSelect', this.deactivate);
+
+ /*
+ * add default field options to the options in case some new options were entered
+ * to be still able to use them for the rest of the fields
+ */
+ if(this.getFieldOptionsByColName('*').field != '*') {
+ this.options.fieldOptions.unshift({
+ field : '*',
+ type : 'Text',
+ options : {},
+ validatorOptions: {
+ validators : [],
+ validateOnBlur: true,
+ validateOnChange : false
+ }
+ });
+ }
+
+ /**
+ * set the keyboard methods here to have a correct reference to the instance of
+ * the editor plugin
+ *
+ * @todo other names maybe? or even completely different way of handling the keyboard events?
+ * @todo more documentation than method name
+ */
+ var self = this;
+ this.keyboardMethods = {
+ saveNClose : function(ev) {
+ if(self.activeCell.fieldOptions.type != 'Textarea' || (self.activeCell.fieldOptions.type == 'Textarea' && ev.key != 'enter')) {
+ self.deactivate()
+ }
+ },
+ saveNGoUp : function(ev) {ev.preventDefault();self.getPrevCellInCol()},
+ saveNGoRight : function(ev) {ev.preventDefault();self.getNextCellInRow()},
+ saveNGoDown : function(ev) {ev.preventDefault();self.getNextCellInCol()},
+ saveNGoLeft : function(ev) {ev.preventDefault();self.getPrevCellInRow()},
+ cancelNClose : function(ev) {ev.preventDefault();self.deactivate(false)},
+ cancelNGoUp : function(ev) {ev.preventDefault();self.getPrevCellInCol(false)},
+ cancelNGoRight : function(ev) {ev.preventDefault();self.getNextCellInRow(false)},
+ cancelNGoDown : function(ev) {ev.preventDefault();self.getNextCellInCol(false)},
+ cancelNGoLeft : function(ev) {ev.preventDefault();self.getPrevCellInRow(false)},
+ valueIncrement : function(ev) {ev.preventDefault();self.cellValueIncrement(true)},
+ valueDecrement : function(ev) {ev.preventDefault();self.cellValueIncrement(false)}
+ };
+
+ var keyboardEvents = {};
+ for(var i in this.options.keys) {
+ if($defined(this.keyboardMethods[this.options.keys[i]])) {
+ keyboardEvents[i] = this.keyboardMethods[this.options.keys[i]];
+ }else if($defined(this.options.keyboardMethods[this.options.keys[i]])){
+ keyboardEvents[i] = this.options.keyboardMethods[this.options.keys[i]].bind(self);
+ }else{
+ $defined(console) ? console.log("keyboard method %o not defined", this.options.keys[i]) : false;
+ }
+ }
+
+ // initalize keyboard support but do NOT activate it (this is done inside this.activate()).
+ this.keyboard = new Keyboard({
+ events: keyboardEvents
+ });
+
+ this.addFormatterUriClickListener();
+ },
+ /**
+ * APIMethod: detach
+ * detaches from the grid
+ *
+ * @return void
+ */
+ detach: function() {
+ if (this.grid) {
+ this.grid.removeEvent('gridClick', this.activate);
+ }
+ this.grid = null;
+ this.keyboard = null;
+ },
+ /**
+ * APIMethod: enable
+ * enables the grid 'externally'
+ *
+ * @return void
+ */
+ enable : function () {
+ this.options.enabled = true;
+ },
+ /**
+ * APIMethod: disable
+ * disables the grid 'externally'
+ *
+ * @var Boolean close - default true: also closes the currently open input/popup
+ * @var Boolean save - default false: also changes the currently open input/popup
+ * @return void
+ */
+ disable : function(close, save) {
+ close = $defined(close) ? close : true;
+ save = $defined(save) ? save : false;
+ if(close && this.activeCell.cell != null) {
+ this.deactivate(save);
+ }
+ this.options.enabled = false;
+ },
+ /**
+ * Method: activate
+ * activates the input field or breaks up if conditions are not fulfilled
+ *
+ * @todo Field validation
+ *
+ * Parameters:
+ * @var {Object} cell Table Element
+ * @return void
+ */
+ activate: function(cell) {
+ if(!this.options.enabled)
+ return;
+
+ var data = cell.retrieve('jxCellData');
+ // @todo Rename Header too??
+ // return if a table header was clicked
+ if(($defined(data.colHeader) && data.colHeader) || ($defined(data.rowHeader) && data.rowHeader))
+ return;
+ var row = data.row,
+ index = data.index;
+
+ clearTimeout(this.activeCell.timeoutId);
+
+ if(this.cellIsInGrid(row, index)) {
+
+ var colIndex = this.grid.options.row.useHeaders ? index-1 : index;
+ var model = this.grid.getModel(),
+ //cell = this.grid.gridTableBody.rows[row].cells[col] ? this.grid.gridTableBody.rows[row].cells[col] : null,
+ colOptions = this.grid.columns.getByGridIndex(colIndex).options;
+ if (!cell || !colOptions.isEditable) {
+ return;
+ }
+ // if disabling a currently active one fails (mandatory for example) do not continue
+ if(this.activeCell.cell != null && this.deactivate() == false) {
+ return;
+ }
+
+ // set active record index to selected row
+ model.moveTo(row);
+
+ // store properties of the active cell
+ this.activeCell = {
+ oldValue : model.get(data.index),
+ newValue : {data: null, error: false},
+ fieldOptions : this.getFieldOptionsByColName(colOptions.name),
+ colOptions : colOptions,
+ coords : {row : row, index : index},
+ cell : cell,
+ span : cell.getElement('span.jxGridCellContent'),
+ validator : null,
+ field : null,
+ timeoutId : null
+ }
+
+ // check if this column has special validation settings - otherwise use default from this.options.validate
+ if(!$defined(this.activeCell.colOptions.validate) || typeof(this.activeCell.colOptions.validate) != 'boolean') {
+ this.activeCell.colOptions.validate = this.options.validate;
+ }
+
+ var jxFieldOptions = $defined(this.activeCell.fieldOptions.options) ? this.activeCell.fieldOptions.options : {}
+
+ // check for different input field types
+ switch(this.activeCell.fieldOptions.type) {
+ case 'Text':
+ case 'Color':
+ case 'Password':
+ case 'File':
+ jxFieldOptions.value = this.activeCell.oldValue;
+ break;
+ case 'Textarea':
+ jxFieldOptions.value = this.activeCell.oldValue.replace(/<br \/>/gi, '\n');
+ break;
+ case 'Select':
+ // find out which visible value fits to the value inside <option>{value}</option> and set it to selected
+ var oldValue = this.activeCell.oldValue.toString()
+ function setCombos(opts, oldValue) {
+ for(var i = 0, j = opts.length; i < j; i++) {
+ if(opts[i].value == oldValue) {
+ opts[i].selected = true;
+ }else{
+ opts[i].selected = false;
+ }
+ }
+ return opts;
+ }
+
+ if(jxFieldOptions.comboOpts) {
+ jxFieldOptions.comboOpts = setCombos(jxFieldOptions.comboOpts, oldValue);
+ }else if(jxFieldOptions.optGroups) {
+ var groups = jxFieldOptions.optGroups;
+ for(var k = 0, n = groups.length; k < n; k++) {
+ groups[k].options = setCombos(groups[k].options, oldValue);
+ }
+ jxFieldOptions.optGroups = groups;
+ }
+ break;
+ case 'Radio':
+ case 'Checkbox':
+ default:
+ $defined(console) ? console.warn("Fieldtype %o is not supported yet. If you have set a validator for a column, you maybe have forgotton to enter a field type.", this.activeCell.fieldOptions.type) : false;
+ return;
+ break;
+ }
+
+ // update the 'oldValue' to the formatted style, to compare the new value with the formatted one instead with the non-formatted-one
+ if(this.options.fieldFormatted && this.activeCell.colOptions.renderer.options.formatter != null) {
+ if(!$defined(this.activeCell.colOptions.fieldFormatted) || this.activeCell.colOptions.fieldFormatted == true ) {
+ jxFieldOptions.value = this.activeCell.colOptions.renderer.options.formatter.format(jxFieldOptions.value);
+ this.activeCell.oldValue = jxFieldOptions.value;
+ }
+ }
+
+ // create jx.field
+ this.activeCell.field = new Jx.Field[this.activeCell.fieldOptions.type.capitalize()](jxFieldOptions);
+ // create validator
+ if(this.options.validate && this.activeCell.colOptions.validate) {
+ this.activeCell.validator = new Jx.Plugin.Field.Validator(this.activeCell.fieldOptions.validatorOptions);
+ this.activeCell.validator.attach(this.activeCell.field);
+ }
+ this.setStyles(cell);
+
+ if(this.options.useKeyboard) {
+ this.keyboard.activate();
+ }
+
+ // convert a string to an integer if somebody entered a numeric value in quotes, if it failes: make false
+ if(typeof(this.options.blurDelay) == 'string') {
+ this.options.blurDelay = this.options.blurDelay.toInt() ? this.options.blurDelay.toInt() : false;
+ }
+
+ // add a onblur() and onfocus() event to the input field if enabled.
+ if(this.options.blurDelay !== false && typeof(this.options.blurDelay) == 'number') {
+ var self = this;
+ this.activeCell.field.field.addEvents({
+ // activate the timeout to close the input/poup
+ 'blur' : function() {
+ // @todo For some reason, webkit does not clear the timeout correctly when navigating through the grid with keyboard
+ clearTimeout(self.activeCell.timeoutId);
+ self.activeCell.timeoutId = self.deactivate.delay(self.options.blurDelay);
+ },
+ // clear the timeout when the user focusses again
+ 'focus' : function() {
+ clearTimeout(self.activeCell.timeoutId);
+ },
+ // clear the timeout when the user puts the mouse over the input
+ 'mouseover' : function() {
+ clearTimeout(self.activeCell.timeoutId);
+ }
+ });
+ if(this.popup.domObj != null) {
+ this.popup.domObj.addEvent('mouseenter', function() {
+ clearTimeout(self.activeCell.timeoutId);
+ });
+ }
+ }
+
+ this.activeCell.field.field.focus();
+ }else{
+ if($defined(console)) {console.warn('out of grid %o',cell)}
+ }
+ },
+ /**
+ * APIMethod: deactivate
+ * hides the currently active field and stores the new entered data if the
+ * value has changed
+ *
+ * Parameters:
+ * @var {Boolean} save (Optional, default: true) - force aborting
+ * @return true if no data error occured, false if error (popup/input stays visible)
+ */
+ deactivate: function(save) {
+
+ clearTimeout(this.activeCell.timeoutId);
+
+ if(this.activeCell.field !== null) {
+ save = $defined(save) ? save : true;
+
+ var newValue = {data : null, error : false};
+
+ // update the value in the model
+ if(save && this.activeCell.field.getValue().toString() != this.activeCell.oldValue.toString()) {
+ this.grid.model.moveTo(this.activeCell.coords.row);
+ /*
+ * @todo webkit shrinks the rows when the value is updated... but refreshing the grid
+ * immidiately returns in a wrong calculating of the cell position (getCoordinates)
+ */
+ switch(this.activeCell.fieldOptions.type) {
+ case 'Select':
+ var index = this.activeCell.field.field.selectedIndex;
+ newValue.data = document.id(this.activeCell.field.field.options[index]).get('value');
+ break;
+ case 'Textarea':
+ newValue.data = this.activeCell.field.getValue().replace(/\n/gi, '<br />');
+ break;
+ default:
+ newValue.data = this.activeCell.field.getValue();
+ break;
+ }
+ if(save) {
+ this.activeCell.newValue.data = newValue.data;
+ // manually blur the field to activate the validator -> continues with this.terminate()
+ //this.activeCell.timeoutId = this.activeCell.field.field.blur.delay(50, this.activeCell.field.field);
+ }
+ // validation only if it should be saved!
+ if(this.activeCell.validator != null && !this.activeCell.validator.isValid()) {
+ newValue.error = true;
+ this.activeCell.field.field.focus.delay(50, this.activeCell.field.field);
+ }
+ }else{
+ this.activeCell.span.show();
+ }
+
+
+ if(save && newValue.data != null && newValue.error == false) {
+ this.grid.model.set(this.activeCell.coords.index, newValue.data);
+ this.addFormatterUriClickListener();
+ // else show error message and cell
+ }else if(newValue.error == true) {
+ this.activeCell.span.show();
+ }
+
+ // update reference to activeCell
+ if($defined(this.activeCell.coords.row) && $defined(this.activeCell.coords.index)) {
+ var colIndex = this.grid.options.row.useHeaders ? this.activeCell.coords.index-1 : this.activeCell.coords.index;
+ this.activeCell.cell = this.grid.gridTableBody.rows[this.activeCell.coords.row].cells[colIndex];
+ }
+
+ if(this.options.useKeyboard) {
+ this.activeCell.field.removeEvent('keypress', this.setKeyboard);
+ }
+
+ /**
+ * COMMENT: this is just an idea how changing a value could be visualized
+ * we could also pass an Fx.Tween element?
+ * the row could probably be highlighted as well?
+ */
+ if(this.options.cellChangeFx.use) {
+ if(newValue.data != null && newValue.error == false) {
+ this.activeCell.cell.highlight(this.options.cellChangeFx.success);
+ }else if(newValue.error){
+ this.activeCell.cell.highlight(this.options.cellChangeFx.error);
+ }
+ //this.activeCell.cell.removeProperty('style').delay(250, this.activeCell.cell);
+ }
+
+ // check for error and keep input field alive
+ if(newValue.error) {
+ if(this.options.cellChangeFx.use) {
+ this.activeCell.field.field.highlight(this.options.cellChangeFx.error);
+ }
+ this.activeCell.field.field.setStyle('border','1px solid '+this.options.cellChangeFx.error);
+ this.activeCell.field.field.focus();
+ return false;
+ // otherwise hide it
+ }else{
+ this.keyboard.deactivate();
+ this.unsetActiveField();
+ return true;
+ }
+ }
+ },
+ /**
+ * Method: setStyles
+ *
+ * sets some styles for the Jx.Field elements...
+ *
+ * Parameters:
+ * @var cell - table cell of the grid
+ * @return void
+ */
+ setStyles : function(cell) {
+ // popup
+ if(this.options.popup.use) {
+ if(this.options.popup.useLabels) {
+ this.activeCell.field.options.label = this.activeCell.colOptions.header;
+ this.activeCell.field.render();
+ }
+ var styles = {
+ field : {
+ 'width' : this.activeCell.field.type == 'Select' ?
+ cell.getContentBoxSize().width + 5 + "px" :
+ cell.getContentBoxSize().width - 14 + "px",
+ 'margin' : 'auto 0'
+ }
+ };
+ this.activeCell.field.field.setStyles(styles.field);
+ this.showPopUp(cell);
+ // No popup
+ }else {
+ var size = cell.getContentBoxSize(),
+ styles = {
+ domObj : {
+ position: 'absolute'
+ },
+ field : {
+ width : size.width + "px",
+ 'margin-left' : 0
+ }
+ };
+
+ this.activeCell.field.domObj.setStyles(styles.domObj);
+ this.activeCell.field.field.setStyles(styles.field);
+
+ this.activeCell.field.domObj.inject(document.body);
+ Jx.Widget.prototype.position(this.activeCell.field.domObj, cell, {
+ horizontal: ['left left'],
+ vertical: ['top top']
+ });
+
+ this.activeCell.span.hide();
+ }
+
+ // COMMENT: an outline of the cell helps identifying the currently active cell
+ if(this.options.cellOutline.use) {
+ cell.setStyle('outline', this.options.cellOutline.style);
+ }
+ },
+ /**
+ * Method: showPopUp
+ *
+ * Shows the PopUp of of the editor if it already exists, otherwise calls Method
+ * this.createPopUp
+ *
+ * Parameters:
+ * @var cell - table cell of the grid
+ */
+ showPopUp : function(cell) {
+ if(this.popup.domObj != null) {
+ Jx.Widget.prototype.position(this.popup.domObj, cell, {
+ horizontal: ['left left'],
+ vertical: ['top top']
+ });
+ this.activeCell.field.domObj.inject(this.popup.innerWrapper, 'top');
+ this.popup.domObj.show();
+ this.setPopUpButtons();
+ this.setPopUpStylesAfterRendering();
+ }else{
+ this.createPopUp(cell);
+ }
+ },
+ /**
+ * Method: createPopUp
+ *
+ * creates the popup for the requested cell.
+ *
+ * COMMENT: this could also be an jx.dialog..? if we use jx.dialog, maybe without a title element?
+ * Maybe a jx.dialog is too much for this little thing?
+ *
+ * Parameters:
+ * @var cell - table cell of the grid
+ */
+ createPopUp : function(cell) {
+ var coords = cell.getCoordinates(),
+ self = this, popup = null, innerWrapper = null,
+ closeIcon = null, submit = null, cancel = null,
+ template = Jx.Widget.prototype.processTemplate(this.options.popup.template, this.classes);
+
+ popup = template.jxGridEditorPopup;
+
+ innerWrapper = template.jxGridEditorPopupInnerWrapper;
+ /**
+ * COMMENT: first positioning is always in the top left of the grid..
+ * don't know why
+ * manual positioning is needed..?
+ */
+ popup.setStyles({
+ 'left' : coords.left+'px',
+ 'top' : coords.top +'px'
+ });
+ /*
+ Jx.Widget.prototype.position(popup, cell, {
+ horizontal: ['left left'],
+ vertical: ['top top']
+ });
+ */
+
+ this.popup.domObj = popup;
+ this.popup.innerWrapper = innerWrapper;
+ this.popup.closeIcon = closeIcon;
+ this.setPopUpButtons();
+
+ this.activeCell.field.domObj.inject(this.popup.innerWrapper, 'top');
+ this.popup.domObj.inject(document.body);
+
+ this.setPopUpStylesAfterRendering();
+ },
+ /**
+ * Method: setPopUpStylesAfterRendering
+ *
+ * - measures the widths of the buttons to set a new min-width for the popup
+ * because custom labels could break the min-width and force a line-break
+ * - resets the size of the field to make it fit inside the popup (looks nicer)
+ *
+ * @return void
+ */
+ setPopUpStylesAfterRendering: function() {
+ if(this.options.popup.useButtons && this.popup.button.submit != null && this.popup.button.cancel != null) {
+ this.popup.domObj.setStyle('min-width', this.popup.button.submit.domObj.getSize().x + this.popup.button.cancel.domObj.getSize().x + "px");
+ }else{
+ if(this.popup.button.submit != null)
+ this.popup.button.submit.domObj.hide();
+ if(this.popup.button.cancel != null)
+ this.popup.button.cancel.domObj.hide();
+ }
+ this.activeCell.field.field.setStyle('width',
+ this.activeCell.field.type == 'Select' ?
+ this.popup.domObj.getSize().x - 7 + "px" :
+ this.popup.domObj.getSize().x - 17 + "px");
+ },
+ /**
+ * Method: setPopUpButtons
+ * creates the PopUp Buttons if enabled in options or deletes them if set to false
+ *
+ * @return void
+ */
+ setPopUpButtons : function() {
+ var self = this,
+ button = {
+ submit : null,
+ cancel : null
+ };
+ // check if buttons are needed, innerWrapper exists and no buttons already exist
+ if(this.options.popup.useButtons && this.popup.innerWrapper != null && this.popup.button.submit == null) {
+ button.submit = new Jx.Button({
+ label : this.options.popup.button.submit.label.length == 0 ? MooTools.lang.get('Jx','plugin.editor').submitButton : this.options.popup.button.submit.label,
+ image : this.options.popup.button.submit.image,
+ onClick: function() {
+ self.deactivate(true);
+ }
+ }).addTo(this.popup.innerWrapper);
+ button.cancel = new Jx.Button({
+ label : this.options.popup.button.cancel.label.length == 0 ? MooTools.lang.get('Jx','plugin.editor').cancelButton : this.options.popup.button.cancel.label,
+ image : this.options.popup.button.cancel.image,
+ onClick: function() {
+ self.deactivate(false);
+ }
+ }).addTo(this.popup.innerWrapper);
+ }else if(this.options.popup.useButtons && this.popup.button.submit != null) {
+ button = {
+ submit : this.popup.button.submit,
+ cancel : this.popup.button.cancel
+ };
+ // check if buttons are not needed and buttons already exist to remove them
+ }else if(this.options.popup.useButtons == false && this.popup.button.submit != null) {
+ this.popup.button.submit.cleanup();
+ this.popup.button.cancel.cleanup();
+ }
+
+ this.popup.button = button;
+ },
+ /**
+ * Method: unsetActiveField
+ * resets the activeField and hides the popup
+ *
+ * @return void
+ */
+ unsetActiveField: function() {
+ this.activeCell.field.destroy();
+ if(this.popup.domObj != null) {
+ this.popup.domObj.removeEvent('mouseenter');
+ this.popup.domObj.hide();
+ }
+
+ this.activeCell.cell.setStyle('outline', '0px');
+
+ this.activeCell = {
+ field : null,
+ oldValue : null,
+ newValue : { data: null, error: false},
+ cell : null,
+ span : null,
+ timeoutId : null,
+ //popup : null, // do not destroy the popup, it might be used again
+ colOptions : {},
+ coords : {},
+ fieldOptions : {},
+ validator : null
+ }
+ },
+ /**
+ * Method: unsetPopUp
+ * resets the popup manually to be able to use it with different settings
+ */
+ unsetPopUp : function() {
+ if(this.popup.domObj != null) {
+ this.popup.domObj.destroy();
+ this.popup.innerWrapper = null;
+ this.popup.closeIcon = null;
+ this.popup.button.submit = null;
+ this.popup.button.cancel = null;
+ }
+ },
+ /**
+ * APIMethod: getNextCellInRow
+ * activates the next cell in a row if it is editable
+ * otherwise the focus jumps to the next editable cell in the next row
+ * or starts at the beginning
+ *
+ * @var {Boolean} save (Optional, default: true)
+ * @return void
+ */
+ getNextCellInRow: function(save) {
+ save = $defined(save) ? save : true;
+ if(this.activeCell.cell != null) {
+ var nextCell = true, nextRow = true,
+ sumCols = this.grid.columns.columns.length,
+ jxCellClass = 'td.jxGridCell';
+ var i = 0;
+ do {
+ nextCell = i > 0 ? nextCell.getNext(jxCellClass) : this.activeCell.cell.getNext(jxCellClass);
+ // check if cell is still in row, otherwise returns null
+ if(nextCell == null) {
+ nextRow = this.activeCell.cell.getParent('tr').getNext();
+ // check if this was the last row in the table
+ if(nextRow == null) {
+ nextRow = this.activeCell.cell.getParent('tbody').getFirst();
+ }
+ nextCell = nextRow.getFirst(jxCellClass);
+ }
+ var data = nextCell.retrieve('jxCellData');
+ i++;
+ // if all columns are set to uneditable during runtime, jump out of the loop after
+ // running through 2 times to prevent an endless-loop and browser crash :)
+ if(i == sumCols*2) {
+ this.deactivate(save);
+ return;
+ }
+ }while(!data.col.options.isEditable);
+
+ if(save === false) {
+ this.deactivate(save);
+ }
+ this.grid.selection.select(nextCell);
+ }
+ },
+ /**
+ * APIMethod: getPrevCellInRow
+ * activates the previous cell in a row if it is editable
+ * otherwise the focus jumps to the previous editable cell in the previous row
+ * or starts at the last cell in the last row at the end
+ *
+ * @var {Boolean} save (Optional, default: true)
+ * @return void
+ */
+ getPrevCellInRow: function(save) {
+ save = $defined(save) ? save : true;
+ if(this.activeCell.cell != null) {
+ var prevCell, prevRow, i = 0,
+ sumCols = this.grid.columns.columns.length,
+ jxCellClass = 'td.jxGridCell';
+ do {
+ prevCell = i > 0 ? prevCell.getPrevious(jxCellClass) : this.activeCell.cell.getPrevious(jxCellClass);
+ // check if cell is still in row, otherwise returns null
+ if(prevCell == null) {
+ prevRow = this.activeCell.cell.getParent('tr').getPrevious();
+ // check if this was the last row in the table
+ if(prevRow == null) {
+ // @todo this does not always work when shift+tab is hold pressed (out of grid error)
+ prevRow = this.activeCell.cell.getParent('tbody').getLast();
+ }
+ prevCell = prevRow.getLast(jxCellClass);
+ }
+ var data = prevCell.retrieve('jxCellData'),
+ row = data.row,
+ index = data.index;
+ i++;
+ // if all columns are set to uneditable during runtime, jump out of the loop after
+ // running through 2 times to prevent an endless-loop and browser crash :)
+ if(i == sumCols*2) {
+ this.deactivate(save);
+ return;
+ }
+ }while(!data.col.options.isEditable);
+
+ if(save === false) {
+ this.deactivate(save);
+ }
+ this.grid.selection.select(prevCell);
+ }
+ },
+ /**
+ * APIMethod: getNextCellInCol
+ * activates the next cell in a column under the currently active one
+ * if the active cell is in the last row, the first one will be used
+ *
+ * @var {Boolean} save (Optional, default: true)
+ * @return void
+ */
+ getNextCellInCol : function(save) {
+ save = $defined(save) ? save : true;
+ if(this.activeCell.cell != null) {
+ var nextRow, nextCell;
+ nextRow = this.activeCell.cell.getParent().getNext();
+ if(nextRow == null) {
+ nextRow = this.activeCell.cell.getParent('tbody').getFirst();
+ }
+ nextCell = nextRow.getElement('td.jxGridCol'+this.activeCell.coords.index);
+ if(save === false) {
+ this.deactivate(save);
+ }
+ this.grid.selection.select(nextCell);
+ }
+ },
+ /**
+ * APIMethod: getPrevCellInCol
+ * activates the previous cell in a column above the currently active one
+ * if the active cell is in the first row, the last one will be used
+ *
+ * @var {Boolean} save (Optional, default: true)
+ * @return void
+ */
+ getPrevCellInCol : function(save) {
+ save = $defined(save) ? save : true;
+ if(this.activeCell.cell != null) {
+ var prevRow, prevCell;
+ prevRow = this.activeCell.cell.getParent().getPrevious();
+ if(prevRow == null) {
+ prevRow = this.activeCell.cell.getParent('tbody').getLast();
+ }
+ prevCell = prevRow.getElement('td.jxGridCol'+this.activeCell.coords.index);
+ if(save === false) {
+ this.deactivate(save);
+ }
+ this.grid.selection.select(prevCell);
+ }
+ },
+ /**
+ * Method: cellValueIncrement
+ * Whether increments or decrements the value of the active cell if the dataType is numeric
+ *
+ * Parameters
+ * @var {Boolean} bool
+ * @return void
+ */
+ cellValueIncrement : function(bool) {
+ var dataType = this.activeCell.colOptions.dataType,
+ valueNew = null;
+ switch(dataType) {
+ case 'numeric':
+ case 'currency':
+ valueNew = this.activeCell.field.getValue().toInt();
+ if(typeof(valueNew) == 'number') {
+ if(bool) {
+ valueNew++;
+ }else{
+ valueNew--;
+ }
+ }
+ break;
+ case 'date':
+ valueNew = Date.parse(this.activeCell.field.getValue());
+ if(valueNew instanceof Date) {
+ if(bool) {
+ valueNew.increment();
+ }else{
+ valueNew.decrement();
+ }
+ var formatter = new Jx.Formatter.Date();
+ valueNew = formatter.format(valueNew);
+ }
+ break;
+ }
+ if(valueNew != null) {
+ this.activeCell.field.setValue(valueNew);
+ }
+ },
+ /**
+ * Method: cellIsInGrid
+ * determins if the given coordinates are within the grid
+ *
+ * Parameters:
+ * @var {Integer} row
+ * @var {Integer} index
+ * @return {Boolean}
+ */
+ cellIsInGrid: function(row, index) {
+ if($defined(row) && $defined(index)) {
+ //console.log("Row %i - max Rows: %i, Col %i - max Cols %i", row, this.grid.gridTableBody.rows.length, index, this.grid.gridTableBody.rows[row].cells.length);
+ if( row >= 0 && index >= 0 &&
+ row <= this.grid.gridTableBody.rows.length &&
+ index <= this.grid.gridTableBody.rows[row].cells.length
+ ) {
+ return true;
+ }else{
+ return false;
+ }
+ }else{
+ return false;
+ }
+ },
+ /**
+ * APIMethod: getFieldOptionsByColName
+ * checks for the name of a column inside the fieldOptions and returns
+ * the object if found, otherwise the default options for the field
+ *
+ * Parameters:
+ * @var {String} colName
+ * @return {Object} default field options
+ */
+ getFieldOptionsByColName : function(colName) {
+ var fo = this.options.fieldOptions,
+ r = this.options.fieldOptions[0];
+ for(var i = 0, j = fo.length; i < j; i++) {
+ if(fo[i].field == colName) {
+ r = fo[i];
+ break;
+ }
+ }
+ return r;
+ },
+ /**
+ * Method: addFormatterUriClickListener
+ *
+ * looks up for Jx.Formatter.Uri columns to disable the link and open the
+ * inline editor instead. set option linkClickListener to false to disable this
+ *
+ */
+ addFormatterUriClickListener : function() {
+ if(this.options.linkClickListener) {
+ // prevent a link from beeing opened if the editor should appear and the uri formatter is activated
+ var uriCols = [], tableCols, anchor;
+ // find out which columns are using a Jx.Formatter.Uri
+ this.grid.columns.columns.each(function(col,i) {
+ if(col.options.renderer.options.formatter != null && col.options.renderer.options.formatter instanceof Jx.Formatter.Uri) {
+ uriCols.push(i);
+ }
+ });
+ // add an event to all anchors inside these columns
+ this.grid.gridTable.getElements('tr').each(function(tr,i) {
+ tableCols = tr.getElements('td.jxGridCell');
+ for(var j = 0, k = uriCols.length; j < k; j++) {
+ anchor = tableCols[uriCols[j]-1].getElement('a');
+ if(anchor) {
+ anchor.removeEvent('click');
+ anchor.addEvent('click', function(ev) {
+ // open link if ctrl was clicked
+ if(!ev.control) {
+ ev.preventDefault();
+ }
+ });
+ }
+ }
+ });
+ }
+ },
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ this.parent();
+ if (this.options.popup.use && this.options.popup.useButtons) {
+ if(this.popup.button.submit != null) {
+ this.popup.button.submit.cleanup();
+ this.popup.button.cancel.cleanup();
+ this.popup.button.submit = null;
+ this.popup.button.cancel = null;
+ this.setPopUpButtons();
+ }
+ }
+ }
+});
+/**
* Namespace: Jx.Plugin.DataView
* The namespace for all dataview plugins
*/
-Jx.Plugin.DataView = {};
+Jx.Plugin.DataView = {};// $Id: slide.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Slide
* Hides and shows an element without depending on a fixed width or height
@@ -28697,7 +33135,7 @@
Jx.Slide = new Class({
Family: 'Jx.Slide',
Implements: Jx.Object,
-
+ Binds: ['handleClick'],
options: {
/**
* Option: target
@@ -28731,25 +33169,25 @@
onSlideIn: $empty
},
/**
- * APIMethod: init
+ * Method: init
* sets up the slide
*/
init: function () {
- this.target = $(this.options.target);
+ this.target = document.id(this.options.target);
this.target.set('tween', {onComplete: this.setDisplay.bind(this)});
if ($defined(this.options.trigger)) {
- this.trigger = $(this.options.trigger);
- this.trigger.addEvent('click', this.handleClick.bindWithEvent(this));
+ this.trigger = document.id(this.options.trigger);
+ this.trigger.addEvent('click', this.handleClick);
}
this.target.store('slider', this);
},
/**
- * APIMethod: handleClick
+ * Method: handleClick
* event handler for clicks on the trigger. Starts the slide process
*/
handleClick: function () {
@@ -28790,10 +33228,10 @@
if (dir === 'in') {
h = this.target.retrieve(this.options.type);
this.target.setStyles({
- 'overflow': 'hidden',
- 'display': 'block'
+ overflow: 'hidden',
+ display: 'block'
});
- this.target.setStyle(this.options.type, 0);
+ this.target.setStyles(this.options.type, 0);
this.target.tween(this.options.type, h);
} else {
if (this.options.type === 'height') {
@@ -28911,7 +33349,7 @@
header.addClass(this.options.headerClass + '-closed');
}
});
-// $Id: $
+// $Id: plugin.field.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Plugin.Field
* Field plugin namespace
@@ -28922,7 +33360,7 @@
*
* This file is licensed under an MIT style license
*/
-Jx.Plugin.Field = {};// $Id: $
+Jx.Plugin.Field = {};// $Id: field.validator.js 754 2010-03-14 20:13:04Z conrad.barthelmes $
/**
* Class: Jx.Plugin.Field.Validator
*
@@ -28992,6 +33430,7 @@
* storage for bound methods useful for working with events
*/
bound: {},
+ validators : new Hash(),
/**
* APIMethod: init
* construct a new instance of the plugin. The plugin must be attached
@@ -29022,7 +33461,7 @@
if (t === 'string') {
this.field.field.addClass(v);
} else if (t === 'object') {
- this.validators.add(v.validator.name, new InputValidator(v.validator.name, v.validator.options));
+ this.validators.set(v.validator.name, new InputValidator(v.validator.name, v.validator.options));
this.field.field.addClass(v.validatorClass);
}
}, this);
@@ -29094,7 +33533,7 @@
});
-// $Id: $
+// $Id: plugin.form.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Plugin.Form
* Form plugin namespace
@@ -29105,7 +33544,7 @@
*
* This file is licensed under an MIT style license
*/
-Jx.Plugin.Form = {};// $Id: $
+Jx.Plugin.Form = {};// $Id: form.validator.js 686 2010-02-01 05:45:28Z jonlb at comcast.net $
/**
* Class: Jx.Plugin.Form.Validator
*
@@ -29196,12 +33635,12 @@
//setup the fields
$H(this.options.fields).each(function (val, key) {
var opts = $merge(this.options.fieldDefaults, val);
- var field = document.id(key).retrieve('field');
- var plugin = new Jx.Plugin.Field.Validator(opts);
- this.plugins.set(key, plugin);
- plugin.attach(field);
- plugin.addEvent('fieldValidationFailed', this.bound.failed);
- plugin.addEvent('fieldValidationPassed', this.bound.passed);
+ var field = this.form.getField(key);
+ var p = new Jx.Plugin.Field.Validator(opts);
+ this.plugins.set(key, p);
+ p.attach(field);
+ p.addEvent('fieldValidationFailed', this.bound.failed);
+ p.addEvent('fieldValidationPassed', this.bound.passed);
}, this);
@@ -29255,7 +33694,7 @@
this.fireEvent('fieldValidationFailed', [field, validator]);
},
/**
- * Method: fielPassed
+ * Method: fieldPassed
* Refires the fieldValidationPassed event from the field validators it contains
*/
fieldPassed: function (field, validator) {
@@ -29274,7 +33713,450 @@
});
-// $Id: context.js 626 2009-11-20 13:22:22Z pagameba $
+/**
+ * Class: Jx.Plugin.Toolbar
+ * Toolbar plugin namespace
+ *
+ *
+ * License:
+ * Copyright (c) 2009, Jon Bomgardner.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Plugin.ToolbarContainer = {};/**
+ * Class: Jx.Plugin.ToolbarContainer.TabMenu
+ *
+ * Extends: <Jx.Plugin>
+ *
+ * This plugin provides a menu of tabs in a toolbar (similar to the button in firefox at the end of the row of tabs).
+ * It is designed to be used only when the toolbar contains tabs and only when the container is allowed to scroll. Also,
+ * this plugin must be added directly to the Toolbar container. You can get a reference to the container for a
+ * <Jx.TabBox> by doing
+ *
+ * (code)
+ * var tabbox = new Jx.TabBox();
+ * var toolbarContainer = document.id(tabBox.tabBar).getParent('.jxBarContainer').retrieve('jxBarContainer');
+ * (end)
+ *
+ * You can then use the attach method to connect the plugin. Otherwise, you can add it via any normal means to a
+ * directly instantiated Container.
+ *
+ * License:
+ * Copyright (c) 2010, Jon Bomgardner.
+ *
+ * This file is licensed under an MIT style license
+ */
+
+
+Jx.Plugin.ToolbarContainer.TabMenu = new Class({
+
+ Family: 'Jx.Plugin.ToolbarContainer.TabMenu',
+ Extends: Jx.Plugin,
+
+ Binds: ['addButton'],
+
+ options: {
+ },
+ /**
+ * Property: tabs
+ * holds all of the tabs that we're tracking
+ */
+ tabs: [],
+
+ init: function () {
+ this.parent();
+ },
+
+ attach: function (toolbarContainer) {
+ this.parent(toolbarContainer);
+
+ this.container = toolbarContainer;
+
+ //we will only be used if the container is allowed to scroll
+ if (!this.container.options.scroll) {
+ return;
+ }
+
+ this.menu = new Jx.Menu({},{
+ buttonTemplate: '<span class="jxButtonContainer"><a class="jxButton jxButtonMenu jxDiscloser"><span class="jxButtonContent"><span class="jxButtonLabel"></span></span></a></span>'
+ }).addTo(this.container.controls,'bottom');
+ document.id(this.menu).addClass('jxTabMenuRevealer');
+ this.container.update();
+
+ //go through all of the existing tabs and add them to the menu
+ //grab the toolbar...
+ var tb = document.id(this.container).getElement('ul').retrieve('jxToolbar');
+ tb.list.each(function(item){
+ this.addButton(item);
+ },this);
+
+ //connect to the add event of the toolbar list to monitor the addition of buttons
+ tb.list.addEvent('add',this.addButton);
+ },
+
+ detach: function () {
+ this.parent();
+ },
+
+ addButton: function (item) {
+ var tab;
+ tab = (item instanceof Jx.Button.Tab) ? item : document.id(item).getFirst().retrieve('jxTab');
+
+
+ var l = tab.getLabel();
+ if (!$defined(l)) {
+ l = '';
+ }
+ var mi = new Jx.Menu.Item({
+ label: tab.getLabel(),
+ image: tab.options.image,
+ onClick: function() {
+ tab.setActive(true);
+ }.bind(this)
+ });
+
+ document.id(tab).store('menuItem', mi);
+
+ tab.addEvent('close', function() {
+ this.menu.remove(mi);
+ }.bind(this));
+
+ this.menu.add([mi]);
+ }
+});
+/**
+ * Class: Jx.Adaptor
+ * Base class for all adaptor implementations. Provides a place to locate all
+ * common code and the Jx.Adaptor namespace. Since it extends <Jx.Plugin> all
+ * adaptors will be able to be used as plugins for their respective classes.
+ * Also as such, they must have the attach() and detach() methods.
+ *
+ * Adaptors are specifically used to conform a <Jx.Store> to any one of
+ * the different widgets (i.e. Jx.Tree, Jx.ListView, etc...) that could
+ * benefit from integration with the store. This approach was taken to minimize
+ * data access code in the widgets themselves. Widgets should have no idea where
+ * the data/items come from so that they will be usable in the broadest number
+ * of situations.
+ */
+Jx.Adaptor = new Class({
+
+ Family: 'Jx.Adaptor',
+ Extends: Jx.Plugin,
+
+ name: 'Jx.Adaptor',
+
+ options: {
+ template: '',
+ useTemplate: true,
+ store: null
+ },
+
+ columnsNeeded: null,
+
+ init: function () {
+ this.parent();
+
+ this.store = this.options.store;
+
+ if (this.options.useTemplate) {
+ this.columnsNeeded = this.store.parseTemplate(this.options.template);
+ }
+ },
+
+ attach: function (widget) {
+ this.parent(widget);
+ this.widget = widget;
+ },
+
+ detach: function () {
+ this.parent();
+ }
+
+});/**
+ * Class: Jx.Adaptor.Tree
+ * This base class is used to change a store (a flat list of records) into the
+ * data structure needed for a Jx.Tree. It will have 2 subclasses:
+ * <Jx.Adapter.Tree.Mptt> and <Jx.Adapter.Tree.Parent>
+ *
+ *
+ */
+Jx.Adaptor.Tree = new Class({
+
+ Family: 'Jx.Adaptor.Tree',
+ Extends: Jx.Adaptor,
+
+ Binds: ['fill','checkFolder'],
+
+ options: {
+ /**
+ * Option: useAjax
+ * Determines if this adapter should use ajax to request data on the
+ * fly.
+ */
+ monitorFolders: false,
+ startingNodeKey: -1,
+ folderOptions: {
+ image: null,
+ imageClass: null
+ },
+ itemOptions: {
+ image: null,
+ imageClass: null
+ }
+ },
+
+ folders: new Hash(),
+
+ currentRecord: -1,
+
+ attach: function (tree) {
+ this.parent(tree);
+
+ this.tree = tree;
+
+ if (this.options.monitorFolders) {
+ this.strategy = this.store.getStrategy('progressive');
+
+ if (!$defined(this.strategy)) {
+ this.strategy = new Jx.Store.Strategy.Progressive({
+ dropRecords: false,
+ getPaginationParams: function () { return {}; }
+ });
+ this.store.addStrategy(this.strategy);
+ } else {
+ this.strategy.options.dropRecords = false;
+ this.strategy.options.getPaginationParams = function () { return {}; };
+ }
+
+ }
+
+ this.store.addEvent('storeDataLoaded', this.fill);
+
+
+ },
+
+ detach: function () {
+ this.parent();
+ this.store.removeEvent('storeDataLoaded', this.fill);
+ },
+
+ firstLoad: function () {
+ //initial store load
+ this.busy = 'tree';
+ this.tree.setBusy(true);
+ this.store.load({
+ node: this.options.startingNodeKey
+ });
+ },
+
+ /**
+ * APIMethod: fill
+ * This function will start at this.currentRecord and add the remaining
+ * items to the tree.
+ */
+ fill: function () {
+ if (this.busy == 'tree') {
+ this.tree.setBusy(false);
+ this.busy = 'none';
+ } else if (this.busy == 'folder') {
+ this.busyFolder.setBusy(false);
+ this.busy = 'none';
+ }
+ var l = this.store.count() - 1;
+ for (var i = this.currentRecord + 1; i <= l; i++) {
+ var template = this.store.fillTemplate(i,this.options.template,this.columnsNeeded);
+
+ var item;
+ if (this.hasChildren(i)) {
+ //add as folder
+ var item = new Jx.TreeFolder($merge(this.options.folderOptions, {
+ label: template
+ }));
+
+ if (this.options.monitorFolders) {
+ item.addEvent('disclosed', this.checkFolder);
+ }
+
+ this.folders.set(i,item);
+ } else {
+ //add as item
+ var item = new Jx.TreeItem($merge(this.options.itemOptions, {
+ label: template
+ }));
+ }
+ document.id(item).store('index', i);
+ document.id(item).store('jxAdaptor', this);
+ //check for a parent
+ if (this.hasParent(i)) {
+ //add as child of parent
+ var p = this.getParentIndex(i);
+ var folder = this.folders.get(p);
+ folder.add(item);
+ } else {
+ //otherwise add to the tree itself
+ this.tree.add(item);
+ }
+ }
+ this.currentRecord = l;
+ },
+
+ checkFolder: function (folder) {
+ var items = folder.items();
+ if (!$defined(items) || items.length === 0) {
+ //get items via the store
+ var index = document.id(folder).retrieve('index');
+ var node = this.store.get('primaryKey', index);
+ this.busyFolder = folder;
+ this.busyFolder.setBusy(true);
+ this.busy = 'folder';
+ this.store.load({
+ node: node
+ });
+ }
+ },
+
+ hasChildren: $empty,
+
+ hasParent: $empty,
+
+ getParentIndex: function(){}
+
+
+});/**
+ * Class: Jx.Adaptor.Tree.Mptt
+ * This class adapts a table adhering to the classic Parent-style "tree table".
+ *
+ * This class requires an MPTT (Modified Preorder Tree Traversal) table. The MPTT
+ * has a 'left' and a 'right' column that indicates the order of nesting. For
+ * more details see the sitepoint.com article at
+ * http://articles.sitepoint.com/article/hierarchical-data-database
+ *
+ * if useAjax option is set to true then this adapter will send an Ajax request
+ * to the server, through the store's strategy (should be Jx.Store.Strategy.Progressive)
+ * to request additional nodes.
+ */
+Jx.Adaptor.Tree.Mptt = new Class({
+
+
+ Family: 'Jx.Adaptor.Tree.Mptt',
+ Extends: Jx.Adaptor.Tree,
+
+ name: 'tree.mptt',
+
+ options: {
+ left: 'left',
+ right: 'right'
+ },
+
+ /**
+ * APIMethod: hasChildren
+ *
+ * Parameters:
+ * index - {integer} the array index of the row in the store (not the
+ * primary key).
+ */
+ hasChildren: function (index) {
+ var l = this.store.get(this.options.left, index).toInt();
+ var r = this.store.get(this.options.right, index).toInt();
+ return (l + 1 !== r);
+ },
+
+ /**
+ * APIMethod: hasParent
+ *
+ * Parameters:
+ * index - {integer} the array index of the row in the store (not the
+ * primary key).
+ */
+ hasParent: function (index) {
+ var i = this.getParentIndex(index);
+ if ($defined(i)) {
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * APIMethod: getParentIndex
+ *
+ * Parameters:
+ * index - {integer} the array index of the row in the store (not the
+ * primary key).
+ */
+ getParentIndex: function (index) {
+ var l = this.store.get(this.options.left, index).toInt();
+ var r = this.store.get(this.options.right, index).toInt();
+ for (var i = index-1; i >= 0; i--) {
+ var pl = this.store.get(this.options.left, i).toInt();
+ var pr = this.store.get(this.options.right, i).toInt();
+ if (pl < l && pr > r) {
+ return i;
+ }
+ }
+ return null;
+ }
+});/**
+ * Class: Jx.Adapter.Tree.Parent
+ * This class adapts a table adhering to the classic Parent-style "tree table".
+ *
+ * Basically, the store needs to have a column that will indicate each the
+ * parent of each row. The root(s) of the tree should be indicated by a "-1"
+ * in this column. The name of the "parent" column is configurable in the
+ * options.
+ *
+ * if useAjax option is set to true then this adapter will send an Ajax request
+ * to the server, through the store's strategy (should be Jx.Store.Strategy.Progressive)
+ * to request additional nodes. Also, a column indicating whether this is a folder needs
+ * to be set as there is no way to tell if a node has children without it.
+ */
+Jx.Adaptor.Tree.Parent = new Class({
+
+ Family: 'Jx.Adaptor.Tree.Parent',
+ Extends: Jx.Adaptor.Tree,
+
+ options: {
+ parentColumn: 'parent',
+ folderColumn: 'folder'
+ },
+
+ /**
+ * APIMethod: hasChildren
+ *
+ * Parameters:
+ * index - {integer} the array index of the row in the store (not the
+ * primary key).
+ */
+ hasChildren: function (index) {
+ return this.store.get(this.options.folderColumn, index);
+ },
+
+ /**
+ * APIMethod: hasParent
+ *
+ * Parameters:
+ * index - {integer} the array index of the row in the store (not the
+ * primary key).
+ */
+ hasParent: function (index) {
+ if (this.store.get(this.options.parentColumn, index).toInt() !== -1) {
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * APIMethod: getParentIndex
+ *
+ * Parameters:
+ * index - {integer} the array index of the row in the store (not the
+ * primary key).
+ */
+ getParentIndex: function (index) {
+ //get the parent based on the index
+ var pk = this.store.get(this.options.parentColumn, index);
+ return this.store.findByColumn('primaryKey', pk);
+ }
+});// $Id: context.js 663 2009-12-08 07:08:21Z jonlb at comcast.net $
/**
* Class: Jx.Menu.Context
*
@@ -29342,8 +34224,8 @@
this.contentContainer.setStyle('visibility','');
this.showChrome(this.contentContainer);
- document.addEvent('mousedown', this.hideWatcher);
- document.addEvent('keyup', this.keypressWatcher);
+ document.addEvent('mousedown', this.bound.mousedown);
+ document.addEvent('keyup', this.bound.keypress);
e.stop();
}
@@ -29412,7 +34294,7 @@
* Show the menu item
*/
show: $empty
-});// $Id: submenu.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: submenu.js 708 2010-03-01 15:45:27Z pagameba $
/**
* Class: Jx.Menu.SubMenu
*
@@ -29561,6 +34443,13 @@
return this;
},
/**
+ * APIMethod: empty
+ * remove all items from the sub menu
+ */
+ empty: function() {
+ this.menu.empty();
+ },
+ /**
* Method: deactivate
* Deactivate the sub menu
*
@@ -29746,7 +34635,7 @@
}
}
}
-});// $Id: tabset.js 626 2009-11-20 13:22:22Z pagameba $
+});// $Id: tabset.js 825 2010-03-31 18:35:28Z pagameba $
/**
* Class: Jx.TabSet
*
@@ -29837,7 +34726,7 @@
* than one tab can be added by passing extra parameters to this method.
*/
add: function() {
- $A(arguments).each(function(tab) {
+ $A(arguments).flatten().each(function(tab) {
if (tab instanceof Jx.Button.Tab) {
tab.addEvent('down',this.setActiveTabFn);
tab.tabSet = this;
@@ -30073,7 +34962,7 @@
this.domObj.appendChild(this.domSpan);
}
});
-// $Id: tree.js 626 2009-11-20 13:22:22Z pagameba $
+// $Id: tree.js 755 2010-03-15 03:09:37Z jonlb at comcast.net $
/**
* Class: Jx.Tree
*
@@ -30094,6 +34983,7 @@
Family: 'Jx.Tree',
Extends: Jx.Widget,
parameters: ['options','container', 'selection'],
+ pluginNamespace: 'Tree',
/**
* APIProperty: selection
* {<Jx.Selection>} the selection object for this tree.
@@ -30379,7 +35269,7 @@
}
});
-// $Id: treeitem.js 626 2009-11-20 13:22:22Z pagameba $
+// $Id: treeitem.js 755 2010-03-15 03:09:37Z jonlb at comcast.net $
/**
* Class: Jx.TreeItem
*
@@ -30449,7 +35339,10 @@
*/
imageClass: '',
lastLeafClass: 'jxTreeLeafLast',
- template: '<li class="jxTreeContainer jxTreeLeaf"><img class="jxTreeImage" src="'+Jx.aPixel.src+'" alt="" title=""><a class="jxTreeItem" href="javascript:void(0);"><img class="jxTreeIcon" src="'+Jx.aPixel.src+'" alt="" title=""><span class="jxTreeLabel"></span></a></li>'
+ template: '<li class="jxTreeContainer jxTreeLeaf"><img class="jxTreeImage" src="'+Jx.aPixel.src+'" alt="" title=""><a class="jxTreeItem" href="javascript:void(0);"><img class="jxTreeIcon" src="'+Jx.aPixel.src+'" alt="" title=""><span class="jxTreeLabel"></span></a></li>',
+ busyMask: {
+ message: null
+ }
},
classes: new Hash({
domObj: 'jxTreeContainer',
@@ -30637,6 +35530,29 @@
},
setSelection: function(selection){
this.selection = selection;
+ },
+
+ /**
+ * APIMethod: setBusy
+ * set the busy state of the widget
+ *
+ * Parameters:
+ * busy - {Boolean} true to set the widget as busy, false to set it as
+ * idle.
+ */
+ setBusy: function(state) {
+ if (this.busy == state) {
+ return;
+ }
+ this.busy = state;
+ this.fireEvent('busy', this.busy);
+ if (this.busy) {
+ this.domImg.addClass(this.options.busyClass)
+ } else {
+ if (this.options.busyClass) {
+ this.domImg.removeClass(this.options.busyClass);
+ }
+ }
}
});
// $Id: treefolder.js 626 2009-11-20 13:22:22Z pagameba $
@@ -30899,10 +35815,10 @@
this.tree.setSelection(selection);
return this;
}
-});
+});// $Id: slider.js 727 2010-03-04 14:04:04Z pagameba $
/**
* Class: Jx.Slider
- * This class wraps the mootools-more slider class to make it more Jx.Slider
+ * This class wraps the mootools-more slider class to make it more Jx friendly
*
* Copyright 2009 by Jonathan Bomgardner
* License: MIT-style
@@ -30976,10 +35892,15 @@
*/
render: function () {
this.parent();
-
+
+ /**
+ * Not sure why this is here...
+ */
+ /**
if (this.domObj) {
return;
}
+ **/
this.sliderOpts = {
range: [this.options.min, this.options.max],
@@ -31002,7 +35923,7 @@
},
/**
* Method: complete
- * Called when the slider stops movingand the mouse button is released.
+ * Called when the slider stops moving and the mouse button is released.
*/
complete: function (step) {
this.fireEvent('complete', [step, this]);
@@ -31017,14 +35938,24 @@
this.slider = new Slider(this.domObj, this.knob, this.sliderOpts);
}
this.slider.set(this.options.startAt);
+ },
+ /**
+ * APIMethod: set
+ * set the value of the slider
+ */
+ set: function(value) {
+ this.slider.set(value);
}
-});// $Id: $
+});// $Id: notice.js 776 2010-03-22 14:35:16Z pagameba $
/**
* Class: Jx.Notice
*
* Extends: <Jx.ListItem>
*
* Events:
+ *
+ * MooTools.lang Keys:
+ * - notice.closeTip
*
* License:
* Copyright (c) 2009, DM Solutions Group.
@@ -31037,10 +35968,32 @@
Extends: Jx.ListItem,
options: {
+ /**
+ * Option: fx
+ * the effect to use on the notice when it is shown and hidden,
+ * 'fade' by default
+ */
fx: 'fade',
+ /**
+ * Option: chrome
+ * {Boolean} should the notice be displayed with chrome or not,
+ * default is false
+ */
chrome: false,
+ /**
+ * Option: enabled
+ * {Boolean} default is false
+ */
enabled: true,
- template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="close this notice"></a></div></li>',
+ /**
+ * Option: template
+ * {String} the HTML template of a notice
+ */
+ template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="' + MooTools.lang.get('Jx','notice').closeTip + '"></a></div></li>',
+ /**
+ * Option: klass
+ * {String} css class to add to the notice
+ */
klass: ''
},
@@ -31052,7 +36005,7 @@
}),
/**
- * APIMethod: render
+ * Method: render
*/
render: function () {
this.parent();
@@ -31064,11 +36017,17 @@
this.domClose.addEvent('click', this.close.bind(this));
}
},
-
+ /**
+ * APIMethod: close
+ * close the notice
+ */
close: function() {
this.fireEvent('close', this);
},
-
+ /**
+ * APIMethod: show
+ * show the notice
+ */
show: function(el, onComplete) {
if (this.options.chrome) {
this.showChrome();
@@ -31081,7 +36040,10 @@
if (onComplete) onComplete();
}
},
-
+ /**
+ * APIMethod: hide
+ * hide the notice
+ */
hide: function(onComplete) {
if (this.options.chrome) {
this.hideChrome();
@@ -31095,38 +36057,63 @@
}
}
});
-
+/**
+ * Class: Jx.Notice.Information
+ * A <Jx.Notice> subclass useful for displaying informational messages
+ */
Jx.Notice.Information = new Class({
Extends: Jx.Notice,
options: {
- template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><img class="jxNoticeIcon" src="'+Jx.aPixel.src+'" title="Success"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="close this notice"></a></div></li>',
+ template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><img class="jxNoticeIcon" src="'+Jx.aPixel.src+'" title="Success"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="' + MooTools.lang.get('Jx','notice').closeTip + '"></a></div></li>',
klass: 'jxNoticeInformation'
}
});
+/**
+ * Class: Jx.Notice.Success
+ * A <Jx.Notice> subclass useful for displaying success messages
+ */
Jx.Notice.Success = new Class({
Extends: Jx.Notice,
options: {
- template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><img class="jxNoticeIcon" src="'+Jx.aPixel.src+'" title="Success"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="close this notice"></a></div></li>',
+ template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><img class="jxNoticeIcon" src="'+Jx.aPixel.src+'" title="Success"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="' + MooTools.lang.get('Jx','notice').closeTip + '"></a></div></li>',
klass: 'jxNoticeSuccess'
}
});
+/**
+ * Class: Jx.Notice.Success
+ * A <Jx.Notice> subclass useful for displaying warning messages
+ */
Jx.Notice.Warning = new Class({
Extends: Jx.Notice,
options: {
- template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><img class="jxNoticeIcon" src="'+Jx.aPixel.src+'" title="Warning"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="close this notice"></a></div></li>',
+ template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><img class="jxNoticeIcon" src="'+Jx.aPixel.src+'" title="Warning"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="' + MooTools.lang.get('Jx','notice').closeTip + '"></a></div></li>',
klass: 'jxNoticeWarning'
}
});
+/**
+ * Class: Jx.Notice.Error
+ * A <Jx.Notice> subclass useful for displaying error messages
+ */
Jx.Notice.Error = new Class({
Extends: Jx.Notice,
options: {
- template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><img class="jxNoticeIcon" src="'+Jx.aPixel.src+'" title="Error"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="close this notice"></a></div></li>',
+ template: '<li class="jxNoticeItemContainer"><div class="jxNoticeItem"><img class="jxNoticeIcon" src="'+Jx.aPixel.src+'" title="Error"><span class="jxNotice"></span><a class="jxNoticeClose" href="javascript:void(0);" title="' + MooTools.lang.get('Jx','notice').closeTip + '"></a></div></li>',
klass: 'jxNoticeError'
}
});
-
-
-
+// $Id: notifier.js 776 2010-03-22 14:35:16Z pagameba $
+/**
+ * Class: Jx.Notifier
+ *
+ * Extends: <Jx.ListView>
+ *
+ * Events:
+ *
+ * License:
+ * Copyright (c) 2009, DM Solutions Group.
+ *
+ * This file is licensed under an MIT style license
+ */
Jx.Notifier = new Class({
Family: 'Jx.Notifier',
@@ -31158,10 +36145,10 @@
listObj: 'jxNoticeList'
}),
- init: function () {
- this.parent();
- },
-
+ /**
+ * Method: render
+ * render the widget
+ */
render: function () {
this.parent();
@@ -31179,6 +36166,13 @@
}.bind(this));
},
+ /**
+ * APIMethod: add
+ * Add a new notice to the notifier
+ *
+ * Parameters:
+ * notice - {<Jx.Notice>} the notice to add
+ */
add: function (notice) {
if (!(notice instanceof Jx.Notice)) {
notice = new Jx.Notice({content: notice});
@@ -31187,36 +36181,89 @@
notice.show(this.listObj);
},
+ /**
+ * APIMethod: remove
+ * Add a new notice to the notifier
+ *
+ * Parameters:
+ * notice - {<Jx.Notice>} the notice to remove
+ */
remove: function (notice) {
if (this.domObj.hasChild(notice)) {
notice.removeEvents('close');
notice.hide();
}
}
-});Jx.Notifier.Float = new Class({
+});// $Id: notifier.float.js 776 2010-03-22 14:35:16Z pagameba $
+/**
+ * Class: Jx.Notice.Float
+ * A floating notice area for displaying notices, notices get chrome if
+ * the notifier has chrome
+ *
+ * Extends: <Jx.Notifier>
+ *
+ * Events:
+ *
+ * License:
+ * Copyright (c) 2009, DM Solutions Group.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Notifier.Float = new Class({
Family: 'Jx.Notifier.Float',
Extends: Jx.Notifier,
options: {
+ /**
+ * Option: chrome
+ * {Boolean} should the notifier have chrome - default true
+ */
chrome: true,
+ /**
+ * Option: fx
+ * {String} the effect to use when showing and hiding the notifier,
+ * default is null
+ */
fx: null,
+ /**
+ * Option: width
+ * {Integer} the width in pixels of the notifier, default is 250
+ */
width: 250,
+ /**
+ * Option: position
+ * {Object} position options to use with <Jx.Widget::position>
+ * for positioning the Notifier
+ */
position: {
horizontal: 'center center',
vertical: 'top top'
}
},
+ /**
+ * Method: render
+ * render the widget
+ */
render: function () {
this.parent();
this.domObj.setStyle('position','absolute');
if ($defined(this.options.width)) {
this.domObj.setStyle('width',this.options.width);
}
- this.position(this.domObj, this.options.parent, this.options.position);
+ this.position(this.domObj,
+ this.options.parent,
+ this.options.position);
},
+ /**
+ * APIMethod: add
+ * Add a new notice to the notifier
+ *
+ * Parameters:
+ * notice - {<Jx.Notice>} the notice to add
+ */
add: function(notice) {
if (!(notice instanceof Jx.Notice)) {
notice = new Jx.Notice({content: notice});
@@ -31224,8 +36271,189 @@
notice.options.chrome = this.options.chrome;
this.parent(notice);
}
-}); // $Id: $
+});// $Id: scrollbar.js 776 2010-03-22 14:35:16Z pagameba $
/**
+ * Class: Jx.Scrollbar
+ * Creates a custom scrollbar either vertically or horizontally (determined by
+ * options). These scrollbars are designed to be styled entirely through CSS.
+ *
+ * Copyright 2009 by Jonathan Bomgardner
+ * License: MIT-style
+ *
+ * Based in part on 'Mootools CSS Styled Scrollbar' on
+ * http://solutoire.com/2008/03/10/mootools-css-styled-scrollbar/
+ */
+Jx.Scrollbar = new Class({
+
+ Family: 'Jx.Scrollbar',
+
+ Extends: Jx.Widget,
+
+ Binds: ['scrollIt'],
+
+ options: {
+ /**
+ * Option: direction
+ * Determines which bars are visible. Valid options are 'horizontal'
+ * or 'vertical'
+ */
+ direction: 'vertical',
+ /**
+ * Option: useMouseWheel
+ * Whether to allow the mouse wheel to move the content. Defaults
+ * to true.
+ */
+ useMouseWheel: true,
+ /**
+ * Option: useScrollers
+ * Whether to show the scrollers. Defaults to true.
+ */
+ useScrollers: true,
+ /**
+ * Option: scrollerInterval
+ * The amount to scroll the content when using the scrollers.
+ * useScrollers option must be true. Default is 50 (px).
+ */
+ scrollerInterval: 50,
+ /**
+ * Option: template
+ * the HTML template for a scrollbar
+ */
+ template: '<div class="jxScrollbarContainer"><div class="jxScrollLeft"></div><div class="jxSlider"></div><div class="jxScrollRight"></div></div>'
+ },
+
+ classes: new Hash({
+ domObj: 'jxScrollbarContainer',
+ scrollLeft: 'jxScrollLeft',
+ scrollRight: 'jxScrollRight',
+ sliderHolder: 'jxSlider'
+ }),
+
+ el: null,
+ //element is the element we want to scroll.
+ parameters: ['element', 'options'],
+
+ /**
+ * Method: render
+ * render the widget
+ */
+ render: function () {
+ this.parent();
+ this.el = document.id(this.options.element);
+ if (this.el) {
+ this.el.addClass('jxHas'+this.options.direction.capitalize()+'Scrollbar');
+
+ //wrap content to make scroll work correctly
+ var children = this.el.getChildren();
+ this.wrapper = new Element('div',{
+ 'class': 'jxScrollbarChildWrapper'
+ });
+
+ /**
+ * the wrapper needs the same settings as the original container
+ * specifically, the width and height
+ */
+ this.wrapper.setStyles({
+ width: this.el.getStyle('width'),
+ height: this.el.getStyle('height')
+ });
+
+ children.inject(this.wrapper);
+ this.wrapper.inject(this.el);
+
+ this.domObj.inject(this.el);
+
+ var scrollSize = this.wrapper.getScrollSize();
+ var size = this.wrapper.getContentBoxSize();
+ this.steps = this.options.direction==='horizontal'?scrollSize.x-size.width:scrollSize.y-size.height;
+ this.slider = new Jx.Slider({
+ snap: false,
+ min: 0,
+ max: this.steps,
+ step: 1,
+ mode: this.options.direction,
+ onChange: this.scrollIt
+
+ });
+
+ if (!this.options.useScrollers) {
+ this.scrollLeft.dispose();
+ this.scrollRight.dispose();
+ //set size of the sliderHolder
+ if (this.options.direction === 'horizontal') {
+ this.sliderHolder.setStyle('width','100%');
+ } else {
+ this.sliderHolder.setStyle('height', '100%');
+ }
+
+ } else {
+ this.scrollLeft.addEvents({
+ mousedown: function () {
+ this.slider.slider.set(this.slider.slider.step - this.options.scrollerInterval);
+ this.pid = function () {
+ this.slider.slider.set(this.slider.slider.step - this.options.scrollerInterval);
+ }.periodical(1000, this);
+ }.bind(this),
+ mouseup: function () {
+ $clear(this.pid);
+ }.bind(this)
+ });
+ this.scrollRight.addEvents({
+ mousedown: function () {
+ this.slider.slider.set(this.slider.slider.step + this.options.scrollerInterval);
+ this.pid = function () {
+ this.slider.slider.set(this.slider.slider.step + this.options.scrollerInterval);
+ }.periodical(1000, this);
+ }.bind(this),
+ mouseup: function () {
+ $clear(this.pid);
+ }.bind(this)
+ });
+ //set size of the sliderHolder
+ var holderSize, scrollerRightSize, scrollerLeftSize;
+ if (this.options.direction === 'horizontal') {
+ scrollerRightSize = this.scrollRight.getMarginBoxSize().width;
+ scrollerLeftSize = this.scrollLeft.getMarginBoxSize().width;
+ holderSize = size.width - scrollerRightSize - scrollerLeftSize;
+ this.sliderHolder.setStyle('width', holderSize + 'px');
+ } else {
+ scrollerRightSize = this.scrollRight.getMarginBoxSize().height;
+ scrollerLeftSize = this.scrollLeft.getMarginBoxSize().height;
+ holderSize = size.height - scrollerRightSize - scrollerLeftSize;
+ this.sliderHolder.setStyle('height', holderSize + 'px');
+ }
+ }
+ document.id(this.slider).inject(this.sliderHolder);
+
+ //allows mouse wheel to function
+ if (this.options.useMouseWheel) {
+ $$(this.el, this.domObj).addEvent('mousewheel', function(e){
+ e = new Event(e).stop();
+ var step = this.slider.slider.step - e.wheel * 30;
+ this.slider.slider.set(step);
+ }.bind(this));
+ }
+
+ //stop slider if we leave the window
+ document.id(document.body).addEvent('mouseleave', function(){
+ this.slider.slider.drag.stop();
+ }.bind(this));
+
+ this.slider.start();
+ }
+ },
+
+ /**
+ * Method: scrollIt
+ * scroll the content in response to the slider being moved.
+ */
+ scrollIt: function (step) {
+ var x = this.options.direction==='horizontal'?step:0;
+ var y = this.options.direction==='horizontal'?0:step;
+ this.wrapper.scrollTo(x,y);
+ }
+}); // $Id: formatter.js 649 2009-11-30 22:19:48Z pagameba $
+/**
* Class: Jx.Formatter
*
* Extends: <Jx.Object>
@@ -31251,7 +36479,7 @@
* the needed formatting functionality.
*/
format: $empty
-});// $Id: $
+});// $Id: number.js 770 2010-03-18 21:12:28Z jonlb at comcast.net $
/**
* Class: Jx.Formatter.Number
*
@@ -31267,6 +36495,10 @@
* Example:
* (code)
* (end)
+ *
+ * MooTools.lang Keys:
+ * - 'formatter.number'.decimalSeparator
+ * - 'formatter.number'.thousandsSeparator
*
* License:
* Copyright (c) 2009, Jon Bomgardner.
@@ -31279,16 +36511,6 @@
options: {
/**
- * Option: decimalSeparator
- * Character to use as the decimal separator
- */
- decimalSeparator: '.',
- /**
- * Option: thousandSeparator
- * Character to use as the thousands separator
- */
- thousandsSeparator: ',',
- /**
* Option: precision
* The number of decimal places to round to
*/
@@ -31345,11 +36567,11 @@
for (var i = 0; i < l; i++) {
ret = ret + main.charAt(i);
if (i === left - 1 && i !== l - 1) {
- ret = ret + this.options.thousandsSeparator;
+ ret = ret + MooTools.lang.get('Jx','formatter.number').thousandsSeparator;
} else if (i >= left) {
j++;
if (j === 3 && i !== l - 1) {
- ret = ret + this.options.thousandsSeparator;
+ ret = ret + MooTools.lang.get('Jx','formatter.number').thousandsSeparator;
j = 0;
}
}
@@ -31360,7 +36582,7 @@
}
if (dec) {
- ret = ret + this.options.decimalSeparator + parts[1];
+ ret = ret + MooTools.lang.get('Jx','formatter.number').decimalSeparator + parts[1];
}
if (neg && this.options.useParens) {
ret = "(" + ret + ")";
@@ -31369,8 +36591,21 @@
}
return ret;
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ this.parent();
}
-});// $Id: $
+});// $Id: currency.js 770 2010-03-18 21:12:28Z jonlb at comcast.net $
/**
* Class: Jx.Formatter.Currency
*
@@ -31383,6 +36618,9 @@
* Example:
* (code)
* (end)
+ *
+ * MooTools.lang Keys:
+ * - 'formatter.currency'.sign
*
* License:
* Copyright (c) 2009, Jon Bomgardner.
@@ -31393,14 +36631,7 @@
Extends: Jx.Formatter.Number,
- options: {
- /**
- * Option: sign
- * The sign to use for this currency. Defaults to
- * the US '$'.
- */
- sign: "$"
- },
+ options: {},
/**
* APIMethod: format
* Takes a number and formats it as currency.
@@ -31422,14 +36653,27 @@
var ret;
if (neg && !this.options.useParens) {
- ret = "-" + this.options.sign + value.substring(1, value.length);
+ ret = "-" + MooTools.lang.get('Jx','formatter.currency').sign + value.substring(1, value.length);
} else {
- ret = this.options.sign + value;
+ ret = MooTools.lang.get('Jx','formatter.currency').sign + value;
}
return ret;
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ this.parent();
}
-});// $Id: $
+});// $Id: date.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Formatter.Date
*
@@ -31472,14 +36716,17 @@
var d = Date.parse(value);
return d.format(this.options.format);
}
-});// $Id: $
+});// $Id: uri.js 767 2010-03-17 19:35:02Z pagameba $
/**
- * Class: Jx.Formatter.Boolean
+ * Class: Jx.Formatter.URI
*
* Extends: <Jx.Formatter>
*
- * This class formats boolean values. You supply the
- * text values for true and false in the options.
+ * This class formats URIs using the mootools-more's
+ * URI extensions. See the -more docs for details of
+ * supported formats for parsing and formatting.
+ *
+ * @url http://mootools.net/docs/more/Native/URI
*
* Example:
* (code)
@@ -31490,24 +36737,79 @@
*
* This file is licensed under an MIT style license
*/
-Jx.Formatter.Boolean = new Class({
+Jx.Formatter.Uri = new Class({
Extends: Jx.Formatter,
options: {
/**
- * Option: true
- * The text to display for true values
+ * Option: format
+ * The format to use. See the mootools-more URI options
+ * to use within a {pattern}
+ * {string} will call the URI.toString() method
*/
- 'true': 'Yes',
- /**
- * Option: false
- * The text to display for false values
- */
- 'false': 'No'
+ format: '<a href="{string}" target="_blank">{host}</a>'
},
/**
* APIMethod: format
+ * Does the work of formatting dates
+ *
+ * Parameters:
+ * value - the text to format
+ */
+ format: function (value) {
+ var uri = new URI(value),
+ uriContent = {},
+ pattern = new Array(),
+ patternTmp = this.options.format.match(/\\?\{([^{}]+)\}/g);
+
+ // remove bracktes
+ patternTmp.each(function(e) {
+ pattern.push(e.slice(1, e.length-1));
+ });
+
+ // build object that contains replacements
+ for(var i = 0, j = pattern.length; i < j; i++) {
+ switch(pattern[i]) {
+ case 'string':
+ uriContent[pattern[i]] = uri.toString();
+ break;
+ default:
+ uriContent[pattern[i]] = uri.get(pattern[i]);
+ break;
+ }
+ }
+ return this.options.format.substitute(uriContent);
+ }
+});// $Id: boolean.js 770 2010-03-18 21:12:28Z jonlb at comcast.net $
+/**
+ * Class: Jx.Formatter.Boolean
+ *
+ * Extends: <Jx.Formatter>
+ *
+ * This class formats boolean values. You supply the
+ * text values for true and false in the options.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * MooTools.lang Keys:
+ * - 'formatter.boolean'.true
+ * - 'formatter.boolean'.false
+ *
+ * License:
+ * Copyright (c) 2009, Jon Bomgardner.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Formatter.Boolean = new Class({
+
+ Extends: Jx.Formatter,
+
+ options: {},
+ /**
+ * APIMethod: format
* Takes a value, determines boolean equivalent and
* displays the appropriate text value.
*
@@ -31534,10 +36836,23 @@
default:
b = true;
}
- return b ? this.options['true'] : this.options['false'];
+ return b ? MooTools.lang.get('Jx','formatter.boolean')['true'] : MooTools.lang.get('Jx','formatter.boolean')['false'];
+ },
+
+ /**
+ * APIMethod: changeText
+ * This method should be overridden by subclasses. It should be used
+ * to change any language specific default text that is used by the widget.
+ *
+ * Parameters:
+ * lang - the language being changed to or that had it's data set of
+ * translations changed.
+ */
+ changeText: function (lang) {
+ this.parent();
}
-});// $Id: $
+});// $Id: phone.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Formatter.Phone
*
@@ -31607,7 +36922,7 @@
ret = ret + v.substring(0, 3) + sep + v.substring(3);
return ret;
}
-});// $Id: $
+});// $Id: fieldset.js 701 2010-02-25 15:39:38Z pagameba $
/**
* Class: Jx.Fieldset
*
@@ -31724,7 +37039,7 @@
for (var x = 0; x < arguments.length; x++) {
field = arguments[x];
//add form to the field and field to the form if not already there
- if (!$defined(field.form) && $defined(this.form)) {
+ if ($defined(field.jxFamily) && !$defined(field.form) && $defined(this.form)) {
field.form = this.form;
this.form.addField(field);
}
@@ -31747,7 +37062,7 @@
}
});
-// $Id: $
+// $Id: checkbox.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Field.Check
*
@@ -31804,7 +37119,7 @@
sibling = this.field.getPrevious();
}
this.field.setStyle('visibility','hidden');
- this.field.inject($(document.body));
+ this.field.inject(document.id(document.body));
this.field.checked = true;
this.field.defaultChecked = true;
this.field.dispose();
@@ -31826,13 +37141,15 @@
* Sets the value property of the field
*
* Parameters:
- * v - The value to set the field to, "checked" if it should be checked.
+ * v - Whether the box shouldbe checked or not. "checked" or "true" if it should be checked.
*/
setValue : function (v) {
- if (v === 'checked') {
- this.field.set('checked', "checked");
- } else {
- this.field.erase('checked');
+ if (!this.options.readonly) {
+ if (v === 'checked' || v === 'true' || v === true) {
+ this.field.set('checked', "checked");
+ } else {
+ this.field.erase('checked');
+ }
}
},
@@ -31864,7 +37181,7 @@
}
});
-// $Id: $
+// $Id: radio.js 826 2010-03-31 18:46:16Z pagameba $
/**
* Class: Jx.Field.Radio
*
@@ -31920,7 +37237,7 @@
sibling = this.field.getPrevious();
}
this.field.setStyle('visibility','hidden');
- this.field.inject($(document.body));
+ this.field.inject(document.id(document.body));
this.field.checked = true;
this.field.defaultChecked = true;
this.field.dispose();
@@ -31945,10 +37262,12 @@
* v - The value to set the field to, "checked" it should be checked.
*/
setValue: function (v) {
- if (v === 'checked') {
- this.field.set('checked', "checked");
- } else {
- this.field.erase('checked');
+ if (!this.options.readonly) {
+ if (v === 'checked' || v === 'true' || v === true) {
+ this.field.set('checked', "checked");
+ } else {
+ this.field.erase('checked');
+ }
}
},
@@ -31983,7 +37302,7 @@
-// $Id: $
+// $Id: select.js 681 2010-01-15 05:45:28Z jonlb at comcast.net $
/**
* Class: Jx.Field.Select
*
@@ -32125,12 +37444,14 @@
* v - The value to set the field to.
*/
setValue: function (v) {
- //loop through the options and set the one that matches v
- $$(this.field.options).each(function (opt) {
- if (opt.get('value') === v) {
- document.id(opt).set("selected", true);
- }
- }, this);
+ if (!this.options.readonly) {
+ //loop through the options and set the one that matches v
+ $$(this.field.options).each(function (opt) {
+ if (opt.get('value') === v) {
+ document.id(opt).set("selected", true);
+ }
+ }, this);
+ }
},
/**
@@ -32140,13 +37461,27 @@
getValue: function () {
var index = this.field.selectedIndex;
//check for a set "value" attribute. If not there return the text
- var ret = this.field.options[index].get("value");
- if (!$defined(ret)) {
- ret = this.field.options[index].get("text");
+ if (index > -1) {
+ var ret = this.field.options[index].get("value");
+ if (!$defined(ret)) {
+ ret = this.field.options[index].get("text");
+ }
+ return ret;
}
- return ret;
+ },
+
+ /**
+ * APIMethod: empty
+ * Empties all options from this select
+ */
+ empty: function () {
+ if ($defined(this.field.options)) {
+ $A(this.field.options).each(function (option) {
+ this.field.remove(option);
+ }, this);
+ }
}
-});// $Id: $
+});// $Id: textarea.js 649 2009-11-30 22:19:48Z pagameba $
/**
* Class: Jx.Field.Textarea
*
@@ -32246,6 +37581,18 @@
options: {
/**
+ * Option: buttonClass
+ * choose the actual Jx.Button subclass to create for this form
+ * field. The default is to create a basic Jx.Button. To create
+ * a different kind of button, pass the class to this option, for
+ * instance:
+ * (code)
+ * buttonClass: Jx.Button.Color
+ * (end)
+ */
+ buttonClass: Jx.Button,
+
+ /**
* Option: buttonOptions
*/
buttonOptions: {},
@@ -32266,7 +37613,7 @@
processTemplate: function(template, classes, container) {
var h = this.parent(template, classes, container);
- this.button = new Jx.Button(this.options.buttonOptions);
+ this.button = new this.options.buttonClass(this.options.buttonOptions);
var c = h.get('jxInputButton');
if (c) {
this.button.domObj.replaces(c);
@@ -32277,8 +37624,245 @@
click: function() {
this.button.clicked();
}
-});// $Id: $
+});// $Id: jxcombo.js 826 2010-03-31 18:46:16Z pagameba $
/**
+ * Class: Jx.Field.Combo
+ *
+ * Extends: <Jx.Field>
+ *
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Events:
+ * change -
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Field.Combo = new Class({
+ Family: 'Jx.Field.Combo',
+ Extends: Jx.Field,
+
+ options: {
+ buttonTemplate: '<a class="jxButtonContainer jxButton" href="javascript:void(0);"><img class="jxButtonIcon" src="'+Jx.aPixel.src+'"></a>',
+ /* Option: template
+ */
+ template: '<span class="jxInputContainer"><label class="jxInputLabel"></label><span class="jxInputWrapper"><input type="text" class="jxInputCombo" name="{name}"><img class="jxInputIcon" src="'+Jx.aPixel.src+'"><span class="jxInputRevealer"></span></span><span class="jxInputTag"></span></span>'
+ },
+
+ type: 'Combo',
+
+ /**
+ * APIMethod: render
+ * create a new instance of Jx.Field.Combo
+ */
+ render: function() {
+ this.classes.combine({
+ wrapper: 'jxInputWrapper',
+ revealer: 'jxInputRevealer',
+ icon: 'jxInputIcon'
+ });
+ this.parent();
+
+ var button = new Jx.Button({
+ template: this.options.buttonTemplate,
+ imageClass: 'jxInputRevealerIcon'
+ }).addTo(this.revealer);
+
+ this.menu = new Jx.Menu();
+ this.menu.button = button;
+ this.buttonSet = new Jx.ButtonSet();
+
+ this.buttonSet = new Jx.ButtonSet({
+ onChange: (function(set) {
+ var button = set.activeButton;
+ var l = button.options.label;
+ if (l == ' ') {
+ l = '';
+ }
+ this.setLabel(l);
+ var img = button.options.image;
+ if (img.indexOf('a_pixel') != -1) {
+ img = '';
+ }
+ this.setImage(img);
+ if (this.options.imageClass && this.icon) {
+ this.icon.removeClass(this.options.imageClass);
+ }
+ if (button.options.imageClass && this.icon) {
+ this.options.imageClass = button.options.imageClass;
+ this.icon.addClass(button.options.imageClass);
+ }
+ this.fireEvent('change', this);
+ }).bind(this)
+ });
+ if (this.options.items) {
+ this.add(this.options.items);
+ }
+ button.addEvent('click', function(e) {
+ if (this.list.count() === 0) {
+ return;
+ }
+ if (!button.options.enabled) {
+ return;
+ }
+ this.contentContainer.setStyle('visibility','hidden');
+ this.contentContainer.setStyle('display','block');
+ document.id(document.body).adopt(this.contentContainer);
+ /* we have to size the container for IE to render the chrome correctly
+ * but just in the menu/sub menu case - there is some horrible peekaboo
+ * bug in IE related to ULs that we just couldn't figure out
+ */
+ this.contentContainer.setContentBoxSize(this.subDomObj.getMarginBoxSize());
+
+ this.showChrome(this.contentContainer);
+
+ this.position(this.contentContainer, this.button.domObj, {
+ horizontal: ['right right'],
+ vertical: ['bottom top', 'top bottom'],
+ offsets: this.chromeOffsets
+ });
+
+ this.contentContainer.setStyle('visibility','');
+
+ document.addEvent('mousedown', this.bound.mousedown);
+ document.addEvent('keyup', this.bound.keypress);
+
+ this.fireEvent('show', this);
+ }.bindWithEvent(this.menu));
+
+ this.menu.addEvents({
+ 'show': (function() {
+ //this.setActive(true);
+ }).bind(this),
+ 'hide': (function() {
+ //this.setActive(false);
+ }).bind(this)
+ });
+
+ this.addEvent('change', function(){
+ console.log('on change detected');
+ })
+ },
+
+ setLabel: function(label) {
+ if ($defined(this.field)) {
+ this.field.value = label;
+ }
+ },
+
+ setImage: function(url) {
+ if ($defined(this.icon)) {
+ this.icon.setStyle('background-image', 'url('+url+')');
+ }
+ if (!url) {
+ this.wrapper.addClass('jxInputIconHidden');
+ } else {
+ this.wrapper.removeClass('jxInputIconHidden');
+ }
+ },
+
+ /**
+ * Method: valueChanged
+ * invoked when the current value is changed
+ */
+ valueChanged: function() {
+ this.fireEvent('change', this);
+ },
+
+ /**
+ * Method: getValue
+ * returns the currently selected value
+ */
+ getValue: function() {
+ return this.options.label;
+ },
+
+ setValue: function(value) {
+ this.buttonSet.buttons.each(function(button){
+ if (button.options.label === value) {
+ button.setActive(true);
+ }
+ },this);
+ },
+
+ /**
+ * Method: onKeyPress
+ * Handle the user pressing a key by looking for an ENTER key to set the
+ * value.
+ *
+ * Parameters:
+ * e - {Event} the keypress event
+ */
+ onKeyPress: function(e) {
+ if (e.key == 'enter') {
+ this.valueChanged();
+ }
+ },
+
+ /**
+ * Method: add
+ * add a new item to the pick list
+ *
+ * Parameters:
+ * options - {Object} object with properties suitable to be passed to
+ * a <Jx.Menu.Item.Options> object. More than one options object can be
+ * passed, comma separated or in an array.
+ */
+ add: function() {
+ $A(arguments).flatten().each(function(opt) {
+ var button = new Jx.Menu.Item($merge(opt,{
+ toggle: true
+ }));
+ this.menu.add(button);
+ this.buttonSet.add(button);
+ if (opt.selected) {
+ this.buttonSet.setActiveButton(button);
+ }
+ }, this);
+ },
+
+ /**
+ * Method: remove
+ * Remove the item at the given index. Not implemented.
+ *
+ * Parameters:
+ * idx - {Mixed} the item to remove by reference or by index.
+ */
+ remove: function(idx) {
+ var item;
+ if ($type(idx) == 'number' && idx < this.buttonSet.buttons.length) {
+ item = this.buttonSet.buttons[idx];
+ } else if ($type(idx) == 'string'){
+ this.buttonSet.buttons.some(function(button){
+ if (button.options.label === idx) {
+ item = button;
+ return true;
+ }
+ return false;
+ },this);
+ }
+ if (item) {
+ this.buttonSet.remove(item);
+ this.menu.remove(item);
+ }
+ },
+ /**
+ * APIMethod: empty
+ * remove all values from the combo
+ */
+ empty: function() {
+ this.menu.empty();
+ this.buttonSet.empty();
+ this.setLabel('');
+ this.setImage(Jx.aPixel.src);
+ }
+});// $Id: password.js 649 2009-11-30 22:19:48Z pagameba $
+/**
* Class: Jx.Field.Password
*
* Extends: <Jx.Field.Text>
@@ -32303,4 +37887,163 @@
},
type: 'Password'
-});
\ No newline at end of file
+});/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+/**
+ * Class: Jx.Field.Color
+ *
+ * Extends: <Jx.Field>
+ *
+ * This class provides a Jx.Field.Text in combination with a Jx.Button.Color
+ * to have a Colorpicker with an input field.
+ *
+ * License:
+ * Copyright (c) 2010, Conrad Barthelmes.
+ *
+ * This file is licensed under an MIT style license
+ */
+ Jx.Field.Color = new Class({
+ Extends: Jx.Field,
+ Binds: ['changed','hide','keyup'],
+ type: 'Color',
+ options: {
+ buttonTemplate: '<a class="jxButtonContainer jxButton" href="javascript:void(0);"><img class="jxButtonIcon" src="'+Jx.aPixel.src+'"></a>',
+ /**
+ * Option: template
+ * The template used to render this field
+ */
+ template: '<span class="jxInputContainer"><label class="jxInputLabel"></label><span class="jxInputWrapper"><input type="text" class="jxInputColor" name="{name}"><img class="jxInputIcon" src="'+Jx.aPixel.src+'"><span class="jxInputRevealer"></span></span><span class="jxInputTag"></span></span>',
+ /**
+ * Option: showOnHover
+ * {Boolean} show the color palette when hovering over the input, default
+ * is false
+ */
+ showOnHover: false,
+ /**
+ * Option: showDelay
+ * set time in milliseconds when to show the color field on mouseenter
+ */
+ showDelay: 250,
+ /**
+ * Option: errorMsg
+ * error message for the validator.
+ */
+ errorMsg: 'Invalid Web-Color',
+ /**
+ * Option: color
+ * a color to initialize the field with, defaults to #000000
+ * (black) if not specified.
+ */
+ color: '#000000'
+
+ },
+ button: null,
+ validator: null,
+ render: function() {
+ this.classes.combine({
+ wrapper: 'jxInputWrapper',
+ revealer: 'jxInputRevealer',
+ icon: 'jxInputIcon'
+ });
+ this.parent();
+
+ var self = this;
+ if (!Jx.Field.Color.ColorPalette) {
+ Jx.Field.Color.ColorPalette = new Jx.ColorPalette(this.options);
+ }
+ this.button = new Jx.Button.Flyout({
+ template: this.options.buttonTemplate,
+ imageClass: 'jxInputRevealerIcon',
+ onBeforeOpen: function() {
+ if (Jx.Field.Color.ColorPalette.currentButton) {
+ Jx.Field.Color.ColorPalette.currentButton.hide();
+ }
+ Jx.Field.Color.ColorPalette.currentButton = this;
+ Jx.Field.Color.ColorPalette.addEvent('change', self.changed);
+ Jx.Field.Color.ColorPalette.addEvent('click', self.hide);
+ this.content.appendChild(Jx.Field.Color.ColorPalette.domObj);
+ Jx.Field.Color.ColorPalette.domObj.setStyle('display', 'block');
+ },
+ onOpen: function() {
+ /* setting these before causes an update problem when clicking on
+ * a second color button when another one is open - the color
+ * wasn't updating properly
+ */
+ Jx.Field.Color.ColorPalette.options.color = self.options.color;
+ Jx.Field.Color.ColorPalette.updateSelected();
+ }
+ }).addTo(this.revealer);
+
+ this.validator = new Jx.Plugin.Field.Validator({
+ validators: [{
+ validatorClass: 'colorHex',
+ validator: {
+ name: 'colorValidator',
+ options: {
+ validateOnChange: false,
+ errorMsg: self.options.errorMsg,
+ test: function(field,props) {
+ try {
+ var c = field.get('value').hexToRgb(true);
+ if(c == null) return false;
+ for(var i = 0; i < 3; i++) {
+ if(c[i].toString() == 'NaN') {
+ return false;
+ }
+ }
+ }catch(e) {
+ return false;
+ }
+ c = c.rgbToHex().toUpperCase();
+ self.setColor(c);
+ return true;
+ }
+ }
+ }
+ }],
+ validateOnBlur: true,
+ validateOnChange: true
+ });
+ this.validator.attach(this);
+ this.field.addEvent('keyup', this.onKeyUp.bind(this));
+ if (this.options.showOnHover) {
+ this.field.addEvent('mouseenter', function(ev) {
+ self.button.clicked.delay(self.options.showDelay, self.button);
+ });
+ }
+ this.setValue(this.options.color);
+ this.icon.setStyle('background-color', this.options.color);
+ //this.addEvent('change', self.changed);
+ },
+ onKeyUp : function(ev) {
+ var color = this.getValue();
+ if (color.substring(0,1) == '#') {
+ color = color.substring(1);
+ }
+ if (color.toLowerCase().match(/^[0-9a-f]{6}$/)) {
+ this.options.color = '#' +color.toUpperCase();
+ this.setColor(this.options.color);
+ }
+ },
+ setColor: function(c) {
+ this.options.color = c;
+ this.setValue(c);
+ this.icon.setStyle('background-color', c);
+ },
+ changed: function() {
+ var c = Jx.Field.Color.ColorPalette.options.color;
+ this.setColor(c);
+ },
+ hide: function() {
+ this.button.setActive(false);
+ Jx.Field.Color.ColorPalette.removeEvent('change', this.changed);
+ Jx.Field.Color.ColorPalette.removeEvent('click', this.hide);
+
+ this.button.hide();
+ Jx.Field.Color.ColorPalette.currentButton = null;
+ }
+ });
More information about the fusion-commits
mailing list