diff --git a/assets/mootools-core/CHANGELOG b/assets/mootools-core/CHANGELOG new file mode 100644 index 00000000..34b06874 --- /dev/null +++ b/assets/mootools-core/CHANGELOG @@ -0,0 +1,24 @@ +MooTools 1.2.1 - October 16th, 2008 + +[ADD] Element.set('html') now allows to set the innerHTML of all Elements (including tables and selects) +[ADD] Browser.Features.query to check if the Browser supports the new querySelector method on the document object +[ADD] Browser.Engine detection for WebKit version 525 +[ADD] Browser.Engine detection for Opera 9.6 +[ADD] Element.removeEvents now also accepts an object +[ADD] Class.removeEvents now also accepts an object +[ADD] Element.match now also accepts an Element +[CHG] Element.js has been refactored to make use of private variables wherever possible +[CHG] $unlink now returns an unlinked Hash instead of an object when a Hash is passed in +[CHG] Faster Element.hasChild +[CHG] The domready event for WebKit version 525 (or later) uses the native DomContentLoaded event +[FIX] Fixed getPosition in Internet Explorer to be faster and more reliable +[FIX] Selector [attribute!=val] now matches elements with empty attribute +[FIX] Element.clone is now much faster and retains state of form elements +[FIX] Fixed memory leaks related to IFrame unloading +[FIX] Fixed memory leaks related to Element storage +[FIX] Custom Events no longer stop the event when the condition returns false +[FIX] Documentation fixes and improvements +[FIX] :checked pseudo now works properly in Internet Explorer +[FIX] Class.js works in Safari 2 again, and contains no more eval hack +[FIX] Element text setter/getter is now working in Safari 2 +[FIX] $exec is now working in Safari 2 diff --git a/assets/mootools-core/Compatibility/Class/Class.js b/assets/mootools-core/Compatibility/Class/Class.js new file mode 100644 index 00000000..08a9db8d --- /dev/null +++ b/assets/mootools-core/Compatibility/Class/Class.js @@ -0,0 +1,8 @@ +Class.empty = $empty; + +//legacy .extend support + +Class.prototype.extend = function(properties){ + properties.Extends = this; + return new Class(properties); +}; diff --git a/assets/mootools-core/Compatibility/Core/Browser.js b/assets/mootools-core/Compatibility/Core/Browser.js new file mode 100644 index 00000000..d0656c55 --- /dev/null +++ b/assets/mootools-core/Compatibility/Core/Browser.js @@ -0,0 +1,9 @@ +window.extend = document.extend = function(properties){ + for (var property in properties) this[property] = properties[property]; +}; + +window[Browser.Engine.name] = window[Browser.Engine.name + Browser.Engine.version] = true; + +window.ie = window.trident; +window.ie6 = window.trident4; +window.ie7 = window.trident5; \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Core/Core.js b/assets/mootools-core/Compatibility/Core/Core.js new file mode 100644 index 00000000..db540984 --- /dev/null +++ b/assets/mootools-core/Compatibility/Core/Core.js @@ -0,0 +1,18 @@ +$A = function(iterable, start, length){ + if (Browser.Engine.trident && $type(iterable) == 'collection'){ + start = start || 0; + if (start < 0) start = iterable.length + start; + length = length || (iterable.length - start); + var array = []; + for (var i = 0; i < length; i++) array[i] = iterable[start++]; + return array; + } + start = (start || 0) + ((start < 0) ? iterable.length : 0); + var end = ((!$chk(length)) ? iterable.length : length) + start; + return Array.prototype.slice.call(iterable, start, end); +}; + +(function(){ + var natives = [Array, Function, String, RegExp, Number]; + for (var i = 0, l = natives.length; i < l; i++) natives[i].extend = natives[i].implement; +})(); \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Element/Element.Event.js b/assets/mootools-core/Compatibility/Element/Element.Event.js new file mode 100644 index 00000000..e240463d --- /dev/null +++ b/assets/mootools-core/Compatibility/Element/Element.Event.js @@ -0,0 +1 @@ +Event.keys = Event.Keys; \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Element/Element.Style.js b/assets/mootools-core/Compatibility/Element/Element.Style.js new file mode 100644 index 00000000..fdc62777 --- /dev/null +++ b/assets/mootools-core/Compatibility/Element/Element.Style.js @@ -0,0 +1,7 @@ +Element.implement({ + + setOpacity: function(op){ + return this.set('opacity', op); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Element/Element.js b/assets/mootools-core/Compatibility/Element/Element.js new file mode 100644 index 00000000..668d6f72 --- /dev/null +++ b/assets/mootools-core/Compatibility/Element/Element.js @@ -0,0 +1,47 @@ +Element.extend = Element.implement; + +Elements.extend = Elements.implement; + +Element.implement({ + + getFormElements: function(){ + return this.getElements('input, textarea, select'); + }, + + replaceWith: function(el){ + el = $(el); + this.parentNode.replaceChild(el, this); + return el; + }, + + removeElements: function(){ + return this.dispose(); + } + +}); + +Element.alias({'dispose': 'remove', 'getLast': 'getLastChild'}); + +Element.implement({ + + getText: function(){ + return this.get('text'); + }, + + setText: function(text){ + return this.set('text', text); + }, + + setHTML: function(){ + return this.set('html', arguments); + }, + + getHTML: function(){ + return this.get('html'); + }, + + getTag: function(){ + return this.get('tag'); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Fx/Fx.Morph.js b/assets/mootools-core/Compatibility/Fx/Fx.Morph.js new file mode 100644 index 00000000..0e8f59f8 --- /dev/null +++ b/assets/mootools-core/Compatibility/Fx/Fx.Morph.js @@ -0,0 +1,9 @@ +Fx.Styles = Fx.Morph; + +Element.implement({ + + effects: function(options){ + return new Fx.Morph(this, options); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Fx/Fx.Scroll.js b/assets/mootools-core/Compatibility/Fx/Fx.Scroll.js new file mode 100755 index 00000000..8f76d904 --- /dev/null +++ b/assets/mootools-core/Compatibility/Fx/Fx.Scroll.js @@ -0,0 +1,7 @@ +Fx.Scroll.implement({ + + scrollTo: function(y, x){ + return this.start(y, x); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Fx/Fx.Tween.js b/assets/mootools-core/Compatibility/Fx/Fx.Tween.js new file mode 100644 index 00000000..1ef9ee12 --- /dev/null +++ b/assets/mootools-core/Compatibility/Fx/Fx.Tween.js @@ -0,0 +1,11 @@ +Fx.Style = function(element, property, options){ + return new Fx.Tween(element, $extend({property: property}, options)); +}; + +Element.implement({ + + effect: function(property, options){ + return new Fx.Tween(this, $extend({property: property}, options)); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Fx/Fx.js b/assets/mootools-core/Compatibility/Fx/Fx.js new file mode 100755 index 00000000..8da142a7 --- /dev/null +++ b/assets/mootools-core/Compatibility/Fx/Fx.js @@ -0,0 +1,17 @@ +Fx.implement({ + + custom: function(from, to){ + return this.start(from, to); + }, + + clearTimer: function(){ + return this.cancel(); + }, + + stop: function(){ + return this.cancel(); + } + +}); + +Fx.Base = Fx; diff --git a/assets/mootools-core/Compatibility/Native/Array.js b/assets/mootools-core/Compatibility/Native/Array.js new file mode 100644 index 00000000..bec54f6d --- /dev/null +++ b/assets/mootools-core/Compatibility/Native/Array.js @@ -0,0 +1,9 @@ +Array.implement({ + + copy: function(start, length){ + return $A(this, start, length); + } + +}); + +Array.alias({erase: 'remove', combine: 'merge'}); \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Native/Function.js b/assets/mootools-core/Compatibility/Native/Function.js new file mode 100644 index 00000000..4486a35d --- /dev/null +++ b/assets/mootools-core/Compatibility/Native/Function.js @@ -0,0 +1,9 @@ +Function.extend({ + + bindAsEventListener: function(bind, args){ + return this.create({'bind': bind, 'event': true, 'arguments': args}); + } + +}); + +Function.empty = $empty; \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Native/Hash.js b/assets/mootools-core/Compatibility/Native/Hash.js new file mode 100644 index 00000000..2eeb1570 --- /dev/null +++ b/assets/mootools-core/Compatibility/Native/Hash.js @@ -0,0 +1,2 @@ +Hash.alias({getKeys: 'keys', getValues: 'values', has: 'hasKey', combine: 'merge'}); +var Abstract = Hash; \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Request/Request.JSON.js b/assets/mootools-core/Compatibility/Request/Request.JSON.js new file mode 100755 index 00000000..0217d265 --- /dev/null +++ b/assets/mootools-core/Compatibility/Request/Request.JSON.js @@ -0,0 +1,24 @@ +JSON.Remote = new Class({ + + options: { + key: 'json' + }, + + Extends: Request.JSON, + + initialize: function(url, options){ + this.parent(options); + this.onComplete = $empty; + this.url = url; + }, + + send: function(data){ + if (!this.check(data)) return this; + return this.parent({url: this.url, data: {json: Json.encode(data)}}); + }, + + failure: function(){ + this.fireEvent('failure', this.xhr); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Request/Request.js b/assets/mootools-core/Compatibility/Request/Request.js new file mode 100644 index 00000000..7f5abfec --- /dev/null +++ b/assets/mootools-core/Compatibility/Request/Request.js @@ -0,0 +1,37 @@ +Object.toQueryString = Hash.toQueryString; + +var XHR = new Class({ + + Extends: Request, + + options: { + update: false + }, + + initialize: function(url, options){ + this.parent(options); + this.url = url; + }, + + request: function(data){ + return this.send(this.url, data || this.options.data); + }, + + send: function(url, data){ + if (!this.check(url, data)) return this; + return this.parent({url: url, data: data}); + }, + + success: function(text, xml){ + text = this.processScripts(text); + if (this.options.update) $(this.options.update).empty().set('html', text); + this.onSuccess(text, xml); + }, + + failure: function(){ + this.fireEvent('failure', this.xhr); + } + +}); + +var Ajax = XHR; diff --git a/assets/mootools-core/Compatibility/Utilities/Cookie.js b/assets/mootools-core/Compatibility/Utilities/Cookie.js new file mode 100644 index 00000000..a1b1a214 --- /dev/null +++ b/assets/mootools-core/Compatibility/Utilities/Cookie.js @@ -0,0 +1,11 @@ +Cookie.set = function(key, value, options){ + return new Cookie(key, options).write(value); +}; + +Cookie.get = function(key){ + return new Cookie(key).read(); +}; + +Cookie.remove = function(key, options){ + return new Cookie(key, options).dispose(); +}; \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Utilities/JSON.js b/assets/mootools-core/Compatibility/Utilities/JSON.js new file mode 100644 index 00000000..97d1b35d --- /dev/null +++ b/assets/mootools-core/Compatibility/Utilities/JSON.js @@ -0,0 +1,4 @@ +var Json = JSON; + +JSON.toString = JSON.encode; +JSON.evaluate = JSON.decode; \ No newline at end of file diff --git a/assets/mootools-core/Compatibility/Utilities/Selectors.js b/assets/mootools-core/Compatibility/Utilities/Selectors.js new file mode 100644 index 00000000..0492b82a --- /dev/null +++ b/assets/mootools-core/Compatibility/Utilities/Selectors.js @@ -0,0 +1,39 @@ +Native.implement([Element, Document], { + + getElementsByClassName: function(className){ + return this.getElements('.' + className); + }, + + getElementsBySelector: function(selector){ + return this.getElements(selector); + } + +}); + +Elements.implement({ + + filterByTag: function(tag){ + return this.filter(tag); + }, + + filterByClass: function(className){ + return this.filter('.' + className); + }, + + filterById: function(id){ + return this.filter('#' + id); + }, + + filterByAttribute: function(name, operator, value){ + return this.filter('[' + name + (operator || '') + (value || '') + ']'); + } + +}); + +var $E = function(selector, filter){ + return ($(filter) || document).getElement(selector); +}; + +var $ES = function(selector, filter){ + return ($(filter) || document).getElements(selector); +}; \ No newline at end of file diff --git a/assets/mootools-core/Docs/Class/Class.Extras.md b/assets/mootools-core/Docs/Class/Class.Extras.md new file mode 100644 index 00000000..ba7878ab --- /dev/null +++ b/assets/mootools-core/Docs/Class/Class.Extras.md @@ -0,0 +1,398 @@ +Class: Chain {#Chain} +===================== + +A Utility Class which executes functions one after another, with each function firing after completion of the previous. +Its methods can be implemented with [Class:implement][] into any [Class][], and it is currently implemented in [Fx][] and [Request][]. +In [Fx][], for example, it is used to create custom, complex animations. + + + +Chain Method: constructor {#Chain:constructor} +---------------------------------------------- + + +### Syntax: + +#### For new classes: + + var MyClass = new Class({ Implements: Chain }); + +#### For existing classes: + + MyClass.implement(Chain); + +#### Stand alone + + var myChain = new Chain; + +### Example: + + var Todo = new Class({ + Implements: Chain, + initialize: function(){ + this.chain.apply(this, arguments); + } + }); + + var myTodoList = new Todo( + function(){ alert('get groceries'); }, + function(){ alert('go workout'); }, + function(){ alert('code mootools documentation until eyes close involuntarily'); }, + function(){ alert('sleep'); } + ); + +### See Also: + +- [Class][] + + + +Chain Method: chain {#Chain:chain} +---------------------------------- + +Adds functions to the end of the call stack of the Chain instance. + +### Syntax: + + myClass.chain(fn[, fn2[, fn3[, ...]]]); + +### Arguments: + +1. fn - (*function* or *array*) The function (or array of functions) to add to the chain call stack. Will accept and number of functions or arrays of functions. + +### Returns: + +* (*object*) The current Class instance. Calls to chain can also be chained. + +### Example: + //Fx.Tween has already implemented the Chain class because of inheritance of the Fx class. + var myFx = new Fx.Tween('myElement', {property: 'opacity'}); + myFx.start(1,0).chain( + //Notice that "this" refers to the calling object (in this case, the myFx object). + function(){ this.start(0,1); }, + function(){ this.start(1,0); }, + function(){ this.start(0,1); } + ); //Will fade the Element out and in twice. + + +### See Also: + +- [Fx][], [Fx.Tween][] + + + +Chain Method: callChain {#Chain:callChain} +------------------------------------------ + +Removes the first function of the Chain instance stack and executes it. The next function will then become first in the array. + +### Syntax: + + myClass.callChain([any arguments]); + +### Arguments: + +1. Any arguments passed in will be passed to the "next" function. + +### Returns: + +* (*mixed*) The return value of the "next" function or false when the chain was empty. + +### Example: + + var myChain = new Chain(); + myChain.chain( + function(){ alert('do dishes'); }, + function(){ alert('put away clean dishes'); } + ); + myChain.callChain(); //Will alert 'do dishes'. + myChain.callChain(); //Will alert 'put away clean dishes'. + + + +Chain Method: clearChain {#Chain:clearChain} +-------------------------------------------- + +Clears the stack of a Chain instance. + +### Syntax: + + myClass.clearChain(); + +### Returns: + +* (*object*) The current Class instance. + +### Example: + + var myFx = Fx.Tween('myElement', 'color'); //Fx.Tween inherited Fx's implementation of Chain. + myFx.chain(function(){ while(true) alert("D'oh!"); }); //Chains an infinite loop of alerts. + myFx.clearChain(); //Cancels the infinite loop of alerts before allowing it to begin. + +### See Also: + +- [Fx][], [Fx.Tween][] + + + +Class: Events {#Events} +======================= + +A Utility Class. Its methods can be implemented with [Class:implement][] into any [Class][]. +In [Fx][], for example, this Class is used to allow any number of functions to be added to the Fx events, like 'complete', 'start', and 'cancel'. +Events in a Class that implements [Events](#Events) must be either added as an option or with addEvent, not directly through .options.onEventName. + +### Syntax: + +#### For new classes: + + var MyClass = new Class({ Implements: Events }); + +#### For existing classes: + + MyClass.implement(Events); + +### Implementing: + +- This class can be implemented into other classes to add its functionality to them. +- Events has been designed to work well with the [Options](#Options) class. When the option property begins with 'on' and is followed by a capital letter it will be added as an event (e.g. 'onComplete' will add as 'complete' event). + +### Example: + + var Widget = new Class({ + Implements: Events, + initialize: function(element){ + // ... + }, + complete: function(){ + this.fireEvent('complete'); + } + }); + + var myWidget = new Widget(); + myWidget.addEvent('complete', myFunction); + +### Notes: + +- Events starting with 'on' are still supported in all methods and are converted to their representation without 'on' (e.g. 'onComplete' becomes 'complete'). + + +### See Also: + +- [Class][], [Options](#Options) + + + +Events Method: addEvent {#Events:addEvent} +------------------------------------------ + +Adds an event to the Class instance's event stack. + +### Syntax: + + myClass.addEvent(type, fn[, internal]); + +### Arguments: + +1. type - (*string*) The type of event (e.g. 'complete'). +2. fn - (*function*) The function to execute. +3. internal - (*boolean*, optional) Sets the function property: internal to true. Internal property is used to prevent removal. + +### Returns: + +* (*object*) This Class instance. + +### Example: + + var myFx = new Fx.Tween('element', 'opacity'); + myFx.addEvent('start', myStartFunction); + + +Events Method: addEvents {#Events:addEvents} +------------------------------------------ + +The same as [addEvent](#Events:addEvent), but accepts an object to add multiple events at once. + +### Syntax: + + myClass.addEvents(events); + +### Arguments: + +1. events - (*object*) An object with key/value representing: key the event name (e.g. 'start'), and value the function that is called when the Event occurs. + +### Returns: + +* (*object*) This Class instance. + +### Example: + + var myFx = new Fx.Tween('element', 'opacity'); + myFx.addEvents({ + 'start': myStartFunction, + 'complete': function() { + alert('Done.'); + } + }); + + + +Events Method: fireEvent {#Events:fireEvent} +-------------------------------------------- + +Fires all events of the specified type in the Class instance. + +### Syntax: + + myClass.fireEvent(type[, args[, delay]]); + +### Arguments: + +1. type - (*string*) The type of event (e.g. 'complete'). +2. args - (*mixed*, optional) The argument(s) to pass to the function. To pass more than one argument, the arguments must be in an array. +3. delay - (*number*, optional) Delay in miliseconds to wait before executing the event (defaults to 0). + +### Returns: + +* (*object*) This Class instance. + +### Example: + + var Widget = new Class({ + Implements: Events, + initialize: function(arg1, arg2){ + //... + this.fireEvent("initialize", [arg1, arg2], 50); + } + }); + + + +Events Method: removeEvent {#Events:removeEvent} +------------------------------------------------ + +Removes an event from the stack of events of the Class instance. + +### Syntax: + + myClass.removeEvent(type, fn); + +### Arguments: + +1. type - (*string*) The type of event (e.g. 'complete'). +2. fn - (*function*) The function to remove. + +### Returns: + +* (*object*) This Class instance. + +### Notes: + +- If the function has the property internal and is set to true, then the event will not be removed. + + +Events Method: removeEvents {#Events:removeEvents} +-------------------------------------------------- + +Removes all events of the given type from the stack of events of a Class instance. If no type is specified, removes all events of all types. + +### Syntax: + + myClass.removeEvents([events]); + +### Arguments: + +1. events - (optional) If not passed removes all events of all types. + - (*string*) The event name (e.g. 'success'). Removes all events of that type. + - (*object*) An object of type function pairs. Like the one passed to [addEvents](#Events:addEvents). + +### Returns: + +* (*object*) The current Class instance. + +### Example: + + var myFx = new Fx.Tween('myElement', 'opacity'); + myFx.removeEvents('complete'); + + +### Notes: + +- removeEvents will not remove internal events. See [Events:removeEvent][]. + + + +Class: Options {#Options} +========================= + +A Utility Class. Its methods can be implemented with [Class:implement][] into any [Class][]. +Used to automate the setting of a Class instance's options. +Will also add Class [Events](#Events) when the option property begins with 'on' and is followed by a capital letter (e.g. 'onComplete' adds a 'complete' event). + +### Syntax: + +#### For new classes: + + var MyClass = new Class({Implements: Options}); + +#### For existing classes: + + MyClass.implement(Options); + + + +Options Method: setOptions {#Options:setOptions} +------------------------------------------------ + +Merges the default options of the Class with the options passed in. + +### Syntax: + + myClass.setOptions([options]); + +### Arguments: + +1. options - (*object*, optional) The user defined options to merge with the defaults. + +### Returns: + +* (*object*) The current Class instance. + +### Example: + + var Widget = new Class({ + Implements: Options, + options: { + color: '#fff', + size: { + width: 100, + height: 100 + } + }, + initialize: function(options){ + this.setOptions(options); + } + }); + + var myWidget = new Widget({ + color: '#f00', + size: { + width: 200 + } + }); + + //myWidget.options is now: {color: #f00, size: {width: 200, height: 100}} + +### Notes: + +- Relies on the default options of a Class defined in its options property. +- If a Class has [Events](#Events) implemented, every option beginning with 'on' and followed by a capital letter (e.g. 'onComplete') becomes a Class instance event, assuming the value of the option is a function. + + +[Class]: /core/Class/Class +[Class:implement]: /core/Class/Class/#Class:implement +[Fx]: /core/Fx/Fx +[Fx.Tween]: /core/Fx/Fx.Tween +[Request]: /core/Request/Request +[Request.HTML]: /core/Request/Request.HTML +[Events:removeEvent]: /core/Element/Element.Event/#Element:removeEvent diff --git a/assets/mootools-core/Docs/Class/Class.md b/assets/mootools-core/Docs/Class/Class.md new file mode 100644 index 00000000..0125ced3 --- /dev/null +++ b/assets/mootools-core/Docs/Class/Class.md @@ -0,0 +1,125 @@ +Native: Class {#Class} +====================== + +The base Class of the [MooTools](http://mootools.net/) framework. + +Class Method: constructor {#Class:constructor} +---------------------------------------------- + +### Syntax: + + var MyClass = new Class(properties); + +### Arguments: + +1. properties - (*object*) The collection of properties that apply to the Class. Also accepts some special properties such as Extends, Implements, and initialize (see below). + +#### Property: Extends + +* (*class*) The Class that this class will extend. + +The methods of This Class that have the same name as the Extends Class, will have a parent property, that allows you to call the other overridden method. + +#### Property: Implements + +* (*object*) A passed object's properties will be copied into this Class. +* (*class*) The properties of a passed Class will be copied into the target Class. +* (*array*) An array of objects or Classes, the properties of which will be copied into this Class. + +Implements is similar to Extends, except that it overrides properties without inheritance. +Useful when implementing a default set of properties in multiple Classes. + +#### Property: initialize + +* (*function*) The initialize function will be the constructor for this class when new instances are created. + +### Returns: + +* (*class*) The created Class. + +### Examples: + +#### Class Example: + + var Cat = new Class({ + initialize: function(name){ + this.name = name; + } + }); + var myCat = new Cat('Micia'); + alert(myCat.name); //alerts 'Micia' + + var Cow = new Class({ + initialize: function(){ + alert('moooo'); + } + }); + var Effie = new Cow($empty); //Will not alert 'moooo', because the initialize method is overridden by the $empty function. + +#### Extends Example: + + var Animal = new Class({ + initialize: function(age){ + this.age = age; + } + }); + var Cat = new Class({ + Extends: Animal, + initialize: function(name, age){ + this.parent(age); //will call initalize of Animal + this.name = name; + } + }); + var myCat = new Cat('Micia', 20); + alert(myCat.name); //Alerts 'Micia'. + alert(myCat.age); //Alerts 20. + +#### Implements Example: + + var Animal = new Class({ + initialize: function(age){ + this.age = age; + } + }); + var Cat = new Class({ + Implements: Animal, + setName: function(name){ + this.name = name + } + }); + var myAnimal = new Cat(20); + myAnimal.setName('Micia'); + alert(myAnimal.name); //Alerts 'Micia'. + + + + +Class Method: implement {#Class:implement} +------------------------------------------ + +Implements the passed in properties into the base Class prototypes, altering the base Class. +The same as creating a [new Class](#Class:constructor) with the Implements property, but handy when you need to modify existing classes. + +### Syntax: + + MyClass.implement(properties); + +### Arguments: + +1. properties - (*object*) The properties to add to the base Class. + +### Examples: + + var Animal = new Class({ + initialize: function(age){ + this.age = age; + } + }); + Animal.implement({ + setName: function(name){ + this.name = name; + } + }); + var myAnimal = new Animal(20); + myAnimal.setName('Micia'); + alert(myAnimal.name); //alerts 'Micia' diff --git a/assets/mootools-core/Docs/Core/Browser.md b/assets/mootools-core/Docs/Core/Browser.md new file mode 100644 index 00000000..1bc9f6ad --- /dev/null +++ b/assets/mootools-core/Docs/Core/Browser.md @@ -0,0 +1,33 @@ +Hash: Browser {#Browser} +======================== + +Some browser properties are attached to the Browser Object for browser and platform detection. + +### Features: + +* Browser.Features.xpath - (*boolean*) True if the browser supports DOM queries using XPath. +* Browser.Features.xhr - (*boolean*) True if the browser supports native XMLHTTP object. + +### Engine: + +* Browser.Engine.trident - (*boolean*) True if the current browser uses the trident engine (e.g. Internet Explorer). +* Browser.Engine.gecko - (*boolean*) True if the current browser uses the gecko engine (e.g. Firefox, or any Mozilla Browser). +* Browser.Engine.webkit - (*boolean*) True if the current browser uses the webkit engine (e.g. Safari, Google Chrome, Konqueror). +* Browser.Engine.presto - (*boolean*) True if the current browser uses the presto engine (e.g. Opera 9). +* Browser.Engine.name - (*string*) The name of the engine. +* Browser.Engine.version - (*number*) The version of the engine. (e.g. 950) +* Browser.Plugins.Flash.version - (*number*) The major version of the flash plugin installed. +* Browser.Plugins.Flash.build - (*number*) The build version of the flash plugin installed. + +### Platform: + +* Browser.Platform.mac - (*boolean*) True if the platform is Mac. +* Browser.Platform.win - (*boolean*) True if the platform is Windows. +* Browser.Platform.linux - (*boolean*) True if the platform is Linux. +* Browser.Platform.ipod - (*boolean*) True if the platform is an iPod touch / iPhone. +* Browser.Platform.other - (*boolean*) True if the platform is neither Mac, Windows, Linux nor iPod. +* Browser.Platform.name - (*string*) The name of the platform. + +### Notes: + +- Engine detection is entirely feature-based. diff --git a/assets/mootools-core/Docs/Core/Core.md b/assets/mootools-core/Docs/Core/Core.md new file mode 100644 index 00000000..dd36eb03 --- /dev/null +++ b/assets/mootools-core/Docs/Core/Core.md @@ -0,0 +1,432 @@ +Core {#Core} +============ + +Core contains an handful of common sense functions used in [MooTools](http://mootools.net). +It also contains some basic [Hash][] and [Array][] methods. + +Function: $chk {#chk} +--------------------- + +Checks to see if a value exists or is 0. Useful for allowing 0. + +### Syntax: + + $chk(item); + +### Arguments: + +1. item - (*mixed*) The item to inspect. + +### Returns: + +* (*boolean*) If the object passed in exists or is 0, returns true. Otherwise, returns false. + +### Example: + + function myFunction(arg){ + if($chk(arg)) alert('The object exists or is 0.'); + else alert('The object is either null, undefined, false, or ""'); + } + + + +Function: $clear {#clear} +------------------------- + +Clears a Timeout or an Interval. Useful when working with [Function:delay][] and [Function:periodical][]. + +### Syntax: + + $clear(timer); + +### Arguments: + +1. timer - (*number*) The identifier of the setInterval (periodical) or setTimeout (delay) to clear. + +### Returns: + +* (*null*) returns null. + +### Example: + + var myTimer = myFunction.delay(5000); //Waits 5 seconds then executes myFunction. + myTimer = $clear(myTimer); //Cancels myFunction. + +### See also: + +- [Function:delay][] +- [Function:periodical][] + + + +Function: $defined {#defined} +----------------------------- + +Checks to see if a value is defined. + +### Syntax: + + $defined(obj); + +### Arguments: + +1. obj - (*mixed*) The object to inspect. + +### Returns: + +* (*boolean*) If the object passed is not null or undefined, returns true. Otherwise, returns false. + +### Example: + + function myFunction(arg){ + if($defined(arg)) alert('The object is defined.'); + else alert('The object is null or undefined.'); + } + + + +Function: $arguments {#arguments} +--------------------------------- + +Creates a function which returns the passed argument according to the index (i) passed. + +### Syntax: + + var argument = $arguments(i); + +### Arguments + +1. i - (*number*) The index of the argument to return. + +### Returns + +* (*function*) The function that returns a certain argument from the function's arguments. + +### Example: + + var secondArgument = $arguments(1); + alert(secondArgument('a','b','c')); //Alerts "b". + + + +Function: $empty {#empty} +------------------------- + +An empty function, that's it. Typically used for as a placeholder inside event methods of classes. + +### Syntax: + + var emptyFn = $empty; + +### Example: + + var myFunc = $empty; + +Function: $lambda {#lambda} +------------------------- + +Creates an empty function which does nothing but return the value passed. + +### Syntax: + + var returnTrue = $lambda(true); + +### Arguments + +1. value - (*mixed*) The value for the created function to return. + +### Returns + +* (*function*) A function which returns the desired value. + +### Example: + + myLink.addEvent('click', $lambda(false)); //Prevents a link Element from being clickable. + + +Function: $extend {#extend} +--------------------------- + +Copies all the properties from the second object passed in to the first object passed in. + +### Syntax: + + $extend(original, extension); + +### Arguments: + +1. original - (*object*) The object to be extended. +2. extension - (*object*) The object whose properties will be copied to original. + +### Returns: + +* (*object*) The first object passed in, extended. + +### Examples: + + var firstObj = { + 'name': 'John', + 'lastName': 'Doe' + }; + var secondObj = { + 'age': '20', + 'sex': 'male', + 'lastName': 'Dorian' + }; + $extend(firstObj, secondObj); + //firstObj is now: {'name': 'John', 'lastName': 'Dorian', 'age': '20', 'sex': 'male'}; + + + +Function: $merge {#merge} +------------------------- + +Merges any number of objects recursively without referencing them or their sub-objects. + +### Syntax: + + var merged = $merge(obj1, obj2[, obj3[, ...]]); + +### Arguments: + +1. (objects) Any number of objects. + +### Returns: + +* (*object*) The object that is created as a result of merging all the objects passed in. + +### Examples: + + var obj1 = {a: 0, b: 1}; + var obj2 = {c: 2, d: 3}; + var obj3 = {a: 4, d: 5}; + var merged = $merge(obj1, obj2, obj3); //returns {a: 4, b: 1, c: 2, d: 5}, (obj1, obj2, and obj3 are unaltered) + + var nestedObj1 = {a: {b: 1, c: 1}}; + var nestedObj2 = {a: {b: 2}}; + var nested = $merge(nestedObj1, nestedObj2); //returns: {a: {b: 2, c: 1}} + + + +Function: $each {#each} +----------------------- + +Used to iterate through iterables that are not regular arrays, such as built in getElementsByTagName calls, arguments of a function, or an object. + +### Syntax: + + $each(iterable, fn[, bind]); + +### Arguments: + +1. iterable - (*object* or *array*) The object or array to iterate through. +2. fn - (*function*) The function to test for each element. +3. bind - (*object*, optional) The object to use as 'this' within the function. For more information see [Function:bind][]. + +#### Argument: fn + +##### Syntax: + + fn(item, index, object) + +##### Arguments: + +1. item - (*mixed*) The current item in the array. +2. index - (*number*) The current item's index in the array. In the case of an object, it is passed the key of that item rather than the index. +3. object - (*mixed*) The actual array/object. + +### Examples: + +#### Array Example: + + $each(['Sun','Mon','Tue'], function(day, index){ + alert('name:' + day + ', index: ' + index); + }); //Alerts "name: Sun, index: 0", "name: Mon, index: 1", etc. + + +#### Object Example: + + //Alerts "The first day of the week is Sunday", "The second day of the week is Monday", etc: + $each({first: "Sunday", second: "Monday", third: "Tuesday"}, function(value, key){ + alert("The " + key + " day of the week is " + value); + }); + + + +Function: $pick {#pick} +----------------------- + +Returns the first defined argument passed in, or null. + +### Syntax: + + var picked = $pick(var1[, var2[, var3[, ...]]]); + +### Arguments: + +* (*mixed*) Any number of variables. + +### Returns: + +* (*mixed*) The first variable that is defined. +* (*null*) If all variables passed in are `null` or `undefined`, returns `null`. + +### Example: + + function say(infoMessage, errorMessage){ + alert($pick(errorMessage, infoMessage, 'There was no message supplied.')); + } + say(); //Alerts "There was no message supplied." + say("This is an info message."); //Alerts "This is an info message." + say("This message will be ignored.", "This is the error message."); //Alerts "This is the error message." + + + +Function: $random {#random} +--------------------------- + +Returns a random integer between the two passed in values. + +### Syntax: + + var random = $random(min, max); + +### Arguments: + +1. min - (*number*) The minimum value (inclusive). +2. max - (*number*) The maximum value (inclusive). + +### Returns: + +* (*number*) A random number between min and max. + +### Example: + + alert($random(5, 20)); //Alerts a random number between 5 and 20. + + + +Function: $splat {#splat} +------------------------- + +Converts the argument passed in to an array if it is defined and not already an array. + +### Syntax: + + var splatted = $splat(obj); + +### Arguments: + +1. obj - (*mixed*) Any type of variable. + +### Returns: + +* (*array*) If the variable passed in is an array, returns the array. Otherwise, returns an array with the only element being the variable passed in. + +### Example: + + $splat('hello'); //Returns ['hello']. + $splat(['a', 'b', 'c']); //Returns ['a', 'b', 'c']. + + + +Function: $time {#time} +----------------------- + +Returns the current time as a timestamp. + +### Syntax: + + var time = $time(); + +### Returns: + +* (*number*) - The current timestamp. + + + +Function: $try {#try} +--------------------- + +Tries to execute a number of functions. Returns immediately the return value of the first non-failed function without executing successive functions, or null. + +### Syntax: + + $try(fn[, fn, fn, fn, ...]); + +### Arguments: + +* fn - (*function*) The function to execute. + +### Returns: + +* (*mixed*) Standard return of the called function. +* (*null*) `null` if all the passed functions fail. + +### Examples: + + var result = $try(function(){ + return some.made.up.object; + }, function(){ + return jibberish.that.doesnt.exists; + }, function(){ + return false; + }); + + //result is false + + var failure, success; + + $try(function(){ + some.made.up.object = 'something'; + success = true; + }, function(){ + failure = true; + }); + + if (success) alert('yey!'); + +Function: $type {#type} +----------------------- + +Returns the type of object that matches the element passed in. + +### Syntax: + + $type(obj); + +### Arguments: + +1. obj - (*object*) The object to inspect. + +### Returns: + +* 'element' - (*string*) If object is a DOM element node. +* 'textnode' - (*string*) If object is a DOM text node. +* 'whitespace' - (*string*) If object is a DOM whitespace node. +* 'arguments' - (*string*) If object is an arguments object. +* 'array' - (*string*) If object is an array. +* 'object' - (*string*) If object is an object. +* 'string' - (*string*) If object is a string. +* 'number' - (*string*) If object is a number. +* 'date' - (*string*) If object is a date. +* 'boolean' - (*string*) If object is a boolean. +* 'function' - (*string*) If object is a function. +* 'regexp' - (*string*) If object is a regular expression. +* 'class' - (*string*) If object is a Class (created with new Class, or the extend of another class). +* 'collection' - (*string*) If object is a native htmlelements collection, such as childNodes, getElementsByTagName, etc. +* 'window' - (*string*) If object is the window object. +* 'document' - (*string*) If object is the document object. +* false - (*boolean*) If object is undefined, null, NaN or none of the above. + +### Example: + + var myString = 'hello'; + $type(myString); //Returns "string". + + +[Hash]: /core/Native/Hash +[Array]: /core/Native/Array +[Function:bind]: /core/Native/Function/#Function:bind +[Function:delay]: /core/Native/Function/#Function:delay +[Function:periodical]: /core/Native/Function/#Function:periodical diff --git a/assets/mootools-core/Docs/Element/Element.Dimensions.md b/assets/mootools-core/Docs/Element/Element.Dimensions.md new file mode 100644 index 00000000..db49a3db --- /dev/null +++ b/assets/mootools-core/Docs/Element/Element.Dimensions.md @@ -0,0 +1,192 @@ +Native: Element {#Element} +========================== + +Custom Native to allow all of its methods to be used with any DOM element via the dollar function [$][]. + +### Note: + +These methods don't take into consideration the body element margins and borders. +If you need margin/borders on the body, consider adding a wrapper div, but always reset the margin and borders of body to 0. + +### 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). + + +Element Method: scrollTo {#Element:scrollTo} +-------------------------------------------- + +Scrolls the element to the specified coordinated (if the element has an overflow). +The following method is also available on the Window object. + +### Syntax: + + myElement.scrollTo(x, y); + +### Arguments: + +1. x - (*number*) The x coordinate. +2. y - (*number*) The y coordinate. + +### Example: + + $('myElement').scrollTo(0, 100); + +### See Also: + +- [MDC Element:scrollLeft][], [MDC Element:scrollTop][] + + + + +Element Method: getSize {#Element:getSize} +------------------------------------------ + +Returns the height and width of the Element, taking into account borders and padding. +The following method is also available on the Window object. + +### Syntax: + + myElement.getSize(); + +### Returns: + +* (*object*) An object containing the width (as x) and the height (as y) of the target Element. + +### Example: + + var size = myElement.getSize(); + alert("The element is "+size.x+" pixels wide and "+size.y+"pixels high."); + + + + +Element Method: getScrollSize {#Element:getScrollSize} +------------------------------------------------------ + +Returns an Object representing the size of the target Element, including scrollable area. +The following method is also available on the Window object. + +### Syntax: + + myElement.getScrollSize(); + +### Returns: + +* (*object*) An object containing the x and y dimensions of the target Element. + +### Example: + + var scroll = $('myElement').getScrollSize(); + alert('My element can scroll to ' + scroll.y + 'px'); //alerts 'My element can scroll down to 820px' + +### See Also: + +- [MDC Element:scrollLeft][], [MDC Element:scrollTop][], [MDC Element:offsetWidth][], [MDC Element:offsetHeight][], [MDC Element:scrollWidth][], [MDC Element:scrollHeight][] + + + +Element Method: getScroll {#Element:getScroll} +---------------------------------------------- + +Returns an Object representing how far the target Element is scrolled in either direction. +The following method is also available on the Window object. + +### Syntax: + + myElement.getScroll(); + +### Returns: + +* (*object*) An object containing the x and y dimensions of the target Element's scroll. + +### Example: + + var scroll = $('myElement').getScroll(); + alert('My element is scrolled down ' + scroll.y + 'px'); //alerts 'My element is scrolled down to 620px' + + +Element Method: getPosition {#Element:getPosition} +-------------------------------------------------- + +Returns the real offsets of the element. + +### Syntax: + + myElement.getPosition(relative); + +### Arguments: + +relative - (Element, defaults to the document) If set, the position will be relative to this Element. + +### Returns: + +* (*object*) An object with the x and y coordinates of the Element's position. + +### Example: + + $('element').getPosition(); //returns {x: 100, y: 500}; + +### See Also: + +- [QuirksMode: Find position](http://www.quirksmode.org/js/findpos.html) + + +Element Method: getCoordinates {#Element:getCoordinates} +-------------------------------------------------------- + +Returns an object with width, height, left, right, top, and bottom coordinate values of the Element. + +### Syntax: + + myElement.getCoordinates(relative); + +### Arguments: + +relative - (*element*, optional) if set, the position will be relative to this element, otherwise relative to the document. + +### Returns: + +* (*object*) An object containing the Element's current: top, left, width, height, right, and bottom. + +### Example: + + var myValues = $('myElement').getCoordinates(); + +#### Returns: + + { + top: 50, + left: 100, + width: 200, + height: 300, + right: 300, + bottom: 350 + } + +### See Also: + +[Element:getPosition](#Element:getPosition) + + +Element Method: getOffsetParent {#Element:getOffsetParent} +---------------------------------------------------------- + +Returns the parent of the element that is positioned, if there is one. + +### Syntax + + myElement.getOffsetParent(); + +### Returns + +* (*mixed*) If the element has a parent that is positioned, it returns that element, otherwise it returns *null*. + +[$]: /core/Element/Element#dollar +[MDC Element:scrollLeft]: http://developer.mozilla.org/en/docs/DOM:element.scrollLeft +[MDC Element:scrollTop]: http://developer.mozilla.org/en/docs/DOM:element.scrollTop +[MDC Element:offsetWidth]: http://developer.mozilla.org/en/docs/DOM:element.offsetWidth +[MDC Element:offsetHeight]: http://developer.mozilla.org/en/docs/DOM:element.offsetHeight +[MDC Element:scrollWidth]: http://developer.mozilla.org/en/docs/DOM:element.scrollWidth +[MDC Element:scrollHeight]: http://developer.mozilla.org/en/docs/DOM:element.scrollHeight \ No newline at end of file diff --git a/assets/mootools-core/Docs/Element/Element.Event.md b/assets/mootools-core/Docs/Element/Element.Event.md new file mode 100644 index 00000000..9d1708a6 --- /dev/null +++ b/assets/mootools-core/Docs/Element/Element.Event.md @@ -0,0 +1,325 @@ +Native: Element {#Element} +========================== + +- Custom Native to allow all of its methods to be used with any DOM element via the dollar function [$][]. +- These methods are also available on window and document. + +### Notes: +- Internet Explorer fires element events in random order if they are not fired by [Element:fireEvent](#Element:fireEvent). + + +Element Method: addEvent {#Element:addEvent} +-------------------------------------------- + +Attaches an event listener to a DOM element. + +### Syntax: + + myElement.addEvent(type, fn); + +### Arguments: + +1. type - (*string*) The event name to monitor ('click', 'load', etc) without the prefix 'on'. +2. fn - (*function*) The function to execute. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### HTML: + +
Click me.
+ +##### JavaScript + + $('myElement').addEvent('click', function(){ + alert('clicked!'); + }); + +### Notes: + +- You can stop the Event by returning false in the listener or calling [Event:stop](#Event:stop). +- This method is also attached to Document and Window. + +### See Also: + +- [w3schools Event Attributes](http://www.w3schools.com/html/html_eventattributes.asp) + + + +Element Method: removeEvent {#Element:removeEvent} +-------------------------------------------------- + +Works as Element.addEvent, but instead removes the specified event listener. + +### Syntax: + + myElement.removeEvent(type, fn); + +### Arguments: + +1. type - (*string*) The event name. +2. fn - (*function*) The function to remove. + +### Returns: + +* (*element*) This Element. + +### Examples: + +#### Standard usage: + + var destroy = function(){ alert('Boom: ' + this.id); } // this refers to the Element. + $('myElement').addEvent('click', destroy); + + // later + $('myElement').removeEvent('click', destroy); + + +#### Examples with bind: + + var destroy = function(){ alert('Boom: ' + this.id); } + var boundDestroy = destroy.bind($('anotherElement')); + $('myElement').addEvent('click', boundDestroy); + + // later + $('myElement').removeEvent('click', destroy); // this won't remove the event. + $('myElement').removeEvent('click', destroy.bind($('anotherElement')); // this won't remove the event either. + $('myElement').removeEvent('click', boundDestroy); // this is the correct way to remove the event. + +### Notes: + +- When the function is added using [Function:bind][] or [Function:pass][], etc, a new reference is created. For removeEvent to work, you must pass a reference to the exact function to be removed. +- This method is also attached to Document and Window. + + + +Element Method: addEvents {#Element:addEvents} +---------------------------------------------- + +The same as [Element:addEvent](#Element:addEvent), but accepts an object to add multiple events at once. + +### Syntax: + + myElement.addEvents(events); + +### Arguments: + +1. events - (*object*) An object with key/value representing: key the event name, and value the function that is called when the Event occurs. + +### Returns: + +* (*element*) This Element. + +### Examples: + + $('myElement').addEvents({ + 'mouseover': function(){ + alert('mouseover'); + }, + 'click': function(){ + alert('click'); + } + }); + +### Notes: + +- This method is also attached to Document and Window. + +### See Also: + +- [Element:addEvent](#Element:addEvent) + + + +Element Method: removeEvents {#Element:removeEvents} +---------------------------------------------------- + +Removes all events of a certain type from an Element. If no argument is passed, removes all events of all types. + +### Syntax: + + myElements.removeEvents([events]); + +### Arguments: + +1. events - (optional) if not passed removes all events from the element. + - (*string*) The event name (e.g. 'click'). Removes all events of that type. + - (*object*) An object of type function pairs. Like the one passed to [Element:addEvent](#Element:addEvent). + +### Returns: + +* (*element*) This Element. + +### Examples: + + var myElement = $('myElement'); + myElement.addEvents({ + 'mouseover': function(){ + alert('mouseover'); + }, + 'click': function(){ + alert('click'); + } + }); + + myElement.addEvent('click', function(){ alert('clicked again'); }); + myElement.addEvent('click', function(){ alert('clicked and again :('); }); + //addEvent will keep appending each function. + //Unfortunately for the visitor, that'll be three alerts they'll have to click on. + myElement.removeEvents('click'); // This saves the visitor's finger by removing every click event. + +### Notes: + +- This method is also attached to Document and Window. + +### See Also: + +- [Element:removeEvent](#Element:removeEvent) + +Element Method: fireEvent {#Element:fireEvent} +---------------------------------------------- + +Executes all events of the specified type present in the Element. + +### Syntax: + + myElement.fireEvent(type[, args[, delay]]); + +### Arguments: + +1. type - (*string*) The event name (e.g. 'click') +2. args - (*mixed*, optional) Array or single object, arguments to pass to the function. If more than one argument, must be an array. +3. delay - (*number*, optional) Delay (in ms) to wait to execute the event. + +### Returns: + +* (*element*) This Element. + +### Examples: + // Fires all the added 'click' events and passes the Element 'anElement' after one second. + $('myElement').fireEvent('click', $('anElement'), 1000); + +### Notes: + +- This will not fire the DOM Event (this concerns all inline events ie. onmousedown=".."). +- This method is also attached to Document and Window. + +Element Method: cloneEvents {#Element:cloneEvents} +-------------------------------------------------- + +Clones all events from an Element to this Element. + +### Syntax: + + myElement.cloneEvents(from[, type]); + +### Arguments: + +1. from - (*element*) Copy all events from this Element. +2. type - (*string*, optional) Copies only events of this type. If null, copies all events. + +### Returns: + +* (*element*) This Element. + +### Examples: + + var myElement = $('myElement'); + var myClone = myElement.clone().cloneEvents(myElement); //clones the element and its events + +### Notes: + +- This method is also attached to Document and Window. + +### Hash: Element.Events + +You can add additional custom events by adding properties (objects) to the Element.Events Hash + +#### Arguments: + +The Element.Events.yourproperty (object) can have: + +1. base - (*string*, optional) the base event the custom event will listen to. Its not optional if condition is set. +2. condition - (*function*, optional) the condition from which we determine if the custom event can be fired. Is bound to the element you add the event to. The Event is passed in. +3. onAdd - (*function*, optional) the function that will get fired when the custom event is added. Is bound to the element you add the event to. +4. onRemove - (*function*, optional) the function that will get fired when the custom event is removed. Is bound to the element you add the event to. + +#### Examples: + + Element.Events.shiftclick = { + base: 'click', //we set a base type + condition: function(event){ //and a function to perform additional checks. + return (event.shift == true); //this means the event is free to fire + } + }; + + $('myInput').addEvent('shiftclick', function(event){ + log('the user clicked the left mouse button while holding the shift key'); + }); + +#### Notes: + +- There are different types of custom Events you can create: + + 1. Custom Events with only base: they will just be a redirect to the base event. + 2. Custom Events with base and condition: they will be redirect to the base event, but only fired if the condition is met. + 3. Custom Events with onAdd and/or onRemove and any other of the above: they will also perform additional functions when the event is added/removed. + +#### Warning: + +If you use the condition option you NEED to specify a base type, unless you plan to overwrite a native event. +(highly unrecommended: use only when you know exactly what you're doing). + +Custom Events +------------- + +### Event: mouseenter + +This event fires when the mouse enters the area of the DOM Element and will not be fired again if the mouse crosses over children of the Element (unlike mouseover). + +#### Examples: + + $('myElement').addEvent('mouseenter', myFunction); + +#### See Also: + +- [Element:addEvent](#Element:addEvent) + +### Event: mouseleave + +This event fires when the mouse leaves the area of the DOM Element and will not be fired if the mouse crosses over children of the Element (unlike mouseout). + +#### Examples: + + $('myElement').addEvent('mouseleave', myFunction); + +#### See Also: + +- [Element:addEvent](#Element:addEvent) + +### Event: mousewheel + +This event fires when the mouse wheel is rotated; + +#### Examples: + + $('myElement').addEvent('mousewheel', myFunction); + +#### Notes: + +- This custom event just redirects DOMMouseScroll (Mozilla) to mousewheel (Opera, Internet Explorer), making it work across browsers. + +#### See Also: + +- [Element:addEvent](#Element:addEvent) + + + +[$]: /core/Element/#dollar +[Function]: /core/Native/Function +[Function:bind]: /core/Native/Function/#Function:bind +[Function:pass]: /core/Native/Function/#Function:pass +[Function:delay]: /core/Native/Function/#Function:delay \ No newline at end of file diff --git a/assets/mootools-core/Docs/Element/Element.Style.md b/assets/mootools-core/Docs/Element/Element.Style.md new file mode 100644 index 00000000..c92e986d --- /dev/null +++ b/assets/mootools-core/Docs/Element/Element.Style.md @@ -0,0 +1,122 @@ +Native: Element {#Element} +========================== + +Custom Native to allow all of its methods to be used with any DOM element via the dollar function [$][]. + + + +Element Method: setStyle {#Element:setStyle} +-------------------------------------------- + +Sets a CSS property to the Element. + +### Syntax: + + myElement.setStyle(property, value); + +### Arguments: + +1. property - (*string*) The property to set. +2. value - (*mixed*) The value to which to set it. Numeric values of properties requiring a unit will automatically be appended with 'px'. + +### Returns: + +* (*element*) This element. + +### Example: + //Both lines have the same effect. + $('myElement').setStyle('width', '300px'); //The width is now 300px. + $('myElement').setStyle('width', 300); //The width is now 300px. + +### Notes: + +- All number values will automatically be rounded to the nearest whole number. + + + +Element Method: getStyle {#Element:getStyle} +-------------------------------------------- + +Returns the style of the Element given the property passed in. + +### Syntax: + + var style = myElement.getStyle(property); + +### Arguments: + +1. property - (*string*) The css style property you want to retrieve. + +### Returns: + +* (*string*) The style value. + +### Examples: + + $('myElement').getStyle('width'); //Returns "300px". + $('myElement').getStyle('width').toInt(); //Returns 300. + + + +Element Method: setStyles {#Element:setStyles} +---------------------------------------------- + +Applies a collection of styles to the Element. + +### Syntax: + + myElement.setStyles(styles); + +### Arguments: + +1. styles - (*object*) An object of property/value pairs for all the styles to apply. + +### Returns: + +* (*element*) This element. + +### Example: + + $('myElement').setStyles({ + border: '1px solid #000', + width: 300, + height: 400 + }); + +### See Also: + +- [Element:getStyle][] + + + +Element Method: getStyles {#Element:getStyles} +---------------------------------------------- + +Returns an object of styles of the Element for each argument passed in. + +### Syntax: + + var styles = myElement.getStyles(property[, property2[, property3[, ...]]]); + +### Arguments: + +1. properties - (*strings*) Any number of style properties. + +### Returns: + +* (*object*) An key/value object with the CSS styles as computed by the browser. + +### Examples: + + $('myElement').getStyles('width', 'height', 'padding'); + //returns {width: "10px", height: "10px", padding: "10px 0px 10px 0px"} + +### See Also: + +- [Element:getStyle][] + + + +[$]: /core/Element/Element/#dollar +[Function]: /core/Native/Function +[Element:getStyle]: #Element:getStyle \ No newline at end of file diff --git a/assets/mootools-core/Docs/Element/Element.md b/assets/mootools-core/Docs/Element/Element.md new file mode 100644 index 00000000..0726dac6 --- /dev/null +++ b/assets/mootools-core/Docs/Element/Element.md @@ -0,0 +1,1788 @@ +Native: Window {#Window} +======================== + +The following functions are treated as Window methods. + + +Function: $ {#dollar} +--------------------- + +The dollar function has a dual purpose: Getting the element by its id, and making an element in Internet Explorer "grab" all the [Element][] methods. + +### Syntax: + + var myElement = $(el); + +### Arguments: + +1. el - The Element to be extended. Can be one of the following types: + * (*element*) The element will be extended if it is not already. + * (*string*) A string containing the id of the DOM element desired. + * (*object*) If the object has a toElement method, toElement will be called to get the Element. + +### Returns: + +* (*element*) A DOM element. +* (*null*) Null if no matching id was found or if toElement did not return an element. + +### Examples: + +#### Get a DOM Element by ID: + + var myElement = $('myElement'); + +#### Get a DOM Element by reference: + + var div = document.getElementById('myElement'); + div = $(div); //The element with all the Element methods applied. + +### Notes: + +- This method is useful when it's unclear if working with an actual element or an id. It also serves as a shorthand for document.getElementById(). +- In Internet Explorer, the [Element][] is extended the first time $ is called on it, and all the [Element][] Methods become available. +- Browsers with native HTMLElement support, such as Safari, Firefox, and Opera, apply all the [Element][] Methods to every DOM element automatically. +- Because MooTools detects if an element needs to be extended or not, this function may be called on the same Element many times with no ill effects. + + + +Function: $$ {#dollars} +----------------------- + +Selects and extends DOM elements. Elements arrays returned with $$ will also accept all the [Element][] methods. + +### Syntax: + + var myElements = $$(aTag[, anElement[, Elements[, ...]); + +### Arguments: + +* Any number of the following as arguments are accepted: + * HTMLCollections, + * arrays of elements, + * elements, or + * strings as selectors. + +### Returns: + +* (*array*) - An array of all the DOM elements matched, extended with [$][]. + +### Examples: + +#### Get Elements by Their Tag Names: + + $$('a'); //Returns all anchor elements in the page. + $$('a', 'b'); //Returns all anchor and bold tags on the page. + +#### Using CSS Selectors When [Selectors][] is Included: + + $$('#myElement'); //Returns an array containing only the element with the id 'myElement'. + $$('#myElement a.myClass'); //Returns an array of all anchor tags with the class 'myClass' within the DOM element with id 'myElement'. + +#### More Complex $$ Usage: + + //Creates an array of all elements and selectors passed as arguments. + $$(myelement1, myelement2, 'a', '#myid, #myid2, #myid3', document.getElementsByTagName('div')); + +### Notes: + +- When [Selectors][] is loaded, [$$][] will also accept CSS Selectors. Otherwise, the only selectors supported are tag names. +- If an expression doesn't find any elements, an empty array will be returned. +- The return type of element methods run through [$$][] is always an array, regardless of the amount of results. + +### See Also: + +- See [Selectors][] for documentation on selectors for use anywhere they are accepted throughout the framework. + + + +Native: Element {#Element} +========================== + +Custom Native to allow all of its methods to be used with any extended DOM Element. + + + +Element Method: constructor {#Element:constructor} +-------------------------------------------------- + +Creates a new Element of the type passed in. + +### Syntax: + + var myEl = new Element(element[, properties]); + +### Arguments: + +1. element - (*mixed*) The tag name for the Element to be created or an actual DOM element. +2. properties - (*object*, optional) Calls the Single Argument version of [Element:set][] with the properties object passed in. + +### Returns: + +* (*element*) A new MooTools extended HTML Element. + +### Examples: + + var myAnchor = new Element('a', { + 'href': 'http://mootools.net', + 'class': 'myClass', + 'html': 'Click me!', + 'styles': { + 'display': 'block', + 'border': '1px solid black' + }, + 'events': { + 'click': function(){ + alert('clicked'); + }, + 'mouseover': function(){ + alert('mouseovered'); + } + } + }); + +### See Also: + +- [$][], [Element:set][] + + + +Element Method: getElement {#Element:getElement} +------------------------------------------------ + +Gets the first descendant element whose tag name matches the tag provided. If [Selectors][] is included, CSS selectors may also be passed. + +### Syntax: + + var myElement = myElement.getElement(tag); + +### Arguments: + +1. tag - (*string*) Tag name of the element to find. + +### Returns: + +* (*mixed*) If a match is found, the Element will be returned. Otherwise, returns null. + +### Examples: + + var firstDiv = $(document.body).getElement('div'); + +### Notes: + +- This method is also available for Document instances. +- This method gets replaced when [Selectors][] is included. +- [Selectors][] enhances [Element:getElement][] so that it matches based on CSS selectors. + +### See Also: + +- See [Selectors][] for documentation on selectors for use anywhere they are accepted throughout the framework. + + + +Element Method: getElements {#Element:getElements} +-------------------------------------------------- + +Collects all decedent elements whose tag name matches the tag provided. If [Selectors][] is included, CSS selectors may also be passed. + +### Syntax: + + var myElements = myElement.getElements(tag); + +### Arguments: + +1. tag - (*string*) String of the tag to match. + +### Returns: + +* (*array*) An [Elements][] array of all matched Elements. + +### Examples: + + var allAnchors = $(document.body).getElements('a'); + +### Notes: + +- This method is also available for Document instances. +- This method gets replaced when [Selectors][] is included. +- [Selectors][] enhances [Element:getElements][] so that it matches based on CSS selectors. + +### See Also: + +- See [Selectors][] for documentation on selectors for use anywhere they are accepted throughout the framework. + + + +Element Method: getElementById {#Element:getElementById} +-------------------------------------------------------- + +Gets the element with the specified id found inside the current Element. + +### Syntax: + + var myElement = anElement.getElementById(id); + +### Arguments: + +1. id - (*string*) The ID of the Element to find. + +### Returns: + +* (*mixed*) If a match is found, returns that Element. Otherwise, returns null. + +### Examples: + + var myChild = $('myParent').getElementById('myChild'); + +### Notes: + +- This method is not provided for Document instances as document.getElementById is provided natively. + + + +Element Method: set {#Element:set} +---------------------------- + +This is a "dynamic arguments" method. Properties passed in can be any of the 'set' properties in the [Element.Properties][] Hash. + +### Syntax: + + myElement.set(arguments); + +### Arguments: + +- Two Arguments (property, value) + 1. property - (*string*) The string key from the [Element.Properties][] Hash representing the property to set. + 2. value - (*mixed*) The value to set for the specified property. +- One Argument (properties) + 1. properties - (*object*) Object with its keys/value pairs representing the properties and values to set for the Element (as described below). + +### Returns: + +* (*element*) This Element. + +### Examples: + +#### With Property and Value: + + $('myElement').set('text', 'text goes here'); + $('myElement').set('class', 'active'); + //The 'styles' property passes the object to Element:setStyles. + var body = $(document.body).set('styles', { + 'font': '12px Arial', + 'color': 'blue' + }); + +#### With an Object: + + var myElement = $('myElement').set({ + //The 'styles' property passes the object to Element:setStyles. + 'styles': { + 'font': '12px Arial', + 'color': 'blue', + 'border': '1px solid #f00' + }, + //The 'events' property passes the object to Element:addEvents. + 'events': { + 'click': function(){ alert('click'); }, + 'mouseover': function(){ this.addClass('over') } + }, + //Any other property uses Element:setProperty. + 'id': 'documentBody' + }); + +### Notes: + +- All the property arguments are passed to the corresponding method of the [Element.Properties][] Hash. +- If no matching property is found in [Element.Properties][], it falls back to [Element:setProperty][]. +- Whenever using [Element:setProperty][] to set an attribute, pass in the lowercase, simplified form of the property. For example: + - use 'for', not 'htmlFor', + - use 'class', not 'className' + - use 'frameborder', not 'frameBorder' + - etc. + + +### See Also: + +- [Element][], [Element.Properties][], [Element:setProperty][], [Element:addEvents][], [Element:setStyles][] + + + +Element Method: get {#Element:get} +---------------------------------- + +This is a "dynamic arguments" method. Properties passed in can be any of the 'get' properties in the [Element.Properties][] Hash. + +### Syntax: + + myElement.get(property); + +### Arguments: + +1. property - (*string*) The string key from the [Element.Properties][] Hash representing the property to get. + +### Returns: + +* (*mixed*) The result of calling the corresponding 'get' function in the [Element.Properties][] Hash. + +### Examples: + +#### Using Custom Getters: + + var tag = $('myDiv').get('tag'); //Returns "div". + +#### Fallback to Element Attributes: + + var id = $('myDiv').get('id'); //Returns "myDiv". + var value = $('myInput').get('value'); //Returns the myInput element's value. + +### Notes: + +- If the corresponding accessor doesn't exist in the [Element.Properties][] Hash, the result of [Element:getProperty][] on the property passed in is returned. + +### See Also: + +- [Element][], [Element.Properties][], [Element:getProperty][] + + + +Element Method: erase {#Element:erase} +-------------------------------------- + +This is a "dynamic arguments" method. Properties passed in can be any of the 'erase' properties in the [Element.Properties][] Hash. + +### Syntax: + + myElement.erase(property); + +### Arguments: + +1. property - (*string*) The string key from the [Element.Properties][] Hash representing the property to erase. + +### Returns: + +* (*mixed*) The result of calling the corresponding 'erase' function in the [Element.Properties][] Hash. + +### Examples: + + $('myDiv').erase('id'); //Removes the id from myDiv. + $('myDiv').erase('class'); //myDiv element no longer has any class names set. + +### Note: + +- If the corresponding eraser doesn't exist in the [Element.Properties][] Hash, [Element:removeProperty][] is called with the property passed in. + +### See Also: + +- [Element][], [Element.Properties][], [Element:removeProperty][] + + + +Element Method: match {#Element:match} +-------------------------------------- + +Tests this Element to see if it matches the argument passed in. + +### Syntax: + + myElement.match(match); + +### Arguments: + +1. match - can be a string or element + - (*string*) The tag name to test against this element. If [Selectors][] is included, any single CSS selectors may also be passed. + - (*element*) An element to match; returns true if this is the actual element passed in. + +### Returns: + +* (*boolean*) If the element matched, returns true. Otherwise, returns false. + +### Examples: + +#### Using a Tag Name: + + //Returns true if #myDiv is a div. + $('myDiv').match('div'); + +#### Using a CSS Selector: + + //Returns true if #myDiv has the class foo and is named "bar" + $('myDiv').match('.foo[name=bar]'); + +#### Using an Element: + + var el = $('myDiv'); + $('myDiv').match(el); //Returns true + $('otherElement').match(el); //Returns false + + + +Element Method: inject {#Element:inject} +---------------------------------------- + +Injects, or inserts, the Element at a particular place relative to the Element's children (specified by the second the argument). + +### Syntax: + + myElement.inject(el[, where]); + +### Arguments: + +1. el - (*mixed*) el can be the id of an element or an element. +2. where - (*string*, optional: defaults to 'bottom') The place to inject this Element. Can be 'top', 'bottom', 'after', or 'before'. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### JavaScript + + var myFirstElement = new Element('div', {id: 'myFirstElement'}); + var mySecondElement = new Element('div', {id: 'mySecondElement'}); + var myThirdElement = new Element('div', {id: 'myThirdElement'}); + +##### Resulting HTML + +
+
+
+ +#### Inject to the bottom: + +##### JavaScript + + myFirstElement.inject(mySecondElement); + +##### Resulting HTML + +
+
+
+ +#### Inject to the top: + +##### JavaScript + + myThirdElement.inject(mySecondElement, 'top'); + +##### Resulting HTML + +
+
+
+
+ +#### Inject before: + +##### JavaScript + + myFirstElement.inject(mySecondElement, 'before'); + +##### Resulting HTML + +
+
+ +#### Inject After: + +##### JavaScript + + myFirstElement.inject(mySecondElement, 'after'); + +##### Resulting HTML + +
+
+ +### See Also: + +[Element:adopt](#Element:adopt), [Element:grab](#Element:grab), [Element:wraps](#Element:wraps) + + + +Element Method: grab {#Element:grab} +------------------------------------ + +Works as [Element:inject](#Element:inject), but in reverse. + +Appends the Element at a particular place relative to the Element's children (specified by the where parameter). + +### Syntax: + + myElement.grab(el[, where]); + +### Arguments: + +1. el - (*mixed*) el can be the id of an element or an Element. +2. where - (*string*, optional: default 'bottom') The place to append this Element. Can be 'top' or 'bottom'. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### JavaScript + + var myFirstElement = new Element('div', {id: 'myFirstElement'}); + var mySecondElement = new Element('div', {id: 'mySecondElement'}); + + myFirstElement.grab(mySecondElement); + +##### Resulting HTML + +
+
+
+ +### See Also: + +[Element:adopt](#Element:adopt), [Element:inject](#Element:inject), [Element:wraps](#Element:wraps) + + + +Element Method: adopt {#Element:adopt} +-------------------------------------- + +Works like [Element:grab](#Element:grab), but allows multiple elements to be adopted. + +Inserts the passed element(s) inside the Element (which will then become the parent element). + +### Syntax: + + myParent.adopt(el[, others]); + +### Arguments: + +1. el - (*mixed*) The id of an element, an Element, or an array of elements. +2. others - (*mixed*, optional) One or more additional Elements separated by a comma or as an array. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### JavaScript + + var myFirstElement = new Element('div', {id: 'myFirstElement'}); + var mySecondElement = new Element('a', {id: 'mySecondElement'}); + var myThirdElement = new Element('ul', {id: 'myThirdElement'}); + + myParent.adopt(myFirstElement); + myParent2.adopt(myFirstElement, 'mySecondElement'); + myParent3.adopt([myFirstElement, mySecondElement, myThirdElement]); + +##### Resulting HTML + +
+
+
+
+
+ +
+
+ + +### See Also: + +[Element:grab](#Element:grab), [Element:inject](#Element:inject), [Element:wraps](#Element:wraps) + + + +Element Method: wraps {#Element:wraps} +-------------------------------------- + +Works like [Element:grab](#Element:grab), but instead of moving the grabbed element from its place, this method moves this Element around its target. + +The Element is moved to the position of the passed element and becomes the parent. + +### Syntax: + + myParent.wraps(el[, where]); + +### Arguments: + +1. el - (*mixed*) The id of an element or an Element. +2. where - (*string*, optional: default 'bottom') The place to insert the passed in element. Can be 'top' or 'bottom'. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### HTML + +
+ +##### JavaScript + + var mySecondElement = new Element('div', {id: 'mySecondElement'}); + mySecondElement.wraps($('myFirstElement')); + +##### Resulting HTML + +
+
+
+ + + +Element Method: appendText {#Element:appendText} +------------------------------------------------ + +Works like [Element:grab](#Element:grab), but instead of accepting an id or an element, it only accepts text. +A text node will be created inside this Element, in either the top or bottom position. + +### Syntax: + + myElement.appendText(text); + +### Arguments: + +1. text - (*string*) The text to append. +1. where - (*string*, optional: default 'bottom') The position to inject the text to. + +### Returns: + +* (*element*) The current Element instance. + +### Examples: + +##### HTML + +
Hey.
+ +##### JavaScript + + $('myElement').appendText(' Howdy.'); + +##### Resulting HTML + +
Hey. Howdy.
+ + + +Element Method: dispose {#Element:dispose} +------------------------------------------ + +Removes the Element from the DOM. + + +### Syntax: + + var removedElement = myElement.dispose(); + +### Returns: + +* (*element*) This Element. Useful to always grab the return from this function, as the element could be [injected](#Element:inject) back. + +### Examples: + +##### HTML + +
+
+ +##### JavaScript + + $('myElement').dispose(); + +##### Resulting HTML + +
+ +### See Also: + +- [MDC Element:removeChild](http://developer.mozilla.org/en/docs/DOM:element.removeChild) + + + +Element Method: clone {#Element:clone} +-------------------------------------- + +Clones the Element and returns the cloned one. + + +### Syntax: + + var copy = myElement.clone([contents, keepid]); + +### Arguments: + +1. contents - (*boolean*, optional: defaults to true) When set to false the Element's contents are not cloned. +2. keepid - (*boolean*, optional: defaults to false) When true the cloned Element keeps the id attribute, if present. Same goes for any of the cloned childNodes. + + +### Returns: + +* (*element*) The cloned Element. + +### Examples: + +##### HTML + +
+ +##### JavaScript + + //Clones the Element and appends the clone after the Element. + var clone = $('myElement').clone().injectAfter('myElement'); + +##### Resulting HTML + +
ciao
+
ciao
+ +### Note: + +- The returned Element does not have attached events. To clone the events use [Element:cloneEvents](/Element/Element.Event#Element:cloneEvents). +- Values stored in Element.Storage are not cloned. +- The clone element and its children are stripped of ids, unless otherwise specified by the keepid parameter. + +### See Also: + +- [Element:cloneEvents](/Element/Element.Event#Element:cloneEvents). + + + +Element Method: replaces {#Element:replaces} +-------------------------------------------------- + +Replaces the Element with an Element passed. + +### Syntax: + + var element = myElement.replaces(el); + +### Arguments: + +1. el - (*mixed*) A string id representing the Element to be replaced with, or an Element reference. + +### Returns: + +* (*element*) This Element. + +### Examples: + + $('myNewElement').replaces($('myOldElement')); + //$('myOldElement') is gone, and $('myNewElement') is in its place. + +### See Also: + +- [MDC Element:replaceChild](http://developer.mozilla.org/en/docs/DOM:element.replaceChild) + + + +Element Method: hasClass {#Element:hasClass} +-------------------------------------------- + +Tests the Element to see if it has the passed in className. + +### Syntax: + + var result = myElement.hasClass(className); + +### Arguments: + +1. className - (*string*) The class name to test. + +### Returns: + +* (*boolean*) Returns true if the Element has the class, otherwise false. + +### Examples: + +##### HTML + +
+ +##### JavaScript + + $('myElement').hasClass('testClass'); //returns true + + + +Element Method: addClass {#Element:addClass} +-------------------------------------------- + +Adds the passed in class to the Element, if the Element doesnt already have it. + +### Syntax: + + myElement.addClass(className); + +### Arguments: + +1. className - (*string*) The class name to add. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### HTML + +
+ +##### JavaScript + + $('myElement').addClass('newClass'); + +##### Resulting HTML + +
+ + + +Element Method: removeClass {#Element:removeClass} +---------------------------- + +Works like [Element:addClass](#Element:addClass), but removes the class from the Element. + + +### Syntax: + + myElement.removeClass(className); + +### Arguments: + +1. className - (*string*) The class name to remove. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### HTML + +
+ +##### JavaScript + + $('myElement').removeClass('newClass'); + +##### Resulting HTML + +
+ + + +Element Method: toggleClass {#Element:toggleClass} +-------------------------------------------------- + +Adds or removes the passed in class name to the Element, depending on whether or not it's already present. + +### Syntax: + + myElement.toggleClass(className); + +### Arguments: + +1. className - (*string*) The class to add or remove. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### HTML + +
+ +##### JavaScript + + $('myElement').toggleClass('myClass'); + +##### Resulting HTML + +
+ +##### JavaScript + + $('myElement').toggleClass('myClass'); + +##### Resulting HTML + +
+ + + +Element Method: getPrevious {#Element:getPrevious} +-------------------------------------------------- + +Returns the previousSibling of the Element (excluding text nodes). + +### Syntax: + + var previousSibling = myElement.getPrevious([match]); + +### Arguments: + +1. match - (*string*, optional): A tag name to match the the found element(s) with. If [Selectors][] is included, a full CSS selector can be passed. + +### Returns: + +* (*mixed*) The previous sibling Element or null if none found. + + + +Element Method: getAllPrevious {#Element:getAllPrevious} +-------------------------------------------------------- + +Like [Element:getPrevious][], but returns a collection of all the matched previousSiblings. + + + +Element Method: getNext {#Element:getNext} +------------------------------------------ + +As [Element:getPrevious][], but tries to find the nextSibling (excluding text nodes). + + +### Syntax: + + var nextSibling = myElement.getNext([match]); + +### Arguments: + +1. match - (*string*, optional): A comma seperated list of tag names to match the found element(s) with. If [Selectors][] is included, a full CSS selector can be passed. + +### Returns: + +* (*mixed*) The next sibling Element or null if none found. + + +Element Method: getAllNext {#Element:getAllNext} +------------------------------------------------ + +Like Element.getNext, but returns a collection of all the matched nextSiblings. + + + +Element Method: getFirst {#Element:getFirst} +-------------------------------------------- + +Works as [Element:getPrevious][], but tries to find the firstChild (excluding text nodes). + + +### Syntax: + + var firstElement = myElement.getFirst([match]); + +### Arguments: + +1. match - (*string*, optional): A tag name to match the found element(s) with. if [Selectors][] is included, a full CSS selector can be passed. + +### Returns: + +* (*mixed*) The first sibling Element or null if none found. + + + +Element Method: getLast {#Element:getLast} +------------------------------------------ + +Works as [Element:getPrevious][], but tries to find the lastChild. + +### Syntax: + + var lastElement = myElement.getLast([match]); + +### Arguments: + +1. match - (*string*, optional): A tag name to match the found element(s) with. if [Selectors][] is included, a full CSS selector can be passed. + +### Returns: + +* (*mixed*) The first sibling Element, or returns null if none found. + + + +Element Method: getParent {#Element:getParent} +---------------------------------------------- + +Works as [Element:getPrevious][], but tries to find the parentNode. + + +### Syntax: + + var parent = myElement.getParent([match]); + +### Arguments: + +1. match - (*string*, optional): A tag name to match the found element(s) with. if [Selectors][] is included, a full CSS selector can be passed. + +### Returns: + +* (*mixed*) The target Element's parent or null if no matching parent is found. + + + +Element Method: getParents {#Element:getParents} +------------------------------------------------ + +Like [Element:getParent](#Element:getParent), but returns a collection of all the matched parentNodes up the tree. + + + +Element Method: getChildren {#Element:getChildren} +-------------------------------------------------- + +Returns all the Element's children (excluding text nodes). Returns as [Elements][]. + + +### Syntax: + + var children = myElement.getChildren([match]); + +### Arguments: + +1. match - (*string*, optional): A tag name to match the found element(s) with. if [Selectors][] is included, a full CSS selector can be passed. + +### Returns: + +* (*array*) A [Elements](#Elements) array with all of the Element's children, except the text nodes. + + + +Element Method: hasChild {#Element:hasChild} +-------------------------------------------- + +Checks all descendants of this Element for a match. + + +### Syntax: + + var result = myElement.hasChild(el); + +### Arguments: + +1. el - (*mixed*) Can be an Element reference or string id. + +### Returns: + +* (*boolean*) Returns true if the passed in Element is a child of the Element, otherwise false. + +### Examples: + +##### HTML + +
+
+
+ +##### JavaScript + + if ($('Darth_Vader').hasChild('Luke')) alert('Luke, I am your father.'); // tan tan tannn... + + + +Element Method: empty {#Element:empty} +-------------------------------------- + +Empties an Element of all its children. + + +### Syntax: + + myElement.empty(); + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### HTML + +
+

+ +
+ +##### JavaScript + + $('myElement').empty(); + +##### Resulting HTML + +
+ + + +Element Method: destroy {#Element:destroy} +------------------------------------------ + +Empties an Element of all its children, removes and garbages the Element. +Useful to clear memory before the pageUnload. + +### Syntax: + + myElement.destroy(); + +### Returns: + +* (*null*) + + + +Element Method: toQueryString {#Element:toQueryString} +------------------------------------------------------ + +Reads the child inputs of the Element and generates a query string based on their values. + + +### Syntax: + + var query = myElement.toQueryString(); + +### Returns: + +* (*string*) A string representation of a all the input Elements' names and values. + +### Examples: + +##### HTML + +
+ + +
+ +##### JavaScript + + $('myForm').toQueryString(); //Returns "email=bob@bob.com&zipCode=90210". + + +Element Method: getSelected {#Element:getSelected} +-------------------------------------------------- + +Returns the selected options of a select element. + + +### Syntax: + + var selected = mySelect.getSelected(); + +### Returns: + +* (*array*) An array of the selected elements. + +### Examples: + +##### HTML + + + +##### JavaScript + + $('country-select').getSelected(); //Returns whatever the user selected. + +### Note: + +This method returns an array, regardless of the multiple attribute of the select element. +If the select is single, it will return an array with only one item. + + + +Element Method: getProperty {#Element:getProperty} +-------------------------------------------------- + +Returns a single element attribute. + +### Syntax: + + var myProp = myElement.getProperty(property); + +### Arguments: + +* property - (*string*) The property to be retrieved. + +### Returns: + +* (*string*) A string containing the Element's requested property. + +### Examples: + +##### HTML + + + +##### JavaScript + + var imgProps = $('myImage').getProperty('src'); //Returns: 'mootools.png'. + + + +Element Method: getProperties {#Element:getProperties} +------------------------------------------------------ + +Gets multiple element attributes. + +### Syntax: + + var myProps = myElement.getProperties(properties); + +### Arguments: + +* properties - (*strings*) Any number of properties to be retrieved. + +### Returns: + +* (*object*) An object containing all of the Element's requested properties. + +### Examples: + +##### HTML + + + +##### JavaScript + + var imgProps = $('myImage').getProperties('id', 'src', 'title', 'alt'); + //Returns: { id: 'myImage', src: 'mootools.png', title: 'MooTools, the compact JavaScript framework', alt: '' } + + + +Element Method: setProperty {#Element:setProperty} +-------------------------------------------------- + +Sets an attribute or special property for this Element. + + +### Arguments: + +1. property - (*string*) The property to assign the value passed in. +2. value - (*mixed*) The value to assign to the property passed in. + +### Returns: + +* (*element*) - This Element. + +### Examples: + +##### HTML + + + +##### JavaScript + + $('myImage').setProperty('src', 'mootools.png'); + +##### Resulting HTML + + + +### Note + +- Whenever using [Element:setProperty][] to set an attribute, pass in the lowercase, simplified form of the property. For example: + - use 'for', not 'htmlFor', + - use 'class', not 'className' + - use 'frameborder', not 'frameBorder' + - etc. + + +Element Method: setProperties {#Element:setProperties} +------------------------------------------------------ + +Sets numerous attributes for the Element. + + +### Arguments: + +1. properties - (*object*) An object with key/value pairs. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### HTML + + + +##### JavaScript + + $('myImage').setProperties({ + src: 'whatever.gif', + alt: 'whatever dude' + }); + +##### Resulting HTML + + whatever dude + + + +Element Method: removeProperty {#Element:removeProperty} +-------------------------------------------------------- + +Removes an attribute from the Element. + + +### Syntax: + + myElement.removeProperty(property); + +### Arguments: + +1. property - (*string*) The attribute to remove. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### HTML + +
+ +##### JavaScript + + //Eww... inline JavaScript is bad! Let's get rid of it. + $('myAnchor').removeProperty('onmousedown'); + +##### Resulting HTML + + + + + +Element Method: removeProperties {#Element:removeProperties} +------------------------------------------------------------ + +Removes numerous attributes from the Element. + + +### Syntax: + + myElement.removeProperties(properties); + +### Arguments: + +1. properties - (*strings*) The attributes to remove, separated by comma. + +### Returns: + +* (*element*) This Element. + +### Examples: + +##### HTML + + + +##### JavaScript + + $('myAnchor').removeProperties('id', 'href', 'title'); + +##### Resulting HTML + + + + +Element Method: store {#Element:store} +-------------------------------------- + +Stores an item in the Elements Storage, linked to this Element. + + +### Syntax: + + myElement.store(key, value); + +### Arguments: + +1. key - (*string*) The key you want to assign to the stored value. +2. value - (*mixed*) Any value you want to store. + +### Returns: + +* (*element*) This Element. + +### Example: + + $('element').store('someProperty', someValue); + + +Element Method: retrieve {#Element:retrieve} +-------------------------------------------- + +Retrieves a value from the Elements storage. + + +### Syntax: + + myElement.retrieve(key[, default]); + +### Arguments: + +1. key - (*string*) The key you want to retrieve from the storage. +2. default - (*mixed*, optional) Default value to store and return if no value is stored. + +### Returns: + +* (*mixed*) The value linked to the key. + +### Example: + + $('element').retrieve('someProperty'); // returns someValue (see example above) + + + + +Hash: Element.Properties {#Element-Properties} +============================================== + +This Hash contains the functions that respond to the first argument passed in [Element:get][], [Element:set][] and [Element:erase][]. + +### Adding a Custom Element Property + + Element.Properties.disabled = { + + get: function(){ + return this.disabled; + } + + set: function(value){ + this.disabled = !!value; + this.setAttribute('disabled', !!value); + } + + }; + +### Using a Custom Element Property + + //Gets the "disabled" property. + $(element).get('disabled'); + //Sets the "disabled" property to true, along with the attribute. + $(element).set('disabled', true); + +### Note: + +Automatically returns the element for setters. + +### Using an Object: + +Additionally, you can access these custom getters and setters using an object as the parameter for the [set](#Element:set) method. + +#### Example: + + //Using set: + $(divElement).set({html: '

Hello People!

', style: 'background:red'}); + + //For new Elements (works the same as set): + new Element('input', {type: 'checkbox', checked: true, disabled: true}); + + + +Element Property: html {#Element-Properties:html} +------------------------------------------------- + +### Setter: + +Sets the innerHTML of the Element. + +#### Syntax: + + myElement.set('html', [htmlString[, htmlString2[, htmlString3[, ..]]]); + +#### Arguments: + +1. Any number of string parameters with HTML. + +#### Returns: + +* (*element*) This Element. + +#### Examples: + +##### HTML + +
+ +##### JavaScript + + $('myElement').set('html', '
', '

'); + +##### Resulting HTML + +
+
+

+
+ +### Getter: + +Returns the inner HTML of the Element. + +#### Syntax: + + myElement.get('html'); + +#### Returns: + +* (*text*) This Element's innerHTML. + + + +Element Property: text {#Element-Properties:text} +------------------------------------------------- + +### Setter: + +Sets the inner text of the Element. + +#### Syntax: + + myElement.set('text', text); + +#### Arguments: + +1. text - (*string*) The new text content for the Element. + +#### Returns: + +* (*element*) This Element. + +#### Examples: + +##### HTML + +
+ +##### JavaScript + + $('myElement').set('text', 'some text'); + //The text of myElement is now 'some text'. + +##### Resulting HTML + +
some text
+ +### Getter: + +Gets the inner text of the Element. + +#### Syntax: + + var myText = myElement.get('text'); + +#### Returns: + +* (*string*) The text of the Element. + +#### Examples: + +##### HTML + +
my text
+ +##### JavaScript + + var myText = $('myElement').get('text'); //myText = 'my text'. + + + +Element Property: tag {#Element-Properties:tag} +----------------------------------------------- + +### Getter: + +Returns the tag name of the Element in lower case. + +#### Syntax: + + var myTag = myElement.get('tag'); + +#### Returns: + +* (*string*) The tag name in lower case. + +#### Examples: + +##### HTML + + + +##### JavaScript + + var myTag = $('myImage').get('tag'); // myTag = 'img'. + + + +Native: IFrame {#IFrame} +======================== + +Custom Native to create and easily work with IFrames. + + + +IFrame Method: constructor {#IFrame:constructor} +------------------------------------------------ + +Creates an IFrame HTML Element and extends its window and document with MooTools. + + +### Syntax: + + var myIFrame = new IFrame([el][, props]); + +### Arguments: + +1. el - (*mixed*, optional) The id of the IFrame to be converted, or the actual IFrame element. If its not passed, a new IFrame will be created (default). +2. props - (*object*, optional) The properties to be applied to the new IFrame. Same as [Element:constructor](#Element:constructor) props argument. + +### Returns: + +* (*element*) A new IFrame HTML Element. + +### Examples: + + var myIFrame = new IFrame({ + + src: 'http://mootools.net/', + + styles: { + width: 800, + height: 600, + border: '1px solid #ccc' + }, + + events: { + + mouseenter: function(){ + alert('Welcome aboard.'); + }, + + mouseleave: function(){ + alert('Goodbye!'); + }, + + load: function(){ + alert('The iframe has finished loading.'); + } + + } + + }); + + +### Notes: + +- If the IFrame is from the same domain as the "host", its document and window will be extended with MooTools functionalities, allowing you to fully use MooTools within it. +- If the IFrame already exists and has a different name than id, the name will be made the same as the id. +- If the IFrame is from a different domain, its window and document will not be extended with MooTools methods. + + + +Native: Elements {#Elements} +============================ + +The Elements class allows [Element][] methods to work on an [Elements][] array, as well as [Array][] Methods. + + + +Elements Method: constructor {#Elements:constructor} +---------------------------------------------------- + + +### Syntax: + + var myElements = new Elements(elements[, options]); + +### Arguments: + +1. elements - (*mixed*) An array of elements or an HTMLCollection Object. + +### Returns: + +* (*array*) An extended array with the [Element][], [Elements][] and [Array][] methods. + +### Examples: + +#### Set Every Paragraph's Color to Red: + + $$('p').each(function(el){ + el.setStyle('color', 'red'); + }); + + //Because $$('myselector') also accepts Element methods, the below + //example has the same effect as the one above. + $$('p').setStyle('color', 'red'); + + +#### Create Elements From an Array: + + var myElements = new Elements(['myElementID', $('myElement'), 'myElementID2', document.getElementById('myElementID3')]); + + +### Notes: + +- In MooTools, every DOM function which returns a collection of nodes (such as [$$][]) returns the nodes as instances of Elements. +- Because Elements is an Array, it accepts all the [Array][] methods, while giving precedence to [Element][] and [Elements][] methods. +- Every node of the Elements instance has all the [Element][] methods. + +### See Also: + +- [$$][], [$][], [Element][], [Elements][], [Array][] + + + +Elements Method: filter {#Elements:filter} +---------------------------------------------- + +Filters a collection of elements by a given tag name. If [Selectors][] is included, this method will be able to filter by any selector. +It also works like [Array:filter](/Native/Array/#Array:filter), by filtering collection of elements with a function. + + +### Syntax: + + var filteredElements = elements.filter(selector); + +### Arguments: + +1. selector - (*mixed*) A single CSS selector. + +### Returns: + +* (*array*) A subset of this [Elements][] instance. + + + +[$]: #dollar +[$$]: #dollars + +[Array]: /core/Native/Array +[Selectors]: /core/Selectors/Selectors + +[Element]: #Element +[Elements]: #Elements +[Element:set]: #Element:set +[Element:get]: #Element:get +[Element:erase]: #Element:erase +[Element:setProperty]: #Element:setProperty +[Element:getProperty]: #Element:getProperty +[Element:removeProperty]: #Element:removeProperty +[Element:getElement]: #Element:getElement +[Element:getElements]: #Element:getElements +[Element.Properties]: #Element-Properties +[Element:getPrevious]: #Element:getPrevious + +[Element:addEvents]: /core/Element/Element.Event#Element:addEvents +[Element:setStyles]: /core/Element/Element.Style#Element:setStyles diff --git a/assets/mootools-core/Docs/Fx/Fx.CSS.md b/assets/mootools-core/Docs/Fx/Fx.CSS.md new file mode 100644 index 00000000..ba451eeb --- /dev/null +++ b/assets/mootools-core/Docs/Fx/Fx.CSS.md @@ -0,0 +1,12 @@ +Class: Fx.CSS {#Fx-CSS} +======================= + +CSS parsing class for effects. Required by [Fx.Tween][], [Fx.Morph][], [Fx.Elements][]. + +Has no public methods. + + + +[Fx.Tween]: /core/Fx/Fx.Tween +[Fx.Morph]: /core/Fx/Fx.Morph +[Fx.Elements]: /more/Fx/Fx.Elements \ No newline at end of file diff --git a/assets/mootools-core/Docs/Fx/Fx.Morph.md b/assets/mootools-core/Docs/Fx/Fx.Morph.md new file mode 100644 index 00000000..a07dd462 --- /dev/null +++ b/assets/mootools-core/Docs/Fx/Fx.Morph.md @@ -0,0 +1,214 @@ +Class: Fx.Morph {#Fx-Morph} +=========================== + +Allows for the animation of multiple CSS properties at once, even by a CSS selector. Inherits methods, properties, options and events from [Fx][]. + +### Extends: + +- [Fx][] + +### Syntax: + + var myFx = new Fx.Morph(element[, options]); + +### Arguments: + +1. element - (*mixed*) A string ID of the Element or an Element to apply the style transitions to. +2. options - (*object*, optional) The [Fx][] options object. + +### Returns: + +* (*object*) A new Fx.Morph instance. + +### Examples: + +Multiple styles with start and end values using an object: + + var myEffect = new Fx.Morph('myElement', {duration: 'long', transition: Fx.Transitions.Sine.easeOut}); + + myEffect.start({ + 'height': [10, 100], //Morphs the 'height' style from 10px to 100px. + 'width': [900, 300] //Morphs the 'width' style from 900px to 300px. + }); + + +Multiple styles with the start value omitted will default to the current Element's value: + + var myEffect = new Fx.Morph('myElement', {duration: 'short', transition: Fx.Transitions.Sine.easeOut}); + + myEffect.start({ + 'height': 100, //Morphs the height from the current to 100px. + 'width': 300 //Morphs the width from the current to 300px. + }); + + +Morphing one Element to match the CSS values within a CSS class: + + var myEffect = new Fx.Morph('myElement', {duration: 1000, transition: Fx.Transitions.Sine.easeOut}); + + //The styles of myClassName will be applied to the target Element. + myEffect.start('.myClassName'); + + +### See Also: + +- [Fx][] + + + +Fx.Morph Method: set {#Fx-Morph:set} +------------------------------------ + +Sets the Element's CSS properties to the specified values immediately. + +### Syntax: + + myFx.set(to); + +### Arguments: + +1. properties - (*mixed*) Either an *object* of key/value pairs of CSS attributes to change or a *string* representing a CSS selector which can be found within the CSS of the page. If only one value is given for any CSS property, the transition will be from the current value of that property to the value given. + +### Returns: + +* (*object*) This Fx.Morph instance. + +### Examples: + + var myFx = new Fx.Morph('myElement').set({ + 'height': 200, + 'width': 200, + 'background-color': '#f00', + 'opacity': 0 + }); + var myFx = new Fx.Morph('myElement').set('.myClass'); + + + +Fx.Morph Method: start {#Fx-Morph:start} +---------------------------------------- + +Executes a transition for any number of CSS properties in tandem. + +### Syntax: + + myFx.start(properties); + +### Arguments: + +1. properties - (*mixed*) An *object* of key/value pairs of CSS attributes to change or a *string* representing a CSS selector which can be found within the CSS of the page. + If only one value is given for any CSS property, the transition will be from the current value of that property to the value given. + +### Returns: + +* (*object*) This Fx.Morph instance. + +### Examples: + + var myEffects = new Fx.Morph('myElement', {duration: 1000, transition: Fx.Transitions.Sine.easeOut}); + + myEffects.start({ + 'height': [10, 100], + 'width': [900, 300], + 'opacity': 0, + 'background-color': '#00f' + }); + +### Notes: + +- If a string is passed as the CSS selector, the selector must be identical to the one within the CSS. +- Multiple selectors (with commas) are not supported. + + +Hash: Element.Properties {#Element-Properties} +============================================== + +see [Element.Properties](/Element/Element/#Element-Properties) + +Element Property: morph {#Element-Properties:morph} +--------------------------------------------------- + +### Setter + +Sets a default Fx.Morph instance for an Element. + +#### Syntax: + + el.set('morph'[, options]); + +#### Arguments: + +1. options - (*object*, optional) The Fx.Morph options. + +#### Returns: + +* (*element*) This Element. + +#### Examples: + + el.set('morph', {duration: 'long', transition: 'bounce:out'}); + el.morph({height: 100, width: 100}); + +### Getter + +Gets the default Fx.Morph instance for the Element. + +#### Syntax: + + el.get('morph'); + +#### Arguments: + +1. options - (*object*, optional) The Fx.Morph options. If these are passed in, a new instance will be generated. + +#### Returns: + +* (*object*) The Fx.Morph instance. + +#### Examples: + + el.set('morph', {duration: 'long', transition: 'bounce:out'}); + el.morph({height: 100, width: 100}); + el.get('morph'); //The Fx.Morph instance. + + + +Native: Element {#Element} +========================== + +Element Method: morph {#Element:morph} +-------------------------------------- + +Animates an Element given the properties passed in. + +### Syntax: + + myElement.morph(properties); + +### Arguments: + +1. properties - (*mixed*) The CSS properties to animate. Can be either an object of CSS properties or a string representing a CSS selector. If only one value is given for any CSS property, the transition will be from the current value of that property to the value given. + +### Returns: + +* (*element*) This Element. + +### Example: + +With an object: + + $('myElement').morph({height: 100, width: 200}); + +With a selector: + + $('myElement').morph('.class1'); + +### See Also: + +- [Fx.Morph][] + + + +[$]: /core/Element/Element#dollar +[Fx]: /core/Fx/Fx +[Fx.Morph]: #Fx-Morph diff --git a/assets/mootools-core/Docs/Fx/Fx.Transitions.md b/assets/mootools-core/Docs/Fx/Fx.Transitions.md new file mode 100644 index 00000000..dd4756c9 --- /dev/null +++ b/assets/mootools-core/Docs/Fx/Fx.Transitions.md @@ -0,0 +1,147 @@ +Class: Fx {#Fx} +=============== + +Fx.Transitions overrides the base [Fx][] constructor, and adds the possibility to use the transition option as string. + +### Transition option: + +The equation to use for the effect. See [Fx.Transitions][]. It accepts both a function (ex: Fx.Transitions.Sine.easeIn) or a string ('sine:in', 'bounce:out' or 'quad:in:out') that will map to Fx.Transitions.Sine.easeIn / Fx.Transitions.Bounce.easeOut / Fx.Transitions.Quad.easeInOut + + +Hash: Fx.Transitions {#Fx-Transitions} +====================================== + +A collection of tweening transitions for use with the [Fx][] classes. + +### Examples: + + //Elastic.easeOut with default values: + var myFx = $('myElement').effect('margin', {transition: Fx.Transitions.Elastic.easeOut}); + +### See also: + +- [Robert Penner's Easing Equations](http://www.robertpenner.com/easing/) + + + +Fx.Transitions Method: linear {#Fx-Transitions:linear} +------------------------------------------------------ + +Displays a linear transition. + +Fx.Transitions Method: quad {#Fx-Transitions:quad} +-------------------------------------------------- + +Displays a quadratic transition. Must be used as Quad.easeIn or Quad.easeOut or Quad.easeInOut. + +Fx.Transitions Method: cubic {#Fx-Transitions:cubic} +---------------------------------------------------- + +Displays a cubicular transition. Must be used as Cubic.easeIn or Cubic.easeOut or Cubic.easeInOut. + + +Fx.Transitions Method: quart {#Fx-Transitions:quart} +---------------------------------------------------- + +Displays a quartetic transition. Must be used as Quart.easeIn or Quart.easeOut or Quart.easeInOut. + +Fx.Transitions Method: quint {#Fx-Transitions:quint} +---------------------------------------------------- + +Displays a quintic transition. Must be used as Quint.easeIn or Quint.easeOut or Quint.easeInOut + +Fx.Transitions Method: pow {#Fx-Transitions:pow} +------------------------------------------------ + +Used to generate Quad, Cubic, Quart and Quint. + +### Note: + +- The default is `p^6`. + +Fx.Transitions Method: expo {#Fx-Transitions:expo} +-------------------------------------------------- + +Displays a exponential transition. Must be used as Expo.easeIn or Expo.easeOut or Expo.easeInOut. + + + +Fx.Transitions Method: circ {#Fx-Transitions:circ} +-------------------------------------------------- + +Displays a circular transition. Must be used as Circ.easeIn or Circ.easeOut or Circ.easeInOut. + + + +Fx.Transitions Method: sine {#Fx-Transitions:sine} +-------------------------------------------------- + +Displays a sineousidal transition. Must be used as Sine.easeIn or Sine.easeOut or Sine.easeInOut. + + + +Fx.Transitions Method: back {#Fx-Transitions:back} +-------------------------------------------------- + +Makes the transition go back, then all forth. Must be used as Back.easeIn or Back.easeOut or Back.easeInOut. + + + +Fx.Transitions Method: bounce {#Fx-Transitions:bounce} +------------------------------------------------------ + +Makes the transition bouncy. Must be used as Bounce.easeIn or Bounce.easeOut or Bounce.easeInOut. + + + +Fx.Transitions Method: elastic {#Fx-Transitions:elastic} +-------------------------------------------------------- + +Elastic curve. Must be used as Elastic.easeIn or Elastic.easeOut or Elastic.easeInOut + + + +Class: Fx.Transition {#Fx-Transition} +===================================== + +This class is only useful for math geniuses who want to write their own easing equations. +Returns an [Fx][] transition function with 'easeIn', 'easeOut', and 'easeInOut' methods. + +### Syntax: + + var myTransition = new Fx.Transition(transition[, params]); + +### Arguments: + +1. transition - (*function*) Can be a [Fx.Transitions][] function or a user-provided function which will be extended with easing functions. +2. params - (*mixed*, optional) Single value or an array for multiple values to pass as the second parameter for the transition function. + +### Returns: + +* (*function*) A function with easing functions. + +### Examples: + + //Elastic.easeOut with user-defined value for elasticity. + var myTransition = new Fx.Transition(Fx.Transitions.Elastic, 3); + var myFx = $('myElement').effect('margin', {transition: myTransition.easeOut}); + +### See Also: + +- [Fx.Transitions][] + + +[Fx]: /core/Fx/Fx +[Fx.Transitions]: #Fx-Transitions +[Element.effect]: /core/Element/#Element:effect +[Linear]: ../Docs/assets/images/Linear.png +[Quad]: ../Docs/assets/images/Quad.png +[Cubic]: ../Docs/assets/images/Cubic.png +[Quart]: ../Docs/assets/images/Quart.png +[Quint]: ../Docs/assets/images/Quint.png +[Expo]: ../Docs/assets/images/Expo.png +[Circ]: ../Docs/assets/images/Circ.png +[Sine]: ../Docs/assets/images/Sine.png +[Back]: ../Docs/assets/images/Back.png +[Bounce]: ../Docs/assets/images/Bounce.png +[Elastic]: ../Docs/assets/images/Elastic.png \ No newline at end of file diff --git a/assets/mootools-core/Docs/Fx/Fx.Tween.md b/assets/mootools-core/Docs/Fx/Fx.Tween.md new file mode 100644 index 00000000..1b42dc1d --- /dev/null +++ b/assets/mootools-core/Docs/Fx/Fx.Tween.md @@ -0,0 +1,269 @@ +Class: Fx.Tween {#Fx-Tween} +=========================== + +Contains [Fx.Tween][] and the Element shortcut [Element.tween][]. + +### Extends: + +[Fx][] + + + +Fx.Tween Method: constructor {#Fx-Tween:constructor} +---------------------------------------------------- + +The Tween effect, used to transition any CSS property from one value to another. + +### Syntax: + + var myFx = new Fx.Tween(element, [, options]); + +### Arguments: + +1. element - (*mixed*) An Element or the string id of an Element to apply the transition to. +2. options - (*object*, optional) The [Fx][] options object, plus the options described below: + +### Options: + +* property - (*string*) The CSS property to transition to, for example 'width', 'color', 'font-size', 'border', etc. If this option is omitted, you are required to use the property as a first argument for the start and set methods. Defaults to null. + + +### Notes: + +- Any CSS property that can be set with Element:setStyle can be transitioned with Fx.Tween. +- If a property is not mathematically calculable, like border-style or background-image, it will be set immediately upon start of the transition. +- If you use the property option, you must not use the property argument in the start and set methods. + +### See Also: + +- [Fx][] + + + +Fx.Tween Method: set {#Fx-Tween:set} +------------------------------------ + +Sets the Element's CSS property to the specified value immediately. + +### Syntax: + + myFx.set(property, value); + +### Arguments: + +1. property - (*string*) The css property to set the value to. Omit this if you use the property option. +2. value - (*mixed*) The value to set the CSS property of this instance to. + +### Returns: + +* (*object*) This Fx.Tween instance. + +### Examples: + + var myFx = new Fx.Tween(element); + //Immediately sets the background color of the element to red: + myFx.set('background-color', '#f00'); + +### Note: + +If you use the property option, you must not use the property argument in the start and set methods. + + +Fx.Tween Method: start {#Fx-Tween:start} +---------------------------------------- + +Transitions the Element's CSS property to the specified value. + +### Syntax: + + myFx.start([property,] [from,] to); + +### Arguments: + +1. property - (*string*, if not in options) The css property to tween. Omit this if you use the property option. +2. from - (*mixed*, optional) The starting CSS property value for the effect. +3. to - (*mixed*) The target CSS property value for the effect. + +### Returns: + +* (*object*) This Fx.Tween instance. + +### Examples: + + var myFx = new Fx.Tween(element); + //Transitions the background color of the Element from black to red: + myFx.start('background-color', '#000', '#f00'); + //Transitions the background color of the Element from its current color to blue: + myFx.start('background-color', '#00f'); + +### Notes: + +- If only one argument is provided, other than the property argument, the first argument to start will be used as the target value, and the initial value will be calculated from the current state of the element. +- When using colors, either RGB or Hex values may be used. +- If you use the property option, you must not use the property argument in the start and set methods. + + + +Hash: Element.Properties {#Element-Properties} +============================================== + +see [Element.Properties](/Element/Element/#Element-Properties) + +Element Property: tween {#Element-Properties:tween} +--------------------------------------------------- + +Sets and gets default options for the Fx.Tween instance of an Element. + +### Setter: + +#### Syntax: + + el.set('tween'[, options]); + +#### Arguments: + +* options - (*object*) the Fx.Tween options. + +#### Returns: + +* (*element*) This Element. + +#### Examples: + + el.set('tween', {duration: 'long'}); + el.tween('color', '#f00'); + +### Getter: + +#### Syntax: + + el.get('tween', [options]); + +#### Arguments: + +1. property - (*string*) the Fx.Tween property argument. +2. options - (*object*) the Fx.Tween options. + +#### Returns: + +* (*object*) The Element's internal Fx.Tween instance. + +#### Examples: + + el.get('tween', {property: 'opacity', duration: 'long'}).start(0); + +### Notes: + +- When initializing the Element's tween instance with Element:set, the property to tween SHOULD NOT be passed. +- The property must be specified when using Element:get to retrieve the actual Fx.Tween instance, and in calls to Element:tween. +- When options are passed to either the setter or the getter, the instance will be recreated. +- As with the other Element shortcuts, the difference between a setter and a getter is that the getter returns the instance, while the setter returns the element (for chaining and initialization). + + + +Native: Element {#Element} +========================== + +Custom Native to allow all of its methods to be used with any DOM element via the dollar function [$][]. + + + +Element Method: tween {#Element:tween} +-------------------------------------- + +Element shortcut method which immediately transitions any single CSS property of an Element from one value to another. + +### Syntax: + + myElement.tween(property, startvalue[, endvalue]); + +### Arguments: + +1. property - (*string*) the css property you want to animate. Omit this if you previously set the property option. +2. startvalue - (*mixed*) The start value for the transition. +2. endvalue - (*mixed*) The end value for the transition. If this is omitted, startvalue will be used as endvalue. + +### Returns: + +* (*element*) This Element. + +### Examples: + + //Transitions the width of "myElement" from its current width to 100px: + $('myElement').tween('width', '100'); + //Transitions the height of "myElement" from 20px to 200px: + $('myElement').tween('height', [20, 200]); + //Transitions the border of "myElement" from its current to "6px solid blue": + $('myElement').tween('border', '6px solid #36f'); + +### See Also: + +- [Fx.Tween][] + + + +Element Method: fade {#Element:fade} +------------------------------------ + +Element shortcut method for tween with opacity. Useful for fading an Element in and out or to a certain opacity level. + +### Syntax: + + myElement.fade([how]); + +### Arguments: + +1. how - (*mixed*, optional: defaults to 'toggle') The opacity level as a number or string representation. Possible values include: + * 'in' - Fade the element to 100% opacity. + * 'out' - Fade the element to 0% opacity. + * 'show' - Immediately set the element's opacity to 100%. + * 'hide' - Immediately set the element's opacity to 0%. + * 'toggle' - If visible, fade the element out, otherwise, fade it in. + * (*number*) - A float value between 0 and 1. Will fade the element to this opacity. + +### Returns: + +* This Element. + +### Examples: + + $('myElement').fade('out'); //Fades "myElement" out. + $('myElement').fade(0.7); //Fades "myElement" to 70% opacity. + + + +Element Method: highlight {#Element:highlight} +---------------------------------------------- + +Element shortcut method for tweening the background color. Immediately transitions an Element's background color to a specified highlight color then back to its set background color. + +### Syntax: + + myElement.highlight([start, end]); + +### Arguments: + +1. start - (*string*, optional: defaults to '#ff8') The color from which to start the transition. +2. end - (*string*, optional: defaults to Element's set background-color) The background color to return to after the highlight effect. + +### Note: + +If no background color is set on the Element, or its background color is set to 'transparent', the default end value will be white. + +### Returns: + +* (*element*) This Element. + +### Examples: + + //Will immediately change the background to light blue, then back to its original color (or white): + $('myElement').highlight('#ddf'); + + //Will immediately change the background to light blue, then fade to grey: + $('myElement').highlight('#ddf', '#ccc'); + + +[$]: /core/Element/Element#dollar +[Fx]: /core/Fx/Fx +[Fx.Tween]: #Fx-Tween +[Element.tween]: #Element-Properties:tween diff --git a/assets/mootools-core/Docs/Fx/Fx.md b/assets/mootools-core/Docs/Fx/Fx.md new file mode 100644 index 00000000..c2660483 --- /dev/null +++ b/assets/mootools-core/Docs/Fx/Fx.md @@ -0,0 +1,169 @@ +Class: Fx {#Fx} +=============== + +This Class will rarely be used on its own, but provides the foundation for all custom Fx Classes. +All of the other Fx Classes inherit from this one. + +### Implements: + +- [Chain][], [Events][], [Options][] + + + +Fx Method: constructor {#Fx:constructor} +---------------------------------------- + +### Syntax: + + var myFx = new Fx([options]); + +### Arguments: + +1. options - (*object*, optional) An object with options for the effect. See below. + +### Options: + +* fps - (*number*: defaults to 50) The frames per second for the transition. +* unit - (*string*: defaults to false) The unit, e.g. 'px', 'em', or '%'. See [Element:setStyle](/Element/Element/#Element:setStyle). +* link - (*string*: defaults to ignore) Can be 'ignore', 'cancel' and 'chain'. + * 'ignore' - Any calls made to start while the effect is running will be ignored. (Synonymous with 'wait': true from 1.x) + * 'cancel' - Any calls made to start while the effect is running will take precedence over the currently running transition. The new transition will start immediately, canceling the one that is currently running. (Synonymous with 'wait': false from 1.x) + * 'chain' - Any calls made to start while the effect is running will be chained up, and will take place as soon as the current effect has finished, one after another. +* duration - (*number*: defaults to 500) The duration of the effect in ms. Can also be one of: + * 'short' - 250ms + * 'normal' - 500ms + * 'long' - 1000ms +* transition - (*function*: defaults to ['sine:in:out'](/Fx/Fx.Transitions) The equation to use for the effect see [Fx.Transitions](/Fx/Fx.Transitions). Also accepts a string in the following form: + + transition\[:in\]\[:out\] - for example, 'linear', 'quad:in', 'back:in', 'bounce:out', 'elastic:out', 'sine:in:out' + +### Events: + +* start - (*function*) The function to execute when the effect begins. +* cancel - (*function*) The function to execute when you manually stop the effect. +* complete - (*function*) The function to execute after the effect has processed. +* chainComplete - (*function*) The function to execute when using link 'chain' ([see options](#Fx:constructor)). It gets called after all effects in the chain have completed. + +### Notes: + +- You cannot change the transition if you haven't included Fx.Transitions.js, (unless you plan on developing your own curve). ;) +- The Fx Class is just a skeleton for other Classes to extend the basic functionality. + +### See Also: + +- [Fx.Tween][], [Fx.Morph][]. + + + +Fx Method: start {#Fx:start} +---------------------------- + +The start method is used to begin a transition. Fires the 'start' event. + +### Syntax: + + myFx.start(from[, to]); + +### Arguments: + +1. from - (*mixed*) The starting value for the effect. If only one argument is provided, this value will be used as the target value. +2. to - (*mixed*, optional) The target value for the effect. + +### Returns: + +* (*object*) - This Fx instance. + +### Examples: + +- See examples in the documentation for each Fx subclass. + +### Notes: + +- If only one parameter is provided, the first argument to start will be used as the target value, and the initial value will be calculated from the current state of the element. +- The format and type of this value will be dependent upon implementation, and may vary greatly on a case by case basis. Check each implementation for more details. + + + +Fx Method: set {#Fx:set} +------------------------ + +The set method is fired on every step of a transition. It can also be called manually to set a specific value to be immediately applied to the effect. + +### Syntax: + + myFx.set(value); + +### Arguments: + +1. value - (*mixed*) The value to immediately apply to the transition. + +### Returns: + +* (*object*) - This Fx instance. + +### Examples: + +- See examples in the documentation for each Fx subclass. + + + +Fx Method: cancel {#Fx:cancel} +------------------------------ + +The cancel method is used to cancel a running transition. Fires the 'cancel' event. + +### Syntax: + + myFx.cancel(); + +### Returns: + +* (*object*) - This Fx instance. + + + +Fx Method: pause {#Fx:pause} +---------------------------- + +Temporarily pause a currently running effect. + +### Syntax: + + myFx.pause(); + +### Returns: + +* (*object*) - This Fx instance. + +### Notes: + +- The timer will be stopped to allow the effect to continue where it left off by calling [Fx:resume](#Fx:resume). +- If you call start on a paused effect, the timer will simply be cleared allowing the new transition to start. + + + +Fx Method: resume {#Fx:resume} +------------------------------ + +Resume a previously paused effect. + +### Syntax: + + myFx.resume(); + +### Returns: + +* (*object*) - This Fx instance. + +### Notes: + +- The effect will only be resumed if it has been previously paused. Otherwise, the call to resume will be ignored. + + + +[Fx]: #Fx +[Chain]: /core/Class/Class.Extras#Chain +[Events]: /core/Class/Class.Extras#Events +[Options]: /core/Class/Class.Extras#Options +[Fx.Tween]: /core/Fx/Fx.Tween +[Fx.Morph]: /core/Fx/Fx.Morph diff --git a/assets/mootools-core/Docs/Native/Array.md b/assets/mootools-core/Docs/Native/Array.md new file mode 100644 index 00000000..23be3eac --- /dev/null +++ b/assets/mootools-core/Docs/Native/Array.md @@ -0,0 +1,641 @@ +Native: Array {#Array} +====================== + +A collection of Array methods. + +### See Also: + +- [MDC Array][] + + +Array Method: each {#Array:each} +--------------------------------- + +Calls a function for each element in the array. + +### Syntax: + + myArray.each(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function which should be executed on each item in the array. This function is passed the item and its index in the array. +2. bind - (*object*, optional) The object to be used as 'this' in the function. For more information see [Function:bind][]. + +#### Argument: fn + +##### Syntax + + fn(item, index, array) + +##### Arguments: + +1. item - (*mixed*) The current item in the array. +2. index - (*number*) The current item's index in the array. +3. array - (*array*) The actual array. + +### Examples: + + //Alerts "0 = apple", "1 = banana", and so on: + ['apple', 'banana', 'lemon'].each(function(item, index){ + alert(index + " = " + item); + }); //The optional second argument for binding isn't used here. + + +### See Also: + +- [MDC Array:forEach][] + +### Notes: + +- This method is only available for browsers without native [MDC Array:forEach][] support. + + + +Array Method: every {#Array:every} +---------------------------------- + +Returns true if every element in the array satisfies the provided testing function. +This method is provided only for browsers without native [Array:every][] support. + +### Syntax: + + var allPassed = myArray.every(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function to test for each element. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information see [Function:bind][]. + +#### Argument: fn + +##### Syntax: + + fn(item, index, array) + +##### Arguments: + +1. item - (*mixed*) The current item in the array. +2. index - (*number*) The current item's index in the array. +3. array - (*array*) The actual array. + +### Returns: + +* (*boolean*) If every element in the array satisfies the provided testing function, returns true. Otherwise, returns false. + +### Examples: + + var areAllBigEnough = [10, 4, 25, 100].every(function(item, index){ + return item > 20; + }); //areAllBigEnough = false + + +### See Also: + +- [MDC Array:every][] + + + +Array Method: filter {#Array:filter} +------------------------------------ + +Creates a new array with all of the elements of the array for which the provided filtering function returns true. +This method is provided only for browsers without native [Array:filter][] support. + +### Syntax: + + var filteredArray = myArray.filter(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function to test each element of the array. This function is passed the item and its index in the array. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information see [Function:bind][]. + +#### Argument: fn + +##### Syntax: + + fn(item, index, array) + +##### Arguments: + +1. item - (*mixed*) The current item in the array. +2. index - (*number*) The current item's index in the array. +3. array - (*array*) The actual array. + +### Returns: + +* (*array*) The new filtered array. + +### Examples: + + var biggerThanTwenty = [10, 3, 25, 100].filter(function(item, index){ + return item > 20; + }); //biggerThanTwenty = [25, 100] + +### See Also: + +- [MDC Array:filter][] + + +Array Method: clean {#Array:clean} +------------------------------------ + +Creates a new array with all of the elements of the array which are defined (i.e. not null or undefined). + +### Syntax: + + var cleanedArray = myArray.clean(); + +### Returns: + +* (*array*) The new filtered array. + +### Examples: + + var myArray = [null, 1, 0, true, false, "foo", undefined, ""]; + myArray.clean() // returns [1, 0, true, false, "foo", ""] + + +Array Method: indexOf {#Array:indexOf} +-------------------------------------- + +Returns the index of the first element within the array equal to the specified value, or -1 if the value is not found. +This method is provided only for browsers without native [Array:indexOf][] support. + +### Syntax: + + var index = myArray.indexOf(item[, from]); + +### Returns: + +* (*number*) The index of the first element within the array equal to the specified value. If not found, returns -1. + +### Arguments: + +1. item - (*object*) The item to search for in the array. +2. from - (*number*, optional: defaults to 0) The index of the array at which to begin the search. + +### Examples: + + ['apple', 'lemon', 'banana'].indexOf('lemon'); //returns 1 + ['apple', 'lemon'].indexOf('banana'); //returns -1 + +### See Also: + +- [MDC Array:indexOf][] + + + +Array Method: map {#Array:map} +------------------------------ + +Creates a new array with the results of calling a provided function on every element in the array. +This method is provided only for browsers without native [Array:map][] support. + +### Syntax: + + var mappedArray = myArray.map(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function to produce an element of the new Array from an element of the current one. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information see [Function:bind][]. + +#### Argument: fn + +##### Syntax: + + fn(item, index, array) + +##### Arguments: + +1. item - (*mixed*) The current item in the array. +2. index - (*number*) The current item's index in the array. +3. array - (*array*) The actual array. + +### Returns: + +* (*array*) The new mapped array. + +### Examples: + + var timesTwo = [1, 2, 3].map(function(item, index){ + return item * 2; + }); //timesTwo = [2, 4, 6]; + +### See Also: + +- [MDC Array:map][] + + + +Array Method: some {#Array:some} +-------------------------------- + +Returns true if at least one element in the array satisfies the provided testing function. +This method is provided only for browsers without native [Array:some][] support. + +### Syntax: + + var somePassed = myArray.some(fn[, bind]); + +### Returns: + +* (*boolean*) If at least one element in the array satisfies the provided testing function returns true. Otherwise, returns false. + +### Arguments: + +1. fn - (*function*) The function to test for each element. This function is passed the item and its index in the array. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information see [Function:bind][]. + +#### Argument: fn + +##### Syntax: + + fn(item, index, array) + +##### Arguments: + +1. item - (*mixed*) The current item in the array. +2. index - (*number*) The current item's index in the array. +3. array - (*array*) The actual array. + +### Examples: + + var isAnyBigEnough = [10, 4, 25, 100].some(function(item, index){ + return item > 20; + }); //isAnyBigEnough = true + +### See Also: + +- [MDC Array:some][] + + + +Array Method: associate {#Array:associate} +------------------------------------------ + +Creates an object with key-value pairs based on the array of keywords passed in and the current content of the array. + +### Syntax: + + var associated = myArray.associate(obj); + +### Arguments: + +1. obj - (*array*) Its items will be used as the keys of the object that will be created. + +### Returns: + +* (*object*) The new associated object. + +### Examples: + + var animals = ['Cow', 'Pig', 'Dog', 'Cat']; + var sounds = ['Moo', 'Oink', 'Woof', 'Miao']; + sounds.associate(animals); + //returns {'Cow': 'Moo', 'Pig': 'Oink', 'Dog': 'Woof', 'Cat': 'Miao'} + + + +Array Method: link {#Array:link} +-------------------------------- + +Accepts an object of key / function pairs to assign values. + +### Syntax: + + var result = Array.link(array, object); + +### Arguments: + +1. object - (*object*) An object containing key / function pairs must be passed to be used as a template for associating values with the different keys. + +### Returns: + +* (*object*) The new associated object. + +### Examples: + + var el = document.createElement('div'); + var arr2 = [100, 'Hello', {foo: 'bar'}, el, false]; + arr2.link({myNumber: Number.type, myElement: Element.type, myObject: Object.type, myString: String.type, myBoolean: $defined}); + //returns {myNumber: 100, myElement: el, myObject: {foo: 'bar'}, myString: 'Hello', myBoolean: false} + + + +Array Method: contains {#Array:contains} +---------------------------------------- + +Tests an array for the presence of an item. + +### Syntax: + + var inArray = myArray.contains(item[, from]); + +### Arguments: + +1. item - (*object*) The item to search for in the array. +2. from - (*number*, optional: defaults to 0) The index of the array at which to begin the search. + +### Returns: + +* (*boolean*) If the array contains the item specified, returns true. Otherwise, returns false. + +### Examples: + + ["a","b","c"].contains("a"); //returns true + ["a","b","c"].contains("d"); //returns false + +### See Also: + +- [MDC Array:indexOf][] + + + +Array Method: extend {#Array:extend} +------------------------------------ + +Extends an array with all the items of another. + +### Syntax: + + myArray.extend(array); + +### Arguments: + +1. array - (*array*) The array whose items should be extended into this array. + +### Returns: + +* (*array*) This array, extended. + +### Examples: + + var animals = ['Cow', 'Pig', 'Dog']; + animals.extend(['Cat', 'Dog']); //animals = ['Cow', 'Pig', 'Dog', 'Cat', 'Dog']; + + + +Array Method: getLast {#Array:getLast} +-------------------------------------- + +Returns the last item from the array. + +### Syntax: + + myArray.getLast(); + +### Returns: + +* (*mixed*) The last item in this array. +* (*null*) If this array is empty, returns null. + +### Examples: + + ['Cow', 'Pig', 'Dog', 'Cat'].getLast(); //returns 'Cat' + + + +Array Method: getRandom {#Array:getRandom} +------------------------------------------ + +Returns a random item from the array. + +### Syntax: + + myArray.getRandom(); + +### Returns: + +* (*mixed*) A random item from this array. If this array is empty, returns null. + +### Examples: + + ['Cow', 'Pig', 'Dog', 'Cat'].getRandom(); //returns one of the items + + + +Array Method: include {#Array:include} +-------------------------------------- + +Pushes the passed element into the array if it's not already present (case and type sensitive). + +### Syntax: + + myArray.include(item); + +### Arguments: + +1. item - (*object*) The item that should be added to this array. + +### Returns: + +* (*array*) This array with the new item included. + +### Examples: + + ['Cow', 'Pig', 'Dog'].include('Cat'); //returns ['Cow', 'Pig', 'Dog', 'Cat'] + ['Cow', 'Pig', 'Dog'].include('Dog'); //returns ['Cow', 'Pig', 'Dog'] + + + +Array Method: combine {#Array:combine} +---------------------------------- + +Combines an array with all the items of another. Does not allow duplicates and is case and type sensitive. + +### Syntax: + + myArray.combine(array); + +### Arguments: + +1. array - (*array*) The array whose items should be combined into this array. + +### Returns: + +* (*array*) This array combined with the new items. + +### Examples: + + var animals = ['Cow', 'Pig', 'Dog']; + animals.combine(['Cat', 'Dog']); //animals = ['Cow', 'Pig', 'Dog', 'Cat']; + + + +Array Method: erase {#Array:erase} +------------------------------------ + +Removes all occurrences of an item from the array. + +### Syntax: + + myArray.erase(item); + +### Arguments: + +1. item - (*object*) The item to search for in the array. + +### Returns: + +* (*array*) This array with all occurrences of the item removed. + +### Examples: + + ['Cow', 'Pig', 'Dog', 'Cat', 'Dog'].erase('Dog') //returns ['Cow', 'Pig', 'Cat'] + ['Cow', 'Pig', 'Dog'].erase('Cat') //returns ['Cow', 'Pig', 'Dog'] + + + +Array Method: empty {#Array:empty} +---------------------------------- + +Empties an array. + +### Syntax: + + myArray.empty(); + +### Returns: + +* (*array*) This array, emptied. + +### Examples: + + var myArray = ['old', 'data']; + myArray.empty(); //myArray is now [] + + +Array Method: flatten {#Array:flatten} +-------------------------------------- + +Flattens a multidimensional array into a single array. + +### Syntax: + + myArray.flatten(); + +### Returns: + +* (*array*) A new flat array. + +### Examples: + + var myArray = [1,2,3,[4,5, [6,7]], [[[8]]]]; + var newArray = myArray.flatten(); //newArray is [1,2,3,4,5,6,7,8] + + + +Array Method: hexToRgb {#Array:hexToRgb} +---------------------------------------- + +Converts an hexidecimal color value to RGB. Input array must be the following hexidecimal color format. +\['FF','FF','FF'\] + +### Syntax: + + myArray.hexToRgb([array]); + +### Arguments: + +1. array - (*boolean*, optional) If true is passed, will output an array (eg. \[255, 51, 0\]) instead of a string (eg. "rgb(255,51,0)"). + +### Returns: + +* (*string*) A string representing the color in RGB. +* (*array*) If the array flag is set, an array will be returned instead. + +### Examples: + + ['11','22','33'].hexToRgb(); //returns "rgb(17,34,51)" + ['11','22','33'].hexToRgb(true); //returns [17, 34, 51] + +### See Also: + +- [String:hexToRgb](/Native/String/#hexToRgb) + + + +Array Method: rgbToHex {#Array:rgbToHex} +---------------------------------------- + +Converts an RGB color value to hexidecimal. Input array must be in one of the following RGB color formats. +\[255,255,255\], or \[255,255,255,1\] + +### Syntax: + + myArray.rgbToHex([array]); + +### Arguments: + +1. array - (*boolean*, optional) If true is passed, will output an array (eg. \['ff','33','00'\]) instead of a string (eg. "#ff3300"). + +### Returns: + +* (*string*) A string representing the color in hexadecimal, or 'transparent' string if the fourth value of rgba in the input array is 0 (rgba). +* (*array*) If the array flag is set, an array will be returned instead. + +### Examples: + + [17,34,51].rgbToHex(); //returns "#112233" + [17,34,51].rgbToHex(true); //returns ['11','22','33'] + [17,34,51,0].rgbToHex(); //returns "transparent" + +### See Also: + +- [String:rgbToHex](/Native/String/#rgbToHex) + +Utility Functions {#Utility} +============================ + + +Function: $A {#A} +----------------- + +Creates a copy of an Array. Useful for applying the Array prototypes to iterable objects such as a DOM Node collection or the arguments object. + +### Syntax: + + var copiedArray = $A(iterable); + +### Arguments: + +1. iterable - (array) The iterable to copy. + +### Returns: + +* (*array*) The new copied array. + +### Examples: + +#### Apply Array to arguments: + + function myFunction(){ + $A(arguments).each(function(argument, index){ + alert(argument); + }); + }; + myFunction("One", "Two", "Three"); //Alerts "One", then "Two", then "Three". + +#### Copy an Array: + + var anArray = [0, 1, 2, 3, 4]; + var copiedArray = $A(anArray); //Returns [0, 1, 2, 3, 4]. + + +[Array]: /core/Native/Array +[Function:bind]: /core/Native/Function/#Function:bind +[MDC Array]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array +[MDC Array:every]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every +[MDC Array:filter]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:filter +[MDC Array:indexOf]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf +[MDC Array:map]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map +[MDC Array:some]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some +[MDC Array:forEach]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach +[Array:every]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every +[Array:filter]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:filter +[Array:indexOf]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf +[Array:map]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map +[Array:some]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some \ No newline at end of file diff --git a/assets/mootools-core/Docs/Native/Event.md b/assets/mootools-core/Docs/Native/Event.md new file mode 100644 index 00000000..b0908a0c --- /dev/null +++ b/assets/mootools-core/Docs/Native/Event.md @@ -0,0 +1,180 @@ +Native: Event {#Event} +====================== + +MooTools Event Methods. + + +Event Method: constructor {#Event:constructor} +---------------------------------------------- + +### Syntax: + + new Event([event[, win]]); + +### Arguments: + +1. event - (*event*) An HTMLEvent Object. +2. win - (*window*, optional: defaults to window) The context of the event. + +#### Properties: + +* shift - (*boolean*) True if the user pressed the shift key. +* control - (*boolean*) True if the user pressed the control key. +* alt - (*boolean*) True if the user pressed the alt key. +* meta - (*boolean*) True if the user pressed the meta key. +* wheel - (*number*) The amount of third button scrolling. +* code - (*number*) The keycode of the key pressed. +* page.x - (*number*) The x position of the mouse, relative to the full window. +* page.y - (*number*) The y position of the mouse, relative to the full window. +* client.x - (*number*) The x position of the mouse, relative to the viewport. +* client.y - (*number*) The y position of the mouse, relative to the viewport. +* key - (*string*) The key pressed as a lowercase string. key can be 'enter', 'up', 'down', 'left', 'right', 'space', 'backspace', 'delete', and 'esc'. +* target - (*element*) The event target, not extended with [$][] for performance reasons. +* relatedTarget - (*element*) The event related target, NOT `extended` with [$][]. + +### Examples: + + $('myLink').addEvent('keydown', function(event){ + //The passed event parameter is already an instance of the Event class. + alert(event.key); //Returns the lowercase letter pressed. + alert(event.shift); //Returns true if the key pressed is shift. + if (event.key == 's' && event.control) alert('Document saved.'); //Executes if the user hits Ctr+S. + }); + +### Notes: + +- Accessing event.page / event.client requires the page to be in [Standards Mode](http://hsivonen.iki.fi/doctype/). +- Every event added with addEvent gets the mootools method automatically, without the need to manually instance it. + + +Event Method: stop {#Event:stop} +-------------------------------- + +Stop an Event from propagating and also executes preventDefault. + +### Syntax: + + myEvent.stop(); + +### Returns: + +* (*object*) This Event instance. + +### Examples: + +##### HTML: + + Visit Google.com + +##### JavaScript + + $('myAnchor').addEvent('click', function(event){ + event.stop(); //Prevents the browser from following the link. + this.set('text', "Where do you think you're going?"); //'this' is Element that fires the Event. + (function(){ + this.set('text', "Instead visit the Blog.").set('href', 'http://blog.mootools.net'); + }).delay(500, this); + }); + +### Notes: + +- Returning false within the function can also stop the propagation of the Event. + +### See Also: + +- [Element.addEvent](#Element:addEvent), [Element.stopPropagation](#Event:stopPropagation), [Event.preventDefault](#Event:preventDefault), [Function:delay][] + + + +Event Method: stopPropagation {#Event:stopPropagation} +------------------------------------------------------ + +Cross browser method to stop the propagation of an event (this stops the event from bubbling up through the DOM). + +### Syntax: + + myEvent.stopPropagation(); + +### Returns: + +* (*object*) This Event object. + +### Examples: + +"#myChild" does not cover the same area as myElement. Therefore, the 'click' differs from parent and child depending on the click location: + +##### HTML: + +
+
+
+ +##### JavaScript + + $('myElement').addEvent('click', function(){ + alert('click'); + return false; // equivalent to stopPropagation. + }); + $('myChild').addEvent('click', function(event){ + event.stopPropagation(); // this will prevent the event to bubble up, and fire the parent's click event. + }); + +### See Also: + +- [Element:addEvent](#Element:addEvent) +- [MDC event.stopPropagation](http://developer.mozilla.org/en/docs/DOM:event.stopPropagation) + + + +Event Method: preventDefault {#Event:preventDefault} +---------------------------------------------------- + +Cross browser method to prevent the default action of the event. + +### Syntax: + + myEvent.preventDefault(); + +### Returns: + +* (*object*) This Event object. + +### Examples: + +##### HTML: + +
+ +
+ +##### JavaScript + + $('myCheckbox').addEvent('click', function(event){ + event.preventDefault(); //Will prevent the checkbox from being "checked". + }); + +### See Also: + +- [Element:addEvent](#Element:addEvent) +- [MDC event.preventDefault](http://developer.mozilla.org/en/docs/DOM:event.preventDefault) + + +Hash: Event.Keys {#Event-Keys} +============================== + +Additional Event key codes can be added by adding properties to the Event.Keys Hash. + +#### Example: + + Event.Keys.shift = 16; + $('myInput').addEvent('keydown', function(event){ + if (event.key == "shift") alert("You pressed shift."); + }); + + + +[$]: /core/Element/#dollar +[Function]: /core/Native/Function +[Function:bind]: /core/Native/Function/#Function:bind +[Function:pass]: /core/Native/Function/#Function:pass +[Function:delay]: /core/Native/Function/#Function:delay \ No newline at end of file diff --git a/assets/mootools-core/Docs/Native/Function.md b/assets/mootools-core/Docs/Native/Function.md new file mode 100644 index 00000000..795019e2 --- /dev/null +++ b/assets/mootools-core/Docs/Native/Function.md @@ -0,0 +1,302 @@ +Native: Function {#Function} +============================ + +Function Methods. + +### See Also: + +- [MDC Function][] + + + +Function Method: create {#Function:create} +------------------------------------------ + +Base function for creating functional closures which is used by all other Function prototypes. + +### Syntax: + + var createdFunction = myFunction.create([options]); + +### Arguments: + +1. [options] - (*object*, optional) The options from which the function will be created. If options is not provided, then creates a copy of the function. + +#### Options: {#Function:create:options} + +* bind - (*object*: defaults to this function) The object that the "this" of the function will refer to. +* event - (*mixed*: defaults to false) If set to true, the function will act as an event listener and receive an event as its first argument. If set to a class name, the function will receive a new instance of this class (with the event passed as argument's constructor) as first argument. +* arguments - (*mixed*: defaults to standard arguments) A single argument or an array of arguments that will be passed as arguments to the function. If both the event and arguments options are set, the event is passed as first argument and the arguments array will follow. +* delay - (*number*: defaults to no delay) If set, the returned function will delay the actual execution by this amount of milliseconds and return a timer handle when called. +* periodical - (*number*: defaults to no periodical execution) If set, the returned function will periodically perform the actual execution with this specified interval and return a timer handle when called. +* attempt - (*boolean*: false) If set to true, the returned function will try to execute and return either the results or null on error. + +### Returns: + +* (*function*) The function that was created as a result of the options passed in. + +### Example: + + var myFunction = function(){ + alert("I'm a function. :D"); + }; + + var mySimpleFunction = myFunction.create(); //Just a simple copy. + + var myAdvancedFunction = myFunction.create({ //When called, this function will attempt. + arguments: [0,1,2,3], + attempt: true, + delay: 1000, + bind: myElement + }); + + + +Function Method: pass {#Function:pass} +-------------------------------------- + +Returns a closure with arguments and bind. + +### Syntax: + + var newFunction = myFunction.pass([args[, bind]]); + +### Arguments: + +1. args - (*mixed*, optional) The arguments to pass to the function (must be an array if passing more than one argument). +2. bind - (*object*, optional) The object that the "this" of the function will refer to. + +### Returns: + +* (*function*) The function whose arguments are passed when called. + +### Example: + + var myFunction = function(){ + var result = 'Passed: '; + for (var i = 0, l = arguments.length; i < l; i++){ + result += (arguments[i] + ' '); + } + return result; + } + var myHello = myFunction.pass('hello'); + var myItems = myFunction.pass(['peach', 'apple', 'orange']); + + //Later in the code, the functions can be executed: + alert(myHello()); //Passes "hello" to myFunction. + alert(myItems()); //Passes the array of items to myFunction. + + + +Function Method: attempt {#Function:attempt} +-------------------------------------------- + +Tries to execute the function. + +### Syntax: + + var result = myFunction.attempt([args[, bind]]); + +### Arguments: + +1. args - (*mixed*, optional) The arguments to pass to the function (must be an array if passing more than one argument). +2. bind - (*object*, optional) The object that the "this" of the function will refer to. + +### Returns: + +* (*mixed*) The function's return value or `null` if an exception is thrown. + +### Example: + + var myObject = { + 'cow': 'moo!' + }; + + var myFunction = function(){ + for (var i = 0; i < arguments.length; i++){ + if(!this[arguments[i]]) throw('doh!'); + } + }; + var result = myFunction.attempt(['pig', 'cow'], myObject); //result = null + + + +Function Method: bind {#Function:bind} +-------------------------------------- + +Changes the scope of `this` within the target function to refer to the bind parameter. + +### Syntax: + + myFunction.bind([bind[, args[, evt]]]); + +### Arguments: + +1. bind - (*object*, optional) The object that the "this" of the function will refer to. +2. args - (*mixed*, optional) The arguments to pass to the function (must be an array if passing more than one argument). + +### Returns: + +* (*function*) The bound function. + +### Example: + + function myFunction(){ + //Note that 'this' here refers to window, not an element. + //The function must be bound to the element we want to manipulate. + this.setStyle('color', 'red'); + }; + var myBoundFunction = myFunction.bind(myElement); + myBoundFunction(); //This will make myElement's text red. + + + +Function Method: bindWithEvent {#Function:bindWithEvent} +-------------------------------------------------------- + +Changes the scope of `this` within the target function to refer to the bind parameter. It also makes "space" for an event. +This allows the function to be used in conjunction with [Element:addEvent][] and arguments. + +### Syntax: + + myFunction.bindWithEvent([bind[, args[, evt]]]); + +### Arguments: + +1. bind - (*object*, optional) The object that the "this" of the function will refer to. +2. args - (*mixed*, optional) The arguments to pass to the function (must be an array if passing more than one argument). + +### Returns: + +* (*function*) The bound function. + +### Example: + + var Logger = new Class({ + log: function(){ + console.log.apply(null, arguments); + } + }); + + var Log = new Logger(); + + $('myElement').addEvent('click', function(event, offset){ + offset += event.client.x; + this.log('clicked; moving to:', offset); // this refers to myClass + event.target.setStyle('top', offset); + return false; + }).bindWithEvent(Log, 100)); + + +Function Method: delay {#Function:delay} +---------------------------------------- + +Delays the execution of a function by a specified duration. + +### Syntax: + + var timeoutID = myFunction.delay(delay[, bind[, args]]); + +### Arguments: + +1. delay - (*number*) The duration to wait (in milliseconds). +2. bind - (*object*, optional) The object that the "this" of the function will refer to. +3. args - (*mixed*, optional) The arguments passed (must be an array if the arguments are greater than one). + +### Returns: + +* (*number*) The JavaScript timeout id (for clearing delays). + +### Example: + + var myFunction = function(){ alert('moo! Element id is: ' + this.id); }; + //Wait 50 milliseconds, then call myFunction and bind myElement to it. + myFunction.delay(50, myElement); //Alerts: 'moo! Element id is: ... ' + + //An anonymous function which waits a second and then alerts. + (function(){ alert('one second later...'); }).delay(1000); + + +### See Also: + +- [$clear][], [MDC setTimeout][] + + + +Function Method: periodical {#Function:periodical} +-------------------------------------------------- + +Executes a function in the specified intervals of time. Periodic execution can be stopped using the [$clear][] function. + +### Syntax: + + var intervalID = myFunction.periodical(period[, bind[, args]]); + +### Arguments: + +1. period - (*number*) The duration of the intervals between executions. +2. bind - (*object*, optional) The object that the "this" of the function will refer to. +3. args - (*mixed*, optional) The arguments passed (must be an array if the arguments are greater than one). + +### Returns: + +* (*number*) The Interval id (for clearing a periodical). + +### Example: + + var Site = { counter: 0 }; + var addCount = function(){ this.counter++; }; + addCount.periodical(1000, Site); //Will add the number of seconds at the Site. + + +### See Also: + +- [$clear][], [MDC setInterval][] + + + +Function Method: run {#Function:run} +------------------------------------ + +Runs the Function with specified arguments and binding. The same as apply but reversed and with support for a single argument. + +### Syntax: + + var myFunctionResult = myFunction.run(args[, bind]); + +### Arguments: + +1. args - (*mixed*) An argument, or array of arguments to run the function with. +2. bind - (*object*, optional) The object that the "this" of the function will refer to. + +### Returns: + +* (*mixed*) This Function's return value. + +### Examples: + +#### Simple Run: + + var myFn = function(a, b, c){ + return a + b + c; + } + var myArgs = [1,2,3]; + myFn.run(myArgs); //Returns: 6 + + +#### Run With Binding: + + var myFn = function(a, b, c) { + return a + b + c + this; + } + var myArgs = [1,2,3]; + myFn.run(myArgs, 6); //Returns: 12 + + + +[options]: #Function:create:options +[Element:addEvent]: /core/Element/Element.Event/#Element:addEvent +[$clear]: /core/Core/Core/#clear +[MDC Function]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Function +[MDC setInterval]: http://developer.mozilla.org/en/docs/DOM:window.setInterval +[MDC setTimeout]: http://developer.mozilla.org/en/docs/DOM:window.setTimeout \ No newline at end of file diff --git a/assets/mootools-core/Docs/Native/Hash.md b/assets/mootools-core/Docs/Native/Hash.md new file mode 100644 index 00000000..b4f72c1e --- /dev/null +++ b/assets/mootools-core/Docs/Native/Hash.md @@ -0,0 +1,629 @@ +Native: Hash {#Hash} +==================== + +A custom Object ({}) implementation which does not account for prototypes when setting, getting, or iterating. +Useful because in JavaScript, we cannot use Object.prototype. Instead, we can use Hash.prototype! + + +Hash Method: constructor {#Hash:constructor} +-------------------------------------------- + +### Syntax: + + var myHash = new Hash([object]); + +### Arguments: + +1. object - (*mixed*) A hash or object to implement. + +### Returns: + +* (*hash*) A new Hash instance. + +### Examples: + + var myHash = new Hash({ + aProperty: true, + aMethod: function(){ + return true; + } + }); + alert(myHash.has('aMethod')); //Returns true. + + + +Hash Method: each {#Hash:each} +------------------------------- + +Calls a function for each key-value pair in the object. + +### Syntax: + + myHash.each(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function which should be executed on each item in the Hash. This function is passed the item and its key in the Hash. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information, see [Function:bind][]. + +#### Argument: fn + +##### Syntax: + + fn(value, key, hash) + +##### Arguments: + +1. value - (*mixed*) The current value in the hash. +2. key - (*string*) The current value's key in the hash. +3. hash - (*hash*) The actual hash. + +### Examples: + + var hash = new Hash({first: "Sunday", second: "Monday", third: "Tuesday"}); + hash.each(function(value, key){ + alert("the " + key + " day of the week is " + value); + }); //Alerts "the first day of the week is Sunday", "the second day of the week is Monday", etc. + + + +Hash Method: has {#Hash:has} +---------------------------- + +Tests for the presence of a specified key in the Hash. + +### Syntax: + + var inHash = myHash.has(item); + +### Arguments: + +1. key - (*string*) The key to search for in the Hash. + +### Returns: + +* (*boolean*) If the Hash has a defined value for the specified key, returns true. Otherwise, returns false. + +### Examples: + + var hash = new Hash({'a': 'one', 'b': 'two', 'c': 'three'}); + hash.has('a'); //returns true + hash.has('d'); //returns false + + +### Notes: + +- Testing for a Hash prototype will never return true. Only testing the actual properties of the Hash will return true. + + + +Hash Method: keyOf {#Hash:keyOf} +-------------------------------- + +Returns the key of the specified value. Synonymous with [Array:indexOf][]. + +### Syntax: + + var key = myHash.keyOf(item); + +### Arguments: + +1. item - (*mixed*) The item to search for in the Hash. + +### Returns: + +* (*string*) If the Hash has a the specified item in it, returns the key of that item. +* (*boolean*) Otherwise, returns false. + +### Examples: + + var hash = new Hash({'a': 'one', 'b': 'two', 'c': 3}); + hash.keyOf('two'); //returns 'b' + hash.keyOf(3); //returns 'c' + hash.keyOf('four') //returns false + +### Notes: + +- Testing for a Hash prototype will never return its key. Only the actual properties of the Hash will return their associated key. + + + +Hash Method: hasValue {#Hash:hasValue} +-------------------------------------- + +Tests for the presence of a specified value in the Hash. + +### Syntax: + + var inHash = myHash.hasValue(value); + +### Arguments: + +1. value - (*mixed*) The value to search for in the Hash. + +### Returns: + +* (*boolean*) If the Hash has the passed in value in any of the keys, returns true. Otherwise, returns false. + +### Examples: + + var hash = new Hash({'a': 'one', 'b': 'two', 'c': 'three'}); + hash.hasValue('one'); //returns true + hash.hasValue('four'); //returns false + + +Hash Method: extend {#Hash:extend} +---------------------------------- + +Extends this Hash with the key-value pairs from the object passed in. + +### Syntax: + + myHash.extend(properties); + +### Arguments: + +1. properties - (*object*) The object whose items should be extended into this Hash + +### Returns: + +* (*hash*) This Hash, extended. + +### Examples: + + var hash = new Hash({ + 'name': 'John', + 'lastName': 'Doe' + }); + var properties = { + 'age': '20', + 'sex': 'male', + 'lastName': 'Dorian' + }; + hash.extend(properties); + //hash now holds an object containing: { 'name': 'John', 'lastName': 'Dorian', 'age': '20', 'sex': 'male' }; + + + +Hash Method: combine {#Hash:combine} +-------------------------------- + +Combines this Hash with the key-value pairs of the object passed in. Does not allow duplicates (old values are **not** overwritten by new ones) and is case and type sensitive. + +### Syntax: + + myHash.combine(properties); + +### Arguments: + +1. properties - (*object*) The object whose items should be combined into this Hash. + +### Returns: + +* (*hash*) This Hash, combined with the new key-value pairs. + +### Examples: + + var hash = new Hash({ + 'name': 'John', + 'lastName': 'Doe' + }); + var properties = { + 'name': 'Jane' + 'age': '20', + 'sex': 'male', + 'lastName': 'Dorian' + }; + hash.combine(properties); + //hash now holds an object containing: { 'name': 'John', 'lastName': 'Doe', 'age': '20', 'sex': 'male' }; + + + +Hash Method: erase {#Hash:erase} +---------------------------------- + +Removes the specified key from the Hash. + +### Syntax: + + myHash.erase(key); + +### Arguments: + +1. key - (*string*) The key to search for in the Hash. + +### Returns: + +* (*hash*) This Hash with the specified key and its value removed. + +### Examples: + + var hash = new Hash({ + 'name': 'John', + 'lastName': 'Doe' + }); + hash.erase('lastName'); + //hash now holds an object containing: { 'name': 'John' }; + + + +Hash Method: get {#Hash:get} +---------------------------- + +Retrieves a value from the hash. + +### Syntax: + + myHash.get(key); + +### Arguments: + +1. key - (*string*) The key to retrieve in the Hash. + +### Returns: + +* (*mixed*) Returns the value that corresponds to the key if found. +* (*null*) null if the key doesn't exist. + +### Examples: + + var hash = new Hash({ + 'name': 'John', + 'lastName': 'Doe' + }); + hash.get('name'); //returns 'John' + + + +Hash Method: set {#Hash:set} +---------------------------- + +Adds a key-value pair to the hash or replaces a previous value associated with the specified key. + +### Syntax: + + myHash.set(key, value); + +### Arguments: + +1. key - (*string*) The key to insert or modify in the Hash. +2. value - (*mixed*) The value to associate with the specified key in the Hash. + +### Returns: + +* (*hash*) This Hash with the specified key set to the specified value. + +### Examples: + + var hash = new Hash({ + 'name': 'John', + 'lastName': 'Doe' + }); + hash.set('name', 'Michelle'); //hash.name is now 'Michelle' + + + +Hash Method: empty {#Hash:empty} +-------------------------------- + +Empties the hash. + +### Syntax: + + myHash.empty(); + +### Examples: + + var hash = new Hash({ + 'name': 'John', + 'lastName': 'Doe' + }); + hash.empty(); + //hash now holds an empty object: {} + + + +Hash Method: include {#Hash:include} +------------------------------------ + +Includes the specified key-value pair in the Hash if the key doesn't already exist. + +### Syntax: + + myHash.include(key, value); + +### Arguments: + +1. key - (*string*) The key to insert into the Hash. +2. value - (*mixed*) The value to associate with the specified key in the Hash. + +### Returns: + +* (*hash*) This Hash with the specified key included if it did not previously exist. + +### Examples: + + var hash = new Hash({ + 'name': 'John', + 'lastName': 'Doe' + }); + hash.include('name', 'Michelle'); //hash is unchanged + hash.include('age', 25); //hash.age is now 25 + + + +Hash Method: map {#Hash:map} +---------------------------- + +Creates a new map with the results of calling a provided function on every value in the map. + +### Syntax: + + var mappedHash = myHash.map(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function to produce an element of the new Hash from an element of the current one. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information see [Function:bind][]. + +#### Argument: fn + +##### Syntax: + + fn(value, key, hash) + +##### Arguments: + +1. value - (mixed) The current value in the hash. +2. key - (string) The current value's key in the hash. +3. hash - (hash) The actual hash. + +### Returns: + +* (*hash*) The new mapped hash. + +### Examples: + + var timesTwo = new Hash({a: 1, b: 2, c: 3}).map(function(value, key){ + return value * 2; + }); //timesTwo now holds an object containing: {a: 2, b: 4, c: 6}; + + + +Hash Method: filter {#Hash:filter} +---------------------------------- + +Creates a new Hash with all of the elements of the Hash for which the provided filtering function returns true. + +### Syntax: + + var filteredHash = myHash.filter(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function to test each element of the Hash. This function is passed the value and its key in the Hash. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information see [Function:bind][]. + +#### Argument: fn + +##### Syntax: + + fn(value, key, hash) + +##### Arguments: + +1. value - (*mixed*) The current value in the hash. +2. key - (*string*) The current value's key in the hash. +3. hash - (*hash*) The actual hash. + +### Returns: + +* (*hash*) The new filtered hash. + +### Examples: + + var biggerThanTwenty = new Hash({a: 10, b: 20, c: 30}).filter(function(value, key){ + return value > 20; + }); //biggerThanTwenty now holds an object containing: {c: 30} + + +Hash Method: every {#Hash:every} +-------------------------------- + +Returns true if every value in the object satisfies the provided testing function. + +### Syntax: + + var allPassed = myHash.every(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function to test each element of the Hash. This function is passed the value and its key in the Hash. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information see [Function:bind]. + +#### Argument: fn + +##### Syntax: + + fn(value, key, hash) + +##### Arguments: + +1. value - (*mixed*) The current value in the hash. +2. key - (*string*) The current value's key in the hash. +3. hash - (*hash*) The actual hash. + +### Returns: + +* (*boolean*) If every value in the Hash satisfies the provided testing function, returns true. Otherwise, returns false. + +### Examples: + + var areAllBigEnough = ({a: 10, b: 4, c: 25, d: 100}).every(function(value, key){ + return value > 20; + }); //areAllBigEnough = false + + +Hash Method: some {#Hash:some} +------------------------------ + +Returns true if at least one value in the object satisfies the provided testing function. + +### Syntax: + + var anyPassed = myHash.any(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function to test each element of the Hash. This function is passed the value and its key in the Hash. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information see [Function:bind][]. + +#### Argument: fn + +##### Syntax: + + fn(value, key, hash) + + +##### Arguments: + +1. value - (*mixed*) The current value in the hash. +2. key - (*string*) The current value's key in the hash. +3. hash - (*hash*) The actual hash. + +### Returns: + +* (*boolean*) If any value in the Hash satisfies the provided testing function, returns true. Otherwise, returns false. + +### Examples: + + var areAnyBigEnough = ({a: 10, b: 4, c: 25, d: 100}).some(function(value, key){ + return value > 20; + }); //isAnyBigEnough = true + + + +Hash Method: getClean {#Hash:getClean} +-------------------------------------- + +Returns a a clean object from an Hash. + +### Syntax: + + myHash.getClean(); + +### Returns: + +* (*object*) a clean object + +### Examples: + + var hash = new Hash({ + 'name': 'John', + 'lastName': 'Doe' + }); + hash = hash.getClean(); // hash doesnt contain Hash prototypes anymore + hash.each() //error! + + + +Hash Method: getKeys {#Hash:getKeys} +------------------------------------ + +Returns an array containing all the keys, in the same order as the values returned by [Hash:getValues][]. + +### Syntax: + + var keys = myHash.getKeys(); + +### Returns: + +* (*array*) An array containing all the keys of the hash. + + + +Hash Method: getValues {#Hash:getValues} +---------------------------------------- + +Returns an array containing all the values, in the same order as the keys returned by [Hash:getKeys][]. + +### Syntax: + + var values = myHash.getValues(); + +### Returns: + +* (*array*) An array containing all the values of the hash. + + + +Hash Method: getLength {#Hash:getLength} +---------------------------------------- + +Returns the number of keys in the Hash. + +### Syntax: + + var length = myHash.getLength(); + +### Returns: + +* (*number*) The length of the Hash. + +### Examples: + + var hash = new Hash({ + 'name': 'John', + 'lastName': 'Doe' + }); + hash.getLength(); // returns 2 + + + +Hash Method: toQueryString {#Hash:toQueryString} +------------------------------------------------ + +Generates a query string from key/value pairs in an object and URI encodes the values. + +### Syntax: + + var queryString = myHash.toQueryString(); + +### Arguments: + +1. source - (*object*) The object to generate the query string from. + +### Returns: + +* (*string*) The query string. + +### Examples: + +#### Using Hash generic: + + Hash.toQueryString({apple: "red", lemon: "yellow"}); //returns "apple=red&lemon=yellow" + +#### Using Hash instance: + + var myHash = new Hash({apple: "red", lemon: "yellow"}); + myHash.toQueryString(); //returns "apple=red&lemon=yellow" + + +Utility Functions {#Utility} +============================ + +Function: $H {#H} +----------------- + +Shortcut for the new [Hash](/Core/#Hash). + +### See Also: + +- [Hash][] + + +[Hash]: #Hash +[Array:indexOf]: /core/Native/Array/#Array:indexOf +[Hash:getKeys]: #Hash:getKeys +[Hash:getValues]: #Hash:getValues +[Function:bind]: /core/Native/Function#Function:bind diff --git a/assets/mootools-core/Docs/Native/Number.md b/assets/mootools-core/Docs/Native/Number.md new file mode 100644 index 00000000..61970202 --- /dev/null +++ b/assets/mootools-core/Docs/Native/Number.md @@ -0,0 +1,135 @@ +Native: Number {#Number} +======================== + +A collection of the Number Object methods. + +### See Also: + +- [MDC Number][] + +### Notes: + +Every Math method is mirrored in the Number object, both as prototype and generic. + + +Number Method: limit {#Number:limit} +------------------------------------ + +Limits this number between two bounds. + +### Syntax: + + myNumber.limit(min, max); + +### Arguments: + +1. min - (*number*) The minimum possible value. +2. max - (*number*) The maximum possible value. + +### Returns: + +* (*number*) The number bounded between the given limits. + +### Examples: + + (12).limit(2, 6.5); //Returns: 6.5 + (-4).limit(2, 6.5); //Returns: 2 + (4.3).limit(2, 6.5); //Returns: 4.3 + + + +Number Method: round {#Number:round} +------------------------------------ + +Returns this number rounded to the specified precision. + +### Syntax: + + myNumber.round([precision]); + +### Arguments: + +1. precision - (*number*, optional: defaults to 0) The number of digits after the decimal place. + +### Returns: + +* (number) The number, rounded. + +### Notes: + +- Argument may also be negative. + +### Examples: + + (12.45).round() //Returns: 12 + (12.45).round(1) //Returns: 12.5 + (12.45).round(-1) //Returns: 10 + + + +Number Method: times {#Number:times} +------------------------------------ + +Executes the function passed in the specified number of times. + +### Syntax: + + myNumber.times(fn[, bind]); + +### Arguments: + +1. fn - (*function*) The function which should be executed on each iteration of the loop. This function is passed the current iteration's index. +2. bind - (*object*, optional) The object to use as 'this' in the function. For more information see [Function:bind](/Native/Function/#Function:bind). + +### Examples: + + (4).times(alert); //Alerts "0", then "1", then "2", then "3". + + + +Number Method: toFloat {#Number:toFloat} +---------------------------------------- + +Returns this number as a float. Useful because toFloat must work on both Strings and Numbers. + +### Syntax: + + myNumber.toFloat(); + +### Returns: + +* (*number*) The number as a float. + +### Examples: + + (111).toFloat(); //returns 111 + (111.1).toFloat(); //returns 111.1 + + + +Number Method: toInt {#Number:toInt} +------------------------------------ + +Returns this number as another number with the passed in base. Useful because toInt must work on both Strings and Numbers. + +### Syntax: + + myNumber.toInt([base]); + +### Arguments: + +1. base - (*number*, optional: defaults to 10) The base to use. + +### Returns: + +* (*number*) A number with the base provided. + +### Examples: + + (111).toInt(); //returns 111 + (111.1).toInt(); //returns 111 + (111).toInt(2); //returns 7 + + + +[MDC Number]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Number \ No newline at end of file diff --git a/assets/mootools-core/Docs/Native/String.md b/assets/mootools-core/Docs/Native/String.md new file mode 100644 index 00000000..ed6df8e3 --- /dev/null +++ b/assets/mootools-core/Docs/Native/String.md @@ -0,0 +1,356 @@ +Native: String {#String} +======================== + +A collection of the String Object prototype methods. + +### See Also: + +- [MDC String][] + + + +String Method: test {#String:test} +---------------------------------- + +Searches for a match between the string and a regular expression. +For more information see [MDC Regexp:test][]. + +### Syntax: + + myString.test(regex[,params]); + +### Arguments: + +1. regex - (*mixed*) The string or regular expression you want to match the string with. +2. params - (*string*, optional) If first parameter is a string, any parameters you want to pass to the regular expression ('g' has no effect). + +### Returns: + +* (*boolean*) `true`, if a match for the regular expression is found in this string. +* (*boolean*) `false` if is not found + +### Examples: + + "I like cookies".test("cookie"); //returns true + "I like cookies".test("COOKIE", "i"); //returns true (ignore case) + "I like cookies".test("cake"); //returns false + +### See Also: + +- [MDC Regular Expressions][] + + + +String Method: contains {#String:contains} +------------------------------------------ + +Checks to see if the string passed in is contained in this string. +If the separator parameter is passed, will check to see if the string is contained in the list of values separated by that parameter. + +### Syntax: + + myString.contains(string[, separator]); + +### Arguments: + +1. string - (*string*) The string to search for. +2. separator - (*string*, optional) The string that separates the values in this string (eg. Element classNames are separated by a ' '). + +### Returns: + +* (*boolean*) `true` if the string is contained in this string +* (*boolean*) `false` if not. + +### Examples: + + 'a bc'.contains('bc'); //returns true + 'a b c'.contains('c', ' '); //returns true + 'a bc'.contains('b', ' '); //returns false + + + +String Method: trim {#String:trim} +---------------------------------- + +Trims the leading and trailing spaces off a string. + +### Syntax: + + myString.trim(); + +### Returns: + +* (*string*) The trimmed string. + +### Examples: + + " i like cookies ".trim(); //"i like cookies" + + + +String Method: clean {#String:clean} +------------------------------------ + +Removes all extraneous whitespace from a string and trims it ([String:trim][]). + +### Syntax: + + myString.clean(); + +### Returns: + +* (*string*) The cleaned string. + +### Examples: + + " i like cookies \n\n".clean(); //returns "i like cookies" + + + +String Method: camelCase {#String:camelCase} +-------------------------------------------- + +Converts a hyphenated string to a camelcased string. + +### Syntax: + + myString.camelCase(); + +### Returns: + +* (*string*) The camelcased string. + +### Examples: + + "I-like-cookies".camelCase(); //returns "ILikeCookies" + + + +String Method: hyphenate {#String:hyphenate} +-------------------------------------------- + +Converts a camelcased string to a hyphenated string. + +### Syntax: + + myString.hyphenate(); + +### Returns: + +* (*string*) The hyphenated string. + +### Examples: + + "ILikeCookies".hyphenate(); //returns "I-like-cookies" + + + +String Method: capitalize {#String:capitalize} +---------------------------------------------- + +Converts the first letter of each word in a string to uppercase. + +### Syntax: + + myString.capitalize(); + +### Returns: + +* (*string*) The capitalized string. + +### Examples: + + "i like cookies".capitalize(); //returns "I Like Cookies" + + + +String Method: escapeRegExp {#String:escapeRegExp} +-------------------------------------------------- + +Escapes all regular expression characters from the string. + +### Syntax: + + myString.escapeRegExp(); + +### Returns: + +* (*string*) The escaped string. + +### Examples: + + 'animals.sheep[1]'.escapeRegExp(); //returns 'animals\.sheep\[1\]' + + + +String Method: toInt {#String:toInt} +------------------------------------ + +Parses this string and returns a number of the specified radix or base. + +### Syntax: + + myString.toInt([base]); + +### Arguments: + +1. base - (*number*, optional) The base to use (defaults to 10). + +### Returns: + +* (*number*) The number. +* (*NaN*) If the string is not numeric, returns NaN. + +### Examples: + + "4em".toInt(); //returns 4 + "10px".toInt(); //returns 10 + +### See Also: + +- [MDC parseInt][] + + + +String Method: toFloat {#String:toFloat} +---------------------------------------- + +Parses this string and returns a floating point number. + +### Syntax: + + myString.toFloat(); + +### Returns: + +* (*number*) The float. +* (*NaN*) If the string is not numeric, returns NaN. + +### Examples: + + "95.25%".toFloat(); //returns 95.25 + "10.848".toFloat(); //returns 10.848 + +### See Also: + +- [MDC parseFloat][] + + + +String Method: hexToRgb {#String:hexToRgb} +------------------------------------------ + +Converts a hexidecimal color value to RGB. Input string must be in one of the following hexidecimal color formats (with or without the hash). +'#ffffff', #fff', 'ffffff', or 'fff' + +### Syntax: + + myString.hexToRgb([array]); + +### Arguments: + +1. array - (*boolean*, optional) If true is passed, will output an array (eg. \[255, 51, 0\]) instead of a string (eg. "rgb(255,51,0)"). + +### Returns: + +* (*string*) A string representing the color in RGB. +* (*array*) If the array flag is set, an array will be returned instead. + +### Examples: + + "#123".hexToRgb(); //returns "rgb(17,34,51)" + "112233".hexToRgb(); //returns "rgb(17,34,51)" + "#112233".hexToRgb(true); //returns [17, 34, 51] + + + +String Method: rgbToHex {#String:rgbToHex} +------------------------------------------ + +Converts an RGB color value to hexidecimal. Input string must be in one of the following RGB color formats. +"rgb(255,255,255)", or "rgba(255,255,255,1)" + +### Syntax: + + myString.rgbToHex([array]); + +### Arguments: + +1. array - (*boolean*, optional) If true is passed, will output an array (eg. \['ff','33','00'\]) instead of a string (eg. "#ff3300"). + +### Returns: + +* (*string*) A string representing the color in hexadecimal, or transparent if the fourth value of rgba in the input string is 0. +* (*array*) If the array flag is set, an array will be returned instead. + +### Examples: + + "rgb(17,34,51)".rgbToHex(); //returns "#112233" + "rgb(17,34,51)".rgbToHex(true); //returns ['11','22','33'] + "rgba(17,34,51,0)".rgbToHex(); //returns "transparent" + +### See Also: + +- [Array:rgbToHex][] + + + +String Method: stripScripts {#String:stripScripts} +------------------------------------------ + +Strips the String of its `Hello, World."; + myString.stripScripts(); //Returns "Hello, World." + myString.stripScripts(true); //Alerts "Hello", then returns "Hello, World." + + +String Method: substitute {#String:substitute} +------------------------------------------ + +Substitutes keywords in a string using an object/array. +Removes undefined keywords and ignores escaped keywords. + +### Syntax: + + myString.substitute(object[, regexp]); + +### Arguments: + +1. object - (*mixed*) The key/value pairs used to substitute a string. +1. regexp - (*regexp*, optional) The regexp pattern to be used in the string keywords, with global flag. Defaults to /\\?\{([^}]+)\}/g . + +### Returns: + +* (*string*) - The substituted string. + +### Examples: + + var myString = "{subject} is {property_1} and {property_2}."; + var myObject = {subject: 'Jack Bauer', property_1: 'our lord', property_2: 'savior'}; + myString.substitute(myObject); //Jack Bauer is our lord and savior + + + +[MDC String]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:String +[MDC Regexp:test]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:RegExp:test +[MDC Regular Expressions]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Regular_Expressions +[MDC parseInt]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:parseInt +[MDC parseFloat]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:parseFloat +[MDC Array]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array +[String:trim]: #String:trim +[Array:rgbToHex]: /core/Native/Array/#Array:rgbToHex \ No newline at end of file diff --git a/assets/mootools-core/Docs/Request/Request.HTML.md b/assets/mootools-core/Docs/Request/Request.HTML.md new file mode 100755 index 00000000..349ccddc --- /dev/null +++ b/assets/mootools-core/Docs/Request/Request.HTML.md @@ -0,0 +1,176 @@ +[Request]: /core/Request/Request + +Class: Request.HTML {#Request-HTML} +=================================== + +Request Specifically made for receiving HTML. + +### Extends: + +[Request][] + +### Syntax: + + var myHTMLRequest = new Request.HTML([options]); + +### Arguments: + +1. options - (*object*, optional) See options below. Also inherited are all the options from [Request][]. + +### Options: + +* evalScripts - (*boolean*: defaults to true) If set to true, `script` tags inside the response will be evaluated. This overrides the `false` default from Request. +* update - (*element*: defaults to null) The Element to insert the response text of the Request into upon completion of the request. + +### Events: + +#### success + +* (*function*) Function to execute when the HTML request completes. This overrides the signature of the Request success event. + +##### Signature: + + onSuccess(responseTree, responseElements, responseHTML, responseJavaScript) + +##### Arguments: + +1. responseTree - (*element*) The node list of the remote response. +2. responseElements - (*array*) An array containing all elements of the remote response. +3. responseHTML - (*string*) The content of the remote response. +4. responseJavaScript - (*string*) The portion of JavaScript from the remote response. + +### Returns: + +* (*object*) A new Request.HTML instance. + +### Examples: + +#### Simple GET Request: + + var myHTMLRequest = new Request.HTML().get('myPage.html'); + +#### POST Request with data as String: + + var myHTMLRequest = new Request.HTML({url:'myPage.html'}).post("user_id=25&save=true"); + +#### Data from Object Passed via GET: + + //Loads "load/?user_id=25". + var myHTMLRequest = new Request.HTML({url:'load/'}).get({'user_id': 25}); + +#### Data from Element via POST: + +##### HTML + +
+

+ Search: + Search in description: + +

+
+ +##### JavaScript + + //Needs to be in a submit event or the form handler. + var myHTMLRequest = new Request.HTML({url:'save/'}).post($('user-form')); + +### See Also: + +[Request][] + + +Hash: Element.Properties {#Element-Properties} +============================================== + +see [Element.Properties](/Element/Element/#Element-Properties) + +Element Property: load {#Element-Properties:load} +------------------------------------------------- + +### Setter + +Sets a default Request.HTML instance for an Element. + +#### Syntax: + + el.set('load'[, options]); + +#### Arguments: + +1. options - (*object*) The Request options. + +#### Returns: + +* (*element*) The target Element. + +#### Example: + + el.set('load', {evalScripts: true}); + el.load('some/request/uri'); + + +### Getter + +Returns either the previously set Request.HTML instance or a new one with default options. + +#### Syntax: + + el.get('load', options); + +#### Arguments: + +1. options - (*object*, optional) The Request.HTML options. If these are passed in, a new instance will be generated, regardless of whether or not one is set. + +#### Returns: + +* (*object*) The Request instance. + +#### Example: + + el.set('load', {method: 'get'}); + el.load('test.html'); + //The getter returns the Request.HTML instance, making its class methods available. + el.get('load').post('http://localhost/script'); + + + +Native: Element {#Element} +========================== + +Custom Native to allow all of its methods to be used with any DOM element via the dollar function [$][]. + +Element Method: load {#Element:load} +------------------------------------ + +Updates the content of the Element with a Request.HTML GET request. + +### Syntax: + + myElement.load(url); + +### Arguments: + +1. url - (*string*) The URL pointing to the server-side document. + +### Returns: + +* (*element*) The target Element. + +### Example: + +##### HTML + +
Loading content...
+ +##### JavaScript + + $('content').load('page_1.html'); + + + +### See Also: + +- [$][], [Request](/Request/Request) + +[$]: /core/Element/Element/#dollar diff --git a/assets/mootools-core/Docs/Request/Request.JSON.md b/assets/mootools-core/Docs/Request/Request.JSON.md new file mode 100755 index 00000000..ca15e0e8 --- /dev/null +++ b/assets/mootools-core/Docs/Request/Request.JSON.md @@ -0,0 +1,48 @@ +Class: Request.JSON {#Request-JSON} +================================= + +Wrapped Request with automated sending and receiving of JavaScript Objects in JSON Format. + +### Extends: + +[Request](/Request/Request) + +### Syntax: + + var myJSONRemote = new Request.JSON([options]); + +### Arguments: + +1. options - (*object*, optional) See below. + +### Options: + +* secure - (*boolean*: defaults to true) If set to true, a syntax check will be done on the result JSON (see [JSON.decode](/Utilities/JSON#JSON:decode)). + +### Events: + +#### success + +Fired when the request completes. This overrides the signature of the Request success event. + +##### Signature: + + onSuccess(responseJSON, responseText) + +##### Arguments: + +1. responseJSON - (*object*) The JSON response object from the remote request. +2. responseText - (*string*) The JSON response as string. + +### Returns: + +* (*object*) A new Request.JSON instance. + +### Example: + + //This code will send a data object via a GET request and alert the retrieved data. + var jsonRequest = new Request.JSON({url: "http://site.com/tellMeAge.php", onComplete: function(person){ + alert(person.age); //Alerts "25 years". + alert(person.height); //Alerts "170 cm". + alert(person.weight); //Alerts "120 kg". + }}).get({'firstName': 'John', 'lastName': 'Doe'}); diff --git a/assets/mootools-core/Docs/Request/Request.md b/assets/mootools-core/Docs/Request/Request.md new file mode 100755 index 00000000..18bec64e --- /dev/null +++ b/assets/mootools-core/Docs/Request/Request.md @@ -0,0 +1,303 @@ +Class: Request {#Request} +========================= + +An XMLHttpRequest Wrapper. + +### Implements: + +[Chain](/Class/Class.Extras#Chain), [Events](/Class/Class.Extras#Events), [Options](/Class/Class.Extras#Options) + +### Syntax: + + var myRequest = new Request([options]); + +### Arguments: + +2. options - (*object*, optional) See below. + +### Options: + +* url - (*string*: defaults to null) The URL to request. +* method - (*string*: defaults to 'post') The HTTP method for the request, can be either 'post' or 'get'. +* data - (*string*: defaults to '') The default data for [Request:send][], used when no data is given. +* link - (*string*: defaults to 'ignore') Can be 'ignore', 'cancel' and 'chain'. + * 'ignore' - Any calls made to start while the request is running will be ignored. (Synonymous with 'wait': true from 1.11) + * 'cancel' - Any calls made to start while the request is running will take precedence over the currently running request. The new request will start immediately, canceling the one that is currently running. (Synonymous with 'wait': false from 1.11) + * 'chain' - Any calls made to start while the request is running will be chained up, and will take place as soon as the current request has finished, one after another. +* async - (*boolean*: defaults to true) If set to false, the requests will be synchronous and freeze the browser during request. +* encoding - (*string*: defaults to 'utf-8') The encoding to be set in the request header. +* headers - (*object*) An object to use in order to set the request headers. +* isSuccess - (*function*) Overrides the built-in isSuccess function. +* evalScripts - (*boolean*: defaults to false) If set to true, `script` tags inside the response will be evaluated. +* evalResponse - (*boolean*: defaults to false) If set to true, the entire response will be evaluated. Responses with javascript content-type will be evaluated automatically. +* emulation - (*boolean*: defaults to true) If set to true, other methods than 'post' or 'get' are appended as post-data named '\_method' (used in rails) +* urlEncoded - (*boolean*: defaults to true) If set to true, the content-type header is set to www-form-urlencoded + encoding +* noCache - (*boolean*; defaults to *false*) If *true*, appends a unique *noCache* value to the request to prevent caching. (IE has a bad habit of caching ajax request values. Including this script and setting the *noCache* value to true will prevent it from caching. The server should ignore the *noCache* value.) + +### Events: + +#### request + +Fired when the Request is sent. + +##### Signature: + + onRequest() + +#### complete + +Fired when the Request is completed. + +##### Signature: + + onComplete() + +#### cancel + +Fired when a request has been cancelled. + +##### Signature: + + onCancel() + +#### success + +Fired when the Request is completed successfully. + +##### Signature: + + onSuccess(responseText, responseXML) + +##### Arguments: + +1. responseText - (*string*) The returned text from the request. +2. responseXML - (*mixed*) The response XML from the request. + +#### failure + +Fired when the request failed (error status code). + +##### Signature: + + onFailure(xhr) + +##### Arguments: + +xhr - (XMLHttpRequest) The transport instance. + +#### exception + +Fired when setting a request header fails. + +##### Signature: + + onException(headerName, value) + +##### Arguments: + +1. headerName - (*string*) The name of the failing header. +2. value - (*string*) The value of the failing header. + +### Properties: + +* running - (*boolean*) True if the request is running. +* response - (*object*) Object with text and XML as keys. You can access this property in the 'success' event. + +### Returns: + +* (*object*) A new Request instance. + +### Example: + + var myRequest = new Request({method: 'get', url: 'requestHandler.php'}); + myRequest.send('name=john&lastname=dorian'); + +### See Also: + + - [Wikipedia: XMLHttpRequest](http://en.wikipedia.org/wiki/XMLHttpRequest) + +Request Method: setHeader {#Request:setHeader} +-------------------------------------- + +Add or modify a header for the request. It will not override headers from the options. + +### Syntax: + + myRequest.setHeader(name, value); + +### Arguments: + +1. name - (*string*) The name for the header. +2. value - (*string*) The value to be assigned. + +### Returns: + +* (*object*) This Request instance. + +### Example: + + var myRequest = new Request({url: 'getData.php', method: 'get', headers: {'X-Request': 'JSON'}}); + myRequest.setHeader('Last-Modified','Sat, 1 Jan 2005 05:00:00 GMT'); + +Request Method: getHeader {#Request:getHeader} +-------------------------------------- + +Returns the given response header or null if not found. + +### Syntax: + + myRequest.getHeader(name); + +### Arguments: + +1. name - (*string*) The name of the header to retrieve the value of. + +### Returns: + +* (*string*) The value of the retrieved header. +* (*null*) `null` if the header is not found. + +### Example: + + var myRequest = new Request(url, {method: 'get', onSuccess: function(responseText, responseXML) { + alert(this.getHeader('Date')); // Alerts the server date (for example, "Thu, 26 Feb 2009 20:26:06 GMT") + }}); + +Request Method: send {#Request:send} +---------------------------- + +Opens the Request connection and sends the provided data with the specified options. + +### Syntax: + + myRequest.send([options]); + +### Arguments: + +1. options - (*object*, optional) The options for the sent Request. Will also accept data as a query string for compatibility reasons. + +### Returns: + +* (*object*) This Request instance. + +### Examples: + + var myRequest = new Request({url: 'http://localhost/some_url'}).send("save=username&name=John"); + +Request Method: cancel {#Request:cancel} +-------------------------------- + +Cancels the currently running request, if any. + +### Syntax: + + myRequest.cancel(); + +### Returns: + +* (*object*) This Request instance. + +### Example: + + var myRequest = new Request({url: 'mypage.html', method: 'get'}).send('some=data'); + myRequest.cancel(); + + + +Hash: Element.Properties {#Element-Properties} +============================================== + +see [Element.Properties](/Element/Element/#Element-Properties) + +Element Property: send {#Element-Properties:send} +------------------------------------------------- + +### Setter + +Sets a default Request instance for an Element. This is useful when handling forms. + +#### Syntax: + + el.set('send'[, options]); + +#### Arguments: + +1. options - (*object*) The Request options. + +#### Returns: + +* (*element*) The original element. + +#### Example: + + myForm.set('send', {url: 'contact.php', method: 'get'}); + myForm.send(); //Sends the form. + +### Getter + +Returns the previously set Request instance (or a new one with default options). + +#### Syntax: + + el.get('send'[, options]); + +#### Arguments: + +1. options - (*object*, optional) The Request options. If passed, this method will generate a new instance of the Request class. + +### Returns: + +* (*object*) The Request instance. + +#### Example: + + el.get('send', {method: 'get'}); + el.send(); + el.get('send'); //Returns the Request instance. + +Native: Element {#Element} +========================== + +Custom Native to allow all of its methods to be used with any DOM element via the dollar function [$][]. + + +Element Method: send {#Element:send} +------------------------------------ + +Sends a form or a container of inputs with an HTML request. + +### Syntax: + + myElement.send(url); + +### Arguments: + +1. url - (*string*, optional) The url you want to send the form or the "container of inputs" to. If url is omitted, the action of the form will be used. url cannot be omitted for "container of inputs". + +### Returns: + +* (element) This Element. + +### Example: + +##### HTML + +
+

+ + +

+
+ +##### JavaScript + + $('myForm').send(); + +### Note: + +* The URL is taken from the action attribute of the form. + + + +[$]: /core/Element/Element/#dollar +[Request:send]: #Request:send diff --git a/assets/mootools-core/Docs/Utilities/Cookie.md b/assets/mootools-core/Docs/Utilities/Cookie.md new file mode 100755 index 00000000..3b8f4768 --- /dev/null +++ b/assets/mootools-core/Docs/Utilities/Cookie.md @@ -0,0 +1,107 @@ +Object: Cookie {#Cookie} +======================== + +Sets and accesses cookies. + +### Credits: + +- Based on the functions by Peter-Paul Koch [QuirksMode][]. + +### Options: {#Cookie-options} + +* domain - (*string*: defaults to false) The domain the Cookie belongs to. +* path - (*string*: defaults to false) The path the Cookie belongs to. +* duration - (*number*: defaults to false) The duration of the Cookie before it expires, in days. If set to false or 0, the cookie will be a session cookie that expires when the browser is closed. +* secure - (*boolean*: defaults to false) Stored cookie information can be accessed only from a secure environment. + +### Notes: + +- In order to share the Cookie with pages located in a different path, the [Cookie.options.domain][] value must be set. + + + +Cookie Method: write {#Cookie:write} +-------------------------------- + +Writes a cookie in the browser. + +### Syntax: + + var myCookie = Cookie.write(key, value[, options]); + +### Arguments: + +1. key - (*string*) The key (or name) of the cookie. +2. value - (*string*) The value to set. Cannot contain semicolons. +3. options - (*mixed*, optional) See [Cookie][]. + +### Returns: + +* (*object*) An object with the options, the key and the value. You can give it as first parameter to Cookie.remove. + +### Examples: + +Saves the Cookie for the Duration of the Session: + + var myCookie = Cookie.write('username', 'Harald'); + +Saves the Cookie for a Day: + + var myCookie = Cookie.write('username', 'JackBauer', {duration: 1}); + + + +Cookie Method: read {#Cookie:read} +-------------------------------- + +Reads the value of a Cookie. + +### Syntax: + + var myCookie = Cookie.read(name); + +### Arguments: + +1. name - (*string*) The name of the Cookie to retrieve. + +### Returns: + +* (*mixed*) The cookie string value, or null if not found. + +### Examples: + + Cookie.read("username"); + + + +Cookie Method: dispose {#Cookie:dispose} +-------------------------------------- + +Removes a cookie from the browser. + +### Syntax: + + var oldCookie = Cookie.dispose(cookie[, options]); + +### Arguments: + +1. name - (*string*) The name of the cookie to remove or a previously saved Cookie instance. +2. options - (*object*, optional) See [Cookie][]. + +### Examples: + +Remove a Cookie: + + Cookie.dispose('username'); //Bye-bye JackBauer! Seeya in 24 Hours. + +Creating a Cookie and Removing it Right Away: + + var myCookie = Cookie.write('username', 'Aaron', {domain: 'mootools.net'}); + if (Cookie.read('username') == 'Aaron') { Cookie.dispose(myCookie); } + + + +[Cookie]: #Cookie +[Cookie.options]: #Cookie-options +[Cookie.options.domain]: #Cookie-options +[QuirksMode]: http://www.quirksmode.org \ No newline at end of file diff --git a/assets/mootools-core/Docs/Utilities/DomReady.md b/assets/mootools-core/Docs/Utilities/DomReady.md new file mode 100644 index 00000000..a7c0864b --- /dev/null +++ b/assets/mootools-core/Docs/Utilities/DomReady.md @@ -0,0 +1,17 @@ +Window Event: domready +======================== + +Contains the window Event 'domready', which will execute when the DOM has loaded. To ensure that DOM elements exist when the code attempting to access them is executed, they should be placed within the 'domready' event. + +This event is only available to the window Element. + +### Example: + + window.addEvent('domready', function() { + alert("The DOM is ready."); + }); + +### See Also: +[Element.Event][] + +[Element.Event]: /core/Element/Element.Event \ No newline at end of file diff --git a/assets/mootools-core/Docs/Utilities/JSON.md b/assets/mootools-core/Docs/Utilities/JSON.md new file mode 100755 index 00000000..e209baa7 --- /dev/null +++ b/assets/mootools-core/Docs/Utilities/JSON.md @@ -0,0 +1,57 @@ +Object: JSON {#JSON} +==================== + +JSON parser and encoder. + +### See Also: + +- [JavaScript Object Notation (JSON.org)](http://www.json.org/) + +JSON Method: encode {#JSON:encode} +---------------------------------- + +Converts an object or array to a JSON string. + +### Syntax: + + var myJSON = JSON.encode(obj); + +### Arguments: + +1. obj - (*object*) The object to convert to string. + +### Returns: + +* (*string*) A JSON string. + +### Examples: + + var fruitsJSON = JSON.encode({apple: 'red', lemon: 'yellow'}); // returns: '{"apple":"red","lemon":"yellow"}' + + + +JSON Method: decode {#JSON:decode} +---------------------------------- + +Converts a JSON string into an JavaScript object. + +### Syntax: + + var object = JSON.decode(string[, secure]); + +### Arguments: + +1. string - (*string*) The string to evaluate. +2. secure - (*boolean*, optional: defaults to false) If set to true, checks for any hazardous syntax and returns null if any found. + +### Returns: + +* (*object*) The object represented by the JSON string. + +### Examples: + + var myObject = JSON.decode('{"apple":"red","lemon":"yellow"}'); //returns: {apple: 'red', lemon: 'yellow'} + +### Credits: + +- JSON test regexp is by [Douglas Crockford](http://crockford.com/) and [Tobie Langel](http://tobielangel.com/). diff --git a/assets/mootools-core/Docs/Utilities/Selectors.md b/assets/mootools-core/Docs/Utilities/Selectors.md new file mode 100644 index 00000000..ac76b153 --- /dev/null +++ b/assets/mootools-core/Docs/Utilities/Selectors.md @@ -0,0 +1,267 @@ +Native: Element {#Element} +========================== + +Custom class to allow all of its methods to be used with any Selectors element via the dollar function [$][]. + +Element Property: getElements {#Element:getElements} +---------------------------------------------------- + +Gets all the elements within an element that match the given selector. + +### Syntax: + + var myElements = myElement.getElements(selector); + +### Arguments: + +1. selector - (*string*) The CSS Selector to match. + +### Returns: + +* (*array*) An [Element][] collection. + +### Examples: + + //Returns all anchors within myElement. + $('myElement').getElements('a'); + + //Returns all input tags with name "dialog". + $('myElement').getElements('input[name=dialog]'); + + //Returns all input tags with names ending with 'log'. + $('myElement').getElements('input[name$=log]'); + + //Returns all email links (starting with "mailto:"). + $('myElement').getElements('a[href^=mailto:]'); + + //Adds events to all Elements with the class name 'email'. + $(document.body).getElements('a.email').addEvents({ + 'mouseenter': function(){ + this.href = 'real@email.com'; + }, + 'mouseleave': function(){ + this.href = '#'; + } + }); + +### Notes: + +- Supports these operators in attribute selectors: + + - '=' : is equal to + - '*=': contains + - '^=' : starts-with + - '$=' : ends-with + - '!=' : is not equal to + - '~=' : contained in a space separated list + - '|=' : contained in a '-' separated list + + + +Element Property: getElement {#Element:getElement} +-------------------------------------------------- + +Same as [Element:getElements](#Element:getElements), but returns only the first. + +### Syntax: + + var anElement = myElement.getElement(selector); + +### Arguments: + +1. selector - (*string*) The CSS Selector to match. + +### Returns: + +* (*mixed*) An extended [Element][], or null if not found. + +### Example: + + var found = $('myElement').getElement('.findMe').setStyle('color', '#f00'); + + + +Selectors.Pseudo {#Selectors} +============================= + +Some default Pseudo Selectors for [Selectors][]. + +### See Also: + +- [W3C Pseudo Classes](http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#pseudo-classes) + + +Selector: enabled {#Selector:enabled} +------------------------------------- + +Matches all Elements that are enabled. + +### Usage: + + ':enabled' + +### Examples: + + $$('*:enabled') + + $('myElement').getElements(':enabled'); + +Selector: empty {#Selector:empty} +--------------------------------- + +Matches all elements which are empty. + +### Usage: + + ':empty' + +### Example: + + $$('div:empty'); + +Selector: contains {#Selector:contains} +--------------------------------------- + +Matches all the Elements which contains the text. + +### Usage: + + ':contains(text)' + +### Variables: + +* text - (string) The text that the Element should contain. + +### Example: + + $$('p:contains("find me")'); + + +Selector: nth-child {#Selector:nth-child} +----------------------------------------- + +Matches every nth child. + +### Usage: + +Nth Expression: + + ':nth-child(nExpression)' + +### Variables: + +* nExpression - (string) A nth expression for the "every" nth-child. + +### Examples: + + $$('#myDiv:nth-child(2n)'); //Returns every even child. + + $$('#myDiv:nth-child(n)'); //Returns all children. + + $$('#myDiv:nth-child(2n+1)') //Returns every odd child. + + $$('#myDiv:nth-child(4n+3)') //Returns Elements 3, 7, 11, 15, etc. + + +Every Odd Child: + + ':nth-child(odd)' + +Every Even Child: + + ':nth-child(even)' + +Only Child: + + ':nth-child(only)' + +First Child: + + 'nth-child(first)' + +Last Child: + + 'nth-child(last)' + +### Note: + +This selector respects the w3c specifications, so it has 1 as its first child, not 0. Therefore nth-child(odd) will actually select the even children, if you think in zero-based indexes. + +Selector: even {#Selector:even} +------------------------------- + +Matches every even child. + +### Usage: + + ':even' + +### Example: + + $$('td:even'); + +### Note: + +This selector is not part of the w3c specification, therefore its index starts at 0. This selector is highly recommended over nth-child(even), as this will return the real even children. + +Selector: odd {#Selector:odd} +----------------------------- + +Matches every odd child. + +### Usage: + + ':odd' + +### Example: + + $$('td:odd'); + +### Note: + +This selector is not part of the w3c specification, therefore its index starts at 0. This selector is highly recommended over nth-child(odd), as this will return the real odd children. + +Selector: first {#Selector:first-child} +--------------------------------- + +Matches the first child. + +### Usage: + + ':first-child' + +### Example: + + $$('td:first-child'); + + +Selector: last {#Selector:last-child} +------------------------------------- + + Matches the last child. + +### Usage: + + ':last-child' + +### Example: + + $$('td:last-child'); + + +Selector: only {#Selector:only-child} +------------------------------------- + +Matches an only child of its parent Element. + +### Usage: + + ':only-child' + +### Example: + + $$('td:only-child'); + +[$]: /core/Element/Element#dollar +[Element]: /core/Element/Element +[Selectors]: /core/Selectors/Selectors diff --git a/assets/mootools-core/Docs/Utilities/Swiff.md b/assets/mootools-core/Docs/Utilities/Swiff.md new file mode 100755 index 00000000..ed0f3ade --- /dev/null +++ b/assets/mootools-core/Docs/Utilities/Swiff.md @@ -0,0 +1,91 @@ +Class: Swiff {#Swiff} +===================== + +Creates and returns a Flash object using supplied parameters. + +### Credits: + +Flash detection and Internet Explorer/Flash Player 9 fix adapted from [SWFObject][]. + +### Syntax: + + var mySwiff = new Swiff(path[, options]); + +### Arguments: + +1. path - (*string*) The path to the SWF file. +2. options - (*object*, optional) See Options below. + +### Options: + +* id - (*string*: defaults to 'Swiff\_' + unique id) The id of the SWF object. +* width - (*number*: defaults to 1) The width of the SWF object. +* height - (*number*: defaults to 1) The height of the SWF object. +* container - (*element*) The container into which the SWF object will be injected. +* params - (*object*) Parameters to be passed to the SWF object (wmode, bgcolor, allowScriptAccess, loop, etc.). + * allowScriptAccess - (*string*: defaults to always) The domain that the SWF object allows access to. + * quality - (*string*: defaults to 'high') The render quality of the movie. + * swLiveConnect - (*boolean*: defaults to true) the swLiveConnect parameter to allow remote scripting. + * wMode - (*string*: defaults to 'transparent') Allows the SWF to be displayed with a transparent background. +* properties - (*object*) Additional attributes for the object element. +* vars - (*object*) Vars will be passed to the SWF as querystring in flashVars. +* callBacks - (*object*) Functions to call from the SWF. These will be available globally in the movie, and bound to the object. + +### Returns: + +* (*element*) A new HTML object Element. + +### Example: + + var obj = new Swiff('myMovie.swf', { + id: 'myBeautifulMovie', + width: 500, + height: 400, + params: { + wmode: 'opaque', + bgcolor: '#ff3300' + }, + vars: { + myVariable: myJsVar, + myVariableString: 'hello' + }, + callBacks: { + load: myOnloadFunc + } + }); + +### Note: + +1. Although Swiff returns the object, this element will NOT have any Element methods applied to it. +2. The $ function on an object/embed tag will only return its reference without further processing. + +Swiff Function: remote {#Swiff:remote} +-------------------------------------- + +Calls an ActionScript function from JavaScript. + +### Syntax: + + var result = Swiff.remote(obj, fn); + +### Arguments: + +1. obj - (*element*) A Swiff instance (an HTML object Element). +2. fn - (*string*) The name of the function to execute in the Flash movie. + +### Returns: + +* (*mixed*) The ActionScript function's result. + +### Example: + + var obj = new Swiff('myMovie.swf'); + //Alerts "This is from the .swf file!". + alert(Swiff.remote(obj, 'myFlashFn')); + +### Note: + +The SWF file must be compiled with the ExternalInterface component. See the Adobe documentation on [External Interface][] for more information. + +[SWFObject]: http://blog.deconcept.com/swfobject/ +[External Interface]: http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001652.html \ No newline at end of file diff --git a/assets/mootools-core/Docs/license.md b/assets/mootools-core/Docs/license.md new file mode 100644 index 00000000..267c276c --- /dev/null +++ b/assets/mootools-core/Docs/license.md @@ -0,0 +1,8 @@ +Attribution-NonCommercial-ShareAlike 3.0 +======================================== + + + +## See Also + + \ No newline at end of file diff --git a/assets/mootools-core/README.md b/assets/mootools-core/README.md new file mode 100644 index 00000000..767669e2 --- /dev/null +++ b/assets/mootools-core/README.md @@ -0,0 +1,6 @@ +MooTools Core +============= +This repository is for MooTools developers, not users. +All users should download MooTools from [MooTools.net](http://mootools.net "MooTools") + +[See the MooTools Wiki for more information](http://github.com/mootools/mootools-core/wikis) diff --git a/assets/mootools-core/Specs/Assets/Scripts/Builder.js b/assets/mootools-core/Specs/Assets/Scripts/Builder.js new file mode 100644 index 00000000..3bd0ceda --- /dev/null +++ b/assets/mootools-core/Specs/Assets/Scripts/Builder.js @@ -0,0 +1,105 @@ +/* +Script: Builder.js + Automatically includes MooTools files right from the project folder. + +License: + MIT-style license. + +Note: + If you use this script in your own page, you must be out of your mind. +*/ + +var Builder = { + + root: '../', + + paths: { + source: 'Source', + specs: 'Specs' + }, + + included: { + source: {}, + specs: {}, + docs: {} + }, + + scripts: { + source: { + 'Core' : ['Core', 'Browser'], + 'Native' : ['Array', 'Function', 'Number', 'String', 'Hash', 'Event'], + 'Class' : ['Class', 'Class.Extras'], + 'Element' : ['Element', 'Element.Event', 'Element.Style', 'Element.Dimensions'], + 'Utilities' : ['Selectors', 'DomReady', 'JSON', 'Cookie', 'Swiff'], + 'Fx' : ['Fx', 'Fx.CSS', 'Fx.Tween', 'Fx.Morph', 'Fx.Transitions'], + 'Request' : ['Request', 'Request.HTML', 'Request.JSON'] + }, + + specs: { + 'Core' : ['Core', 'Browser'], + 'Native' : ['Array', 'String', 'Function', 'Number', 'Hash'], + 'Class' : ['Class', 'Class.Extras'], + 'Element' : ['Element', 'Element.Style'], + 'Utilities' : ['Selectors'] + } + }, + + initialize: function(root){ + if (root) this.root = root; + this.includeType('source'); + return this; + }, + + getFolder: function(type, file){ + var scripts = this.scripts[type]; + for (var folder in scripts){ + for (var i = 0; i < scripts[folder].length; i++){ + var script = scripts[folder][i]; + if (script == file) return folder; + } + } + return false; + }, + + getRequest: function(){ + var pairs = window.location.search.substring(1).split('&'); + var obj = {}; + for (var i = 0, l = pairs.length; i < l; i++){ + var pair = pairs[i].split('='); + obj[pair[0]] = pair[1]; + } + return obj; + }, + + includeFile: function(type, folder, file){ + folder = folder || this.getFolder(type, file); + if (!folder) return false; + this.included[type][folder] = this.included[type][folder] || []; + var files = this.included[type][folder]; + for (var i = 0; i < files.length; i++){ + if (files[i] == file) return false; + } + this.included[type][folder].push(file); + return document.writeln(''); + }, + + includeFolder: function(type, folder){ + var scripts = this.scripts[type][folder]; + for (var i = 0, l = scripts.length; i < l; i++) this.includeFile(type, folder, scripts[i]); + }, + + includeType: function(type){ + for (var folder in this.scripts[type]) this.includeFolder(type, folder); + }, + + includeRequest: function(type){ + var req = this.getRequest(); + if (!req.files && !req.folders) return false; + var files = (req.files) ? req.files.split('+') : []; + var folders = (req.folders) ? req.folders.split('+') : []; + for (var j = 0; j < files.length; j++) this.includeFile(type, null, files[j]); + for (var i = 0; i < folders.length; i++) this.includeFolder(type, folders[i]); + return true; + } + +}; \ No newline at end of file diff --git a/assets/mootools-core/Specs/Assets/Scripts/DiffMatchPatch.js b/assets/mootools-core/Specs/Assets/Scripts/DiffMatchPatch.js new file mode 100755 index 00000000..885e051d --- /dev/null +++ b/assets/mootools-core/Specs/Assets/Scripts/DiffMatchPatch.js @@ -0,0 +1 @@ +function diff_match_patch(){this.Diff_Timeout=1.0;this.Diff_EditCost=4;this.Diff_DualThreshold=32;this.Match_Balance=0.5;this.Match_Threshold=0.5;this.Match_MinLength=100;this.Match_MaxLength=1000;this.Patch_Margin=4;function getMaxBits(){var maxbits=0;var oldi=1;var newi=2;while(oldi!=newi){maxbits++;oldi=newi;newi=newi<<1}return maxbits}this.Match_MaxBits=getMaxBits()}var DIFF_DELETE=-1;var DIFF_INSERT=1;var DIFF_EQUAL=0;diff_match_patch.prototype.diff_main=function(text1,text2,opt_checklines){if(text1==text2){return[[DIFF_EQUAL,text1]]}if(typeof opt_checklines=='undefined'){opt_checklines=true}var checklines=opt_checklines;var commonlength=this.diff_commonPrefix(text1,text2);var commonprefix=text1.substring(0,commonlength);text1=text1.substring(commonlength);text2=text2.substring(commonlength);commonlength=this.diff_commonSuffix(text1,text2);var commonsuffix=text1.substring(text1.length-commonlength);text1=text1.substring(0,text1.length-commonlength);text2=text2.substring(0,text2.length-commonlength);var diffs=this.diff_compute(text1,text2,checklines);if(commonprefix){diffs.unshift([DIFF_EQUAL,commonprefix])}if(commonsuffix){diffs.push([DIFF_EQUAL,commonsuffix])}this.diff_cleanupMerge(diffs);return diffs};diff_match_patch.prototype.diff_compute=function(text1,text2,checklines){var diffs;if(!text1){return[[DIFF_INSERT,text2]]}if(!text2){return[[DIFF_DELETE,text1]]}var longtext=text1.length>text2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;var i=longtext.indexOf(shorttext);if(i!=-1){diffs=[[DIFF_INSERT,longtext.substring(0,i)],[DIFF_EQUAL,shorttext],[DIFF_INSERT,longtext.substring(i+shorttext.length)]];if(text1.length>text2.length){diffs[0][0]=diffs[2][0]=DIFF_DELETE}return diffs}longtext=shorttext=null;var hm=this.diff_halfMatch(text1,text2);if(hm){var text1_a=hm[0];var text1_b=hm[1];var text2_a=hm[2];var text2_b=hm[3];var mid_common=hm[4];var diffs_a=this.diff_main(text1_a,text2_a,checklines);var diffs_b=this.diff_main(text1_b,text2_b,checklines);return diffs_a.concat([[DIFF_EQUAL,mid_common]],diffs_b)}if(checklines&&text1.length+text2.length<250){checklines=false}var linearray;if(checklines){var a=this.diff_linesToChars(text1,text2);text1=a[0];text2=a[1];linearray=a[2]}diffs=this.diff_map(text1,text2);if(!diffs){diffs=[[DIFF_DELETE,text1],[DIFF_INSERT,text2]]}if(checklines){this.diff_charsToLines(diffs,linearray);this.diff_cleanupSemantic(diffs);diffs.push([DIFF_EQUAL,'']);var pointer=0;var count_delete=0;var count_insert=0;var text_delete='';var text_insert='';while(pointer=1&&count_insert>=1){var a=this.diff_main(text_delete,text_insert,false);diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert);pointer=pointer-count_delete-count_insert;for(var j=a.length-1;j>=0;j--){diffs.splice(pointer,0,a[j])}pointer=pointer+a.length}count_insert=0;count_delete=0;text_delete='';text_insert=''}pointer++}diffs.pop()}return diffs};diff_match_patch.prototype.diff_linesToChars=function(text1,text2){var linearray=[];var linehash={};linearray.push('');function diff_linesToCharsMunge(text){var chars='';while(text){var i=text.indexOf('\n');if(i==-1){i=text.length}var line=text.substring(0,i+1);text=text.substring(i+1);if(linehash.hasOwnProperty?linehash.hasOwnProperty(line):(linehash[line]!==undefined)){chars+=String.fromCharCode(linehash[line])}else{linearray.push(line);linehash[line]=linearray.length-1;chars+=String.fromCharCode(linearray.length-1)}}return chars}var chars1=diff_linesToCharsMunge(text1);var chars2=diff_linesToCharsMunge(text2);return[chars1,chars2,linearray]};diff_match_patch.prototype.diff_charsToLines=function(diffs,linearray){for(var x=0;x0&&(new Date()).getTime()>ms_end){return null}v_map1[d]={};for(var k=-d;k<=d;k+=2){if(k==-d||k!=d&&v1[k-1]=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_DELETE,text1.charAt(x)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[0][1]=text2.charAt(y)+path[0][1]}else{path.unshift([DIFF_INSERT,text2.charAt(y)])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_EQUAL,text1.charAt(x)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_path2=function(v_map,text1,text2){var path=[];var x=text1.length;var y=text2.length;var last_op=null;for(var d=v_map.length-2;d>=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[path.length-1][1]+=text1.charAt(text1.length-x-1)}else{path.push([DIFF_DELETE,text1.charAt(text1.length-x-1)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[path.length-1][1]+=text2.charAt(text2.length-y-1)}else{path.push([DIFF_INSERT,text2.charAt(text2.length-y-1)])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[path.length-1][1]+=text1.charAt(text1.length-x-1)}else{path.push([DIFF_EQUAL,text1.charAt(text1.length-x-1)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_commonPrefix=function(text1,text2){if(!text1||!text2||text1.charCodeAt(0)!==text2.charCodeAt(0)){return 0}var pointermin=0;var pointermax=Math.min(text1.length,text2.length);var pointermid=pointermax;var pointerstart=0;while(pointermintext2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;if(longtext.length<10||shorttext.length<1){return null}var dmp=this;function diff_halfMatchI(longtext,shorttext,i){var seed=longtext.substring(i,i+Math.floor(longtext.length/4));var j=-1;var best_common='';var best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b;while((j=shorttext.indexOf(seed,j+1))!=-1){var prefixLength=dmp.diff_commonPrefix(longtext.substring(i),shorttext.substring(j));var suffixLength=dmp.diff_commonSuffix(longtext.substring(0,i),shorttext.substring(0,j));if(best_common.length=longtext.length/2){return[best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b,best_common]}else{return null}}var hm1=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/4));var hm2=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/2));var hm;if(!hm1&&!hm2){return null}else if(!hm2){hm=hm1}else if(!hm1){hm=hm2}else{hm=hm1[4].length>hm2[4].length?hm1:hm2}var text1_a,text1_b,text2_a,text2_b;if(text1.length>text2.length){text1_a=hm[0];text1_b=hm[1];text2_a=hm[2];text2_b=hm[3]}else{text2_a=hm[0];text2_b=hm[1];text1_a=hm[2];text1_b=hm[3]}var mid_common=hm[4];return[text1_a,text1_b,text2_a,text2_b,mid_common]};diff_match_patch.prototype.diff_cleanupSemantic=function(diffs){var changes=false;var equalities=[];var lastequality=null;var pointer=0;var length_changes1=0;var length_changes2=0;while(pointer=bestScore){bestScore=score;bestEquality1=equality1;bestEdit=edit;bestEquality2=equality2}}if(diffs[pointer-1][1]!=bestEquality1){diffs[pointer-1][1]=bestEquality1;diffs[pointer][1]=bestEdit;diffs[pointer+1][1]=bestEquality2}}pointer++}};diff_match_patch.prototype.diff_cleanupEfficiency=function(diffs){var changes=false;var equalities=[];var lastequality='';var pointer=0;var pre_ins=false;var pre_del=false;var post_ins=false;var post_del=false;while(pointer0&&diffs[pointer-count_delete-count_insert-1][0]==DIFF_EQUAL){diffs[pointer-count_delete-count_insert-1][1]+=text_insert.substring(0,commonlength)}else{diffs.splice(0,0,[DIFF_EQUAL,text_insert.substring(0,commonlength)]);pointer++}text_insert=text_insert.substring(commonlength);text_delete=text_delete.substring(commonlength)}commonlength=this.diff_commonSuffix(text_insert,text_delete);if(commonlength!==0){diffs[pointer][1]=text_insert.substring(text_insert.length-commonlength)+diffs[pointer][1];text_insert=text_insert.substring(0,text_insert.length-commonlength);text_delete=text_delete.substring(0,text_delete.length-commonlength)}}if(count_delete===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_INSERT,text_insert])}else if(count_insert===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_DELETE,text_delete])}else{diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_DELETE,text_delete],[DIFF_INSERT,text_insert])}pointer=pointer-count_delete-count_insert+(count_delete?1:0)+(count_insert?1:0)+1}else if(pointer!==0&&diffs[pointer-1][0]==DIFF_EQUAL){diffs[pointer-1][1]+=diffs[pointer][1];diffs.splice(pointer,1)}else{pointer++}count_insert=0;count_delete=0;text_delete='';text_insert=''}}if(diffs[diffs.length-1][1]===''){diffs.pop()}var changes=false;pointer=1;while(pointerloc){break}last_chars1=chars1;last_chars2=chars2}if(diffs.length!=x&&diffs[x][0]===DIFF_DELETE){return last_chars2}return last_chars2+(loc-last_chars1)};diff_match_patch.prototype.diff_prettyHtml=function(diffs){this.diff_addIndex(diffs);var html=[];for(var x=0;x/g,'>');t=t.replace(/\n/g,'¶
');if(m===DIFF_DELETE){html.push('',t,'')}else if(m===DIFF_INSERT){html.push('',t,'')}else{html.push('',t,'')}}return html.join('')};diff_match_patch.prototype.diff_text1=function(diffs){var txt=[];for(var x=0;xthis.Match_MaxBits){return alert('Pattern too long for this browser.')}var s=this.match_alphabet(pattern);var score_text_length=text.length;score_text_length=Math.max(score_text_length,this.Match_MinLength);score_text_length=Math.min(score_text_length,this.Match_MaxLength);var dmp=this;function match_bitapScore(e,x){var d=Math.abs(loc-x);return(e/pattern.length/dmp.Match_Balance)+(d/score_text_length/(1.0-dmp.Match_Balance))}var score_threshold=this.Match_Threshold;var best_loc=text.indexOf(pattern,loc);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}best_loc=text.lastIndexOf(pattern,loc+pattern.length);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}var matchmask=1<<(pattern.length-1);best_loc=null;var bin_min,bin_mid;var bin_max=Math.max(loc+loc,text.length);var last_rd;for(var d=0;d=start;j--){if(d===0){rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]}else{rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]|((last_rd[j+1]<<1)|1)|((last_rd[j]<<1)|1)|last_rd[j+1]}if(rd[j]&matchmask){var score=match_bitapScore(d,j);if(score<=score_threshold){score_threshold=score;best_loc=j;if(j>loc){start=Math.max(0,loc-(j-loc))}else{break}}}}if(match_bitapScore(d+1,loc)>score_threshold){break}last_rd=rd}return best_loc};diff_match_patch.prototype.match_alphabet=function(pattern){var s=Object();for(var i=0;i2){this.diff_cleanupSemantic(diffs);this.diff_cleanupEfficiency(diffs)}}if(diffs.length===0){return[]}var patches=[];var patch=new patch_obj();var char_count1=0;var char_count2=0;var prepatch_text=text1;var postpatch_text=text1;for(var x=0;x=2*this.Patch_Margin){if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch);patch=new patch_obj();prepatch_text=postpatch_text}}if(diff_type!==DIFF_INSERT){char_count1+=diff_text.length}if(diff_type!==DIFF_DELETE){char_count2+=diff_text.length}}if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch)}return patches};diff_match_patch.prototype.patch_apply=function(patches,text){this.patch_splitMax(patches);var results=[];var delta=0;for(var x=0;xthis.Match_MaxBits){var bigpatch=patches[x];patches.splice(x,1);var patch_size=this.Match_MaxBits;var start1=bigpatch.start1;var start2=bigpatch.start2;var precontext='';while(bigpatch.diffs.length!==0){var patch=new patch_obj();var empty=true;patch.start1=start1-precontext.length;patch.start2=start2-precontext.length;if(precontext!==''){patch.length1=patch.length2=precontext.length;patch.diffs.push([DIFF_EQUAL,precontext])}while(bigpatch.diffs.length!==0&&patch.length1 -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') === -1, + KHTML: navigator.userAgent.indexOf('KHTML') !== -1, + Presto: navigator.appName === "Opera", + + // By Platforms + Mac: navigator.userAgent.indexOf("Macintosh") !== -1, + Ubuntu: navigator.userAgent.indexOf('Ubuntu') !== -1, + Win: navigator.userAgent.indexOf('Windows') !== -1, + + // By Browsers + IE: navigator.appName === "Microsoft Internet Explorer", + IE6: navigator.userAgent.indexOf('MSIE 6') !== -1, + IE7: navigator.userAgent.indexOf('MSIE 7') !== -1, + IE8: navigator.userAgent.indexOf('MSIE 8') !== -1, + + FF: navigator.userAgent.indexOf('Firefox') !== -1, + FF2: navigator.userAgent.indexOf('Firefox/2') !== -1, + FF3: navigator.userAgent.indexOf('Firefox/3') !== -1, + Safari: navigator.userAgent.indexOf('Safari') !== -1 + } +}; + + + +/** + * Executor + */ +JSSpec.Executor = function(target, onSuccess, onException) { + this.target = target; + this.onSuccess = typeof onSuccess == 'function' ? onSuccess : JSSpec.EMPTY_FUNCTION; + this.onException = typeof onException == 'function' ? onException : JSSpec.EMPTY_FUNCTION; + + if(JSSpec.Browser.Trident) { + // Exception handler for Trident. It helps to collect exact line number where exception occured. + window.onerror = function(message, fileName, lineNumber) { + var self = window._curExecutor; + var ex = {message:message, fileName:fileName, lineNumber:lineNumber}; + + if(JSSpec._secondPass) { + ex = self.mergeExceptions(JSSpec._assertionFailure, ex); + delete JSSpec._secondPass; + delete JSSpec._assertionFailure; + + ex.type = "failure"; + self.onException(self, ex); + } else if(JSSpec._assertionFailure) { + JSSpec._secondPass = true; + self.run(); + } else { + self.onException(self, ex); + } + + return true; + }; + } +}; +JSSpec.Executor.prototype.mergeExceptions = function(assertionFailure, normalException) { + var merged = { + message:assertionFailure.message, + fileName:normalException.fileName, + lineNumber:normalException.lineNumber + }; + + return merged; +}; + +JSSpec.Executor.prototype.run = function() { + var self = this; + var target = this.target; + var onSuccess = this.onSuccess; + var onException = this.onException; + + window.setTimeout( + function() { + var result; + if(JSSpec.Browser.Trident) { + try{ + window._curExecutor = self; + + result = self.target(); + self.onSuccess(self, result); + }catch(ex){ + self.onException(self, ex); + }; + } else { + try { + result = self.target(); + self.onSuccess(self, result); + } catch(ex) { + if(JSSpec.Browser.Webkit) ex = {message:ex.message, fileName:ex.sourceURL, lineNumber:ex.line}; + + if(JSSpec._secondPass) { + ex = self.mergeExceptions(JSSpec._assertionFailure, ex); + delete JSSpec._secondPass; + delete JSSpec._assertionFailure; + + ex.type = "failure"; + self.onException(self, ex); + } else if(JSSpec._assertionFailure) { + JSSpec._secondPass = true; + self.run(); + } else { + self.onException(self, ex); + } + } + } + }, + 0 + ); +}; + + + +/** + * CompositeExecutor composites one or more executors and execute them sequencially. + */ +JSSpec.CompositeExecutor = function(onSuccess, onException, continueOnException) { + this.queue = []; + this.onSuccess = typeof onSuccess == 'function' ? onSuccess : JSSpec.EMPTY_FUNCTION; + this.onException = typeof onException == 'function' ? onException : JSSpec.EMPTY_FUNCTION; + this.continueOnException = !!continueOnException; +}; + +JSSpec.CompositeExecutor.prototype.addFunction = function(func) { + this.addExecutor(new JSSpec.Executor(func)); +}; + +JSSpec.CompositeExecutor.prototype.addExecutor = function(executor) { + var last = this.queue.length == 0 ? null : this.queue[this.queue.length - 1]; + if(last) { + last.next = executor; + } + + executor.parent = this; + executor.onSuccessBackup = executor.onSuccess; + executor.onSuccess = function(result) { + this.onSuccessBackup(result); + if(this.next) { + this.next.run(); + } else { + this.parent.onSuccess(); + } + }; + executor.onExceptionBackup = executor.onException; + executor.onException = function(executor, ex) { + this.onExceptionBackup(executor, ex); + + if(this.parent.continueOnException) { + if(this.next) { + this.next.run(); + } else { + this.parent.onSuccess(); + } + } else { + this.parent.onException(executor, ex); + } + }; + + this.queue.push(executor); +}; + +JSSpec.CompositeExecutor.prototype.run = function() { + if(this.queue.length > 0) { + this.queue[0].run(); + } +}; + +/** + * Spec is a set of Examples in a specific context + */ +JSSpec.Spec = function(context, entries) { + this.id = JSSpec.Spec.id++; + this.context = context; + this.url = location.href; + + this.filterEntriesByEmbeddedExpressions(entries); + this.extractOutSpecialEntries(entries); + this.examples = this.makeExamplesFromEntries(entries); + this.examplesMap = this.makeMapFromExamples(this.examples); +}; + +JSSpec.Spec.id = 0; +JSSpec.Spec.prototype.getExamples = function() { + return this.examples; +}; + +JSSpec.Spec.prototype.hasException = function() { + return this.getTotalFailures() > 0 || this.getTotalErrors() > 0; +}; + +JSSpec.Spec.prototype.getTotalFailures = function() { + var examples = this.examples; + var failures = 0; + for(var i = 0; i < examples.length; i++) { + if(examples[i].isFailure()) failures++; + } + return failures; +}; + +JSSpec.Spec.prototype.getTotalErrors = function() { + var examples = this.examples; + var errors = 0; + for(var i = 0; i < examples.length; i++) { + if(examples[i].isError()) errors++; + } + return errors; +}; + +JSSpec.Spec.prototype.filterEntriesByEmbeddedExpressions = function(entries) { + var isTrue; + for(name in entries) if(entries.hasOwnProperty(name)) { + var m = name.match(/\[\[(.+)\]\]/); + if(m && m[1]) { + eval("isTrue = (" + m[1] + ")"); + if(!isTrue) delete entries[name]; + } + } +}; + +JSSpec.Spec.prototype.extractOutSpecialEntries = function(entries) { + this.beforeEach = JSSpec.EMPTY_FUNCTION; + this.beforeAll = JSSpec.EMPTY_FUNCTION; + this.afterEach = JSSpec.EMPTY_FUNCTION; + this.afterAll = JSSpec.EMPTY_FUNCTION; + + for(name in entries) if(entries.hasOwnProperty(name)) { + if(name == 'before' || name == 'before each' || name == 'before_each') { + this.beforeEach = entries[name]; + } else if(name == 'before all' || name == 'before_all') { + this.beforeAll = entries[name]; + } else if(name == 'after' || name == 'after each' || name == 'after_each') { + this.afterEach = entries[name]; + } else if(name == 'after all' || name == 'after_all') { + this.afterAll = entries[name]; + } + } + + delete entries['before']; + delete entries['before each']; + delete entries['before_each']; + delete entries['before all']; + delete entries['before_all']; + delete entries['after']; + delete entries['after each']; + delete entries['after_each']; + delete entries['after all']; + delete entries['after_all']; +}; + +JSSpec.Spec.prototype.makeExamplesFromEntries = function(entries) { + var examples = []; + for(name in entries) if(entries.hasOwnProperty(name)) { + examples.push(new JSSpec.Example(name, entries[name], this.beforeEach, this.afterEach)); + } + return examples; +}; + +JSSpec.Spec.prototype.makeMapFromExamples = function(examples) { + var map = {}; + for(var i = 0; i < examples.length; i++) { + var example = examples[i]; + map[example.id] = examples[i]; + } + return map; +}; + +JSSpec.Spec.prototype.getExampleById = function(id) { + return this.examplesMap[id]; +}; + +JSSpec.Spec.prototype.getExecutor = function() { + var self = this; + var onException = function(executor, ex) { + self.exception = ex; + }; + + var composite = new JSSpec.CompositeExecutor(); + composite.addFunction(function() {JSSpec.log.onSpecStart(self);}); + composite.addExecutor(new JSSpec.Executor(this.beforeAll, null, function(exec, ex) { + self.exception = ex; + JSSpec.log.onSpecEnd(self); + })); + + var exampleAndAfter = new JSSpec.CompositeExecutor(null,null,true); + for(var i = 0; i < this.examples.length; i++) { + exampleAndAfter.addExecutor(this.examples[i].getExecutor()); + } + exampleAndAfter.addExecutor(new JSSpec.Executor(this.afterAll, null, onException)); + exampleAndAfter.addFunction(function() {JSSpec.log.onSpecEnd(self);}); + composite.addExecutor(exampleAndAfter); + + return composite; +}; + +/** + * Example + */ +JSSpec.Example = function(name, target, before, after) { + this.id = JSSpec.Example.id++; + this.name = name; + this.target = target; + this.before = before; + this.after = after; +}; + +JSSpec.Example.id = 0; +JSSpec.Example.prototype.isFailure = function() { + return this.exception && this.exception.type == "failure"; +}; + +JSSpec.Example.prototype.isError = function() { + return this.exception && !this.exception.type; +}; + +JSSpec.Example.prototype.getExecutor = function() { + var self = this; + var onException = function(executor, ex) { + self.exception = ex; + }; + + var composite = new JSSpec.CompositeExecutor(); + composite.addFunction(function() {JSSpec.log.onExampleStart(self);}); + composite.addExecutor(new JSSpec.Executor(this.before, null, function(exec, ex) { + self.exception = ex; + JSSpec.log.onExampleEnd(self); + })); + + var targetAndAfter = new JSSpec.CompositeExecutor(null,null,true); + + targetAndAfter.addExecutor(new JSSpec.Executor(this.target, null, onException)); + targetAndAfter.addExecutor(new JSSpec.Executor(this.after, null, onException)); + targetAndAfter.addFunction(function() {JSSpec.log.onExampleEnd(self);}); + + composite.addExecutor(targetAndAfter); + + return composite; +}; + +/** + * Runner + */ +JSSpec.Runner = function(specs, logger) { + JSSpec.log = logger; + + this.totalExamples = 0; + this.specs = []; + this.specsMap = {}; + this.addAllSpecs(specs); +}; + +JSSpec.Runner.prototype.addAllSpecs = function(specs) { + for(var i = 0; i < specs.length; i++) { + this.addSpec(specs[i]); + } +}; + +JSSpec.Runner.prototype.addSpec = function(spec) { + this.specs.push(spec); + this.specsMap[spec.id] = spec; + this.totalExamples += spec.getExamples().length; +}; + +JSSpec.Runner.prototype.getSpecById = function(id) { + return this.specsMap[id]; +}; + +JSSpec.Runner.prototype.getSpecByContext = function(context) { + for(var i = 0; i < this.specs.length; i++) { + if(this.specs[i].context == context) return this.specs[i]; + } + return null; +}; + +JSSpec.Runner.prototype.getSpecs = function() { + return this.specs; +}; + +JSSpec.Runner.prototype.hasException = function() { + return this.getTotalFailures() > 0 || this.getTotalErrors() > 0; +}; + +JSSpec.Runner.prototype.getTotalFailures = function() { + var specs = this.specs; + var failures = 0; + for(var i = 0; i < specs.length; i++) { + failures += specs[i].getTotalFailures(); + } + return failures; +}; + +JSSpec.Runner.prototype.getTotalErrors = function() { + var specs = this.specs; + var errors = 0; + for(var i = 0; i < specs.length; i++) { + errors += specs[i].getTotalErrors(); + } + return errors; +}; + + +JSSpec.Runner.prototype.run = function() { + JSSpec.log.onRunnerStart(); + var executor = new JSSpec.CompositeExecutor(function() {JSSpec.log.onRunnerEnd()},null,true); + for(var i = 0; i < this.specs.length; i++) { + executor.addExecutor(this.specs[i].getExecutor()); + } + executor.run(); +}; + + +JSSpec.Runner.prototype.rerun = function(context) { + JSSpec.runner = new JSSpec.Runner([this.getSpecByContext(context)], JSSpec.log); + JSSpec.runner.run(); +}; + +/** + * Logger + */ +JSSpec.Logger = function() { + this.finishedExamples = 0; + this.startedAt = null; +}; + +JSSpec.Logger.prototype.onRunnerStart = function() { + this._title = document.title; + + this.startedAt = new Date(); + var container = document.getElementById('jsspec_container'); + if(container) { + container.innerHTML = ""; + } else { + container = document.createElement("DIV"); + container.id = "jsspec_container"; + document.body.appendChild(container); + } + + var title = document.createElement("DIV"); + title.id = "title"; + title.innerHTML = [ + '

JSSpec

', + '
    ', + JSSpec.options.rerun ? '
  • [X] ' + JSSpec.util.escapeTags(decodeURIComponent(JSSpec.options.rerun)) + '
  • ' : '', + '
  • ' + JSSpec.runner.totalExamples + ' examples
  • ', + '
  • 0 failures
  • ', + '
  • 0 errors
  • ', + '
  • 0% done
  • ', + '
  • 0 secs
  • ', + '
', + '

JSSpec homepage

', + ].join(""); + container.appendChild(title); + + var list = document.createElement("DIV"); + list.id = "list"; + list.innerHTML = [ + '

List

', + '' + ].join(""); + container.appendChild(list); + + var log = document.createElement("DIV"); + log.id = "log"; + log.innerHTML = [ + '

Log

', + '
    ', + function() { + var specs = JSSpec.runner.getSpecs(); + var sb = []; + for(var i = 0; i < specs.length; i++) { + var spec = specs[i]; + sb.push('
  • '); + sb.push('

    ' + JSSpec.util.escapeTags(specs[i].context) + ' [rerun]

    '); + sb.push('
      '); + for(var j = 0; j < spec.examples.length; j++) { + var example = spec.examples[j]; + sb.push('
    • '); + sb.push('

      ' + JSSpec.util.escapeTags(example.name) + '

      '); + sb.push('
      '+JSSpec.util.escapeTags(example.target.toString())+'
      '); + sb.push('
    • '); + } + sb.push('
    '); + sb.push('
  • '); + } + return sb.join(""); + }(), + '
' + ].join(""); + + container.appendChild(log); + + // add event handler for toggling + var specs = JSSpec.runner.getSpecs(); + var sb = []; + for(var i = 0; i < specs.length; i++) { + var spec = document.getElementById("spec_" + specs[i].id); + var title = spec.getElementsByTagName("H3")[0]; + title.onclick = function(e) { + var target = document.getElementById(this.parentNode.id + "_examples"); + target.style.display = target.style.display == "none" ? "block" : "none"; + return true; + } + } +}; + +JSSpec.Logger.prototype.onRunnerEnd = function() { + if(JSSpec.runner.hasException()) { + var times = 4; + var title1 = "*" + this._title; + var title2 = "*F" + JSSpec.runner.getTotalFailures() + " E" + JSSpec.runner.getTotalErrors() + "* " + this._title; + } else { + var times = 2; + var title1 = this._title; + var title2 = "Success"; + } + this.blinkTitle(times,title1,title2); +}; + +JSSpec.Logger.prototype.blinkTitle = function(times, title1, title2) { + var times = times * 2; + var mode = true; + + var f = function() { + if(times > 0) { + document.title = mode ? title1 : title2; + mode = !mode; + times--; + window.setTimeout(f, 500); + } else { + document.title = title1; + } + }; + + f(); +}; + +JSSpec.Logger.prototype.onSpecStart = function(spec) { + var spec_list = document.getElementById("spec_" + spec.id + "_list"); + var spec_log = document.getElementById("spec_" + spec.id); + + spec_list.className = "ongoing"; + spec_log.className = "ongoing"; +}; + +JSSpec.Logger.prototype.onSpecEnd = function(spec) { + var spec_list = document.getElementById("spec_" + spec.id + "_list"); + var spec_log = document.getElementById("spec_" + spec.id); + var examples = document.getElementById("spec_" + spec.id + "_examples"); + var className = spec.hasException() ? "exception" : "success"; + + spec_list.className = className; + spec_log.className = className; + + if(JSSpec.options.autocollapse && !spec.hasException()) examples.style.display = "none"; + + if(spec.exception) { + spec_log.appendChild(document.createTextNode(" - " + spec.exception.message)); + } +}; + +JSSpec.Logger.prototype.onExampleStart = function(example) { + var li = document.getElementById("example_" + example.id); + li.className = "ongoing"; +}; + +JSSpec.Logger.prototype.onExampleEnd = function(example) { + var li = document.getElementById("example_" + example.id); + li.className = example.exception ? "exception" : "success"; + + if(example.exception) { + var div = document.createElement("DIV"); + div.innerHTML = example.exception.message + "


" + " at " + example.exception.fileName + ", line " + example.exception.lineNumber + "

"; + li.appendChild(div); + } + + var title = document.getElementById("title"); + var runner = JSSpec.runner; + + title.className = runner.hasException() ? "exception" : "success"; + + this.finishedExamples++; + document.getElementById("total_failures").innerHTML = runner.getTotalFailures(); + document.getElementById("total_errors").innerHTML = runner.getTotalErrors(); + var progress = parseInt(this.finishedExamples / runner.totalExamples * 100); + document.getElementById("progress").innerHTML = progress; + document.getElementById("total_elapsed").innerHTML = (new Date().getTime() - this.startedAt.getTime()) / 1000; + + document.title = progress + "%: " + this._title; +}; + +/** + * IncludeMatcher + */ +JSSpec.IncludeMatcher = function(actual, expected, condition) { + this.actual = actual; + this.expected = expected; + this.condition = condition; + this.match = false; + this.explaination = this.makeExplain(); +}; + +JSSpec.IncludeMatcher.createInstance = function(actual, expected, condition) { + return new JSSpec.IncludeMatcher(actual, expected, condition); +}; + +JSSpec.IncludeMatcher.prototype.matches = function() { + return this.match; +}; + +JSSpec.IncludeMatcher.prototype.explain = function() { + return this.explaination; +}; + +JSSpec.IncludeMatcher.prototype.makeExplain = function() { + if(typeof this.actual.length == 'undefined') { + return this.makeExplainForNotArray(); + } else { + return this.makeExplainForArray(); + } +}; + +JSSpec.IncludeMatcher.prototype.makeExplainForNotArray = function() { + if(this.condition) { + this.match = !!this.actual[this.expected]; + } else { + this.match = !this.actual[this.expected]; + } + + var sb = []; + sb.push('

actual value:

'); + sb.push('

' + JSSpec.util.inspect(this.actual, false, this.expected) + '

'); + sb.push('

should ' + (this.condition ? '' : 'not') + ' include:

'); + sb.push('

' + JSSpec.util.inspect(this.expected) + '

'); + return sb.join(""); +}; + +JSSpec.IncludeMatcher.prototype.makeExplainForArray = function() { + var matches; + if(this.condition) { + for(var i = 0; i < this.actual.length; i++) { + matches = JSSpec.EqualityMatcher.createInstance(this.expected, this.actual[i]).matches(); + if(matches) { + this.match = true; + break; + } + } + } else { + for(var i = 0; i < this.actual.length; i++) { + matches = JSSpec.EqualityMatcher.createInstance(this.expected, this.actual[i]).matches(); + if(matches) { + this.match = false; + break; + } + } + } + + if(this.match) return ""; + + var sb = []; + sb.push('

actual value:

'); + sb.push('

' + JSSpec.util.inspect(this.actual, false, this.condition ? null : i) + '

'); + sb.push('

should ' + (this.condition ? '' : 'not') + ' include:

'); + sb.push('

' + JSSpec.util.inspect(this.expected) + '

'); + return sb.join(""); +}; + +/** + * PropertyLengthMatcher + */ +JSSpec.PropertyLengthMatcher = function(num, property, o, condition) { + this.num = num; + this.o = o; + this.property = property; + if((property == 'characters' || property == 'items') && typeof o.length != 'undefined') { + this.property = 'length'; + } + + this.condition = condition; + this.conditionMet = function(x) { + if(condition == 'exactly') return x.length == num; + if(condition == 'at least') return x.length >= num; + if(condition == 'at most') return x.length <= num; + + throw "Unknown condition '" + condition + "'"; + }; + this.match = false; + this.explaination = this.makeExplain(); +}; + +JSSpec.PropertyLengthMatcher.prototype.makeExplain = function() { + if(this.o._type == 'String' && this.property == 'length') { + this.match = this.conditionMet(this.o); + return this.match ? '' : this.makeExplainForString(); + } else if(typeof this.o.length != 'undefined' && this.property == "length") { + this.match = this.conditionMet(this.o); + return this.match ? '' : this.makeExplainForArray(); + } else if(typeof this.o[this.property] != 'undefined' && this.o[this.property] != null) { + this.match = this.conditionMet(this.o[this.property]); + return this.match ? '' : this.makeExplainForObject(); + } else if(typeof this.o[this.property] == 'undefined' || this.o[this.property] == null) { + this.match = false; + return this.makeExplainForNoProperty(); + } + + this.match = true; +}; + +JSSpec.PropertyLengthMatcher.prototype.makeExplainForString = function() { + var sb = []; + + var exp = this.num == 0 ? + 'be an empty string' : + 'have ' + this.condition + ' ' + this.num + ' characters'; + + sb.push('

actual value has ' + this.o.length + ' characters:

'); + sb.push('

' + JSSpec.util.inspect(this.o) + '

'); + sb.push('

but it should ' + exp + '.

'); + + return sb.join(""); +}; + +JSSpec.PropertyLengthMatcher.prototype.makeExplainForArray = function() { + var sb = []; + + var exp = this.num == 0 ? + 'be an empty array' : + 'have ' + this.condition + ' ' + this.num + ' items'; + + sb.push('

actual value has ' + this.o.length + ' items:

'); + sb.push('

' + JSSpec.util.inspect(this.o) + '

'); + sb.push('

but it should ' + exp + '.

'); + + return sb.join(""); +}; + +JSSpec.PropertyLengthMatcher.prototype.makeExplainForObject = function() { + var sb = []; + + var exp = this.num == 0 ? + 'be empty' : + 'have ' + this.condition + ' ' + this.num + ' ' + this.property + '.'; + + sb.push('

actual value has ' + this.o[this.property].length + ' ' + this.property + ':

'); + sb.push('

' + JSSpec.util.inspect(this.o, false, this.property) + '

'); + sb.push('

but it should ' + exp + '.

'); + + return sb.join(""); +}; + +JSSpec.PropertyLengthMatcher.prototype.makeExplainForNoProperty = function() { + var sb = []; + + sb.push('

actual value:

'); + sb.push('

' + JSSpec.util.inspect(this.o) + '

'); + sb.push('

should have ' + this.condition + ' ' + this.num + ' ' + this.property + ' but there\'s no such property.

'); + + return sb.join(""); +}; + +JSSpec.PropertyLengthMatcher.prototype.matches = function() { + return this.match; +}; + +JSSpec.PropertyLengthMatcher.prototype.explain = function() { + return this.explaination; +}; + +JSSpec.PropertyLengthMatcher.createInstance = function(num, property, o, condition) { + return new JSSpec.PropertyLengthMatcher(num, property, o, condition); +}; + +/** + * EqualityMatcher + */ +JSSpec.EqualityMatcher = {}; + +JSSpec.EqualityMatcher.createInstance = function(expected, actual) { + if(expected == null || actual == null) { + return new JSSpec.NullEqualityMatcher(expected, actual); + } else if(expected._type && expected._type == actual._type) { + if(expected._type == "String") { + return new JSSpec.StringEqualityMatcher(expected, actual); + } else if(expected._type == "Date") { + return new JSSpec.DateEqualityMatcher(expected, actual); + } else if(expected._type == "Number") { + return new JSSpec.NumberEqualityMatcher(expected, actual); + } else if(expected._type == "Array") { + return new JSSpec.ArrayEqualityMatcher(expected, actual); + } else if(expected._type == "Boolean") { + return new JSSpec.BooleanEqualityMatcher(expected, actual); + } + } + + return new JSSpec.ObjectEqualityMatcher(expected, actual); +}; + +JSSpec.EqualityMatcher.basicExplain = function(expected, actual, expectedDesc, actualDesc) { + var sb = []; + + sb.push(actualDesc || '

actual value:

'); + sb.push('

' + JSSpec.util.inspect(actual) + '

'); + sb.push(expectedDesc || '

should be:

'); + sb.push('

' + JSSpec.util.inspect(expected) + '

'); + + return sb.join(""); +}; + +JSSpec.EqualityMatcher.diffExplain = function(expected, actual) { + var sb = []; + + sb.push('

diff:

'); + sb.push('

'); + + var dmp = new diff_match_patch(); + var diff = dmp.diff_main(expected, actual); + dmp.diff_cleanupEfficiency(diff); + + sb.push(JSSpec.util.inspect(dmp.diff_prettyHtml(diff), true)); + + sb.push('

'); + + return sb.join(""); +}; + +/** + * BooleanEqualityMatcher + */ +JSSpec.BooleanEqualityMatcher = function(expected, actual) { + this.expected = expected; + this.actual = actual; +}; + +JSSpec.BooleanEqualityMatcher.prototype.explain = function() { + var sb = []; + + sb.push('

actual value:

'); + sb.push('

' + JSSpec.util.inspect(this.actual) + '

'); + sb.push('

should be:

'); + sb.push('

' + JSSpec.util.inspect(this.expected) + '

'); + + return sb.join(""); +}; + +JSSpec.BooleanEqualityMatcher.prototype.matches = function() { + return this.expected == this.actual; +}; + +/** + * NullEqualityMatcher + */ +JSSpec.NullEqualityMatcher = function(expected, actual) { + this.expected = expected; + this.actual = actual; +}; + +JSSpec.NullEqualityMatcher.prototype.matches = function() { + return this.expected == this.actual && typeof this.expected == typeof this.actual; +}; + +JSSpec.NullEqualityMatcher.prototype.explain = function() { + return JSSpec.EqualityMatcher.basicExplain(this.expected, this.actual); +}; + +JSSpec.DateEqualityMatcher = function(expected, actual) { + this.expected = expected; + this.actual = actual; +}; + +JSSpec.DateEqualityMatcher.prototype.matches = function() { + return this.expected.getTime() == this.actual.getTime(); +}; + +JSSpec.DateEqualityMatcher.prototype.explain = function() { + var sb = []; + + sb.push(JSSpec.EqualityMatcher.basicExplain(this.expected, this.actual)); + sb.push(JSSpec.EqualityMatcher.diffExplain(this.expected.toString(), this.actual.toString())); + + return sb.join(""); +}; + +/** + * ObjectEqualityMatcher + */ +JSSpec.ObjectEqualityMatcher = function(expected, actual) { + this.expected = expected; + this.actual = actual; + this.match = this.expected == this.actual; + this.explaination = this.makeExplain(); +}; + +JSSpec.ObjectEqualityMatcher.prototype.matches = function() {return this.match}; + +JSSpec.ObjectEqualityMatcher.prototype.explain = function() {return this.explaination}; + +JSSpec.ObjectEqualityMatcher.prototype.makeExplain = function() { + if(this.expected == this.actual) { + this.match = true; + return ""; + } + + if(JSSpec.util.isDomNode(this.expected)) { + return this.makeExplainForDomNode(); + } + + var key, expectedHasItem, actualHasItem; + + for(key in this.expected) { + expectedHasItem = this.expected[key] != null && typeof this.expected[key] != 'undefined'; + actualHasItem = this.actual[key] != null && typeof this.actual[key] != 'undefined'; + if(expectedHasItem && !actualHasItem) return this.makeExplainForMissingItem(key); + } + for(key in this.actual) { + expectedHasItem = this.expected[key] != null && typeof this.expected[key] != 'undefined'; + actualHasItem = this.actual[key] != null && typeof this.actual[key] != 'undefined'; + if(actualHasItem && !expectedHasItem) return this.makeExplainForUnknownItem(key); + } + + for(key in this.expected) { + var matcher = JSSpec.EqualityMatcher.createInstance(this.expected[key], this.actual[key]); + if(!matcher.matches()) return this.makeExplainForItemMismatch(key); + } + + this.match = true; +}; + +JSSpec.ObjectEqualityMatcher.prototype.makeExplainForDomNode = function(key) { + var sb = []; + + sb.push(JSSpec.EqualityMatcher.basicExplain(this.expected, this.actual)); + + return sb.join(""); +}; + +JSSpec.ObjectEqualityMatcher.prototype.makeExplainForMissingItem = function(key) { + var sb = []; + + sb.push('

actual value has no item named ' + JSSpec.util.inspect(key) + '

'); + sb.push('

' + JSSpec.util.inspect(this.actual, false, key) + '

'); + sb.push('

but it should have the item whose value is ' + JSSpec.util.inspect(this.expected[key]) + '

'); + sb.push('

' + JSSpec.util.inspect(this.expected, false, key) + '

'); + + return sb.join(""); +}; + +JSSpec.ObjectEqualityMatcher.prototype.makeExplainForUnknownItem = function(key) { + var sb = []; + + sb.push('

actual value has item named ' + JSSpec.util.inspect(key) + '

'); + sb.push('

' + JSSpec.util.inspect(this.actual, false, key) + '

'); + sb.push('

but there should be no such item

'); + sb.push('

' + JSSpec.util.inspect(this.expected, false, key) + '

'); + + return sb.join(""); +}; + +JSSpec.ObjectEqualityMatcher.prototype.makeExplainForItemMismatch = function(key) { + var sb = []; + + sb.push('

actual value has an item named ' + JSSpec.util.inspect(key) + ' whose value is ' + JSSpec.util.inspect(this.actual[key]) + '

'); + sb.push('

' + JSSpec.util.inspect(this.actual, false, key) + '

'); + sb.push('

but it\'s value should be ' + JSSpec.util.inspect(this.expected[key]) + '

'); + sb.push('

' + JSSpec.util.inspect(this.expected, false, key) + '

'); + + return sb.join(""); +}; + + + + +/** + * ArrayEqualityMatcher + */ +JSSpec.ArrayEqualityMatcher = function(expected, actual) { + this.expected = expected; + this.actual = actual; + this.match = this.expected == this.actual; + this.explaination = this.makeExplain(); +}; + +JSSpec.ArrayEqualityMatcher.prototype.matches = function() {return this.match}; + +JSSpec.ArrayEqualityMatcher.prototype.explain = function() {return this.explaination}; + +JSSpec.ArrayEqualityMatcher.prototype.makeExplain = function() { + if(this.expected.length != this.actual.length) return this.makeExplainForLengthMismatch(); + + for(var i = 0; i < this.expected.length; i++) { + var matcher = JSSpec.EqualityMatcher.createInstance(this.expected[i], this.actual[i]); + if(!matcher.matches()) return this.makeExplainForItemMismatch(i); + } + + this.match = true; +}; + +JSSpec.ArrayEqualityMatcher.prototype.makeExplainForLengthMismatch = function() { + return JSSpec.EqualityMatcher.basicExplain( + this.expected, + this.actual, + '

but it should be ' + this.expected.length + '

', + '

actual value has ' + this.actual.length + ' items

' + ); +}; + +JSSpec.ArrayEqualityMatcher.prototype.makeExplainForItemMismatch = function(index) { + var postfix = ["th", "st", "nd", "rd", "th"][Math.min((index + 1) % 10,4)]; + + var sb = []; + + sb.push('

' + (index + 1) + postfix + ' item (index ' + index + ') of actual value is ' + JSSpec.util.inspect(this.actual[index]) + ':

'); + sb.push('

' + JSSpec.util.inspect(this.actual, false, index) + '

'); + sb.push('

but it should be ' + JSSpec.util.inspect(this.expected[index]) + ':

'); + sb.push('

' + JSSpec.util.inspect(this.expected, false, index) + '

'); + + return sb.join(""); +}; + +/** + * NumberEqualityMatcher + */ +JSSpec.NumberEqualityMatcher = function(expected, actual) { + this.expected = expected; + this.actual = actual; +}; + +JSSpec.NumberEqualityMatcher.prototype.matches = function() { + if(this.expected == this.actual) return true; +}; + +JSSpec.NumberEqualityMatcher.prototype.explain = function() { + return JSSpec.EqualityMatcher.basicExplain(this.expected, this.actual); +}; + +/** + * StringEqualityMatcher + */ +JSSpec.StringEqualityMatcher = function(expected, actual) { + this.expected = expected; + this.actual = actual; +}; + +JSSpec.StringEqualityMatcher.prototype.matches = function() { + return this.expected == this.actual; +}; + +JSSpec.StringEqualityMatcher.prototype.explain = function() { + var sb = []; + + sb.push(JSSpec.EqualityMatcher.basicExplain(this.expected, this.actual)); + sb.push(JSSpec.EqualityMatcher.diffExplain(this.expected, this.actual)); + return sb.join(""); +}; + +/** + * PatternMatcher + */ +JSSpec.PatternMatcher = function(actual, pattern, condition) { + this.actual = actual; + this.pattern = pattern; + this.condition = condition; + this.match = false; + this.explaination = this.makeExplain(); +}; + +JSSpec.PatternMatcher.createInstance = function(actual, pattern, condition) { + return new JSSpec.PatternMatcher(actual, pattern, condition); +}; + +JSSpec.PatternMatcher.prototype.makeExplain = function() { + var sb; + if(this.actual == null || this.actual._type != 'String') { + sb = []; + sb.push('

actual value:

'); + sb.push('

' + JSSpec.util.inspect(this.actual) + '

'); + sb.push('

should ' + (this.condition ? '' : 'not') + ' match with pattern:

'); + sb.push('

' + JSSpec.util.inspect(this.pattern) + '

'); + sb.push('

but pattern matching cannot be performed.

'); + return sb.join(""); + } else { + this.match = this.condition == !!this.actual.match(this.pattern); + if(this.match) return ""; + + sb = []; + sb.push('

actual value:

'); + sb.push('

' + JSSpec.util.inspect(this.actual) + '

'); + sb.push('

should ' + (this.condition ? '' : 'not') + ' match with pattern:

'); + sb.push('

' + JSSpec.util.inspect(this.pattern) + '

'); + return sb.join(""); + } +}; + +JSSpec.PatternMatcher.prototype.matches = function() { + return this.match; +}; + +JSSpec.PatternMatcher.prototype.explain = function() { + return this.explaination; +}; + +/** + * Domain Specific Languages + */ +JSSpec.DSL = {}; + +JSSpec.DSL.forString = { + normalizeHtml: function() { + var html = this; + + // Uniformize quotation, turn tag names and attribute names into lower case + html = html.replace(/<(\/?)(\w+)([^>]*?)>/img, function(str, closingMark, tagName, attrs) { + var sortedAttrs = JSSpec.util.sortHtmlAttrs(JSSpec.util.correctHtmlAttrQuotation(attrs).toLowerCase()) + return "<" + closingMark + tagName.toLowerCase() + sortedAttrs + ">" + }); + + // validation self-closing tags + html = html.replace(/<(br|hr|img)([^>]*?)>/mg, function(str, tag, attrs) { + return "<" + tag + attrs + " />"; + }); + + // append semi-colon at the end of style value + html = html.replace(/style="(.*?)"/mg, function(str, styleStr) { + styleStr = JSSpec.util.sortStyleEntries(styleStr.strip()); // for Safari + if(styleStr.charAt(styleStr.length - 1) != ';') styleStr += ";" + + return 'style="' + styleStr + '"' + }); + + // sort style entries + + // remove empty style attributes + html = html.replace(/ style=";"/mg, ""); + + // remove new-lines + html = html.replace(/\r/mg, ''); + html = html.replace(/\n/mg, ''); + + return html; + } +}; + + +JSSpec.DSL.describe = function(context, entries, base) { + if(base) { + for(var i = 0; i < JSSpec.specs.length; i++) { + if(JSSpec.specs[i].context === base) { + base = JSSpec.specs[i]; + break; + } + } + + for(var i = 0; i < base.examples.length; i++) { + var example = base.examples[i]; + + if(!entries[example.name]) entries[example.name] = example.target; + } + } + + JSSpec.specs.push(new JSSpec.Spec(context, entries)); +}; + +JSSpec.DSL.value_of = function(target) { + if(JSSpec._secondPass) return {}; + + var subject = new JSSpec.DSL.Subject(target); + return subject; +}; + +JSSpec.DSL.Subject = function(target) { + this.target = target; +}; + +JSSpec.DSL.Subject.prototype._type = 'Subject'; + +JSSpec.DSL.Subject.prototype.should_fail = function(message) { + JSSpec._assertionFailure = {message:message}; + throw JSSpec._assertionFailure; +}; + +JSSpec.DSL.Subject.prototype.should_be = function(expected) { + var matcher = JSSpec.EqualityMatcher.createInstance(expected, this.target); + if(!matcher.matches()) { + JSSpec._assertionFailure = {message:matcher.explain()}; + throw JSSpec._assertionFailure; + } +}; + +JSSpec.DSL.Subject.prototype.should_not_be = function(expected) { + // TODO JSSpec.EqualityMatcher should support 'condition' + var matcher = JSSpec.EqualityMatcher.createInstance(expected, this.target); + if(matcher.matches()) { + JSSpec._assertionFailure = {message:"'" + this.target + "' should not be '" + expected + "'"}; + throw JSSpec._assertionFailure; + } +}; + +JSSpec.DSL.Subject.prototype.should_be_empty = function() { + this.should_have(0, this.getType() == 'String' ? 'characters' : 'items'); +}; + +JSSpec.DSL.Subject.prototype.should_not_be_empty = function() { + this.should_have_at_least(1, this.getType() == 'String' ? 'characters' : 'items'); +}; + +JSSpec.DSL.Subject.prototype.should_be_true = function() { + this.should_be(true); +}; + +JSSpec.DSL.Subject.prototype.should_be_false = function() { + this.should_be(false); +}; + +JSSpec.DSL.Subject.prototype.should_be_null = function() { + this.should_be(null); +}; + +JSSpec.DSL.Subject.prototype.should_be_undefined = function() { + this.should_be(undefined); +}; + +JSSpec.DSL.Subject.prototype.should_not_be_null = function() { + this.should_not_be(null); +}; + +JSSpec.DSL.Subject.prototype.should_not_be_undefined = function() { + this.should_not_be(undefined); +}; + +JSSpec.DSL.Subject.prototype._should_have = function(num, property, condition) { + var matcher = JSSpec.PropertyLengthMatcher.createInstance(num, property, this.target, condition); + if(!matcher.matches()) { + JSSpec._assertionFailure = {message:matcher.explain()}; + throw JSSpec._assertionFailure; + } +}; + +JSSpec.DSL.Subject.prototype.should_have = function(num, property) { + this._should_have(num, property, "exactly"); +}; + +JSSpec.DSL.Subject.prototype.should_have_exactly = function(num, property) { + this._should_have(num, property, "exactly"); +}; + +JSSpec.DSL.Subject.prototype.should_have_at_least = function(num, property) { + this._should_have(num, property, "at least"); +}; + +JSSpec.DSL.Subject.prototype.should_have_at_most = function(num, property) { + this._should_have(num, property, "at most"); +}; + +JSSpec.DSL.Subject.prototype.should_include = function(expected) { + var matcher = JSSpec.IncludeMatcher.createInstance(this.target, expected, true); + if(!matcher.matches()) { + JSSpec._assertionFailure = {message:matcher.explain()}; + throw JSSpec._assertionFailure; + } +}; + +JSSpec.DSL.Subject.prototype.should_not_include = function(expected) { + var matcher = JSSpec.IncludeMatcher.createInstance(this.target, expected, false); + if(!matcher.matches()) { + JSSpec._assertionFailure = {message:matcher.explain()}; + throw JSSpec._assertionFailure; + } +}; + +JSSpec.DSL.Subject.prototype.should_match = function(pattern) { + var matcher = JSSpec.PatternMatcher.createInstance(this.target, pattern, true); + if(!matcher.matches()) { + JSSpec._assertionFailure = {message:matcher.explain()}; + throw JSSpec._assertionFailure; + } +} +JSSpec.DSL.Subject.prototype.should_not_match = function(pattern) { + var matcher = JSSpec.PatternMatcher.createInstance(this.target, pattern, false); + if(!matcher.matches()) { + JSSpec._assertionFailure = {message:matcher.explain()}; + throw JSSpec._assertionFailure; + } +}; + +JSSpec.DSL.Subject.prototype.getType = function() { + if(typeof this.target == 'undefined') { + return 'undefined'; + } else if(this.target == null) { + return 'null'; + } else if(this.target._type) { + return this.target._type; + } else if(JSSpec.util.isDomNode(this.target)) { + return 'DomNode'; + } else { + return 'object'; + } +}; + +/** + * Utilities + */ +JSSpec.util = { + escapeTags: function(string) { + return string.replace(//img, '>'); + }, + escapeMetastring: function(string) { + return string.replace(/\r/img, '\\r').replace(/\n/img, '\\n').replace(/\¶\;\/img, '\\n').replace(/\t/img, '\\t'); + }, + parseOptions: function(defaults) { + var options = defaults; + + var url = location.href; + var queryIndex = url.indexOf('?'); + if(queryIndex == -1) return options; + + var query = url.substring(queryIndex + 1).split('#')[0]; + var pairs = query.split('&'); + for(var i = 0; i < pairs.length; i++) { + var tokens = pairs[i].split('='); + options[tokens[0]] = tokens[1]; + } + + return options; + }, + correctHtmlAttrQuotation: function(html) { + html = html.replace(/(\w+)=['"]([^'"]+)['"]/mg,function (str, name, value) {return name + '=' + '"' + value + '"';}); + html = html.replace(/(\w+)=([^ '"]+)/mg,function (str, name, value) {return name + '=' + '"' + value + '"';}); + html = html.replace(/'/mg, '"'); + + return html; + }, + sortHtmlAttrs: function(html) { + var attrs = []; + html.replace(/((\w+)="[^"]+")/mg, function(str, matched) { + attrs.push(matched); + }); + return attrs.length == 0 ? "" : " " + attrs.sort().join(" "); + }, + sortStyleEntries: function(styleText) { + var entries = styleText.split(/; /); + return entries.sort().join("; "); + }, + escapeHtml: function(str) { + if(!this._div) { + this._div = document.createElement("DIV"); + this._text = document.createTextNode(''); + this._div.appendChild(this._text); + } + this._text.data = str; + return this._div.innerHTML; + }, + isDomNode: function(o) { + // TODO: make it more stricter + return (typeof o.nodeName == 'string') && (typeof o.nodeType == 'number'); + }, + inspectDomPath: function(o) { + var sb = []; + while(o && o.nodeName != '#document' && o.parent) { + var siblings = o.parentNode.childNodes; + for(var i = 0; i < siblings.length; i++) { + if(siblings[i] == o) { + sb.push(o.nodeName + (i == 0 ? '' : '[' + i + ']')); + break; + } + } + o = o.parentNode; + } + return sb.join(" > "); + }, + inspectDomNode: function(o) { + if(o.nodeType == 1) { + var nodeName = o.nodeName.toLowerCase(); + var sb = []; + sb.push(''); + sb.push("<"); + sb.push(nodeName); + + var attrs = o.attributes; + for(var i = 0; i < attrs.length; i++) { + if( + attrs[i].nodeValue && + attrs[i].nodeName != 'contentEditable' && + attrs[i].nodeName != 'style' && + typeof attrs[i].nodeValue != 'function' + ) sb.push(' ' + attrs[i].nodeName.toLowerCase() + '="' + attrs[i].nodeValue + '"'); + } + if(o.style && o.style.cssText) { + sb.push(' style="' + o.style.cssText + '"'); + } + sb.push('>'); + sb.push(JSSpec.util.escapeHtml(o.innerHTML)); + sb.push('</' + nodeName + '>'); + sb.push(' (' + JSSpec.util.inspectDomPath(o) + ')' ); + sb.push(''); + return sb.join(""); + } else if(o.nodeType == 3) { + return '#text ' + o.nodeValue + ''; + } else { + return 'UnknownDomNode'; + } + }, + inspect: function(o, dontEscape, emphasisKey) { + var sb, inspected; + + if(typeof o == 'undefined') return 'undefined'; + if(o == null) return 'null'; + if(o._type == 'String') return '"' + (dontEscape ? JSSpec.util.escapeMetastring(o) : JSSpec.util.escapeHtml(JSSpec.util.escapeMetastring(o))) + '"'; + + if(o._type == 'Date') { + return '"' + o.toString() + '"'; + } + + if(o._type == 'Number') return '' + (dontEscape ? o : JSSpec.util.escapeHtml(o)) + ''; + + if(o._type == 'Boolean') return '' + o + ''; + + if(o._type == 'RegExp') return '' + JSSpec.util.escapeHtml(o.toString()) + ''; + + if(JSSpec.util.isDomNode(o)) return JSSpec.util.inspectDomNode(o); + + if(o._type == 'Array' || typeof o.length != 'undefined') { + sb = []; + for(var i = 0; i < o.length; i++) { + inspected = JSSpec.util.inspect(o[i]); + sb.push(i == emphasisKey ? ('' + inspected + '') : inspected); + } + return '[' + sb.join(', ') + ']'; + } + + // object + sb = []; + for(var key in o) { + if(key == 'should') continue; + + inspected = JSSpec.util.inspect(key) + ":" + JSSpec.util.inspect(o[key]); + sb.push(key == emphasisKey ? ('' + inspected + '') : inspected); + } + return '{' + sb.join(', ') + '}'; + } +}; + +describe = JSSpec.DSL.describe; +behavior_of = JSSpec.DSL.describe; +value_of = JSSpec.DSL.value_of; +expect = JSSpec.DSL.value_of; // @deprecated + +String.prototype._type = "String"; +Number.prototype._type = "Number"; +Date.prototype._type = "Date"; +Array.prototype._type = "Array"; +Boolean.prototype._type = "Boolean"; +RegExp.prototype._type = "RegExp"; + +var targets = [Array.prototype, Date.prototype, Number.prototype, String.prototype, Boolean.prototype, RegExp.prototype]; + +String.prototype.normalizeHtml = JSSpec.DSL.forString.normalizeHtml; +String.prototype.asHtml = String.prototype.normalizeHtml; //@deprecated +String.prototype.strip = function() {return this.replace(/^\s+/, '').replace(/\s+$/, '');} + + +/** + * Main + */ +JSSpec.defaultOptions = { + autorun: 1, + specIdBeginsWith: 0, + exampleIdBeginsWith: 0, + autocollapse: 1 +}; +JSSpec.options = JSSpec.util.parseOptions(JSSpec.defaultOptions); + +JSSpec.Spec.id = JSSpec.options.specIdBeginsWith; +JSSpec.Example.id = JSSpec.options.exampleIdBeginsWith; + + + +window.onload = function() { + if(JSSpec.specs.length > 0) { + if(!JSSpec.options.inSuite) { + JSSpec.runner = new JSSpec.Runner(JSSpec.specs, new JSSpec.Logger()); + if(JSSpec.options.rerun) { + JSSpec.runner.rerun(decodeURIComponent(JSSpec.options.rerun)); + } else { + JSSpec.runner.run(); + } + } else { + // in suite, send all specs to parent + var parentWindow = window.frames.parent.window; + for(var i = 0; i < JSSpec.specs.length; i++) { + parentWindow.JSSpec.specs.push(JSSpec.specs[i]); + } + } + } else { + var links = document.getElementById('list').getElementsByTagName('A'); + var frameContainer = document.createElement('DIV'); + frameContainer.style.display = 'none'; + document.body.appendChild(frameContainer); + + for(var i = 0; i < links.length; i++) { + var frame = document.createElement('IFRAME'); + frame.src = links[i].href + '?inSuite=0&specIdBeginsWith=' + (i * 10000) + '&exampleIdBeginsWith=' + (i * 10000); + frameContainer.appendChild(frame); + } + } +} \ No newline at end of file diff --git a/assets/mootools-core/Specs/Assets/Scripts/JSSpecSpecs.js b/assets/mootools-core/Specs/Assets/Scripts/JSSpecSpecs.js new file mode 100644 index 00000000..a503e06a --- /dev/null +++ b/assets/mootools-core/Specs/Assets/Scripts/JSSpecSpecs.js @@ -0,0 +1,140 @@ +/* +Script: JSSpecSpecs.js + Failure Examples for JSSpec.js + +License: + MIT-style license. + +Note: + All examples should fail to demonstrate the usage and output of all the availible types of specs in JSSpec. +*/ + +describe('Should be', { + 'Array should be (Array) 1': function() { + value_of(['ab','cd','ef']).should_be(['ab','bd','ef']); + }, + 'Array should be (Array) 2': function() { + value_of(['a',2,'4',5]).should_be([1,2,[4,5,6],6,7]); + }, + 'Boolean should be (Boolean)': function() { + value_of(true).should_be(false); + }, + 'Boolean should be false': function() { + value_of(true).should_be_false(); + }, + 'Boolean should be true': function() { + value_of(false).should_be_true(); + }, + 'Date should be (Date)': function() { + value_of(new Date(1979, 3, 27)).should_be(new Date(1976, 7, 23)); + }, + 'Null should be (String)': function() { + value_of(null).should_be("Test"); + }, + 'Null should be (undefined)': function() { + value_of(null).should_be(undefined); + }, + 'Number should be (Number)': function() { + value_of(1+2).should_be(4); + }, + 'Object should be (Object) 1': function() { + var actual = {a:1, b:2}; + var expected = {a:1, b:2, d:3}; + value_of(actual).should_be(expected); + }, + 'Object should be (Object) 2': function() { + var actual = {a:1, b:2, c:3, d:4}; + var expected = {a:1, b:2, c:3}; + value_of(actual).should_be(expected); + }, + 'Object should be (Object) 3': function() { + var actual = {a:1, b:4, c:3}; + var expected = {a:1, b:2, c:3}; + value_of(actual).should_be(expected); + }, + 'String should be (String)': function() { + value_of("Hello world").should_be("Good-bye world"); + }, + 'String should be (undefined)': function() { + value_of("Test").should_be(undefined); + } +}); + +describe('Should be empty', { + 'String should be empty': function() { + value_of("").should_be_empty(); + value_of("Hello").should_be_empty(); + }, + 'String should notbe empty': function() { + value_of("Hello").should_not_be_empty(); + value_of("").should_not_be_empty(); + }, + 'Array should be empty': function() { + value_of([]).should_be_empty(); + value_of([1,2,3]).should_be_empty(); + }, + 'Array should not be empty': function() { + value_of([1,2,3]).should_not_be_empty(); + value_of([]).should_not_be_empty(); + }, + 'Object\'s item should be empty': function() { + value_of({name:'Alan Kang', email:'jania902@gmail.com', accounts:['A', 'B']}).should_have(0, "accounts"); + }, + 'Object\'s item should not be empty': function() { + value_of({name:'Alan Kang', email:'jania902@gmail.com', accounts:[]}).should_have(2, "accounts"); + } +}); + +describe('Should have', { + 'Array should have (Number, "items")': function() { + value_of([1,2,3]).should_have(4, "items"); + }, + 'Array should have exactly (Number, "items")': function() { + value_of([1,2,3]).should_have_exactly(2, "items"); + }, + 'Array should have at least (Number, "items")': function() { + value_of([1,2,3]).should_have_at_least(4, "items"); + }, + 'Array should have at most (Number, "items")': function() { + value_of([1,2,3]).should_have_at_most(2, "items"); + }, + 'Object\'s item should have (Number, "[property]s")': function() { + value_of({name:'Alan Kang', email:'jania902@gmail.com', accounts:['A', 'B']}).should_have(3, "accounts"); + }, + 'String should have (Number, "characters")': function() { + value_of("Hello").should_have(4, "characters"); + }, + 'String should have (Number, "[No match]s")': function() { + value_of("This is a string").should_have(5, "players"); + } +}); + +describe('Should include', { + 'Array should include (mixed)': function() { + value_of([1,2,3]).should_include(4); + }, + 'Array should not include (mixed)': function() { + value_of([1,2,3]).should_not_include(2); + }, + 'Non-Array should include (mixed)': function() { + value_of(new Date()).should_include(4); + }, + 'Non-Array should not include (mixed)': function() { + value_of(new Date()).should_not_include(4); + } +}); + +describe('Should match', { + 'String should match (RegExp)': function() { + value_of("Hello").should_match(/x/); + }, + 'String should not match (RegExp)': function() { + value_of("Hello").should_not_match(/ell/); + }, + 'Array should match (RegExp)': function() { + value_of([1,2,3]).should_match(/x/); + }, + 'Array should not match (RegExp)': function() { + value_of([1,2,3]).should_not_match(/x/); + } +}); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Assets/Styles/Specs.css b/assets/mootools-core/Specs/Assets/Styles/Specs.css new file mode 100644 index 00000000..fc71b85a --- /dev/null +++ b/assets/mootools-core/Specs/Assets/Styles/Specs.css @@ -0,0 +1,293 @@ +/* +File: Style.css + Slick Style for JSSpec. + +License: + Copyright (c)2007 Valerio Proietti, . + You can only use this stylesheet to run MooTools JSSpec Runner. +*/ + +/* @group Reset */ + +* { + margin: 0; + padding: 0; +} + +ul { + list-style: none; +} + +/* @end */ + +/* @group Base */ + +html { + overflow: hidden; +} + +body { + font: 11px/1.5 Lucida Grande, Helvetica, Arial, sans-serif; + background: #F3F1F1; + color: #41464D; +} + +body, #container { + width: 100%; + height: 100%; + overflow: hidden; +} + +a { + text-decoration:none; +} + +#title { + position: absolute; + top: 0; + left: 0; + width: 100%; + padding: 5px 0; + background: #aaa; + background: #41464D; + color: #F3F1F1; + height: 30px; +} + +#list { + position: absolute; + width: 30%; + overflow-y: auto; + overflow-x: hidden; + top: 40px; + left: 0; + bottom: 0; + height: expression(document.body.clientHeight-40); +} + +#log { + position: absolute; + top: 40px; + right: 0; + bottom: 0; + overflow-y: auto; + overflow-x: hidden; + width: 70%; + height: expression(document.body.clientHeight-40); +} + +span.spc { + display: block; + height: 16px; +} + +#log-wrapper, #list-wrapper { + overflow: hidden; + padding: 4px 4px 0; + background: #fff; +} + +#log-wrapper { + margin: 16px 16px 0 8px; +} + +#list-wrapper { + margin: 16px 8px 0 16px; +} + +.success a:link, .success a:visited { + color: #657528; +} + +.exception a:link, .exception a:visited { + color: #B33F3F; +} + +a:link, a:visited { + color: #528CE0; +} + +a:hover, a:active { + color: #41464D !important; + cursor: pointer !important; +} + +#title h1 { + font: 25px/1.1 Arial, sans-serif; + font-weight: bolder; + float: left; + margin: 1px 0 2px 20px; + text-shadow: 0 2px 2px rgba(0,0,0,0.4); +} + +#title h1 span { + color: #D2E0E6; +} + +#title ul li { + font-weight: bold; + font-size: 12px; + float: right; + margin: 10px 5px 0; +} + +#title ul { + margin-right: 20px; +} + +h2 { + font-size: 14px; + background: #D0C8C8; + color: #8A7575; + margin-bottom: 4px; + padding: 2px 5px; +} + +h2#runner { + cursor: pointer; + background-color: #CFE773; + color: #657528; +} + +h2#runner:hover { + color: #41464D; +} + +h2#runner.disabled { + color: #fff; + background: #C8CBD0; + cursor: default; +} + +br { + display: none; +} + +h3 { + font-size: 12px; + padding: 3px 5px 1px; +} + +h4 { + font-size: 11px; + background: #C8CBD0; + padding: 3px 5px 1px; + margin-bottom: 4px; +} + +h3, h4 { + cursor: default; +} + +#list h3 { + background: #D2E0E6; + color: #528CE0; + margin-bottom: 4px; +} + +#log h3 { + background: #D0C8C8; + color: #8A7575; + margin-bottom: 4px; +} + +#log li div { + overflow: hidden; + padding: 0 4px 4px; +} + +p { + color: #575d67; +} + +p.uri { + float: right; + margin-top: -15px; + font-size: 10px; +} + +p.left, p.uri { + font-family: Monaco, Courier New, monospace; +} + +p#footer { + text-align: right; + padding: 10px 16px 0 0; +} + +/* @end */ + +/* @group Success/Failure Colors */ + +#log .exception h3 { + color: #B33F3F; + background: #EE9A9A; +} + +#log .exception h4 { + color: #B33F3F; + background: #eed8d8; + cursor: pointer; +} + +#log .success h3 { + background-color: #CFE773; + color: #657528; +} + +#log .success h4 { + background-color: #e2e5d2; + color: #657528; + cursor: default; +} + +#log .stub h4 { + background-color: #e5e5e1; + color: #a1a87e; + cursor: default; +} + +#list .exception h3 { + color: #B33F3F; + background: #eed8d8; +} + +#list .success h3 { + background-color: #e2e5d2; + color: #657528; +} + +a.rerun { + font-size: 11px; + color: #fff !important; +} + +/* @end */ + +/* @group Code */ + +.number_value { + color: red; +} + +.string_value { + color: green; +} + +.regexp_value { + color: olive; +} + +.boolean_value { + color: red; +} + +.dom_value { + color: purple; +} + +.undefined_value, .null_value { + color: gray; +} + +/* @end */ \ No newline at end of file diff --git a/assets/mootools-core/Specs/Class/Class.Extras.js b/assets/mootools-core/Specs/Class/Class.Extras.js new file mode 100644 index 00000000..493ed122 --- /dev/null +++ b/assets/mootools-core/Specs/Class/Class.Extras.js @@ -0,0 +1,288 @@ +/* +Script: Class.Extras.js + Specs for Class.Extras.js + +License: + MIT-style license. +*/ + +var Local = Local || {}; + +describe("Chain Class", { + + "before all": function(){ + Local.Chain = new Class({ + + Implements: Chain + + }); + }, + + "callChain should not fail when nothing was added to the chain": function(){ + var chain = new Local.Chain(); + chain.callChain(); + }, + + "should pass arguments to the function and return values": function(){ + var chain = new Local.Chain(); + var arr = []; + chain.chain(function(a, b){ + var str = "0" + b + a; + arr.push(str); + return str; + }); + chain.chain(function(a, b){ + var str = "1" + b + a; + arr.push(str); + return str; + }); + var ret; + value_of(arr).should_be([]); + ret = chain.callChain("a", "A"); + value_of(ret).should_be("0Aa"); + value_of(arr).should_be(["0Aa"]); + + ret = chain.callChain("b", "B"); + value_of(ret).should_be("1Bb"); + value_of(arr).should_be(["0Aa", "1Bb"]); + + ret = chain.callChain(); + value_of(ret).should_be(false); + value_of(arr).should_be(["0Aa", "1Bb"]); + }, + + "should chain any number of functions": function(){ + var chain = new Local.Chain(); + var arr = []; + + chain.chain(function(){ + arr.push(0); + }, function(){ + arr.push(1); + }); + + value_of(arr).should_be([]); + chain.callChain(); + value_of(arr).should_be([0]); + chain.chain(function(){ + arr.push(2); + }); + chain.callChain(); + value_of(arr).should_be([0, 1]); + chain.callChain(); + value_of(arr).should_be([0, 1, 2]); + chain.callChain(); + value_of(arr).should_be([0, 1, 2]); + }, + + "should allow an array of functions": function(){ + var chain = new Local.Chain(); + var arr = []; + + chain.chain([function(){ + arr.push(0); + }, function(){ + arr.push(1); + }, function(){ + arr.push(2); + }]); + + value_of(arr).should_be([]); + chain.callChain(); + value_of(arr).should_be([0]); + chain.callChain(); + value_of(arr).should_be([0, 1]); + chain.callChain(); + value_of(arr).should_be([0, 1, 2]); + chain.callChain(); + value_of(arr).should_be([0, 1, 2]); + }, + + "each instance should have its own chain": function(){ + var foo = new Local.Chain(); + var bar = new Local.Chain(); + foo.val = "F"; + bar.val = "B"; + foo.chain(function(){ + this.val += 'OO'; + }); + bar.chain(function(){ + this.val += 'AR'; + }); + value_of(foo.val).should_be('F'); + value_of(bar.val).should_be('B'); + foo.callChain(); + bar.callChain(); + value_of(foo.val).should_be('FOO'); + value_of(bar.val).should_be('BAR'); + } + +}); + + +describe("Events Class", { + + "before all": function(){ + Local.EventsTest = new Class({ + Implements: Events, + + called: 0, + + initialize: function(){ + this.called = 0; + } + }); + }, + + "before each": function(){ + Local.called = 0; + Local.fn = function(){ + return Local.called++; + }; + }, + + "should add an Event to the Class": function(){ + var myTest = new Local.EventsTest(); + myTest.addEvent("event", Local.fn); + + var events = myTest.$events; + var myEvent = events["event"]; + value_of(myEvent).should_not_be(undefined); + value_of(myEvent.contains(Local.fn)).should_be_true(); + }, + + "should add multiple Events to the Class": function(){ + var myTest = new Local.EventsTest(); + myTest.addEvents({ + "event1": Local.fn, + "event2": Local.fn + }); + + var events = myTest.$events; + var myEvent1 = events["event1"]; + value_of(myEvent1).should_not_be(undefined); + value_of(myEvent1.contains(Local.fn)).should_be_true(); + + var myEvent2 = events["event2"]; + value_of(myEvent2).should_not_be(undefined); + value_of(myEvent2.contains(Local.fn)).should_be_true(); + }, + + "should add an internal event": function(){ + var myTest = new Local.EventsTest(); + myTest.addEvent("internal", Local.fn, true); + + var events = myTest.$events; + var myEvent = events["internal"]; + value_of(myEvent).should_not_be(undefined); + value_of(myEvent.contains(Local.fn)).should_be_true(); + value_of(myEvent[0].internal).should_be_true(); + }, + + "should remove a specific method for an event": function(){ + var myTest = new Local.EventsTest(); + var fn = function(){ return true; }; + myTest.addEvent("event", Local.fn); + myTest.addEvent("event", fn); + myTest.removeEvent("event", Local.fn); + + var events = myTest.$events; + var myEvent = events["event"]; + value_of(myEvent).should_not_be(undefined); + value_of(myEvent.contains(fn)).should_be_true(); + }, + + "should remove an event and its methods": function(){ + var myTest = new Local.EventsTest(); + var fn = function(){ return true; }; + myTest.addEvent("event", Local.fn); + myTest.addEvent("event", fn); + myTest.removeEvents("event"); + + var events = myTest.$events; + value_of(events["event"].length).should_be(0); + }, + + "should remove all events": function(){ + var myTest = new Local.EventsTest(); + var fn = function(){ return true; }; + myTest.addEvent("event1", Local.fn); + myTest.addEvent("event2", fn); + myTest.removeEvents(); + + var events = myTest.$events; + value_of(events["event1"].length).should_be(0); + value_of(events["event2"].length).should_be(0); + }, + + "should remove events with an object": function(){ + var myTest = new Local.EventsTest(); + var events = { + event1: Local.fn.create(), + event2: Local.fn.create() + }; + myTest.addEvent('event1', Local.fn.create()).addEvents(events); + myTest.fireEvent('event1'); + value_of(Local.called).should_be(2); + myTest.removeEvents(events); + myTest.fireEvent('event1'); + value_of(Local.called).should_be(3); + myTest.fireEvent('event2'); + value_of(Local.called).should_be(3); + } + +}); + +describe("Options Class", { + + "before all": function(){ + Local.OptionsTest = new Class({ + Implements: Options, + + initialize: function(options){ + this.setOptions(options); + } + }); + }, + + "should set options": function(){ + var myTest = new Local.OptionsTest({ a: 1, b: 2}); + value_of(myTest.options).should_not_be(undefined); + }, + + "should override default options": function(){ + Local.OptionsTest.implement({ + options: { + a: 1, + b: 2 + } + }); + var myTest = new Local.OptionsTest({a: 3, b: 4}); + value_of(myTest.options.a).should_be(3); + value_of(myTest.options.b).should_be(4); + }, + + "should add events in the options object if class has implemented the Events class": function(){ + Local.OptionsTest.implement(new Events).implement({ + options: { + onEvent1: function(){ + return true; + }, + onEvent2: function(){ + return false; + } + } + }); + var myTest = new Local.OptionsTest({ + onEvent3: function(){ + return true; + } + }); + var events = myTest.$events; + value_of(events).should_not_be(undefined); + value_of(events["event1"].length).should_be(1); + value_of(events["event2"].length).should_be(1); + value_of(events["event3"].length).should_be(1); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Class/Class.js b/assets/mootools-core/Specs/Class/Class.js new file mode 100644 index 00000000..aa71d21e --- /dev/null +++ b/assets/mootools-core/Specs/Class/Class.js @@ -0,0 +1,274 @@ +/* +Script: Class.js + Specs for Class.js + +License: + MIT-style license. +*/ + +(function(){ + +var Animal = new Class({ + + initialized: false, + + initialize: function(name, sound){ + this.name = name; + this.sound = sound || ''; + this.initialized = true; + }, + + eat: function(){ + return 'animal:eat:' + this.name; + }, + + say: function(){ + return 'animal:say:' + this.name; + } + +}); + +var Cat = new Class({ + + Extends: Animal, + + ferocious: false, + + initialize: function(name, sound){ + this.parent(name, sound || 'miao'); + }, + + eat: function(){ + return 'cat:eat:' + this.name; + }, + + play: function(){ + return 'cat:play:' + this.name; + } + +}); + +var Lion = new Class({ + + Extends: Cat, + + ferocious: true, + + initialize: function(name){ + this.parent(name, 'rarr'); + }, + + eat: function(){ + return 'lion:eat:' + this.name; + } + +}); + +var Actions = new Class({ + + jump: function(){ + return 'actions:jump:' + this.name; + }, + + sleep: function(){ + return 'actions:sleep:' + this.name; + } + +}); + +var Attributes = new Class({ + + color: function(){ + return 'attributes:color:' + this.name; + }, + + size: function(){ + return 'attributes:size:' + this.name; + } + +}); + + +describe('Class creation', { + + "Classes should be of type 'class'": function(){ + value_of($type(Animal)).should_be('class'); + value_of(Class.type(Animal)).should_be_true(); + }, + + "should call initialize upon instantiation": function(){ + var animal = new Animal('lamina'); + value_of(animal.name).should_be('lamina'); + value_of(animal.initialized).should_be_true(); + value_of(animal.say()).should_be('animal:say:lamina'); + }, + + "should use 'Extend' property to extend another class": function(){ + var cat = new Cat('fluffy'); + value_of(cat.name).should_be('fluffy'); + value_of(cat.sound).should_be('miao'); + value_of(cat.ferocious).should_be_false(); + value_of(cat.say()).should_be('animal:say:fluffy'); + value_of(cat.eat()).should_be('cat:eat:fluffy'); + value_of(cat.play()).should_be('cat:play:fluffy'); + }, + + "should use 'Extend' property to extend an extended class": function(){ + var leo = new Lion('leo'); + value_of(leo.name).should_be('leo'); + value_of(leo.sound).should_be('rarr'); + value_of(leo.ferocious).should_be_true(); + value_of(leo.say()).should_be('animal:say:leo'); + value_of(leo.eat()).should_be('lion:eat:leo'); + value_of(leo.play()).should_be('cat:play:leo'); + }, + + "should use 'Implements' property to implement another class": function(){ + var Dog = new Class({ + Implements: Animal + }); + + var rover = new Dog('rover'); + value_of(rover.name).should_be('rover'); + value_of(rover.initialized).should_be_true(); + value_of(rover.eat()).should_be('animal:eat:rover'); + }, + + "should use 'Implements' property to implement any number of classes": function(){ + var Dog = new Class({ + Extends: Animal, + Implements: [Actions, Attributes] + }); + + var rover = new Dog('rover'); + value_of(rover.initialized).should_be_true(); + value_of(rover.eat()).should_be('animal:eat:rover'); + value_of(rover.say()).should_be('animal:say:rover'); + value_of(rover.jump()).should_be('actions:jump:rover'); + value_of(rover.sleep()).should_be('actions:sleep:rover'); + value_of(rover.size()).should_be('attributes:size:rover'); + value_of(rover.color()).should_be('attributes:color:rover'); + }, + + "should alter the Class's prototype when implementing new methods": function(){ + var Dog = new Class({ + Extends: Animal + }); + + var rover = new Dog('rover'); + + Dog.implement({ + jump: function(){ + return 'dog:jump:' + this.name; + } + }); + + var spot = new Dog('spot'); + + value_of(spot.jump()).should_be('dog:jump:spot'); + value_of(rover.jump()).should_be('dog:jump:rover'); + }, + + "should alter the Class's prototype when implementing new methods into the super class": function(){ + var Dog = new Class({ + Extends: Animal + }); + + var rover = new Dog('rover'); + + Animal.implement({ + jump: function(){ + return 'animal:jump:' + this.name; + } + }); + + var spot = new Dog('spot'); + + value_of(spot.jump()).should_be('animal:jump:spot'); + value_of(rover.jump()).should_be('animal:jump:rover'); + }, + + "should alter the Class's prototype when overwriting methods in the super class": function(){ + var Dog = new Class({ + Extends: Animal + }); + + var rover = new Dog('rover'); + value_of(rover.say()).should_be('animal:say:rover'); + + Animal.implement({ + say: function(){ + return 'NEW:animal:say:' + this.name; + } + }); + + var spot = new Dog('spot'); + + value_of(spot.say()).should_be('NEW:animal:say:spot'); + value_of(rover.say()).should_be('NEW:animal:say:rover'); + } + + //We might attempt to add support for the following at a later date + + /* + "should access the proper parent when it is overwritten after instantiation": function(){ + var Dog = new Class({ + Extends: Animal, + say: function(){ + return this.parent(); + } + }); + + var rover = new Dog('rover'); + value_of(rover.say()).should_be('animal:say:rover'); + + Animal.implement({ + say: function(){ + return 'NEW:animal:say:' + this.name; + } + }); + + var spot = new Dog('spot'); + + value_of(spot.say()).should_be('NEW:animal:say:spot'); + value_of(rover.say()).should_be('NEW:animal:say:rover'); + } + */ + +}); + +describe('Class::implement', { + + 'should implement an object': function(){ + var Dog = new Class({ + Extends: Animal + }); + + Dog.implement(new Actions); + + var rover = new Dog('rover'); + + value_of(rover.name).should_be('rover'); + value_of(rover.jump()).should_be('actions:jump:rover'); + value_of(rover.sleep()).should_be('actions:sleep:rover'); + }, + + 'should implement any number of objects': function(){ + var Dog = new Class({ + Extends: Animal + }); + + Dog.implement(new Actions).implement(new Attributes); + + var rover = new Dog('rover'); + + value_of(rover.name).should_be('rover'); + value_of(rover.jump()).should_be('actions:jump:rover'); + value_of(rover.sleep()).should_be('actions:sleep:rover'); + value_of(rover.size()).should_be('attributes:size:rover'); + value_of(rover.color()).should_be('attributes:color:rover'); + } + +}); + +})(); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Core/Browser.js b/assets/mootools-core/Specs/Core/Browser.js new file mode 100644 index 00000000..e78e9b03 --- /dev/null +++ b/assets/mootools-core/Specs/Core/Browser.js @@ -0,0 +1,40 @@ +/* +Script: Browser.js + Specs for Browser.js + +License: + MIT-style license. +*/ + +describe('$exec', { + + 'should evaluate on global scope': function(){ + $exec.call($exec, 'var execSpec = 42'); + value_of(window.execSpec).should_be(42); + }, + + 'should return the evaluated script': function(){ + value_of($exec('$empty();')).should_be('$empty();'); + } + +}); + +describe('Document', { + + 'should hold the parent window': function(){ + value_of(document.window).should_be(window); + }, + + 'should hold the head element': function(){ + value_of(document.head.tagName.toLowerCase()).should_be('head'); + } + +}); + +describe('Window', { + + 'should set the Element prototype': function(){ + value_of($defined(window.Element.prototype)).should_be_true(); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Core/Core.js b/assets/mootools-core/Specs/Core/Core.js new file mode 100644 index 00000000..83d4c1b2 --- /dev/null +++ b/assets/mootools-core/Specs/Core/Core.js @@ -0,0 +1,443 @@ +/* +Script: Core.js + Examples for Core.js + +License: + MIT-style license. +*/ + +(function(){ + +var Instrument = new Native({ + + name: 'instrument', + + initialize: function(name){ + this.name = name; + } + +}); + +Instrument.implement({ + + method: function(){ + return this.property + ' ' + this.name; + }, + + property: 'stuff' + +}); + +var Car = new Native({ + + name: 'car', + + protect: true, + + initialize: function(name){ + this.name = name; + } + +}); + +Car.implement({ + + property: 'stuff', + + method: function(){ + return this.name + '_' + this.property; + } + +}); + +describe('Native', { + + 'should allow implementation over existing methods when browser option is not set': function(){ + Instrument.implement({ property: 'staff' }); + var myInstrument = new Instrument('xeelophone'); + value_of(myInstrument.method()).should_be('staff xeelophone'); + }, + + 'should not override existing methods when browser option is set': function(){ + Car.implement({ property: 'staff' }); + var myCar = new Car('smart'); + value_of(myCar.method()).should_be('smart_stuff'); + }, + + 'should allow generic calls': function(){ + value_of(Car.method({name: 'ciccio', property: 'bello'})).should_be('ciccio_bello'); + }, + + "should have a 'native' type": function(){ + value_of(Native.type(Car)).should_be_true(); + } + +}); + +describe('$A', { + + 'should return a copy for an array': function(){ + var arr1 = [1,2,3]; + var arr2 = $A(arr1); + value_of(arr1 !== arr2).should_be_true(); + }, + + 'should return an array for an Elements collection': function(){ + var div1 = document.createElement('div'); + var div2 = document.createElement('div'); + var div3 = document.createElement('div'); + + div1.appendChild(div2); + div1.appendChild(div3); + + var array = $A(div1.getElementsByTagName('*')); + value_of(Array.type(array)).should_be_true(); + }, + + 'should return an array for arguments': function(){ + var fnTest = function(){ + return $A(arguments); + }; + var arr = fnTest(1,2,3); + value_of(Array.type(arr)).should_be_true(); + value_of(arr).should_have(3, 'items'); + } + +}); + +describe('$arguments', { + + 'should return the argument passed according to the index': function(){ + value_of($arguments(0)('a','b','c','d')).should_be('a'); + value_of($arguments(1)('a','b','c','d')).should_be('b'); + value_of($arguments(2)('a','b','c','d')).should_be('c'); + value_of($arguments(3)('a','b','c','d')).should_be('d'); + } + +}); + +describe('$chk', { + + 'should return false on false': function(){ + value_of($chk(false)).should_be_false(); + }, + + 'should return false on null': function(){ + value_of($chk(null)).should_be_false(); + }, + + 'should return false on undefined': function(){ + value_of($chk(undefined)).should_be_false(); + }, + + 'should return true on 0': function(){ + value_of($chk(0)).should_be_true(); + }, + + 'should return true for any truthsie': function(){ + value_of($chk(1)).should_be_true(); + value_of($chk({})).should_be_true(); + value_of($chk(true)).should_be_true(); + } + +}); + +describe('$clear', { + + 'should clear timeouts': function(){ + var timeout = setTimeout(function(){}, 100); + value_of($clear(timeout)).should_be_null(); + }, + + 'should clear intervals': function(){ + var interval = setInterval(function(){}, 100); + value_of($clear(interval)).should_be_null(); + } + +}); + +describe('$defined', { + + 'should return true on 0': function(){ + value_of($defined(0)).should_be_true(); + }, + + 'should return true on false': function(){ + value_of($defined(false)).should_be_true(); + }, + + 'should return false on null': function(){ + value_of($defined(null)).should_be_false(); + }, + + 'should return false on undefined': function(){ + value_of($defined(undefined)).should_be_false(); + } + +}); + +describe('$each', { + + 'should call the function for each item in Function arguments': function(){ + var daysArr = []; + (function(){ + $each(arguments, function(value, key){ + daysArr[key] = value; + }); + })('Sun','Mon','Tue'); + + value_of(daysArr).should_be(['Sun','Mon','Tue']); + }, + + 'should call the function for each item in the array': function(){ + var daysArr = []; + $each(['Sun','Mon','Tue'], function(value, key){ + daysArr[key] = value; + }); + + value_of(daysArr).should_be(['Sun','Mon','Tue']); + }, + + 'should call the function for each item in the object': function(){ + var daysObj = {}; + $each({first: "Sunday", second: "Monday", third: "Tuesday"}, function(value, key){ + daysObj[key] = value; + }); + + value_of(daysObj).should_be({first: 'Sunday', second: 'Monday', third: 'Tuesday'}); + } + +}); + +describe('$extend', { + + 'should extend two objects': function(){ + var obj1 = {a: 1, b: 2}; + var obj2 = {b: 3, c: 4}; + $extend(obj1, obj2); + value_of(obj1).should_be({a: 1, b: 3, c: 4}); + }, + + 'should overwrite properties': function(){ + var obj1 = {a: 1, b: 2}; + var obj2 = {b: 3, c: 4, a: 5}; + $extend(obj1, obj2); + value_of(obj1).should_be({a: 5, b: 3, c: 4}); + }, + + 'should not extend with null argument': function(){ + var obj1 = {a: 1, b: 2}; + $extend(obj1); + value_of(obj1).should_be({a: 1, b: 2}); + } + +}); + +describe('$lambda', { + + 'if a function is passed in that function should be returned': function(){ + var fn = function(a,b){ return a; }; + value_of($lambda(fn)).should_be(fn); + }, + + 'should return a function that returns the value passed when called': function(){ + value_of($lambda('hello world!')()).should_be('hello world!'); + } + +}); + +describe('$merge', { + + 'should dereference objects': function(){ + var obj1 = {a: 1, b: 2}; + var obj2 = $merge(obj1); + value_of(obj1 === obj2).should_be_false(); + }, + + 'should merge any arbitrary number of nested objects': function(){ + var obj1 = {a: {a: 1, b: 2, c: 3}, b: 2}; + var obj2 = {a: {a: 2, b: 8, c: 3, d: 8}, b: 3, c: 4}; + var obj3 = {a: {a: 3}, b: 3, c: false}; + value_of($merge(obj1, obj2, obj3)).should_be({a: {a: 3, b: 8, c: 3, d: 8}, b: 3, c: false}); + } + +}); + +describe('$pick', { + + 'should return the first false argument': function(){ + var picked1 = $pick(null, undefined, false, [1,2,3], {}); + value_of(picked1).should_be_false(); + }, + + 'should return the first defined argument': function(){ + var picked1 = $pick(null, undefined, null, [1,2,3], {}); + value_of(picked1).should_be([1,2,3]); + } + +}); + +describe('$random', { + + 'should return a number between two numbers specified': function(){ + var rand = $random(1, 3); + value_of((rand <= 3 && rand >= 1)).should_be_true(); + } + +}); + +describe('$splat', { + + 'should transform a non array into an array': function(){ + value_of($splat(1)).should_be([1]); + }, + + 'should transforum an undefined or null into an empty array': function(){ + value_of($splat(null)).should_be([]); + value_of($splat(undefined)).should_be([]); + }, + + 'should ignore and return an array': function(){ + value_of($splat([1,2,3])).should_be([1,2,3]); + } + +}); + +describe('$time', { + + 'should return a timestamp': function(){ + value_of(Number.type($time())).should_be_true(); + } + +}); + +describe('$try', { + + 'should return the result of the first successful function without executing successive functions': function(){ + var calls = 0; + var attempt = $try(function(){ + calls++; + throw new Exception(); + }, function(){ + calls++; + return 'success'; + }, function(){ + calls++; + return 'moo'; + }); + value_of(calls).should_be(2); + value_of(attempt).should_be('success'); + }, + + 'should return null when no function succeeded': function(){ + var calls = 0; + var attempt = $try(function(){ + calls++; + return I_invented_this(); + }, function(){ + calls++; + return uninstall_ie(); + }); + value_of(calls).should_be(2); + value_of(attempt).should_be_null(); + } + +}); + +describe('$type', { + + "should return 'array' for Array objects": function(){ + value_of($type([1,2])).should_be('array'); + }, + + "should return 'string' for String objects": function(){ + value_of($type('ciao')).should_be('string'); + }, + + "should return 'regexp' for RegExp objects": function(){ + value_of($type(/_/)).should_be('regexp'); + }, + + "should return 'function' for Function objects": function(){ + value_of($type(function(){})).should_be('function'); + }, + + "should return 'number' for Number objects": function(){ + value_of($type(10)).should_be('number'); + value_of($type(NaN)).should_not_be('number'); + }, + + "should return 'boolean' for Boolean objects": function(){ + value_of($type(true)).should_be('boolean'); + value_of($type(false)).should_be('boolean'); + }, + + "should return 'object' for Object objects": function(){ + value_of($type({a:2})).should_be('object'); + }, + + "should return 'arguments' for Function arguments": function(){ + value_of($type(arguments)).should_be((window.opera) ? 'array' : 'arguments'); //opera's arguments behave like arrays--which is actually better. + }, + + "should return false for null objects": function(){ + value_of($type(null)).should_be_false(); + }, + + "should return false for undefined objects": function(){ + value_of($type(undefined)).should_be_false(); + }, + + "should return 'collection' for HTMLElements collections": function(){ + value_of($type(document.getElementsByTagName('*'))).should_be('collection'); + }, + + "should return 'element' for an Element": function(){ + var div = document.createElement('div'); + value_of($type(div)).should_be('element'); + }, + + "should return 'window' for the window object": function(){ + value_of($type(window)).should_be('window'); + }, + + "should return 'document' for the document object": function(){ + value_of($type(document)).should_be('document'); + } + +}); + +describe('$unlink', { + + "should unlink an object recursivly": function(){ + var inner = {b: 2}; + var obj = {a: 1, inner: inner}; + var copy = $unlink(obj); + obj.a = 10; + inner.b = 20; + + value_of(obj.a).should_be(10); + value_of(obj.inner.b).should_be(20); + value_of($type(obj)).should_be('object'); + + value_of(copy.a).should_be(1); + value_of(copy.inner.b).should_be(2); + value_of($type(copy)).should_be('object'); + }, + + "should unlink an Hash": function(){ + var hash = new Hash({a: 'one'}); + var copy = $unlink(hash); + + value_of($type(hash)).should_be('hash'); + value_of($type(copy)).should_be('hash'); + + copy.set('a', 'two'); + + value_of(hash.get('a')).should_be('one'); + value_of(copy.get('a')).should_be('two'); + } + +}); + +})(); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Element/Element.Style.js b/assets/mootools-core/Specs/Element/Element.Style.js new file mode 100644 index 00000000..95f85abe --- /dev/null +++ b/assets/mootools-core/Specs/Element/Element.Style.js @@ -0,0 +1,73 @@ +/* +Script: Element.Style.js + Specification Examples of Element.Style.js. + +License: + MIT-style license. +*/ + +describe('Element.set `opacity`', { + + 'should set the opacity of an Element': function() { + var el = new Element('div').set('opacity', 0.4); + if (Browser.Engine.trident) value_of(el.style.filter).should_be('alpha(opacity=40)'); + value_of(el.style.opacity).should_be(0.4); + }, + + 'should return the opacity of an Element': function() { + value_of(new Element('div').set('opacity', 0.4).get('opacity')).should_be(0.4); + } + +}); + +describe('Element.getStyle', { + + 'should get a six digit hex code from a three digit hex code': function() { + var el = new Element('div').set('html', '
'); + value_of(el.getElement('div').getStyle('color')).should_be('#00ff00'); + }, + + 'should getStyle a six digit hex code from an RGB value': function() { + var el = new Element('div').set('html', '
'); + value_of(el.getElement('div').getStyle('color')).should_be('#00ff00'); + }, + + 'should `getStyle` with a dash in it': function() { + var el = new Element('div').set('html', '
'); + value_of(el.getElement('div').getStyle('list-style-type')).should_be('square'); + } + +}); + +describe('Element.setStyle', { + + 'should set the `styles` property on an Element using the Element constructor': function() { + value_of(new Element('div', {styles:{'color':'#00ff00'}}).getStyle('color')).should_be('#00ff00'); + }, + + 'should `setStyle` on an Element': function() { + value_of(new Element('div').setStyle('color','#00ff00').getStyle('color')).should_be('#00ff00'); + }, + + 'should properly `setStyle` for a property with a dash in it': function() { + value_of(new Element('div').setStyle('list-style-type', 'square').getStyle('list-style-type')).should_be('square'); + } + +}); + +describe('Element.getStyles', { + + 'should return multiple styles': function() { + var el = new Element('div').set('html', '
'); + value_of(el.getElement('div').getStyles('color', 'list-style-type')).should_be({color:'#00ff00', 'list-style-type':'square'}); + } + +}); + +describe('Element.setStyles', { + + 'should set multiple styles': function() { + value_of(new Element('div').setStyles({'list-style-type':'square', 'color':'#00ff00'}).getStyles('list-style-type', 'color')).should_be({'list-style-type':'square', color:'#00ff00'}); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Element/Element.js b/assets/mootools-core/Specs/Element/Element.js new file mode 100644 index 00000000..4a1e19b9 --- /dev/null +++ b/assets/mootools-core/Specs/Element/Element.js @@ -0,0 +1,1535 @@ +/* +Script: Element.js + Specs for Element.js + +License: + MIT-style license. +*/ + +describe('Element constructor', { + + "should return an Element with the correct tag": function(){ + var element = new Element('div'); + value_of($type(element)).should_be('element'); + value_of($defined(element.addEvent)).should_be_true(); + value_of(element.tagName.toLowerCase()).should_be('div'); + }, + + 'should return an Element with various attributes': function(){ + var element = new Element('div', { 'id': 'divID', 'title': 'divTitle' }); + value_of(element.id).should_be('divID'); + value_of(element.title).should_be('divTitle'); + }, + + 'should return an Element with for attribute': function(){ + var label = new Element('label', { 'for': 'myId' }); + value_of(label.htmlFor).should_be('myId'); + }, + + 'should return an Element with class attribute': function(){ + var div1 = new Element('div', { 'class': 'class' }); + var div2 = new Element('div', { 'class': 'class1 class2 class3' }); + + value_of(div1.className).should_be('class'); + value_of(div2.className).should_be('class1 class2 class3'); + }, + + 'should return input Elements with name and type attributes': function(){ + var username = new Element('input', { type: 'text', name: 'username', value: 'username' }); + var password = new Element('input', { type: 'password', name: 'password', value: 'password' }); + + value_of(username.type).should_be('text'); + value_of(username.name).should_be('username'); + value_of(username.value).should_be('username'); + + value_of(password.type).should_be('password'); + value_of(password.name).should_be('password'); + value_of(password.value).should_be('password'); + }, + + 'should return input Elements that are checked': function(){ + var check1 = new Element('input', { type: 'checkbox' }); + var check2 = new Element('input', { type: 'checkbox', checked: true }); + var check3 = new Element('input', { type: 'checkbox', checked: 'checked' }); + + value_of(check1.checked).should_be_false(); + value_of(check2.checked).should_be_true(); + value_of(check2.checked).should_be_true(); + }, + + "should return a select Element that retains it's selected options": function(){ + var div = new Element('div', { 'html': + '' + }); + + var select1 = div.getFirst(); + var select2 = new Element('select', { name: 'select[]', multiple: true }).adopt( + new Element('option', { name: 'none', value: '', html: '--' }), + new Element('option', { name: 'volvo', value: 'volvo', html: 'Volvo' }), + new Element('option', { name: 'saab', value: 'saab', html: 'Saab', selected: true }), + new Element('option', { name: 'opel', value: 'opel', html: 'Opel', selected: 'selected' }), + new Element('option', { name: 'bmw', value: 'bmw', html: 'BMW' }) + ); + + value_of(select1.multiple).should_be_true(); + value_of(select2.multiple).should_be_true(); + + value_of(select1.name).should_be(select2.name); + value_of(select1.options.length).should_be(select2.options.length); + value_of(select1.toQueryString()).should_be(select2.toQueryString()); + } + +}); + +describe('Element.set', { + + "should set a single attribute of an Element": function(){ + var div = new Element('div').set('id', 'some_id'); + value_of(div.id).should_be('some_id'); + }, + + "should set the checked attribute of an Element": function(){ + var input1 = new Element('input', {type: 'checkbox'}).set('checked', 'checked'); + var input2 = new Element('input', {type: 'checkbox'}).set('checked', true); + value_of(input1.checked).should_be_true(); + value_of(input2.checked).should_be_true(); + }, + + "should set the class name of an element": function(){ + var div = new Element('div').set('class', 'some_class'); + value_of(div.className).should_be('some_class'); + }, + + "should set the for attribute of an element": function(){ + var input = new Element('input', {type: 'text'}).set('for', 'some_element'); + value_of(input.htmlFor).should_be('some_element'); + }, + + "should set the html of an Element": function(){ + var html = 'Link'; + var parent = new Element('div').set('html', html); + value_of(parent.innerHTML.toLowerCase()).should_be(html.toLowerCase()); + }, + + "should set the html of an Element with multiple arguments": function(){ + var html = ['

Paragraph

', 'Link']; + var parent = new Element('div').set('html', html); + value_of(parent.innerHTML.toLowerCase()).should_be(html.join('').toLowerCase()); + }, + + "should set the html of a select Element": function(){ + var html = ''; + var select = new Element('select').set('html', html); + value_of(select.getChildren().length).should_be(2); + value_of(select.options.length).should_be(2); + value_of(select.selectedIndex).should_be(1); + }, + + "should set the html of a table Element": function(){ + var html = 'cell 1cell 2cell 1cell 2'; + var table = new Element('table').set('html', html); + value_of(table.getChildren().length).should_be(1); + value_of(table.getFirst().getFirst().getChildren().length).should_be(2); + value_of(table.getFirst().getLast().getFirst().className).should_be('cell'); + }, + + "should set the html of a tbody Element": function(){ + var html = 'cell 1cell 2cell 1cell 2'; + var tbody = new Element('tbody').inject(new Element('table')).set('html', html); + value_of(tbody.getChildren().length).should_be(2); + value_of(tbody.getLast().getFirst().className).should_be('cell'); + }, + + "should set the html of a tr Element": function(){ + var html = 'cell 1cell 2'; + var tr = new Element('tr').inject(new Element('tbody').inject(new Element('table'))).set('html', html); + value_of(tr.getChildren().length).should_be(2); + value_of(tr.getFirst().className).should_be('cell'); + }, + + "should set the html of a td Element": function(){ + var html = 'Some SpanSome Link'; + var td = new Element('td').inject(new Element('tr').inject(new Element('tbody').inject(new Element('table')))).set('html', html); + value_of(td.getChildren().length).should_be(2); + value_of(td.getFirst().className).should_be('span'); + }, + + "should set the style attribute of an Element": function(){ + var style = 'font-size:12px;line-height:23px;'; + var div = new Element('div').set('style', style); + value_of(div.style.lineHeight).should_be('23px'); + value_of(div.style.fontSize).should_be('12px'); + }, + + "should set the text of an element": function(){ + var div = new Element('div').set('text', 'some text content'); + value_of(div.get('text')).should_be('some text content'); + value_of(div.innerHTML).should_be('some text content'); + }, + + "should set multiple attributes of an Element": function(){ + var div = new Element('div').set({ id: 'some_id', 'title': 'some_title', 'html': 'some_content' }); + value_of(div.id).should_be('some_id'); + value_of(div.title).should_be('some_title'); + value_of(div.innerHTML).should_be('some_content'); + }, + + "should set various attributes of a script Element": function(){ + var script = new Element('script').set({ type: 'text/javascript', defer: 'defer' }); + value_of(script.type).should_be('text/javascript'); + value_of(script.defer).should_be_true(); + }, + + "should set various attributes of a table Element": function(){ + var table1 = new Element('table').set({ border: '2', cellpadding: '3', cellspacing: '4', align: 'center' }); + var table2 = new Element('table').set({ cellPadding: '3', cellSpacing: '4' }); + value_of(table1.border).should_be(2); + value_of(table1.cellPadding).should_be(3); + value_of(table2.cellPadding).should_be(3); + value_of(table1.cellSpacing).should_be(4); + value_of(table2.cellSpacing).should_be(4); + value_of(table1.align).should_be('center'); + } + +}); + +var myElements = new Elements([ + new Element('div'), + document.createElement('a'), + new Element('div', {id: 'el-' + $time()}) +]); + +describe('Elements', { + + 'should return an array type': function(){ + value_of(Array.type(myElements)).should_be_true(); + }, + + 'should return an array of Elements': function(){ + value_of(myElements.every(Element.type)).should_be_true(); + }, + + 'should apply Element prototypes to the returned array': function(){ + value_of($defined(myElements.addEvent)).should_be_true(); + }, + + 'should return all Elements that match the string matcher': function(){ + value_of(myElements.filter('div')).should_be([myElements[0], myElements[2]]); + }, + + 'should return all Elements that match the comparator': function(){ + var elements = myElements.filter(function(element){ + return element.match('a'); + }); + value_of(elements).should_be([myElements[1]]); + } + +}); + +describe('TextNode.constructor', { + + 'should return a new textnode element': function(){ + var text = document.newTextNode('yo'); + value_of($type(text)).should_be('textnode'); + } + +}); + +describe('IFrame constructor', { + + 'should return a new IFrame': function(){ + var iFrame1 = document.createElement('iframe'); + var iFrame2 = new IFrame(); + value_of(iFrame1.tagName).should_be(iFrame2.tagName); + }, + + 'should return the same IFrame if passed': function(){ + var iFrame1 = document.createElement('iframe'); + var iFrame2 = new IFrame(iFrame1); + value_of(iFrame1).should_be(iFrame2); + } + +}); + +describe('$', { + + 'before all': function(){ + Container = document.createElement('div'); + Container.innerHTML = '
'; + document.body.appendChild(Container); + }, + + 'after all': function(){ + document.body.removeChild(Container); + Container = null; + }, + + 'should return an extended Element by string id': function(){ + var dollar1 = document.getElementById('dollar'); + var dollar2 = $('dollar'); + + value_of(dollar1).should_be(dollar2); + value_of($defined(dollar1.addEvent)).should_be_true(); + }, + + 'should return the window if passed': function(){ + value_of($(window)).should_be(window); + }, + + 'should return the document if passed': function(){ + value_of($(document)).should_be(document); + }, + + 'should return null if string not found or type mismatch': function(){ + value_of($(1)).should_be_null(); + value_of($('nonexistant')).should_be_null(); + } + +}); + +describe('$$', { + + 'should return all Elements of a specific tag': function(){ + var divs1 = $$('div'); + var divs2 = Array.flatten(document.getElementsByTagName('div')); + value_of(divs1).should_be(divs2); + }, + + 'should return multiple Elements for each specific tag': function(){ + var headers1 = $$('h3', 'h4'); + var headers2 = Array.flatten([document.getElementsByTagName('h3'), document.getElementsByTagName('h4')]); + value_of(headers1).should_be(headers2); + }, + + 'should return an empty array if not is found': function(){ + value_of($$('not_found')).should_be([]); + } + +}); + +describe('getDocument', { + + 'should return the owner document for elements': function(){ + var doc = document.newElement('div').getDocument(); + value_of(doc).should_be(document); + }, + + 'should return the owned document for window': function(){ + var doc = window.getDocument(); + value_of(doc).should_be(document); + }, + + 'should return self for document': function(){ + var doc = document.getDocument(); + value_of(doc).should_be(document); + } + +}); + +describe('getWindow', { + + 'should return the owner window for elements': function(){ + var win = document.newElement('div').getWindow(); + value_of(win).should_be(window); + }, + + 'should return the owner window for document': function(){ + var win = document.getWindow(); + value_of(win).should_be(window); + }, + + 'should return self for window': function(){ + var win = window.getWindow(); + value_of(win).should_be(window); + } + +}); + +describe('Element.getElement', { + + 'before all': function(){ + Container = new Element('div'); + Container.innerHTML = '

'; + }, + + 'after all': function(){ + Container = null; + }, + + 'should return the first Element to match the tag, otherwise null': function(){ + var child = Container.getElement('div'); + value_of(child.id).should_be('first'); + value_of(Container.getElement('iframe')).should_be_null(); + } + +}); + +describe('Element.getElements', { + + 'before all': function(){ + Container = new Element('div'); + Container.innerHTML = '

'; + }, + + 'after all': function(){ + Container = null; + }, + + 'should return all the elements that match the tag': function(){ + var children = Container.getElements('div'); + value_of(children).should_have(2, 'items'); + }, + + 'should return all the elements that match the tags': function(){ + var children = Container.getElements('div,a'); + value_of(children).should_have(3, 'items'); + value_of(children[2].tagName.toLowerCase()).should_be('a'); + } + +}); + +describe('Document.getElement', { + + 'should return the first Element to match the tag, otherwise null': function(){ + var div = document.getElement('div'); + var ndiv = document.getElementsByTagName('div')[0]; + value_of(div).should_be(ndiv); + + var notfound = document.getElement('canvas'); + value_of(notfound).should_be_null(); + } + +}); + +describe('Document.getElements', { + + 'should return all the elements that match the tag': function(){ + var divs = document.getElements('div'); + var ndivs = $A(document.getElementsByTagName('div')); + value_of(divs).should_be(ndivs); + }, + + 'should return all the elements that match the tags': function(){ + var headers = document.getElements('h3,h4'); + var headers2 = Array.flatten([document.getElementsByTagName('h3'), document.getElementsByTagName('h4')]); + value_of(headers.length).should_be(headers2.length); + } + +}); + +describe('Element.getElementById', { + + 'before all': function(){ + Container = new Element('div'); + Container.innerHTML = '

'; + document.body.appendChild(Container); + }, + + 'after all': function(){ + document.body.removeChild(Container); + Container = null; + }, + + 'should getElementById that matches the id, otherwise null': function(){ + value_of(Container.getElementById('first')).should_be(Container.childNodes[0]); + value_of(Container.getElementById('not_found')).should_be_null(); + } + +}); + +describe('Element.get style', { + + "should return a CSS string representing the Element's styles": function(){ + var style = 'font-size:12px;color:rgb(255,255,255)'; + var myElement = new Element('div').set('style', style); + value_of(myElement.get('style').toLowerCase().replace(/\s/g, '').replace(/;$/, '')).should_be(style); + //I'm replacing these characters (space and the last semicolon) as they are not vital to the style, and browsers sometimes include them, sometimes not. + } + +}); + +describe('Element.get tag', { + + "should return the Element's tag": function(){ + var myElement = new Element('div'); + value_of(myElement.get('tag')).should_be('div'); + } + +}); + +describe('Element.get', { + + "should get an absolute href": function(){ + var link = new Element('a', {href: "http://google.com/"}); + value_of(link.get('href')).should_be("http://google.com/"); + }, + + "should get an absolute href to the same domain": function(){ + var link = new Element('a', {href: window.location.href}); + value_of(link.get('href')).should_be(window.location.href); + }, + + "should get a relative href": function(){ + var link = new Element('a', {href: "../index.html"}); + value_of(link.get('href')).should_be("../index.html"); + }, + + "should get a host absolute href": function(){ + var link = new Element('a', {href: "/developers"}); + value_of(link.get('href')).should_be("/developers"); + }, + + "should return null when attribute is missing": function(){ + var link = new Element('a'); + value_of(link.get('href')).should_be_null(); + } + +}); + +describe('Element.erase', { + + "should erase an Element's property": function(){ + var myElement = new Element('a', {href: 'http://mootools.net/', title: 'mootools!'}); + value_of(myElement.get('title')).should_be('mootools!'); + value_of(myElement.erase('title').get('title')).should_be_null(); + }, + + "should erase an Element's style": function(){ + var myElement = new Element('div', {style: "color:rgb(255, 255, 255); font-size:12px;"}); + myElement.erase('style'); + value_of(myElement.get('style')).should_be(''); + } + +}); + +describe('Element.match', { + + 'should return true if tag is not provided': function(){ + var element = new Element('div'); + value_of(element.match()).should_be_true(); + }, + + "should return true if the Element's tag matches": function(){ + var element = new Element('div'); + value_of(element.match('div')).should_be_true(); + } + +}); + +describe('Element.inject', { + + 'before all': function(){ + var html = [ + '
', + '
', + '
', + '
', + '
' + ].join(''); + Container = new Element('div', {style: 'position:absolute;top:0;left:0;visibility:hidden;', html: html}); + document.body.appendChild(Container); + + test = new Element('div', {id:'inject-test'}); + }, + + 'after all': function(){ + document.body.removeChild(Container); + Container.set('html', ''); + Container = null; + test = null; + }, + + 'should inject the Element before an Element': function(){ + test.inject($('first'), 'before'); + value_of(Container.childNodes[0]).should_be(test); + + test.inject($('second-child'), 'before'); + value_of(Container.childNodes[1].childNodes[1]).should_be(test); + }, + + 'should inject the Element after an Element': function(){ + test.inject($('first'), 'after'); + value_of(Container.childNodes[1]).should_be(test); + + test.inject($('first-child'), 'after'); + value_of(Container.childNodes[1].childNodes[1]).should_be(test); + }, + + 'should inject the Element at bottom of an Element': function(){ + var first = $('first'); + test.inject(first, 'bottom'); + value_of(first.childNodes[0]).should_be(test); + + var second = $('second'); + test.inject(second, 'bottom'); + value_of(second.childNodes[2]).should_be(test); + + test.inject(Container, 'bottom'); + value_of(Container.childNodes[2]).should_be(test); + }, + + 'should inject the Element inside an Element': function(){ + var first = $('first'); + test.inject(first, 'inside'); + value_of(first.childNodes[0]).should_be(test); + + var second = $('second'); + test.inject(second, 'inside'); + value_of(second.childNodes[2]).should_be(test); + + test.inject(Container, 'inside'); + value_of(Container.childNodes[2]).should_be(test); + }, + + 'should inject the Element at the top of an Element': function(){ + test.inject(Container, 'top'); + value_of(Container.childNodes[0]).should_be(test); + + var second = $('second'); + test.inject(second, 'top'); + value_of(second.childNodes[0]).should_be(test); + }, + + 'should inject the Element in an Element': function(){ + var first = $('first'); + test.inject(first); + value_of(first.childNodes[0]).should_be(test); + + var second = $('second'); + test.inject(second); + value_of(second.childNodes[2]).should_be(test); + + test.inject(Container); + value_of(Container.childNodes[2]).should_be(test); + } + +}); + +describe('Element.replaces', { + + 'should replace an Element with the Element': function(){ + var parent = new Element('div'); + var div = new Element('div', {id: 'original'}).inject(parent); + var el = new Element('div', {id: 'replaced'}); + el.replaces(div); + value_of(parent.childNodes[0]).should_be(el); + } + +}); + +describe('Element.grab', { + + 'before all': function(){ + var html = [ + '
', + '
', + '
', + '
', + '
' + ].join(''); + Container = new Element('div', {style: 'position:absolute;top:0;left:0;visibility:hidden;', html: html}).inject(document.body); + + test = new Element('div', {id:'grab-test'}); + }, + + 'after all': function(){ + document.body.removeChild(Container); + Container.set('html', ''); + Container = null; + test = null; + }, + + 'should grab the Element before this Element': function(){ + $('first').grab(test, 'before'); + value_of(Container.childNodes[0]).should_be(test); + + $('second-child').grab(test, 'before'); + value_of(Container.childNodes[1].childNodes[1]).should_be(test); + }, + + 'should grab the Element after this Element': function(){ + $('first').grab(test, 'after'); + value_of(Container.childNodes[1]).should_be(test); + + $('first-child').grab(test, 'after'); + value_of(Container.childNodes[1].childNodes[1]).should_be(test); + }, + + 'should grab the Element at the bottom of this Element': function(){ + var first = $('first'); + first.grab(test, 'bottom'); + value_of(first.childNodes[0]).should_be(test); + + var second = $('second'); + second.grab(test, 'bottom'); + value_of(second.childNodes[2]).should_be(test); + + Container.grab(test, 'bottom'); + value_of(Container.childNodes[2]).should_be(test); + }, + + 'should grab the Element inside this Element': function(){ + var first = $('first'); + first.grab(test, 'inside'); + value_of(first.childNodes[0]).should_be(test); + + var second = $('second'); + second.grab(test, 'inside'); + value_of(second.childNodes[2]).should_be(test); + + Container.grab(test, 'inside'); + value_of(Container.childNodes[2]).should_be(test); + }, + + 'should grab the Element at the top of this Element': function(){ + Container.grab(test, 'top'); + value_of(Container.childNodes[0]).should_be(test); + + var second = $('second'); + second.grab(test, 'top'); + value_of(second.childNodes[0]).should_be(test); + }, + + 'should grab an Element in the Element': function(){ + var first = $('first').grab(test); + value_of(first.childNodes[0]).should_be(test); + + var second = $('second').grab(test); + value_of(second.childNodes[2]).should_be(test); + + Container.grab(test); + value_of(Container.childNodes[2]).should_be(test); + } + +}); + +describe('Element.wraps', { + + 'should replace and adopt the Element': function(){ + var div = new Element('div'); + var child = new Element('p').inject(div); + + var wrapper = new Element('div', {id: 'wrapper'}).wraps(div.childNodes[0]); + value_of(div.childNodes[0]).should_be(wrapper); + value_of(wrapper.childNodes[0]).should_be(child); + } + +}); + +describe('Element.appendText', { + + 'before all': function(){ + Container = new Element('div', {style: 'position:absolute;top:0;left:0;visibility:hidden;'}).inject(document.body); + }, + + 'before each': function(){ + var html = [ + '
', + '
', + '
', + '
', + '
' + ].join(''); + Container.set('html', html); + }, + + 'after all': function(){ + document.body.removeChild(Container); + Container.set('html', ''); + Container = null; + test = null; + }, + + 'should append a TextNode before this Element': function(){ + $('first').appendText('test', 'before'); + value_of(Container.childNodes[0].nodeValue).should_be('test'); + + $('second-child').appendText('test', 'before'); + value_of(Container.childNodes[2].childNodes[1].nodeValue).should_be('test'); + }, + + 'should append a TextNode the Element after this Element': function(){ + $('first').appendText('test', 'after'); + value_of(Container.childNodes[1].nodeValue).should_be('test'); + + $('first-child').appendText('test', 'after'); + value_of(Container.childNodes[2].childNodes[1].nodeValue).should_be('test'); + }, + + 'should append a TextNode the Element at the bottom of this Element': function(){ + var first = $('first'); + first.appendText('test', 'bottom'); + value_of(first.childNodes[0].nodeValue).should_be('test'); + + var second = $('second'); + second.appendText('test', 'bottom'); + value_of(second.childNodes[2].nodeValue).should_be('test'); + + Container.appendText('test', 'bottom'); + value_of(Container.childNodes[2].nodeValue).should_be('test'); + }, + + 'should append a TextNode the Element inside this Element': function(){ + var first = $('first'); + first.appendText('test', 'inside'); + value_of(first.childNodes[0].nodeValue).should_be('test'); + + var second = $('second'); + second.appendText('test', 'inside'); + value_of(second.childNodes[2].nodeValue).should_be('test'); + + Container.appendText('test', 'inside'); + value_of(Container.childNodes[2].nodeValue).should_be('test'); + }, + + 'should append a TextNode the Element at the top of this Element': function(){ + Container.appendText('test', 'top'); + value_of(Container.childNodes[0].nodeValue).should_be('test'); + + var second = $('second'); + second.appendText('test', 'top'); + value_of(second.childNodes[0].nodeValue).should_be('test'); + }, + + 'should append a TextNode an Element in the Element': function(){ + var first = $('first').appendText('test'); + value_of(first.childNodes[0].nodeValue).should_be('test'); + + var second = $('second').appendText('test'); + value_of(second.childNodes[2].nodeValue).should_be('test'); + + Container.appendText('test'); + value_of(Container.childNodes[2].nodeValue).should_be('test'); + } + +}); + +describe('Element.adopt', { + + 'before all': function(){ + Container = new Element('div').inject(document.body); + }, + + 'after all': function(){ + document.body.removeChild(Container); + Container.set('html', ''); + Container = null; + }, + + 'before each': function(){ + Container.empty(); + }, + + 'should adopt an Element by its id': function(){ + var child = new Element('div', {id: 'adopt-me'}); + document.body.appendChild(child); + Container.adopt('adopt-me'); + value_of(Container.childNodes[0]).should_be(child); + }, + + 'should adopt an Element': function(){ + var child = new Element('p'); + Container.adopt(child); + value_of(Container.childNodes[0]).should_be(child); + }, + + 'should adopt any number of Elements or ids': function(){ + var children = []; + (4).times(function(i){ children[i] = new Element('span', {id: 'child-' + i}); }); + Container.adopt(children); + value_of(Container.childNodes).should_have(4, 'items'); + value_of(Container.childNodes[3]).should_be(children[3]); + } + +}); + +describe('Element.dispose', { + + 'before all': function(){ + Container = new Element('div').inject(document.body); + }, + + 'after all': function(){ + document.body.removeChild(Container); + Container.set('html', ''); + Container = null; + }, + + 'should dispose the Element from the DOM': function(){ + var child = new Element('div').inject(Container); + child.dispose(); + value_of(Container.childNodes.length).should_be(0); + } + +}); + +describe('Element.clone', { + + 'before all': function(){ + Container = new Element('div', {'id': 'outer', 'class': 'moo'}); + Container.innerHTML = '
under
'; + }, + + 'after all': function(){ + Container = null; + }, + + 'should return a clone': function(){ + var div = new Element('div'); + var clone = div.clone(); + value_of(div).should_not_be(clone); + value_of($type(div)).should_be('element'); + value_of($type(clone)).should_be('element'); + }, + + 'should remove id from clone and clone children by default': function(){ + var clone = Container.clone(); + value_of(clone.getElementsByTagName('*').length).should_be(3); + value_of(clone.className).should_be('moo'); + value_of(clone.id).should_be(''); + value_of(Container.id).should_be('outer'); + }, + + 'should remove all ids': function(){ + var clone = Container.clone(true); + value_of(clone.id).should_be(''); + value_of(clone.childNodes.length).should_be(2); + value_of(clone.childNodes[0].id).should_be(''); + value_of(clone.childNodes[0].childNodes[0].id).should_be(''); + value_of(clone.childNodes[0].className).should_be('foo'); + }, + + 'should keep id if specified': function(){ + var clone = Container.clone(true, true); + value_of(clone.id).should_be('outer'); + value_of(clone.childNodes.length).should_be(2); + value_of(clone.childNodes[0].id).should_be('inner1'); + value_of(clone.childNodes[0].childNodes[0].id).should_be('sixfeet'); + value_of(clone.childNodes[0].className).should_be('foo'); + }, + + 'should clone empty href attribute': function(){ + var clone = new Element('div', { + html: 'empty anchor' + }).getFirst().clone(); + + value_of(clone.getAttribute('href', 2)).should_be(''); + }, + + 'should not clone Element Storage': function(){ + Container.store('drink', 'milk'); + var clone = Container.clone(); + value_of(clone.retrieve('drink')).should_be_null(); + value_of(Container.retrieve('drink')).should_be('milk'); + }, + + 'should clone child nodes and not copy their uid': function(){ + var cloned = Container.clone(true).getElements('*'); + var old = Container.getElements('*'); + value_of(cloned.length).should_be(3); + value_of(old.length).should_be(3); + value_of($$(old, cloned).length).should_be(6); + }, + + 'should clone a text input and retain value': function(){ + var inputs = new Element('div', { 'html': '' + + '' + + '' + }).getChildren(); + + var input1 = inputs[0].clone(); + var input2 = inputs[1].clone(false, true); + + value_of(!input1.id).should_be_true(); + value_of(input2.id).should_be('input2'); + value_of(input1.value).should_be('Some Value'); + value_of(input2.value).should_be(''); + }, + + 'should clone a textarea and retain value': function(){ + var textareas = new Element('div', { 'html': '' + + '' + + '' + }).getChildren(); + + var textarea1 = textareas[0].clone(); + var textarea2 = textareas[1].clone(false, true); + + value_of(!textarea1.id).should_be_true(); + value_of(textarea2.id).should_be('textarea2'); + value_of(textarea1.value).should_be(''); + value_of(textarea2.value).should_be('Some-Text-Here'); + }, + + 'should clone a checkbox and retain checked state': function(){ + var checks = new Element('div', { 'html': '' + + '' + + '' + }).getChildren(); + + var check1 = checks[0].clone(); + var check2 = checks[1].clone(false, true); + + value_of(!check1.id).should_be_true(); + value_of(check2.id).should_be('check2'); + value_of(check1.checked).should_be_false(); + value_of(check2.checked).should_be_true(); + }, + + 'should clone a select and retain selected state': function(){ + var selects = new Element('div', { 'html': '' + + '' + + '' + }).getChildren(); + + var select1 = selects[0].clone(true); + var select2 = selects[1].clone(true, true); + + value_of(!select1.id).should_be_true(); + value_of(select2.id).should_be('select2'); + value_of(select1.selectedIndex).should_be(3); + value_of(select2.options[3].selected).should_be_true(); + value_of(select2.options[4].selected).should_be_true(); + }, + + 'should clone custom attributes': function(){ + var div = new Element('div'); + div.setAttribute('foo', 'FOO'); + div.setAttribute('bar', ['BAR']); + var clone = div.clone(); + + value_of(clone.getAttribute('foo')).should_be('FOO'); + value_of(clone.getAttribute('bar')).should_be(['BAR']); + } + +}); + +describe('Element className methods', { + + 'should return true if the Element has the given class': function(){ + var div = new Element('div', {'class': 'header bold'}); + value_of(div.hasClass('header')).should_be_true(); + value_of(div.hasClass('bold')).should_be_true(); + value_of(div.hasClass('random')).should_be_false(); + }, + + 'should add the class to the Element': function(){ + var div = new Element('div'); + div.addClass('myclass'); + value_of(div.hasClass('myclass')).should_be_true(); + }, + + 'should append classes to the Element': function(){ + var div = new Element('div', {'class': 'myclass'}); + div.addClass('aclass'); + value_of(div.hasClass('aclass')).should_be_true(); + }, + + 'should remove the class in the Element': function(){ + var div = new Element('div', {'class': 'myclass'}); + div.removeClass('myclass'); + value_of(div.hasClass('myclass')).should_be_false(); + }, + + 'should only remove the specific class': function(){ + var div = new Element('div', {'class': 'myclass aclass'}); + div.removeClass('myclass'); + value_of(div.hasClass('myclass')).should_be_false(); + }, + + 'should not remove any class if the class is not found': function(){ + var div = new Element('div', {'class': 'myclass'}); + div.removeClass('extra'); + value_of(div.hasClass('myclass')).should_be_true(); + }, + + 'should add the class if the Element does not have the class': function(){ + var div = new Element('div'); + div.toggleClass('myclass'); + value_of(div.hasClass('myclass')).should_be_true(); + }, + + 'should remove the class if the Element does have the class': function(){ + var div = new Element('div', {'class': 'myclass'}); + div.toggleClass('myclass'); + value_of(div.hasClass('myclass')).should_be_false(); + } + +}); + +describe('Element.empty', { + + 'should remove all children': function(){ + var children = []; + (5).times(function(i){ children[i] = new Element('p'); }); + var div = new Element('div').adopt(children); + div.empty(); + value_of(div.get('html')).should_be(''); + } + +}); + +describe('Element.destroy', { + + 'should obliterate the Element from the universe': function(){ + var div = new Element('div', {id: 'destroy-test'}).inject(document.body); + var result = div.destroy(); + value_of(result).should_be_null(); + value_of($('destroy-test')).should_be_null(); + } + +}); + +describe('Element.toQueryString', { + + 'should return an empty string for an Element that does not have form Elements': function(){ + var div = new Element('div'); + value_of(div.toQueryString()).should_be(''); + }, + + 'should ignore any form Elements that do not have a name, disabled, or whose value is false': function(){ + var form = new Element('form').adopt( + new Element('input', { name: 'input', disabled: true, type: 'checkbox', checked: true, value: 'checked' }), + new Element('select').adopt( + new Element('option', { name: 'volvo', value: false, html: 'Volvo' }), + new Element('option', { value: 'saab', html: 'Saab', selected: true }) + ), + new Element('textarea', { name: 'textarea', disabled: true, value: 'textarea-value' }) + ); + value_of(form.toQueryString()).should_be(''); + }, + + "should return a query string from the Element's form Elements": function(){ + var form = new Element('form', { 'html': '' + + '' + + '' + + '' + }); + value_of(form.toQueryString()).should_be('input=checked&select[]=saab&select[]=opel&textarea=textarea-value'); + }, + + "should return a query string containing even empty values, single select must have a selected option": function() { + var form = new Element('form').adopt( + new Element('input', {name: 'input', type: 'checkbox', checked: true, value: ''}), + new Element('select', {name: 'select[]'}).adopt( + new Element('option', {name: 'none', value: '', html: '--', selected: true}), + new Element('option', {name: 'volvo', value: 'volvo', html: 'Volvo'}), + new Element('option', {name: 'saab', value: 'saab', html: 'Saab'}), + new Element('option', {name: 'opel', value: 'opel', html: 'Opel'}), + new Element('option', {name: 'bmw', value: 'bmw', html: 'BMW'}) + ), + new Element('textarea', {name: 'textarea', value: ''}) + ); + value_of(form.toQueryString()).should_be('input=&select[]=&textarea='); + value_of(form.getElementsByTagName('select')[0].selectedIndex).should_be(0); + }, + + "should return a query string containing even empty values, multiple select may have no selected options": function() { + var form = new Element('form',{'html': + '' + + '' + + '' + }); + value_of(form.toQueryString()).should_be('input=&textarea='); + } + +}); + +describe('Element.getProperty', { + + 'should getProperty from an Element': function(){ + var anchor1 = new Element('a'); + anchor1.href = 'http://mootools.net'; + value_of(anchor1.getProperty('href')).should_be('http://mootools.net'); + + var anchor2 = new Element('a'); + anchor2.href = '#someLink'; + value_of(anchor2.getProperty('href')).should_be('#someLink'); + }, + + 'should getProperty type of an input Element': function(){ + var input1 = new Element('input', {type: 'text'}); + value_of(input1.getProperty('type')).should_be('text'); + + var input2 = new Element('input', {type: 'checkbox'}); + value_of(input2.getProperty('type')).should_be('checkbox'); + }, + + 'should getPropety checked from an input Element': function(){ + var checked1 = new Element('input', { type: 'checkbox' }); + checked1.checked = 'checked'; + value_of(checked1.getProperty('checked')).should_be_true(); + + var checked2 = new Element('input', { type: 'checkbox' }); + checked2.checked = true; + value_of(checked2.getProperty('checked')).should_be_true(); + + var checked3 = new Element('input', { type: 'checkbox' }); + checked3.checked = false; + value_of(checked3.getProperty('checked')).should_be_false(); + }, + + 'should getProperty disabled from an input Element': function(){ + var disabled1 = new Element('input', { type: 'text' }); + disabled1.disabled = 'disabled'; + value_of(disabled1.getProperty('disabled')).should_be_true(); + + var disabled2 = new Element('input', { type: 'text' }); + disabled2.disabled = true; + value_of(disabled2.getProperty('disabled')).should_be_true(); + + var disabled3 = new Element('input', { type: 'text' }); + disabled3.disabled = false; + value_of(disabled3.getProperty('disabled')).should_be_false(); + }, + + 'should getProperty readonly from an input Element': function(){ + var readonly1 = new Element('input', { type: 'text' }); + readonly1.readOnly = 'readonly'; + value_of(readonly1.getProperty('readonly')).should_be_true(); + + var readonly2 = new Element('input', { type: 'text' }); + readonly2.readOnly = true; + value_of(readonly2.getProperty('readonly')).should_be_true(); + + var readonly3 = new Element('input', { type: 'text' }); + readonly3.readOnly = false; + value_of(readonly3.getProperty('readonly')).should_be_false(); + } + +}); + +describe('Element.setProperty', { + + 'should setProperty from an Element': function(){ + var anchor1 = new Element('a').setProperty('href', 'http://mootools.net/'); + value_of(anchor1.getProperty('href')).should_be('http://mootools.net/'); + + var anchor2 = new Element('a').setProperty('href', '#someLink'); + value_of(anchor2.getProperty('href')).should_be('#someLink'); + }, + + 'should setProperty type of an input Element': function(){ + var input1 = new Element('input').setProperty('type', 'text'); + value_of(input1.getProperty('type')).should_be('text'); + + var input2 = new Element('input').setProperty('type', 'checkbox'); + value_of(input2.getProperty('type')).should_be('checkbox'); + }, + + 'should setProperty checked from an input Element': function(){ + var checked1 = new Element('input', { type: 'checkbox' }).setProperty('checked', 'checked'); + value_of(checked1.getProperty('checked')).should_be_true(); + + var checked2 = new Element('input', { type: 'checkbox' }).setProperty('checked', true); + value_of(checked2.getProperty('checked')).should_be_true(); + + var checked3 = new Element('input', { type: 'checkbox' }).setProperty('checked', false); + value_of(checked3.getProperty('checked')).should_be_false(); + }, + + 'should setProperty disabled of an input Element': function(){ + var disabled1 = new Element('input', { type: 'text' }).setProperty('disabled', 'disabled'); + value_of(disabled1.getProperty('disabled')).should_be_true(); + + var disabled2 = new Element('input', { type: 'text' }).setProperty('disabled', true); + value_of(disabled2.getProperty('disabled')).should_be_true(); + + var disabled3 = new Element('input', { type: 'text' }).setProperty('disabled', false); + value_of(disabled3.getProperty('disabled')).should_be_false(); + }, + + 'should setProperty readonly of an input Element': function(){ + var readonly1 = new Element('input', { type: 'text' }).setProperty('readonly', 'readonly'); + value_of(readonly1.getProperty('readonly')).should_be_true(); + + var readonly2 = new Element('input', { type: 'text' }).setProperty('readonly', true); + value_of(readonly2.getProperty('readonly')).should_be_true(); + + var readonly3 = new Element('input', { type: 'text' }).setProperty('readonly', false); + value_of(readonly3.getProperty('readonly')).should_be_false(); + } + +}); + +describe('Element.getProperties', { + + 'should return an object associate with the properties passed': function(){ + var readonly = new Element('input', { type: 'text', readonly: 'readonly' }); + var props = readonly.getProperties('type', 'readonly'); + value_of(props).should_be({ type: 'text', readonly: true }); + } + +}); + +describe('Element.setProperties', { + + 'should set each property to the Element': function(){ + var readonly = new Element('input').setProperties({ type: 'text', readonly: 'readonly' }); + var props = readonly.getProperties('type', 'readonly'); + value_of(props).should_be({ type: 'text', readonly: true }); + } + +}); + +describe('Element.removeProperty', { + + 'should removeProperty from an Element': function () { + var readonly = new Element('input', { type: 'text', readonly: 'readonly' }); + readonly.removeProperty('readonly'); + var props = readonly.getProperties('type', 'readonly'); + value_of(props).should_be({ type: 'text', readonly: false }); + } + +}); + +describe('Element.removeProperties', { + + 'should remove each property from the Element': function(){ + var anchor = new Element('a', {href: '#', title: 'title', rel: 'left'}); + anchor.removeProperties('title', 'rel'); + value_of(anchor.getProperties('href', 'title', 'rel')).should_be({ href: '#' }); + } + +}); + +describe('Element.getPrevious', { + + 'should return the previous Element, otherwise null': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('div'), new Element('div')]; + container.adopt(children); + value_of(children[1].getPrevious()).should_be(children[0]); + value_of(children[0].getPrevious()).should_be_null(); + }, + + 'should return the previous Element that matches, otherwise null': function(){ + var container = new Element('div'); + var children = [new Element('a'), new Element('div'), new Element('div'), new Element('div')]; + container.adopt(children); + value_of(children[1].getPrevious('a')).should_be(children[0]); + value_of(children[1].getPrevious('span')).should_be_null(); + } + +}); + +describe('Element.getAllPrevious', { + + 'should return all the previous Elements, otherwise an empty array': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('div'), new Element('div')]; + container.adopt(children); + value_of(children[2].getAllPrevious()).should_be([children[1], children[0]]); + value_of(children[0].getAllPrevious()).should_be([]); + }, + + 'should return all the previous Elements that match, otherwise an empty array': function(){ + var container = new Element('div'); + var children = [new Element('a'), new Element('div'), new Element('a'), new Element('div')]; + container.adopt(children); + value_of(children[3].getAllPrevious('a')).should_be([children[2], children[0]]); + value_of(children[1].getAllPrevious('span')).should_be([]); + } + +}); + +describe('Element.getNext', { + + 'should return the next Element, otherwise null': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('div'), new Element('div')]; + container.adopt(children); + value_of(children[1].getNext()).should_be(children[2]); + value_of(children[2].getNext()).should_be_null(); + }, + + 'should return the previous Element that matches, otherwise null': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('div'), new Element('div'), new Element('a')]; + container.adopt(children); + value_of(children[1].getNext('a')).should_be(children[3]); + value_of(children[1].getNext('span')).should_be_null(); + } + +}); + +describe('Element.getAllNext', { + + 'should return all the next Elements, otherwise an empty array': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('div'), new Element('div')]; + container.adopt(children); + value_of(children[0].getAllNext()).should_be(children.slice(1)); + value_of(children[2].getAllNext()).should_be([]); + }, + + 'should return all the next Elements that match, otherwise an empty array': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('a'), new Element('div'), new Element('a')]; + container.adopt(children); + value_of(children[0].getAllNext('a')).should_be([children[1], children[3]]); + value_of(children[0].getAllNext('span')).should_be([]); + } + +}); + +describe('Element.getFirst', { + + 'should return the first Element in the Element, otherwise null': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('a'), new Element('div')]; + container.adopt(children); + value_of(container.getFirst()).should_be(children[0]); + value_of(children[0].getFirst()).should_be_null(); + }, + + 'should return the first Element in the Element that matches, otherwise null': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('a'), new Element('div')]; + container.adopt(children); + value_of(container.getFirst('a')).should_be(children[1]); + value_of(container.getFirst('span')).should_be_null(); + } + +}); + +describe('Element.getLast | Element.getLastChild', { + + 'should return the last Element in the Element, otherwise null': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('a'), new Element('div')]; + container.adopt(children); + value_of(container.getLast()).should_be(children[2]); + value_of(children[0].getLast()).should_be_null(); + }, + + 'should return the last Element in the Element that matches, otherwise null': function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('a'), new Element('div'), new Element('a')]; + container.adopt(children); + value_of(container.getLast('a')).should_be(children[3]); + value_of(container.getLast('span')).should_be_null(); + } + +}); + +describe('Element.getParent', { + + 'should return the parent of the Element, otherwise null': function(){ + var container = new Element('p'); + var children = [new Element('div'), new Element('div'), new Element('div')]; + container.adopt(children); + value_of(children[1].getParent()).should_be(container); + value_of(container.getParent()).should_be_null(); + }, + + 'should return the parent of the Element that matches, otherwise null': function(){ + var container = new Element('p'); + var children = [new Element('div'), new Element('div'), new Element('div')]; + container.adopt(new Element('div').adopt(children)); + value_of(children[1].getParent('p')).should_be(container); + value_of(children[1].getParent('table')).should_be_null(); + } + +}); + +describe('Element.getParents', { + + 'should return the parents of the Element, otherwise returns an empty array': function(){ + var container = new Element('p'); + var children = [new Element('div'), new Element('div'), new Element('div')]; + container.adopt(new Element('div').adopt(new Element('div').adopt(children))); + value_of(children[1].getParents()).should_be([container.getFirst().getFirst(), container.getFirst(), container]); + value_of(container.getParents()).should_be([]); + }, + + 'should return the parents of the Element that match, otherwise returns an empty array': function(){ + var container = new Element('p'); + var children = [new Element('div'), new Element('div'), new Element('div')]; + container.adopt(new Element('div').adopt(new Element('div').adopt(children))); + value_of(children[1].getParents('div')).should_be([container.getFirst().getFirst(), container.getFirst()]); + value_of(children[1].getParents('table')).should_be([]); + } + +}); + +describe('Element.getChildren', { + + "should return the Element's children, otherwise returns an empty array": function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('div'), new Element('div')]; + container.adopt(children); + value_of(container.getChildren()).should_be(children); + value_of(children[0].getChildren()).should_be([]); + }, + + "should return the Element's children that match, otherwise returns an empty array": function(){ + var container = new Element('div'); + var children = [new Element('div'), new Element('a'), new Element('a')]; + container.adopt(children); + value_of(container.getChildren('a')).should_be([children[1], children[2]]); + value_of(container.getChildren('span')).should_be([]); + } + +}); + +describe('Element.hasChild', { + + "before all": function(){ + window.Local = {}; + Local.container = new Element('div'); + Local.children = [new Element('div'), new Element('div'), new Element('div')]; + Local.container.adopt(Local.children); + Local.grandchild = new Element('div').inject(Local.children[1]); + }, + + "after all": function(){ + Local = null; + }, + + "should return true if the Element is a child or grandchild": function(){ + value_of(Local.container.hasChild(Local.children[0])).should_be_true(); + value_of(Local.container.hasChild(Local.children[2])).should_be_true(); + value_of(Local.container.hasChild(Local.grandchild)).should_be_true(); + }, + + "should return false if it's the Element itself": function(){ + value_of(Local.container.hasChild(Local.container)).should_be_false(); + }, + + "should return false if the Element is the parent or a sibling": function(){ + value_of(Local.children[2].hasChild(Local.container)).should_be_false(); + value_of(Local.children[2].hasChild(Local.children[1])).should_be_false(); + } + +}); diff --git a/assets/mootools-core/Specs/Native/Array.js b/assets/mootools-core/Specs/Native/Array.js new file mode 100644 index 00000000..37d28e6b --- /dev/null +++ b/assets/mootools-core/Specs/Native/Array.js @@ -0,0 +1,207 @@ +/* +Script: Array.js + Specs for Array.js + +License: + MIT-style license. +*/ + +describe("Array Methods", { + + // Array.flatten + + 'should flatten a multidimensional array': function(){ + var arr = [1,2,3,[4,5,[6,7,[8]]], [[[[[9]]]]]]; + value_of(arr.flatten()).should_be([1,2,3,4,5,6,7,8,9]); + }, + + 'should flatten arguments': function(){ + var test = function(){ + return Array.flatten(arguments); + }; + value_of(test(1,2,3)).should_be([1,2,3]); + value_of(test([1,2,3])).should_be([1,2,3]); + value_of(test(1,2,[3])).should_be([1,2,3]); + }, + + // Array.filter + + 'should filter an array': function(){ + var array = [1,2,3,0,0,0]; + var arr = array.concat([false, null, 4]).filter(Number.type); + value_of(arr).should_be(array.concat(4)); + }, + + // Array.clean + + 'should clean an array from undefined and null values': function(){ + var array = [null, 1, 0, true, false, "foo", undefined]; + var arr = array.clean(); + value_of(arr).should_be([1, 0, true, false, "foo"]); + }, + + // Array.map + + 'should return a mapping of an array': function(){ + var arr = [1,2,3,0,0,0].map(function(item){ + return (item + 1); + }); + + value_of(arr).should_be([2,3,4,1,1,1]); + }, + + // Array.every + + 'should return true if every item matches the comparator, otherwise false': function(){ + value_of([1,2,3,0,0,0].every(Number.type)).should_be_true(); + + value_of(['1',2,3,0].every(Number.type)).should_be_false(); + }, + + // Array.some + + 'should return true if some of the items in the array match the comparator, otherwise false': function(){ + value_of(['1',2,3,0].some(Number.type)).should_be_true(); + + value_of([1,2,3,0,0,0].map(String).some(Number.type)).should_be_false(); + }, + + // Array.indexOf + + 'should return the index of the item': function(){ + value_of([1,2,3,0,0,0].indexOf(0)).should_be(3); + }, + + 'should return -1 if the item is not found in the array': function(){ + value_of([1,2,3,0,0,0].indexOf('not found')).should_be(-1); + }, + + // Array.erase + + 'should remove all items in the array that match the specified item': function(){ + var arr = [1,2,3,0,0,0].erase(0); + value_of(arr).should_be([1,2,3]); + }, + + // Array.contains + + 'should return true if the array contains the specified item': function(){ + value_of([1,2,3,0,0,0].contains(0)).should_be_true(); + }, + + 'should return false if the array does not contain the specified item': function(){ + value_of([0,1,2].contains('not found')).should_be_false(); + }, + + // Array.associate + + 'should associate an array with a specified array': function(){ + var obj = [1,2,3,0,0,0].associate(['a', 'b', 'c', 'd']); + value_of(obj).should_be({a:1, b:2, c:3, d:0}); + }, + + // Array.link + + 'should link an array items to a new object according to the specified matchers': function(){ + var el = document.createElement('div'); + var assoc2 = [100, 'Hello', {foo: 'bar'}, el, false].link({ + myNumber: Number.type, + myElement: Element.type, + myObject: Object.type, + myString: String.type, + myBoolean: $defined + }); + + value_of(assoc2).should_be({ + myNumber: 100, + myElement: el, + myObject: {foo: 'bar'}, + myString: 'Hello', + myBoolean: false + }); + }, + + // Array.extend + + 'should extend an array': function(){ + var a = [1,2,4]; + var b = [2,3,4,5]; + a.extend(b); + value_of(a).should_be([1,2,4,2,3,4,5]); + value_of(b).should_be([2,3,4,5]); + }, + + // Array.combine + + 'should combine an array': function(){ + var arr = [1,2,3,4].combine([3,1,4,5,6,7]); + value_of(arr).should_be([1,2,3,4,5,6,7]); + }, + + // Array.include + + 'should include only new items': function(){ + var arr = [1,2,3,4].include(1).include(5); + value_of(arr).should_be([1,2,3,4,5]); + }, + + // Array.getLast + + 'should return the last item in the array': function(){ + value_of([1,2,3,0,0,0].getLast()).should_be(0); + value_of([3].getLast()).should_be(3); + }, + + 'should return null if there are no items': function(){ + value_of([].getLast()).should_be(null); + }, + + // Array.empty + + 'should empty the array': function(){ + var arr = [1,2,3,4].empty(); + value_of(arr).should_be([]); + } + +}); + +describe("Array Color Methods", { + + // Array.hexToRgb + + 'should return null if the length of the array is not 3': function(){ + value_of([].hexToRgb()).should_be_null(); + }, + + 'should return a CSS rgb string': function(){ + value_of(['0','0','0'].hexToRgb()).should_be('rgb(0,0,0)'); + }, + + 'should support shorthand hex': function(){ + value_of(['c','c','c'].hexToRgb()).should_be('rgb(204,204,204)'); + }, + + 'should return an array with 16-based numbers when passed true': function(){ + value_of(['ff','ff','ff'].hexToRgb(true)).should_be([255,255,255]); + }, + + // Array.rgbToHex + + 'should return null if the array does not have at least 3 times': function(){ + value_of([0,1].rgbToHex()).should_be_null(); + }, + + 'should return a css hexadecimal string': function(){ + value_of(['255', '0', '0'].rgbToHex()).should_be('#ff0000'); + value_of([0,0,255].rgbToHex()).should_be('#0000ff'); + }, + + 'should return an array with hexadecimal string items': function(){ + value_of([0,255,0].rgbToHex(true)).should_be(['00', 'ff', '00']); + }, + + 'should return `transparent` if the fourth item is 0 and first param is not true': function(){ + value_of([0,0,0,0].rgbToHex()).should_be('transparent'); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Native/Function.js b/assets/mootools-core/Specs/Native/Function.js new file mode 100644 index 00000000..61a5dd1b --- /dev/null +++ b/assets/mootools-core/Specs/Native/Function.js @@ -0,0 +1,155 @@ +/* +Script: Function.js + Specs for Function.js + +License: + MIT-style license. +*/ + +(function(){ + +var fn = function(){ + return $A(arguments); +}; + +var Rules = function(){ + return this + ' rules'; +}; + +var Args = function(){ + return [this].concat($A(arguments)); +}; + +describe("Function Methods", { + + // Function.create + + 'should return a new function': function(){ + var fnc = $empty.create(); + value_of($empty === fnc).should_be_false(); + }, + + 'should return a new function with specified argument': function(){ + var fnc = fn.create({'arguments': 'rocks'}); + value_of(fnc()).should_be(['rocks']); + }, + + 'should return a new function with multiple arguments': function(){ + var fnc = fn.create({'arguments': ['MooTools', 'rocks']}); + value_of(fnc()).should_be(['MooTools', 'rocks']); + }, + + 'should return a new function bound to an object': function(){ + var fnc = Rules.create({'bind': 'MooTools'}); + value_of(fnc()).should_be('MooTools rules'); + }, + + 'should return a new function as an event': function(){ + var fnc = fn.create({'arguments': [0, 1], 'event': true}); + value_of(fnc('an Event occurred')).should_be(['an Event occurred', 0, 1]); + }, + + // Function.bind + + 'should return the function bound to an object': function(){ + var fnc = Rules.bind('MooTools'); + value_of(fnc()).should_be('MooTools rules'); + }, + + 'should return the function bound to an object with specified argument': function(){ + var fnc = Args.bind('MooTools', 'rocks'); + value_of(fnc()).should_be(['MooTools', 'rocks']); + }, + + 'should return the function bound to an object with multiple arguments': function(){ + var fnc = Args.bind('MooTools', ['rocks', 'da house']); + value_of(fnc()).should_be(['MooTools', 'rocks', 'da house']); + }, + + 'should return the function bound to an object and make the function an event listener': function(){ + var fnc = Args.bindWithEvent('MooTools'); + value_of(fnc('an Event ocurred')).should_be(['MooTools', 'an Event ocurred']); + }, + + 'should return the function bound to an object and make the function event listener with multiple arguments': function(){ + var fnc = Args.bindWithEvent('MooTools', ['rocks', 'da house']); + value_of(fnc('an Event ocurred')).should_be(['MooTools', 'an Event ocurred', 'rocks', 'da house']); + }, + + // Function.pass + + 'should return a function that when called passes the specified arguments to the original function': function(){ + var fnc = fn.pass('MooTools is beautiful and elegant'); + value_of(fnc()).should_be(['MooTools is beautiful and elegant']); + }, + + 'should pass multiple arguments and bind the function to a specific object when it is called': function(){ + var fnc = Args.pass(['rocks', 'da house'], 'MooTools'); + value_of(fnc()).should_be(['MooTools', 'rocks', 'da house']); + }, + + // Function.run + + 'should run the function': function(){ + var result = fn.run(); + value_of(result).should_be([]); + }, + + 'should run the function with multiple arguments': function(){ + var result = fn.run(['MooTools', 'beautiful', 'elegant']); + value_of(result).should_be(['MooTools', 'beautiful', 'elegant']); + }, + + 'should run the function with multiple arguments and bind the function to an object': function(){ + var result = Args.run(['beautiful', 'elegant'], 'MooTools'); + value_of(result).should_be(['MooTools', 'beautiful', 'elegant']); + }, + + // Function.extend + + "should extend the function's properties": function(){ + var fnc = (function(){}).extend({a: 1, b: 'c'}); + value_of(fnc.a).should_be(1); + value_of(fnc.b).should_be('c'); + }, + + // Function.attempt + + 'should call the function without raising an exception': function(){ + var fnc = function(){ + this_should_not_work(); + }; + fnc.attempt(); + }, + + "should return the function's return value": function(){ + var fnc = $lambda('hello world!'); + value_of(fnc.attempt()).should_be('hello world!'); + }, + + 'should return null if the function raises an exception': function(){ + var fnc = function(){ + this_should_not_work(); + }; + value_of(fnc.attempt()).should_be_null(); + }, + + // Function.delay + + 'delay should return a timer pointer': function(){ + var timer = $empty.delay(10000); + value_of(Number.type(timer)).should_be_true(); + $clear(timer); + }, + + // Function.periodical + + 'periodical should return a timer pointer': function(){ + var timer = $empty.periodical(10000); + value_of(Number.type(timer)).should_be_true(); + $clear(timer); + } + +}); + +})(); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Native/Hash.js b/assets/mootools-core/Specs/Native/Hash.js new file mode 100644 index 00000000..ff75a33b --- /dev/null +++ b/assets/mootools-core/Specs/Native/Hash.js @@ -0,0 +1,203 @@ +/* +Script: Hash.js + Specs for Hash.js + +License: + MIT-style license. +*/ + +(function(){ + +var hash2 = new Hash({ a: 'string', b: 233, c: {} }); + +describe("Hash Methods", { + + // Hash.constructor + + 'should return a new hash': function(){ + value_of(Hash.type(new Hash())).should_be_true(); + }, + + 'should return a copy of a hash': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + var copy = new Hash(hash); + value_of(copy !== hash).should_be_true(); + value_of(copy).should_be(hash); + }, + + // Hash.erase + + 'should remove a key and its value from the hash': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.erase('a')).should_be(new Hash({b:2,c:3})); + value_of(hash.erase('d')).should_be(new Hash({b:2,c:3})); + + hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.erase('a')).should_be(new Hash({b:2,c:3})); + value_of(hash.erase('d')).should_be(new Hash({b:2,c:3})); + }, + + // Hash.get + + 'should return the value corresponding to the specified key otherwise null': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.get('c')).should_be(3); + value_of(hash.get('d')).should_be_null(); + }, + + // Hash.set + + 'should set the key with the corresponding value': function(){ + var myHash = new Hash({a: 1, b: 2, c: 3}).set('c', 7).set('d', 8); + value_of(myHash).should_be(new Hash({a:1,b:2,c:7,d:8})); + }, + + // Hash.empty + + 'should empty the hash': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.empty()).should_be(new Hash()); + }, + + // Hash.include + + 'should include a key value if the hash does not have the key otherwise ignore': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.include('e', 7)).should_be(new Hash({a:1,b:2,c:3,e:7})); + value_of(hash.include('a', 7)).should_be(new Hash({a:1,b:2,c:3,e:7})); + }, + + // Hash.keyOf | Hash.indexOf + + 'should return the key of the value or null if not found': function(){ + var hash = new Hash({a: 1, b: 2, c: 3, d: 1}); + value_of(hash.keyOf(1)).should_be('a'); + value_of(hash.keyOf('not found')).should_be_null(); + + value_of(hash.indexOf(1)).should_be('a'); + value_of(hash.indexOf('not found')).should_be_null(); + }, + + // Hash.has + + 'should return true if the hash has the key otherwise false': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.has('a')).should_be_true(); + value_of(hash.has('d')).should_be_false(); + }, + + // Hash.hasValue | Hash.contains + + 'should return true if the hash hasValue otherwise false': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.hasValue(1)).should_be_true(); + value_of(hash.hasValue('not found')).should_be_false(); + + value_of(hash.contains(1)).should_be_true(); + value_of(hash.contains('not found')).should_be_false(); + }, + + // Hash.getClean + + 'should getClean JavaScript object': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.getClean()).should_be({a:1,b:2,c:3}); + }, + + // Hash.extend + + 'should extend a Hash with an object': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.extend({a:4,d:7,e:8})).should_be(new Hash({a:4,b:2,c:3,d:7,e:8})); + }, + + 'should extend a Hash with another Hash': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.extend(new Hash({a:4,d:7,e:8}))).should_be(new Hash({a:4,b:2,c:3,d:7,e:8})); + }, + + // Hash.combine + + 'should merge a Hash with an object': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.combine({a:4,d:7,e:8})).should_be(new Hash({a:1,b:2,c:3,d:7,e:8})); + }, + + 'should merge a Hash with another Hash': function(){ + var hash = new Hash({a: 1, b: 2, c: 3}); + value_of(hash.combine(new Hash({a:4,d:7,e:8}))).should_be(new Hash({a:1,b:2,c:3,d:7,e:8})); + }, + + // Hash.each + + 'should iterate through each property': function(){ + var newHash = new Hash(); + var hash = new Hash({a: 1, b: 2, c: 3}); + hash.each(function(value, key){ + newHash.set(key, value); + }); + value_of(newHash).should_be(hash); + }, + + // Hash.map + + 'should map a new Hash according to the comparator': function(){ + value_of(hash2.map(Number.type)).should_be(new Hash({a:false,b:true,c:false})); + }, + + // Hash.filter + + 'should filter the Hash according to the comparator': function(){ + value_of(hash2.filter(Number.type)).should_be(new Hash({b:233})); + }, + + // Hash.every + + 'should return true if every value matches the comparator, otherwise false': function(){ + value_of(hash2.every($defined)).should_be_true(); + value_of(hash2.every(Number.type)).should_be_false(); + }, + + // Hash.some + + 'should return true if some of the values match the comparator, otherwise false': function(){ + value_of(hash2.some(Number.type)).should_be_true(); + value_of(hash2.some(Array.type)).should_be_false(); + }, + + // Hash.getKeys + + 'getKeys should return an empty array': function(){ + value_of(new Hash().getKeys()).should_be([]); + }, + + 'should return an array containing the keys of the hash': function(){ + value_of(hash2.getKeys()).should_be(['a', 'b', 'c']); + }, + + // Hash.getValues + + 'getValues should return an empty array': function(){ + value_of(new Hash().getValues()).should_be([]); + }, + + 'should return an array with the values of the hash': function(){ + value_of(hash2.getValues()).should_be(['string', 233, {}]); + }, + + // Hash.toQueryString + + 'should return a query string': function(){ + var myHash = new Hash({apple: "red", lemon: "yellow"}); + value_of(myHash.toQueryString()).should_be('apple=red&lemon=yellow'); + + var myHash2 = new Hash({apple: ['red', 'yellow'], lemon: ['green', 'yellow']}); + value_of(myHash2.toQueryString()).should_be('apple[0]=red&apple[1]=yellow&lemon[0]=green&lemon[1]=yellow'); + + var myHash3 = new Hash({fruits: {apple: ['red', 'yellow'], lemon: ['green', 'yellow']}}); + value_of(myHash3.toQueryString()).should_be('fruits[apple][0]=red&fruits[apple][1]=yellow&fruits[lemon][0]=green&fruits[lemon][1]=yellow'); + } + +}); + +})(); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Native/Number.js b/assets/mootools-core/Specs/Native/Number.js new file mode 100644 index 00000000..3ccdf189 --- /dev/null +++ b/assets/mootools-core/Specs/Native/Number.js @@ -0,0 +1,114 @@ +/* +Script: Number.js + Specs for Number.js + +License: + MIT-style license. +*/ + +describe("Number Methods", { + + // Number.toInt + + 'should convert a number to an integer': function(){ + value_of((111).toInt()).should_be(111); + }, + + 'should convert a number depending on the radix provided': function(){ + value_of((111).toInt(2)).should_be(7); + value_of((0x16).toInt(10)).should_be(22); //ECMA standard, radix is optional so if starts with 0x then parsed as hexadecimal + value_of((016).toInt(10)).should_be(14); //ECMA standard, radix is optional so if starts with 0 then parsed as octal + }, + + // Number.toFloat + + 'should convert a number to a float': function(){ + value_of((1.00).toFloat()).should_be(1); + value_of((1.12 - 0.12).toFloat()).should_be(1); + value_of((0.0010).toFloat()).should_be(0.001); + value_of((Number.MIN_VALUE).toFloat()).should_be(Number.MIN_VALUE); + }, + + // Number.limit + + 'should limit a number within a range': function(){ + value_of((-1).limit(0, 1)).should_be(0); + value_of((3).limit(1, 2)).should_be(2); + }, + + 'should not limit a number if within the range': function(){ + value_of((2).limit(0,4)).should_be(2); + }, + + // Number.round + + 'should round a number to the nearest whole number if units place is not specified': function(){ + value_of((0.01).round()).should_be(0); + }, + + 'should round a number according the units place specified': function(){ + value_of((0.01).round(2)).should_be(0.01); + value_of((1).round(3)).should_be(1); + value_of((-1.01).round()).should_be(-1); + value_of((-1.01).round(2)).should_be(-1.01); + value_of((111).round(-1)).should_be(110); + value_of((-111).round(-2)).should_be(-100); + value_of((100).round(-5)).should_be(0); + }, + + // Number.times + + 'should call the function for the specified number of times': function(){ + var found = 0; + (3).times(function(i){ + found = i; + }); + + var found2 = -1; + (0).times(function(i){ + found2 = i; + }); + + value_of(found).should_be(2); + value_of(found2).should_be(-1); + }, + + 'should bind and call the function for the specified number of times': function(){ + var aTest = 'hi'; + var found3 = false; + (1).times(function(i){ + found3 = (this == aTest); + }, aTest); + value_of(found3).should_be_true(); + } + +}); + +(function(math){ + var examples = {}; + new Hash(math).each(function(value, key){ + var example = {}; + var b = value.test[1]; + examples['should return the ' + value.title + ' value of the number' + ((b) ? ' and the passed number' : '')] = function(){ + value_of(value.test[0][key](b)).should_be(Math[key].apply(null, value.test)); + }; + }); + describe("Number Math Methods", examples); +})({ + abs: { test: [-1], title: 'absolute' }, + acos: { test: [0], title: 'arc cosine' }, + asin: { test: [0.5], title: 'arc sine' }, + atan: { test: [0.5], title: 'arc tangent' }, + atan2: { test: [0.1, 0.5], title: 'arc tangent' }, + ceil: { test: [0.6], title: 'number closest to and not less than the' }, + cos: { test: [30], title: 'cosine' }, + exp: { test: [2], title: 'exponent' }, + floor: { test: [2.4], title: 'integer closet to and not greater than' }, + log: { test: [2], title: 'log' }, + max: { test: [5, 3], title: 'maximum' }, + min: { test: [-4, 2], title: 'minimum' }, + pow: { test: [2, 2], title: 'power' }, + sin: { test: [0.5], title: 'sine' }, + sqrt: { test: [4], title: 'square root' }, + tan: { test: [0.3], title: 'tangent' } +}); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Native/String.js b/assets/mootools-core/Specs/Native/String.js new file mode 100644 index 00000000..caa54000 --- /dev/null +++ b/assets/mootools-core/Specs/Native/String.js @@ -0,0 +1,158 @@ +/* +Script: String.js + Specs for String.js + +License: + MIT-style license. +*/ + +describe("String Methods", { + + // String.capitalize + + 'should capitalize each word': function(){ + value_of('i like cookies'.capitalize()).should_be('I Like Cookies'); + value_of('I Like cOOKIES'.capitalize()).should_be('I Like COOKIES'); + }, + + // String.camelCase + + 'should convert a hyphenated string into a camel cased string': function(){ + value_of('i-like-cookies'.camelCase()).should_be('iLikeCookies'); + value_of('I-Like-Cookies'.camelCase()).should_be('ILikeCookies'); + }, + + // String.hyphenate + + 'should convert a camel cased string into a hyphenated string': function(){ + value_of('iLikeCookies'.hyphenate()).should_be('i-like-cookies'); + value_of('ILikeCookies'.hyphenate()).should_be('-i-like-cookies'); + }, + + // String.clean + + 'should clean all extraneous whitespace from the string': function(){ + value_of(' i like cookies '.clean()).should_be("i like cookies"); + value_of(' i\nlike \n cookies \n\t '.clean()).should_be("i like cookies"); + }, + + // String.trim + + 'should trim left and right whitespace from the string': function(){ + value_of(' i like cookies '.trim()).should_be('i like cookies'); + value_of(' i \tlike cookies '.trim()).should_be('i \tlike cookies'); + }, + + // String.contains + + 'should return true if the string contains a string otherwise false': function(){ + value_of('i like cookies'.contains('cookies')).should_be_true(); + value_of('i,like,cookies'.contains('cookies')).should_be_true(); + value_of('mootools'.contains('inefficient javascript')).should_be_false(); + }, + + 'should return true if the string constains the string and separator otherwise false': function(){ + value_of('i like cookies'.contains('cookies', ' ')).should_be_true(); + value_of('i like cookies'.contains('cookies', ',')).should_be_false(); + + value_of('i,like,cookies'.contains('cookies', ' ')).should_be_false(); + value_of('i,like,cookies'.contains('cookies', ',')).should_be_true(); + }, + + // String.test + + 'should return true if the test matches the string otherwise false': function(){ + value_of('i like teh cookies'.test('cookies')).should_be_true(); + value_of('i like cookies'.test('ke coo')).should_be_true(); + value_of('I LIKE COOKIES'.test('cookie', 'i')).should_be_true(); + value_of('i like cookies'.test('cookiez')).should_be_false(); + }, + + 'should return true if the regular expression test matches the string otherwise false': function(){ + value_of('i like cookies'.test(/like/)).should_be_true(); + value_of('i like cookies'.test(/^l/)).should_be_false(); + }, + + // String.toInt + + 'should convert the string into an integer': function(){ + value_of('10'.toInt()).should_be(10); + value_of('10px'.toInt()).should_be(10); + value_of('10.10em'.toInt()).should_be(10); + }, + + 'should convert the string into an integer with a specific base': function(){ + value_of('10'.toInt(5)).should_be(5); + }, + + // String.toFloat + + 'should convert the string into a float': function(){ + value_of('10.11'.toFloat()).should_be(10.11); + value_of('10.55px'.toFloat()).should_be(10.55); + }, + + // String.rgbToHex + + 'should convert the string into a CSS hex string': function(){ + value_of('rgb(255,255,255)'.rgbToHex()).should_be('#ffffff'); + value_of('rgb(255,255,255,0)'.rgbToHex()).should_be('transparent'); + }, + + // String.hexToRgb + + 'should convert the CSS hex string into a CSS rgb string': function(){ + value_of('#fff'.hexToRgb()).should_be('rgb(255,255,255)'); + value_of('ff00'.hexToRgb()).should_be('rgb(255,0,0)'); + value_of('#000000'.hexToRgb()).should_be('rgb(0,0,0)'); + }, + + // String.stripScripts + + 'should strip all script tags from a string': function(){ + value_of('
'.stripScripts()).should_be('
'); + }, + + 'should execute the stripped tags from the string': function(){ + value_of('
'.stripScripts(true)).should_be('
'); + value_of(window.stripScriptsSpec).should_be(42); + value_of('
'.stripScripts(true)).should_be('
'); + value_of(window.stripScriptsSpec).should_be(24); + value_of('
'.stripScripts(true)).should_be('
'); + value_of(window.stripScriptsSpec).should_be(4242); + }, + + // String.substitute + + 'should substitute values from objects': function(){ + value_of('This is {color}.'.substitute({'color': 'blue'})).should_be('This is blue.'); + value_of('This is {color} and {size}.'.substitute({'color': 'blue', 'size': 'small'})).should_be('This is blue and small.'); + }, + + 'should substitute values from arrays': function(){ + value_of('This is {0}.'.substitute(['blue'])).should_be('This is blue.'); + value_of('This is {0} and {1}.'.substitute(['blue', 'small'])).should_be('This is blue and small.'); + }, + + 'should remove undefined values': function(){ + value_of('Checking {0}, {1}, {2}, {3} and {4}.'.substitute([1, 0, undefined, null])).should_be('Checking 1, 0, , and .'); + value_of('This is {not-set}.'.substitute({})).should_be('This is .'); + }, + + 'should ignore escaped placeholders': function(){ + value_of('Ignore \\{this} but not {that}.'.substitute({'that': 'the others'})).should_be('Ignore {this} but not the others.'); + }, + + 'should substitute with a custom regex': function(){ + var php = (/\$([\w-]+)/g); + value_of('I feel so $language.'.substitute({'language': 'PHP'}, php)).should_be('I feel so PHP.'); + var ror = (/#\{([^}]+)\}/g); + value_of('I feel so #{language}.'.substitute({'language': 'RoR'}, ror)).should_be('I feel so RoR.'); + }, + + 'should substitute without goofing up nested curly braces': function(){ + value_of("fred {is {not} very} cool".substitute({ 'is {not':'BROKEN' })).should_not_be("fred BROKEN very} cool"); + value_of('this {should {break} mo} betta'.substitute({ 'break':'work' })).should_be('this {should work mo} betta'); + } + +}); diff --git a/assets/mootools-core/Specs/Plugins/Selectors.Children.js b/assets/mootools-core/Specs/Plugins/Selectors.Children.js new file mode 100644 index 00000000..8f7a43c2 --- /dev/null +++ b/assets/mootools-core/Specs/Plugins/Selectors.Children.js @@ -0,0 +1,61 @@ +/* +Script: Selectors.Children.js + Specification Examples of Pseudo Selector :children. + +License: + MIT-style license. +*/ + +var Container, Children = []; + +describe('PSeudo Selector :children', { + + 'before all': function(){ + Container = new Element('div', {styles: {position: 'absolute', top: 0, left: 0, visibility: 'hidden'}}); + (10).times(function(i){ + Children.push(new Element('span', {id: 'child-' + i}).set('html', i)); + }); + Container.adopt(Children).inject(document.body); + }, + + 'after all': function(){ + Container.destroy(); + }, + + 'should use zero-based indexing': function(){ + value_of(Container.getElement(':children(0)')).should_be(Children[0]); + }, + + 'should use negative indexing': function(){ + value_of(Container.getElement(':children(-2)')).should_be(Children[8]); + }, + + 'should return a range of child nodes': function(){ + value_of(Container.getElements(':children(0:2)')).should_be(Children.slice(0,3)); + }, + + 'should return a range of child nodes including negative index sorted from first to last node': function(){ + var children = Children.slice(0,3).extend(Children.slice(8)); + value_of(Container.getElements(':children(-2:2)')).should_be(children); + value_of(Container.getElements(':children(2:-2)')).should_be(Children.slice(2,9)); + }, + + 'should return the node and n-number of child nodes to the right': function(){ + value_of(Container.getElements(':children(3+2)')).should_be(Children.slice(3,6)); + }, + + 'should return the node and n-number of child nodes to the right and wrap if necessary and sorting from first to last': function(){ + var children = Children.slice(0,3).extend(Children.slice(8)); + value_of(Container.getElements(':children(8+4)')).should_be(children); + }, + + 'should return the node and n-number of child nodes to the left': function(){ + value_of(Container.getElements(':children(5-5)')).should_be(Children.slice(0,6)); + }, + + 'should return the node and n-number of child nodes to the left and wrap if necessary and sorting from first to last': function(){ + var children = Children.slice(0,3).extend(Children.slice(7)); + value_of(Container.getElements(':children(2-5)')).should_be(children); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Utilities/Color.js b/assets/mootools-core/Specs/Utilities/Color.js new file mode 100644 index 00000000..205ea874 --- /dev/null +++ b/assets/mootools-core/Specs/Utilities/Color.js @@ -0,0 +1,62 @@ +var myColor; +//colors compared with photoshop values. + +describe('Color constructor, hex', { + + 'before all': function(){ + myColor = new Color('#a2c240'); + }, + + 'should have the correct rgb': function(){ + value_of(myColor).should_be([162, 194, 64]); + }, + + 'should have the correct hsb': function(){ + value_of(myColor.hsb).should_be([75, 67, 76]); + }, + + 'should have the correct hex': function(){ + value_of(myColor.hex).should_be('#a2c240'); + } + +}); + +describe('Color constructor, hsb', { + + 'before all': function(){ + myColor = new Color('hsb(75, 67, 76)'); + }, + + 'should have the correct rgb': function(){ + value_of(myColor).should_be([161, 194, 64]); + }, + + 'should have the correct hsb': function(){ + value_of(myColor.hsb).should_be([75, 67, 76]); + }, + + 'should have the correct hex': function(){ + value_of(myColor.hex).should_be('#a1c240'); + } + +}); + +describe('Color constructor, rgb', { + + 'before all': function(){ + myColor = new Color('rgb(162, 194, 64)'); + }, + + 'should have the correct rgb': function(){ + value_of(myColor).should_be([162, 194, 64]); + }, + + 'should have the correct hsb': function(){ + value_of(myColor.hsb).should_be([75, 67, 76]); + }, + + 'should have the correct hex': function(){ + value_of(myColor.hex).should_be('#a2c240'); + } + +}); \ No newline at end of file diff --git a/assets/mootools-core/Specs/Utilities/Selectors.js b/assets/mootools-core/Specs/Utilities/Selectors.js new file mode 100644 index 00000000..30dca7fb --- /dev/null +++ b/assets/mootools-core/Specs/Utilities/Selectors.js @@ -0,0 +1,8 @@ +/* +Script: Selectors.js + Specs for Selectors.js + +License: + MIT-style license. +*/ + diff --git a/assets/mootools-core/Specs/Utilities/index.html b/assets/mootools-core/Specs/Utilities/index.html new file mode 100644 index 00000000..bfb493aa --- /dev/null +++ b/assets/mootools-core/Specs/Utilities/index.html @@ -0,0 +1,17 @@ + + + + Selectors Sample Document + + + + + + diff --git a/assets/mootools-core/Specs/application.xml b/assets/mootools-core/Specs/application.xml new file mode 100644 index 00000000..94e21e3f --- /dev/null +++ b/assets/mootools-core/Specs/application.xml @@ -0,0 +1,16 @@ + + + + net.mootools.specs + Specs + v1 + + Specs/index.html + true + 900 + 500 + 50 + 50 + 200 100 + + diff --git a/assets/mootools-core/Specs/demo.html b/assets/mootools-core/Specs/demo.html new file mode 100644 index 00000000..769a774c --- /dev/null +++ b/assets/mootools-core/Specs/demo.html @@ -0,0 +1,14 @@ + + + + JSSpec Sample Specs + + + + + + + + + + \ No newline at end of file diff --git a/assets/mootools-core/Specs/index.html b/assets/mootools-core/Specs/index.html new file mode 100644 index 00000000..fa66c99a --- /dev/null +++ b/assets/mootools-core/Specs/index.html @@ -0,0 +1,26 @@ + + + + + + + MooTools Specs + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/mootools-core/Tests/DemoScripts/Source/Methods/StringMethods.js b/assets/mootools-core/Tests/DemoScripts/Source/Methods/StringMethods.js new file mode 100644 index 00000000..c646a70a --- /dev/null +++ b/assets/mootools-core/Tests/DemoScripts/Source/Methods/StringMethods.js @@ -0,0 +1,9 @@ +var trim = function(str){ + return str.replace(/^\s+|\s+$/g, ''); +}; + +var capitalize = function(str){ + return str.replace(/\b[a-z]/g, function(match){ + return match.toUpperCase(); + }); +}; diff --git a/assets/mootools-core/Tests/DemoScripts/Source/Methods/getElement.js b/assets/mootools-core/Tests/DemoScripts/Source/Methods/getElement.js new file mode 100644 index 00000000..7d769b63 --- /dev/null +++ b/assets/mootools-core/Tests/DemoScripts/Source/Methods/getElement.js @@ -0,0 +1,3 @@ +var get = function(id){ + return document.getElementById(trim(id)); //using trim here just so there's a dependency on StringMethods.js +}; diff --git a/assets/mootools-core/Tests/DemoScripts/Source/Methods/setHTML.js b/assets/mootools-core/Tests/DemoScripts/Source/Methods/setHTML.js new file mode 100644 index 00000000..6d782b98 --- /dev/null +++ b/assets/mootools-core/Tests/DemoScripts/Source/Methods/setHTML.js @@ -0,0 +1,4 @@ +var setHTML = function(el, html){ + //yeah, yeah, this will cause memory leaks - it's just a demo! + return el.innerHTML = trim(html); //using trim here just so there's a dependency on StringMethods.js +}; \ No newline at end of file diff --git a/assets/mootools-core/Tests/DemoScripts/Source/PromptUser/SimplePrompt.js b/assets/mootools-core/Tests/DemoScripts/Source/PromptUser/SimplePrompt.js new file mode 100644 index 00000000..02834255 --- /dev/null +++ b/assets/mootools-core/Tests/DemoScripts/Source/PromptUser/SimplePrompt.js @@ -0,0 +1,5 @@ +var simplePrompt = function(el, promptQuestion, autoFill, cap){ + var userInput = trim(prompt(promptQuestion, autoFill||'')); + if (cap){ userInput = capitalize(userInput); } + setHTML(el, userInput); +}; \ No newline at end of file diff --git a/assets/mootools-core/Tests/DemoScripts/Source/scripts.json b/assets/mootools-core/Tests/DemoScripts/Source/scripts.json new file mode 100644 index 00000000..463c4fe3 --- /dev/null +++ b/assets/mootools-core/Tests/DemoScripts/Source/scripts.json @@ -0,0 +1,21 @@ +{ + "Methods":{ + "StringMethods":{ + "deps":[], + "desc":"Helper methods for String manipulation." + }, + "getElement": { + "deps":["StringMethods"], + "desc":"Retrieves a DOM element by its ID." + }, + "setHTML":{ + "deps":["StringMethods"], + "desc":"Sets the inner HTML of a DOM element." + } + }, + "PromptUser": { + "SimplePrompt":{ + "deps":["setHTML"] //this will include both DOM and String methods because of the dependency chain + } + } +} diff --git a/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.capitalization.html b/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.capitalization.html new file mode 100644 index 00000000..908ac83b --- /dev/null +++ b/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.capitalization.html @@ -0,0 +1,3 @@ +
+ My name is . +
diff --git a/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.capitalization.js b/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.capitalization.js new file mode 100644 index 00000000..ff8edba1 --- /dev/null +++ b/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.capitalization.js @@ -0,0 +1,14 @@ +{ + tests: [ + { + title: "Simple Prompt :: capitalization enabled", //the title of the test + description: "Prompts the user to enter their name and then capitalizes it for them.", //a one liner description of the test + verify: "Was your name added to the test frame capitalized?", //the question the user should answer + //"yes" to that signifies success + before: function(){ + simplePrompt(get("usersName"), "Enter your name (lower case):", "fred flintstone", true); + } + } + ], + otherScripts: ["getElement"] //getElement isn't in our dependency chain, but I use it in the test itself +} diff --git a/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.nocaps.html b/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.nocaps.html new file mode 100644 index 00000000..908ac83b --- /dev/null +++ b/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.nocaps.html @@ -0,0 +1,3 @@ +
+ My name is . +
diff --git a/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.nocaps.js b/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.nocaps.js new file mode 100644 index 00000000..39d9ff96 --- /dev/null +++ b/assets/mootools-core/Tests/DemoTests/PromptUser/SimplePrompt.nocaps.js @@ -0,0 +1,14 @@ +{ + tests: [ + { + title: "Simple Prompt :: capitalization disabled", //the title of the test + description: "Prompts the user to enter their name; does NOT capitalize it for them.", //a one liner description of the test + verify: "Was your name added to the test frame (not capitalized)?", //the question the user should answer + //"yes" to that signifies success + before: function(){ + simplePrompt(get("usersName"), "Enter your name (lower case):", "fred flintstone", false); + } + } + ], + otherScripts: ["getElement"] //getElement isn't in our dependency chain, but I use it in the test itself +} diff --git a/assets/mootools-core/Tests/DemoTests/tests.json b/assets/mootools-core/Tests/DemoTests/tests.json new file mode 100644 index 00000000..a7ee0ae1 --- /dev/null +++ b/assets/mootools-core/Tests/DemoTests/tests.json @@ -0,0 +1,5 @@ +{ + "PromptUser":{ + "SimplePrompt":['capitalization', 'nocaps'] + } +} \ No newline at end of file diff --git a/assets/mootools-core/Tests/UserTests/Element/Element.Dimensions.offsets.html b/assets/mootools-core/Tests/UserTests/Element/Element.Dimensions.offsets.html new file mode 100644 index 00000000..0c3e1c9d --- /dev/null +++ b/assets/mootools-core/Tests/UserTests/Element/Element.Dimensions.offsets.html @@ -0,0 +1,77 @@ + + + + +
+
FIXED
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+ SCROLL
+
diff --git a/assets/mootools-core/Tests/UserTests/Element/Element.Dimensions.offsets.js b/assets/mootools-core/Tests/UserTests/Element/Element.Dimensions.offsets.js new file mode 100644 index 00000000..5cd875ba --- /dev/null +++ b/assets/mootools-core/Tests/UserTests/Element/Element.Dimensions.offsets.js @@ -0,0 +1,10 @@ +{ + tests: [ + { + title: "Element.offsets", + description: "Tests the offset logic for elements.", + verify: "When you scroll does offset value remain fixed in place?" + } + ], + otherScripts: ['DomReady'] +} \ No newline at end of file diff --git a/assets/mootools-core/Tests/UserTests/Request/Request.all.html b/assets/mootools-core/Tests/UserTests/Request/Request.all.html new file mode 100644 index 00000000..42489094 --- /dev/null +++ b/assets/mootools-core/Tests/UserTests/Request/Request.all.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/assets/mootools-core/Tests/UserTests/Request/Request.all.js b/assets/mootools-core/Tests/UserTests/Request/Request.all.js new file mode 100644 index 00000000..508aed02 --- /dev/null +++ b/assets/mootools-core/Tests/UserTests/Request/Request.all.js @@ -0,0 +1,26 @@ +{ + tests: [ + { + title: "Request", + description: "Sends an AJAX request to the server.", + verify: "Did the ajax log to the screen a success?", + before: function(){ + new Request({ + url: 'UserTests/Request/simple.php', + method: 'get', + onRequest: function(){ + $('log').adopt(new Element('li', { + html: 'attempting request...' + })) + }, + onSuccess: function(r){ + $('log').adopt(new Element('li', { + html: 'success: ' + r + })) + } + }).send(); + } + } + ], + otherScripts: ['Element'] +} \ No newline at end of file diff --git a/assets/mootools-core/Tests/UserTests/Request/simple.php b/assets/mootools-core/Tests/UserTests/Request/simple.php new file mode 100644 index 00000000..90a00351 --- /dev/null +++ b/assets/mootools-core/Tests/UserTests/Request/simple.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/assets/mootools-core/Tests/UserTests/tests.json b/assets/mootools-core/Tests/UserTests/tests.json new file mode 100644 index 00000000..1c17de77 --- /dev/null +++ b/assets/mootools-core/Tests/UserTests/tests.json @@ -0,0 +1,8 @@ +{ + "Element": { + "Element.Dimensions":['offsets'] + }, + "Request": { + "Request":['all'] + } +} \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/Debugger.cnet.js b/assets/mootools-core/Tests/assets/Debugger.cnet.js new file mode 100644 index 00000000..15ba2931 --- /dev/null +++ b/assets/mootools-core/Tests/assets/Debugger.cnet.js @@ -0,0 +1,23 @@ +//adds the debugger for non FF browsers (or FF w/o firebug) +//sets up the dbug alias; see dbug.js in Clientside lib +window.addEvent('domready', function(){ + try { + if (!window.debug || !window.debug.path){ + var debug = { + path: 'assets/moobugger/' + }; + var script = document.createElement('script'); + script.id = 'debug-bookmarklet'; + script.src = debug.path + 'debugger.js'; + script.onload = function(){ + if (typeof dbug == "undefined") return; + (function(){ + dbug.firebug = true; + dbug.enable(); + }).delay(400); + }; + document.getElementsByTagName('head')[0].appendChild(script); + } + } catch(e){ + } +}); diff --git a/assets/mootools-core/Tests/assets/UnitTester.js b/assets/mootools-core/Tests/assets/UnitTester.js new file mode 100644 index 00000000..d5ef0f21 --- /dev/null +++ b/assets/mootools-core/Tests/assets/UnitTester.js @@ -0,0 +1,581 @@ +setCNETAssetBaseHref('assets/'); +/* +Script: UnitTester.js + +License: + MIT-style license. +*/ + +$E = document.getElement.bind(document); + +/* redefine Request so it always execs scripts and uses method: get */ + +var Request = new Class({ + + Extends: Request, + + options: { + method: 'get', + includeScripts: true + }, + +/* redefine processScripts so that it doesn't attempt to read headers; this enables the tester to + run locally w/o a web server for browsers that allow it */ + + processScripts: function(text){ + return text; + if (this.options.evalResponse) return $exec(text); + return text.stripScripts(this.options.evalScripts); + } + +}); + + +/* +Script: UnitTester.js + Automatically builds unit tests based on an external js script, loading the html, js, and any depedencies. + +License: + MIT-style license. +*/ + + +var UnitTester = new Class({ + Implements: [Events, Options], + options: { + autoplay: true + }, + testScripts: { + //include as many sources as you like + //provide the directory that contians tests.json + demos: 'DemoTests/' + }, + tests: {}, + sources: { + //list any locations that contain a MooTools organized + //code repository (eg: Source/scripts.json) + DemoScripts: 'DemoScripts/' + }, + data: {}, + initialize: function(sources, testScripts, options){ + this.setOptions(options); + this.sources = sources || this.sources; + this.testScripts = testScripts || this.testScripts; + this.waiter = new Waiter($('script'), { + msg: 'Loading dependencies' + }); + //when sources are loaded, inject the tree of tests into the nav + this.addEvent('onReady', function(target, sources){ + if (sources == this.sources) this.mapTree(); + else this.setupLoaderSelection(); + }.bind(this)); + //load each test and source + $each(this.sources, function(v, k){ + this.loadSource(k, '/Source/scripts.json', this.data, this.sources); + }, this); + $each(this.testScripts, function(v, k){ + this.loadSource(k, '/tests.json', this.tests, this.testScripts); + }, this); + //set up the textarea that lets you run your own code + this.setupManual(); + }, + //fetch the test iframe + getFrame: function(){ + if (Browser.Engine.webkit) return frames["testFrame"]; + return $('testFrame').contentWindow; + }, + //load a scripts.json set + loadSource: function(source, suffix, target, sources){ + this.request(sources[source]+suffix, function(result){ + this.loadJson(source, result, target, sources); + }.bind(this)); + }, + //handle scripts.json decoding + loadJson: function(source, result, target, sources){ + if (result){ + target[source] = JSON.decode(result); + this.dataLoaded(target, sources); + } + }, + //manage loaded data; fire onReady when all sources are loaded + dataLoaded: function(target, sources){ + var loaded = true; + $each(sources, function(v, k){ + if (!target[k]) loaded = false; + }, this); + if (loaded) this.fireEvent('onReady', [target, sources]); + }, + //map dependencies + deps: {}, + pathMap: {}, + //create a map of source to paths + mapTree: function(){ + $each(this.data, function(data, source){ + $each(data, function(scripts, folder){ + $each(scripts, function(details, script){ + this.deps[source+':'+folder+':'+script] = details.deps; + this.pathMap[script] = source+':'+folder+':'+script; + }, this); + }, this); + }, this); + }, + //get the dependencies for a given script + getDepsForScript: function(script){ + return this.deps[this.pathMap[script]]; + }, + //calculate the dependencies for a given script + calculateDependencies: function(script){ + var reqs = []; + if (script == "None") return reqs; + var deps = this.getDepsForScript(script); + if (!deps){ + dbug.log('dependencies not mapped: script: %o, map: %o, :deps: %o', script, this.pathMap, this.deps); + } else { + deps.each(function(scr){ + if (scr == script || scr == "None") return; + if (!reqs.contains(scr)) reqs.combine(this.calculateDependencies(scr)); + reqs.include(scr); + }, this); + return reqs; + } + }, + //get the path for a script + getPath: function(script){ + try { + var chunks = this.pathMap[script].split(':'); + var dir = this.sources[chunks[0]] + '/Source/'; + chunks.erase(chunks[0]); + return dir + chunks.join('/') + '.js'; + } catch(e){ + return script; + } + }, + //dbug is loaded already by default - technically, it maps to the dbug in the parent window + loadedScripts: ['dbug'], + //load the missing dependencies for a given script + loadDependencies: function(script, target, win){ + var scripts = this.calculateDependencies(script).include(script); + scripts = scripts.filter(function(s){return !this.loadedScripts.contains(s)}, this); + this.loadedScripts.combine(scripts); + if (scripts.length){ + scripts.filter(function(scr){ + return scr != "None" + }).each(function(scr){ + this.loadScr(scr, target, win); + }.bind(this)); + } else { + this.fireEvent('scriptsLoaded'); + } + }, + //keep track of how many scripts we're loading at a given time so the user + //this just stacks up scripts so that they have a buffer of 100ms between loading + //I found that injecting them into the iframe without it caused issues in + //some browsers + loaders: [], + clearLoaders: function(){ + this.loaders.empty(); + }, + //loads a script; if there is a script loading, pushes it onto the stack + loadScr: function(scr, target, win){ + var run = this.loaders.length == 0; + this.waiter.start(); + win = win||this.getFrame(); + target = target||win.document.getElementsByTagName('head')[0]; + var finish = function(){ + if (this.loaders[0]){ + try { + this.loaders[0].apply(this); + } catch(e){} + } else { + this.waiter.stop(); + this.fireEvent('scriptsLoaded'); + } + }; + this.loaders.push(function(){ + if (scr.contains('dbug.js')){ + finish.delay(100, this); + } else if (Browser.Engine.trident){ + win.$LoadScript(this.getPath(scr)); + finish.delay(100, this); + } else { + try { + var s = new Element('script', { + src: this.getPath(scr)+"?noCache="+new Date().getTime(), + 'type': 'text/javascript', + events: { + load: finish.bind(this) + } + }).inject(target); + } catch(e){ + } + } + this.loaders.erase(this.loaders[0]); + }); + if (run) this.loaders[0].delay(100, this); + }, + //creates the left nav of all the tests + setupLoaderSelection: function(){ + var sel = $('testLoaderSel').empty(); + $('testLoaderSel').setStyle('opacity', 0); + var dts = []; + var dds = []; + $each(this.tests, function(tests, section){ + new Element('h3', {html: section}).inject(sel); + $each(tests, function(dir, dirName){ + new Element('h4', {html: dirName}).inject(sel); + $each(dir, function(tests, script){ + var dt = new Element('dt', {html: script}).inject(sel); + dts.push(dt); + var container = new Element('div', {'class':'testList'}).inject(dt, 'after'); + dds.push(container); + if (tests.length == 1){ + var dd = new Element('dd').inject(container).hide(); + dd.store('testindex', 0); + dd.store('testPath', section+'/'+dirName+'/'+script+'/'+tests[0]); + dt.addEvent('click', function(){ + this.loadTest(section+'/'+dirName+'/'+script+'/'+tests[0]); + selectTest(dd); + }.bind(this)); + dt.store('testPath', section+'/'+dirName+'/'+script+'/'+tests[0]); + } else { + tests.each(function(test, i){ + var dd = new Element('dd', { + html: '» '+test + }).inject(container); + dd.store('testindex', i); + dd.store('testPath', section+'/'+dirName+'/'+script+'/'+tests); + dd.addEvent('click', function(){ + this.loadTest(section+'/'+dirName+'/'+script+'/'+test); + selectTest(dd); + }.bind(this)); + }, this); + } + }, this); + }, this); + }, this); + var selectTest = function(container){ + dds.each(function(div){ + div.getElements('dd').each(function(dd){ + if (container != dd) dd.removeClass('selected'); + else dd.addClass('selected'); + }); + div.getElements('dt').removeClass('selected'); + }); + var dt = $E('dd.selected').getParent().getPrevious('dt'); + if (dt) dt.addClass('selected'); + }; + new Accordion(dts, dds, { + duration: 250 + }); + $('testLoaderSel').tween('opacity', 1); + }, + //gets the test json for a given path + getTestFilePath: function(testPath){ + var chunks = testPath.split('/'); + var base = chunks[0]; + var dir = chunks[1]; + chunks.splice(chunks.indexOf(base), 1); + if (chunks.contains(dir) >= 0) chunks.splice(chunks.indexOf(dir), 1); + var script = chunks[0]; + var file = chunks.join('.'); + var name = base+': '+dir+' » '+file; + var filePath = this.testScripts[base]+dir+'/'+file; + return { + filePath: filePath, + script: script, + name: name, + dir: dir, + file: file, + base: base + }; + }, + //loads a test given a path + loadTest: function(testPath){ + console.log('load: ', testPath); + this.clearLoaders(); + this.getFrame().location.href = this.getFrame().location.href.split("#")[0]; + $('testFrame').removeEvents('load'); + $('testFrame').addEvent('load', function(){ + testPath = testPath || $('testLoaderSel').get('value'); + if (!testPath) return; + var test = this.getTestFilePath(testPath); + this.removeEvents('scriptsLoaded').addEvent('scriptsLoaded', function(){ + var dr = function(){ + this.removeEvents('scriptsLoaded'); + this.exec(this.currentTest['scripts']); + dbug.log('test scripts loaded'); + this.loadScr('assets/fireDomReady.js'); + if (this.options.autoplay) this.runTest.delay(100, this, 0); + }.bind(this); + this.removeEvents('scriptsLoaded').addEvent('scriptsLoaded', dr); + if (this.testObjs.otherScripts){ + var head = this.getFrame().document.getElementsByTagName('head')[0]; + this.testObjs.otherScripts.each(function(s){ + this.loadDependencies(s, head, this.getFrame()) + }, this); + } else { + dr(); + } + }); + this.request(test.filePath+'.html', function(result){ + this.loadTestHtml(test.name, result, test.script); + this.request(test.filePath+'.js', function(result){ + this.loadTestJs(result); + }.bind(this)); + }.bind(this)); + }.bind(this)); + }, + //the current test + currentTest: {}, + //load the html into the iframe + loadTestHtml: function(name, html, script){ + if ($defined(name)){ + this.currentTest['name'] = name; + this.currentTest['html'] = html; + } + var head = this.getFrame().document.getElementsByTagName('head')[0]; + this.loadedScripts.empty(); + this.loadDependencies(script, head, this.getFrame()) + + var body = this.getFrame().document.body; + body.innerHTML = '

'+this.currentTest['name']+'

'; + var scripts = ''; + var styles = ''; + var links = ''; + var text = this.currentTest['html'].replace(/]*>([\s\S]*?)<\/script>/gi, function(){ + scripts += arguments[1] + '\n'; + return ''; + }); + if (!Browser.Engine.trident){ + text = this.currentTest['html'].replace(/]*>([\s\S]*?)<\/style>/gi, function(){ + styles += arguments[1] + '\n'; + return ''; + }); + } + this.currentTest['scripts'] = scripts; + this.currentTest['html'] = text; + if (!this.currentTest['html']) { + body.innerHTML += "No HTML for this test."; + } else { + body.innerHTML += this.currentTest['html']; + } + if (styles){ + var style = new Element('style'); + style.inject(head); + $(style).set('text', styles); + } + }, + //sets up the manual code entry textarea + setupManual: function(){ + var code = $E('#testFrameContainer textarea'); + code.makeResizable({ + handle: $E('#testFrameContainer div.handle'), + modifiers: {x: null} + }); + code.addEvent('keydown', function(e){ + if ((e.control||e.meta) && e.key == "enter"){ + e.stop(); + this.exec(code.get('value')); + } + }.bind(this)); + $E('#testFrameContainer button').addEvent('click', function(){ + this.exec(code.get('value')); + }.bind(this)); + }, + //loads the json for a given test into the test menu + //js = the test.js contents + loadTestJs: function(js){ + this.currentTest['js'] = js; + if (this.currentTest['js']){ + $('tests').empty(); + this.waiter.start(); + this.testObjs = JSON.decode(this.currentTest['js']); + this.testElements = []; + this.testResults = []; + var tmpl = $('testTemplate').get('html'); + this.testObjs.tests.each(function(test, i){ + var html = tmpl.substitute(test); + var testEl = new Element('div').addClass('testBlock').set('html', html).inject($('tests')); + this.testElements[i] = testEl; + var btn = testEl.getElement('button'); + var code = testEl.getElement('textarea'); + var ver = testEl.getElement('div.verify'); + var handle = testEl.getElement('div.handle'); + var header = testEl.getElement('dt b'); + header.addEvent('click', function(){ + testEl.getElement('dd').get('reveal').toggle(); + }); + var interactive = code.get('value') != ""; + if (!interactive){ + code.dispose(); + handle.dispose(); + } else { + code.makeResizable({ + handle: handle, + modifiers: {x: null} + }); + } + if (!test.verify){ + ver.dispose(); + } else { + ver.getElement('a.pass').addEvent('click', this.pass.bind(this, i)) + ver.getElement('a.fail').addEvent('click', this.fail.bind(this, i)) + } + btn.addEvent('click', function(){ + this.runTest(i); + }.bind(this)); + }, this); + } + }, + //execs a chunk of code in the frame; + //if wrapFunc is true, it'll wrap the string like (val)() + exec: function(val, wrapFunc){ + if (!val) return; + this.getFrame().dbug = dbug; + if (val){ + if (wrapFunc) val = '('+val+')()'; + return this.getFrame().$exec(val); + } + }, + //starts a test + runTest: function(testIndex){ + $E('iframe').contentWindow.dbug = dbug; + $E('iframe').contentWindow.dbug.enable(true) + var container = this.testElements[testIndex]; + var code = container.getElement('textarea'); + var ver = container.getElement('div.verify'); + var test = this.testObjs.tests[testIndex]; + dbug.log('---- %s :: %s ----', this.currentTest.name.replace('»', '::'), test.title); + try { + if (test.before) this.exec(test.before.toString(), true); + if (code) this.exec(code.get('value')); + if (test.post){ + if (!this.exec(test.post.toString(), true)){ + alert('The conditions for this test have failed.'); + this.fail(testIndex); + } + } + } catch (e){ + dbug.log('test failed: ', e); + this.fail(testIndex); + return; + } + container.addClass('selected'); + if (ver){ + ver.reveal(); + } else { + this.pass(testIndex); + } + }, + //executed when a test passes + //i = index of the successful test + pass: function(i){ + this.testElements[i].addClass('passed').removeClass('failed').removeClass('selected'); + this.testResults[i] = true; + this.testElements[i].getElement('dd').dissolve(); + this.evaluateAll(); + if (this.options.autoplay) this.loadNextTest(i); + }, + //executed when a test failes + //i = index of the failed test + fail: function(i){ + this.testElements[i].removeClass('passed').addClass('failed').removeClass('selected'); + this.testResults[i] = false; + this.evaluateAll(); + if (this.options.autoplay) this.loadNextTest(i); + }, + loadNextTest: function(current){ + var div, dt; + if (this.testElements[current+1]){ + //load the next test in the currently loaded set + this.runTest(current+1); + } else { + + var dd = $E('dd.selected'); + var next = dd.getNext('dd'); + if (!next){ + dt = dd.getParent().getNext('dt'); + if (dt && dt.retrieve('testPath')){ + next = dt; + } else if (dt){ + div = dt.getNext(); + if (div && div.get('tag') == 'div'){ + next = div.getElement('dd'); + } + } + } + if (next){ + new StickyWin({ + content: StickyWin.ui("Move to next test?", "Would you like to move to the next set of tests?", { + buttons: [ + {text: 'Cancel'}, + { + text: 'Next Tests >>', + onClick: function(){ + if (div) dt.fireEvent('click'); + next.fireEvent('click'); + } + } + ] + }) + }); + } + + } + }, + //evaluates if all the tests have passed (used to highlight that section in the left nav) + evaluateAll: function(){ + var passed = true; + this.testElements.each(function(el, i){ + if (passed === false) return; + if (passed != null && $defined(this.testResults[i]) && !this.testResults[i]) passed = false; + else if (!$defined(this.testResults[i])) passed = null; + }, this); + if (passed === true){ + $E('dd.selected').addClass('success'); + } else if (passed === false){ + $E('dd.selected').addClass('exception'); + } else if (passed === null){ + $E('dd.selected').removeClass('exception').removeClass('success'); + } + if (passed === true){ + var dt = $E('dd.selected').getParent().getPrevious(); + if (dt.get('tag') != 'dt') return; + $E('dd.selected').getParent().getElements('dd').each(function(dd){ + if (!dd.hasClass('success') && !dd.hasClass('exception')){ + passed = null; + } else if (dd.hasClass('exception')){ + passed = false; + } + }); + if (passed === false){ + dt.addClass('exception'); + } else if (passed === true){ + dt.addClass('success'); + } + } + }, + //runs a test + //adds no-cache values to prevent caching + //also tests for whether or not the page is served from a webserver + //url - the url to get + //callback - executed on success/complete, passed the reponse text + request: function(url, callback){ + url = url+(url.test(/\?/)?"&":"?")+"nocache="+new Date().getTime() + var req = new Request({ + url: url, + onComplete: function(result){ + if (result){ + callback(result); + } + }.bind(this) + }).send(); + if (!window.location.href.test('http')){ + (function(){ + callback(req.xhr.responseText); + }).delay(100); + } + } +}); +UnitTester.site = 'Clientside'; +UnitTester.title = 'Unit Test Framework'; diff --git a/assets/mootools-core/Tests/assets/clientside.js b/assets/mootools-core/Tests/assets/clientside.js new file mode 100644 index 00000000..af7a495f --- /dev/null +++ b/assets/mootools-core/Tests/assets/clientside.js @@ -0,0 +1,1413 @@ +/* +Script: dbug.js + A wrapper for Firebug console.* statements. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ +var dbug = { + logged: [], + timers: {}, + firebug: false, + enabled: false, + log: function(){ + dbug.logged.push(arguments); + }, + nolog: function(msg){ + dbug.logged.push(arguments); + }, + time: function(name){ + dbug.timers[name] = new Date().getTime(); + }, + timeEnd: function(name){ + if (dbug.timers[name]){ + var end = new Date().getTime() - dbug.timers[name]; + dbug.timers[name] = false; + dbug.log('%s: %s', name, end); + } else dbug.log('no such timer: %s', name); + }, + enable: function(silent){ + if (dbug.firebug){ + try { + dbug.enabled = true; + dbug.log = function(){ + (console.debug || console.log).apply(console, arguments); + }; + dbug.time = function(){ + console.time.apply(console, arguments); + }; + dbug.timeEnd = function(){ + console.timeEnd.apply(console, arguments); + }; + if (!silent) dbug.log('enabling dbug'); + for(var i=0;i0 || debugCookie=='true') dbug.enable(); + if (debugCookie=='true')dbug.log('debugging cookie enabled'); + if (window.location.href.indexOf("jsdebugCookie=true")>0){ + dbug.cookie(); + if (!dbug.enabled)dbug.enable(); + } + if (window.location.href.indexOf("jsdebugCookie=false")>0)dbug.disableCookie(); +} + + +/* +Script: IframeShim.js + Defines IframeShim, a class for obscuring select lists and flash objects in IE. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ +var IframeShim = new Class({ + Implements: [Options, Events], + options: { + name: '', + className:'iframeShim', + display:false, + zindex: null, + margin: 0, + offset: { + x: 0, + y: 0 + }, + browsers: (Browser.Engine.trident4 || (Browser.Engine.gecko && !Browser.Engine.gecko19 && Browser.Platform.mac)) + }, + initialize: function (element, options){ + this.setOptions(options); + //legacy + if (this.options.offset && this.options.offset.top) this.options.offset.y = this.options.offset.top; + if (this.options.offset && this.options.offset.left) this.options.offset.x = this.options.offset.left; + this.element = $(element); + this.makeShim(); + return; + }, + makeShim: function(){ + this.shim = new Element('iframe'); + this.id = this.options.name || new Date().getTime() + "_shim"; + if (this.element.getStyle('z-Index').toInt()<1 || isNaN(this.element.getStyle('z-Index').toInt())) + this.element.setStyle('z-Index',5); + var z = this.element.getStyle('z-Index')-1; + + if ($chk(this.options.zindex) && + this.element.getStyle('z-Index').toInt() > this.options.zindex) + z = this.options.zindex; + + this.shim.setStyles({ + 'position': 'absolute', + 'zIndex': z, + 'border': 'none', + 'filter': 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)' + }).setProperties({ + 'src':'javascript:void(0);', + 'frameborder':'0', + 'scrolling':'no', + 'id':this.id + }).addClass(this.options.className); + + this.element.store('shim', this); + + var inject = function(){ + this.shim.inject(this.element, 'after'); + if (this.options.display) this.show(); + else this.hide(); + this.fireEvent('onInject'); + }; + if (this.options.browsers){ + if (Browser.Engine.trident && !IframeShim.ready){ + window.addEvent('load', inject.bind(this)); + } else { + inject.run(null, this); + } + } + }, + position: function(shim){ + if (!this.options.browsers || !IframeShim.ready) return this; + var before = this.element.getStyles('display', 'visibility', 'position'); + this.element.setStyles({ + display: 'block', + position: 'absolute', + visibility: 'hidden' + }); + var size = this.element.getSize(); + this.element.setStyles(before); + if ($type(this.options.margin)){ + 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.setStyles({ + 'width': size.x, + 'height': size.y + }).setPosition({ + relativeTo: this.element, + offset: this.options.offset + }); + return this; + }, + hide: function(){ + if (this.options.browsers) this.shim.setStyle('display','none'); + return this; + }, + show: function(){ + if (!this.options.browsers) return this; + this.shim.setStyle('display','block'); + return this.position(); + }, + dispose: function(){ + if (this.options.browsers) this.shim.dispose(); + return this; + } +}); +window.addEvent('load', function(){ + IframeShim.ready = true; +}); + + +/* +Script: Hash.Extras.js + Extends the Hash native object to include getFromPath which allows a path notation to child elements. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ + +Hash.implement({ + getFromPath: function(notation){ + var source = this.getClean(); + notation.replace(/\[([^\]]+)\]|\.([^.[]+)|[^[.]+/g, function(match){ + if (!source) return; + 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; + } +}); + +/* +Script: String.Extras.js + Extends the String native object to include methods useful in managing various kinds of strings (query strings, urls, html, etc). + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ +String.implement({ + stripTags: function(){ + return this.replace(/<\/?[^>]+>/gi, ''); + }, + parseQuery: function(encodeKeys, encodeValues){ + encodeKeys = $pick(encodeKeys, true); + encodeValues = $pick(encodeValues, true); + var vars = this.split(/[&;]/); + var rs = {}; + if (vars.length) vars.each(function(val){ + var keys = val.split('='); + if (keys.length && keys.length == 2){ + rs[(encodeKeys)?encodeURIComponent(keys[0]):keys[0]] = (encodeValues)?encodeURIComponent(keys[1]):keys[1]; + } + }); + return rs; + }, + tidy: function(){ + var txt = this.toString(); + $each({ + "[\xa0\u2002\u2003\u2009]": " ", + "\xb7": "*", + "[\u2018\u2019]": "'", + "[\u201c\u201d]": '"', + "\u2026": "...", + "\u2013": "-", + "\u2014": "--", + "\uFFFD": "»" + }, function(value, key){ + txt = txt.replace(new RegExp(key, 'g'), value); + }); + return txt; + }, + cleanQueryString: function(method){ + return this.split("&").filter(method||function(set){ + return $chk(set.split("=")[1]); + }).join("&"); + } +}); + + +/* +Script: Element.Measure.js + Extends the Element native object to include methods useful in measuring dimensions. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ + +Element.implement({ + + expose: function(){ + if (this.getStyle('display') != 'none') return $empty; + var before = {}; + var styles = { visibility: 'hidden', display: 'block', position:'absolute' }; + //use this method instead of getStyles + $each(styles, function(value, style){ + before[style] = this.style[style]||''; + }, this); + //this.getStyles('visibility', 'display', 'position'); + this.setStyles(styles); + return (function(){ this.setStyles(before); }).bind(this); + }, + + getDimensions: function(options){ + options = $merge({computeSize: false},options); + var dim = {}; + function getSize(el, options){ + return (options.computeSize)?el.getComputedSize(options):el.getSize(); + }; + if (this.getStyle('display') == 'none'){ + var restore = this.expose(); + dim = getSize(this, options); //works now, because the display isn't none + restore(); //put it back where it was + } else { + try { //safari sometimes crashes here, so catch it + dim = getSize(this, options); + }catch(e){} + } + 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 = this.getStyles.apply(this, getStyles); + var subtracted = []; + $each(options.plains, function(plain, key){ //keys: width, height, plains: ['left','right'], ['top','bottom'] + size['total'+key.capitalize()] = 0; + size['computed'+key.capitalize()] = 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(); //styles['padding-left'] = 5; + if (isNaN(styles[style]))styles[style]=0; + size['total'+key.capitalize()] = size['total'+key.capitalize()]+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'+key.capitalize()] = size['computed'+key.capitalize()]-styles[style]; + } + }); + }); + }); + if ($chk(size.width)){ + size.width = size.width+this.offsetWidth+size.computedWidth; + size.totalWidth = size.width + size.totalWidth; + delete size.computedWidth; + } + if ($chk(size.height)){ + size.height = size.height+this.offsetHeight+size.computedHeight; + size.totalHeight = size.height + size.totalHeight; + delete size.computedHeight; + } + return $extend(styles, size); + } +}); + + +/* +Script: Element.Pin.js + Extends the Element native object to include the pin method useful for fixed positioning for elements. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ + +window.addEvent('domready', function(){ + var test = new Element('div').setStyles({ + position: 'fixed', + top: 0, + right: 0 + }).inject(document.body); + var supported = (test.offsetTop === 0); + test.dispose(); + Browser.supportsPositionFixed = supported; +}); + +Element.implement({ + pin: function(enable){ + if (this.getStyle('display') == 'none'){ + dbug.log('cannot pin ' + this + ' because it is hidden'); + return; + } + if (enable!==false){ + var p = this.getPosition(); + if (!this.get('pinned')){ + var pos = { + top: (p.y - window.getScroll().y), + left: (p.x - window.getScroll().x) + }; + if (Browser.supportsPositionFixed){ + this.setStyle('position','fixed').setStyles(pos); + } else { + this.setStyles({ + position: 'absolute', + top: p.y, + left: p.x + }); + window.addEvent('scroll', function(){ + if (this.get('pinned')){ + var to = { + top: (pos.top.toInt() + window.getScroll().y), + left: (pos.left.toInt() + window.getScroll().x) + }; + this.setStyles(to); + } + }.bind(this)); + } + this.set('pinned', true); + } + } else { + var op; + if (!Browser.Engine.trident){ + if (this.getParent().getComputedStyle('position') != 'static') op = this.getParent(); + else op = this.getParent().getOffsetParent(); + } + var p = this.getPosition(op); + this.set('pinned', false); + var reposition = (Browser.get('supportsPositionFixed'))? + { + top: (p.y + window.getScroll().y), + left: (p.x + window.getScroll().x) + }: + { + top: (p.y), + left: (p.x) + }; + this.setStyles($merge(reposition, {position: 'absolute'})); + } + return this; + }, + unpin: function(){ + return this.pin(false); + }, + togglepin: function(){ + this.pin(!this.get('pinned')); + } +}); + + +/* +Script: Element.Position.js + Extends the Element native object to include methods useful positioning elements relative to others. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ + +Element.implement({ + + setPosition: function(options){ + $each(options||{}, function(v, k){ if (!$defined(v)) delete options[k]; }); + options = $merge({ + 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 + }, options); + //compute the offset of the parent positioned element if this element is in one + var parentOffset = {x: 0, y: 0}; + var parentPositioned = false; + var putItBack = this.expose(); + /* 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.getOffsetParent()); + putItBack(); + if (offsetParent && offsetParent != this.getDocument().body){ + var putItBack = offsetParent.expose(); + parentOffset = offsetParent.getPosition(); + putItBack(); + parentPositioned = true; + 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 + function fixValue(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 = $(options.relativeTo) || document.body; + var top = (rel == document.body)?window.getScroll().y:rel.getPosition().y; + var left = (rel == document.body)?window.getScroll().x:rel.getPosition().x; + + if (top < 0) top = 0; + if (left < 0) left = 0; + var dim = this.getDimensions({computeSize: true, styles:['padding', 'border','margin']}); + if (options.ignoreMargins){ + options.offset.x = options.offset.x - dim['margin-left']; + options.offset.y = options.offset.y - dim['margin-top']; + } + var pos = {}; + var prefY = options.offset.y.toInt(); + var prefX = options.offset.x.toInt(); + 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)?window.getSize().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)?window.getSize().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.x/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.y/2); + break; + }; + pos.x = pos.x+edgeOffset.x; + pos.y = pos.y+edgeOffset.y; + } + pos = { + left: ((pos.x >= 0 || parentPositioned)?pos.x:0).toInt(), + top: ((pos.y >= 0 || parentPositioned)?pos.y:0).toInt() + }; + if (rel.getStyle('position') == "fixed"||options.relFixedPosition){ + pos.top = pos.top.toInt() + window.getScroll().y; + pos.left = pos.left.toInt() + window.getScroll().x; + } + + if (options.returnPos) return pos; + else this.setStyles(pos); + return this; + } +}); + + +/* +Script: Element.Shortcuts.js + Extends the Element native object to include some shortcut methods. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ + +Element.implement({ + isVisible: function(){ + return this.getStyle('display') != 'none'; + }, + toggle: function(){ + return this[this.isVisible() ? 'hide' : 'show'](); + }, + hide: function(){ + var d; + try { + //IE fails here if the element is not in the dom + if ('none' != this.getStyle('display')) d = this.getStyle('display'); + } catch(e){} + this.store('originalDisplay', d||'block'); + this.setStyle('display','none'); + return this; + }, + show: function(display){ + original = this.retrieve('originalDisplay')?this.retrieve('originalDisplay'):this.get('originalDisplay'); + this.setStyle('display',(display || original || 'block')); + return this; + }, + swapClass: function(remove, add){ + return this.removeClass(remove).addClass(add); + }, + //TODO + //DO NOT USE THIS METHOD + //it is temporary, as Mootools 1.1 will negate its requirement + fxOpacityOk: function(){ + return !Browser.Engine.trident4; + } +}); + +/* +Script: Fx.Reveal.js + Defines Fx.Reveal, a class that shows and hides elements with a transition. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ +Fx.Reveal = new Class({ + Extends: Fx.Morph, + options: { + styles: ['padding','border','margin'], + transitionOpacity: true, + mode:'vertical', + heightOverride: null, + widthOverride: null +/* onShow: $empty, + onHide: $empty */ + }, + 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.element.fxOpacityOk() && 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'); + //put the final fx method at the front of the chain + if (!this.$chain) this.$chain = []; + 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) this.element.setStyle('height', 'auto'); + } + this.fireEvent('onShow', this.element); + this.callChain(); + }.bind(this)); + this.start(zero); + } else { + this.callChain.delay(10, this); + this.fireEvent('onComplete', this.element); + this.fireEvent('onHide', this.element); + } + } + } catch(e){ + this.hiding = false; + this.element.hide(); + this.callChain.delay(10, this); + this.fireEvent('onComplete', this.element); + this.fireEvent('onHide', 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 = false; + this.hidden = false; + //toggle display, but hide it + var before = this.element.getStyles('visibility', 'display', 'position'); + this.element.setStyles({ + visibility: 'hidden', + display: 'block', + position:'absolute' + }); + var setToAuto = this.element.style.height === ""||this.element.style.height=="auto"; + //enable opacity effects + if (this.element.fxOpacityOk() && this.options.transitionOpacity) this.element.setStyle('opacity',0); + //create the styles for the opened/visible state + var startStyles = this.element.getComputedSize({ + styles: this.options.styles, + mode: this.options.mode + }); + //reset the styles back to hidden now + this.element.setStyles(before); + $each(startStyles, function(style, name){ + startStyles[name] = style; + }, this); + //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.element.fxOpacityOk() && this.options.transitionOpacity) startStyles.opacity = 1; + //create the zero state for the beginning of the transition + var zero = { + height: 0, + display: 'block' + }; + $each(startStyles, function(style, name){ zero[name] = 0 }, this); + var overflowBefore = this.element.getStyle('overflow'); + //set to zero + this.element.setStyles($merge(zero, {overflow: 'hidden'})); + //start the effect + this.start(startStyles); + if (!this.$chain) this.$chain = []; + this.$chain.unshift(function(){ + if (!this.options.heightOverride && setToAuto){ + if (["vertical", "both"].contains(this.options.mode)) this.element.setStyle('height', 'auto'); + if (["width", "both"].contains(this.options.mode)) this.element.setStyle('width', 'auto'); + } + if (!this.hidden) this.showing = false; + this.element.setStyle('overflow', overflowBefore); + this.callChain(); + this.fireEvent('onShow', this.element); + }.bind(this)); + } else { + this.callChain(); + this.fireEvent('onComplete', this.element); + this.fireEvent('onShow', this.element); + } + } + } catch(e){ + this.element.setStyles({ + display: 'block', + visiblity: 'visible', + opacity: 1 + }); + this.showing = false; + this.callChain.delay(10, this); + this.fireEvent('onComplete', this.element); + this.fireEvent('onShow', this.element); + } + return this; + }, + toggle: function(){ + try { + if (this.element.getStyle('display') == "none" || + this.element.getStyle('visiblity') == "hidden" || + this.element.getStyle('opacity')==0){ + this.reveal(); + } else { + this.dissolve(); + } + } catch(e){ this.show(); } + return this; + } +}); + +Element.Properties.reveal = { + + set: function(options){ + var reveal = this.retrieve('reveal'); + if (reveal) reveal.cancel(); + return this.eliminate('reveal').store('reveal:options', $extend({link: 'cancel'}, 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; + } + +}); + +Element.implement({ + 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':'erase'](); + }.bind(this)); + return this; + } +}); + + +/* +Script: StyleWriter.js + +Provides a simple method for injecting a css style element into the DOM if it's not already present. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ + +var StyleWriter = new Class({ + createStyle: function(css, id){ + window.addEvent('domready', function(){ + try { + if ($(id) && id) return; + var style = new Element('style', {id: id||''}).inject($$('head')[0]); + if (Browser.Engine.trident) style.styleSheet.cssText = css; + else style.set('text', css); + }catch(e){dbug.log('error: %s',e);} + }.bind(this)); + } +}); + +/* +Script: StickyWin.js + +Creates a div within the page with the specified contents at the location relative to the element you specify; basically an in-page popup maker. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ + +var StickyWin = new Class({ + Implements: [Options, Events, StyleWriter], + options: { +// onDisplay: $empty, +// onClose: $empty, + closeClassName: 'closeSticky', + pinClassName: 'pinSticky', + content: '', + zIndex: 10000, + className: '', + //id: ... set above in initialize function +/* these are the defaults for setPosition anyway +/************************************************ +// edge: false, //see Element.setPosition in element.cnet.js +// position: 'center', //center, corner == upperLeft, upperRight, bottomLeft, bottomRight +// offset: {x:0,y:0}, +// relativeTo: document.body, */ + width: false, + height: false, + timeout: -1, + allowMultipleByClass: false, + allowMultiple: true, + showNow: true, + useIframeShim: true, + iframeShimSelector: '' + }, + css: '.SWclearfix:after {content: "."; display: block; height: 0; clear: both; visibility: hidden;}'+ + '.SWclearfix {display: inline-table;}'+ + '* html .SWclearfix {height: 1%;}'+ + '.SWclearfix {display: block;}', + initialize: function(options){ + this.options.inject = { + target: document.body, + where: 'bottom' + }; + this.setOptions(options); + + this.id = this.options.id || 'StickyWin_'+new Date().getTime(); + this.makeWindow(); + if (this.options.content) this.setContent(this.options.content); + if (this.options.timeout > 0){ + this.addEvent('onDisplay', function(){ + this.hide.delay(this.options.timeout, this) + }.bind(this)); + } + if (this.options.showNow) this.show(); + //add css for clearfix + this.createStyle(this.css, 'StickyWinClearFix'); + }, + toElement: function(){ + return this.win; + }, + makeWindow: function(){ + this.destroyOthers(); + if (!$(this.id)){ + this.win = new Element('div', { + id: this.id + }).addClass(this.options.className).addClass('StickyWinInstance').addClass('SWclearfix').setStyles({ + display:'none', + position:'absolute', + zIndex:this.options.zIndex + }).inject(this.options.inject.target, this.options.inject.where).store('StickyWin', this); + } else this.win = $(this.id); + if (this.options.width && $type(this.options.width.toInt())=="number") this.win.setStyle('width', this.options.width.toInt()); + if (this.options.height && $type(this.options.height.toInt())=="number") this.win.setStyle('height', this.options.height.toInt()); + return this; + }, + show: function(){ + this.fireEvent('onDisplay'); + this.showWin(); + if (this.options.useIframeShim) this.showIframeShim(); + this.visible = true; + return this; + }, + showWin: function(){ + this.win.setStyle('display','block'); + if (!this.positioned) this.position(); + }, + hide: function(suppressEvent){ + if (!suppressEvent) this.fireEvent('onClose'); + this.hideWin(); + if (this.options.useIframeShim) this.hideIframeShim(); + this.visible = false; + return this; + }, + hideWin: function(){ + this.win.setStyle('display','none'); + }, + destroyOthers: function(){ + if (!this.options.allowMultipleByClass || !this.options.allowMultiple){ + $$('div.StickyWinInstance').each(function(sw){ + if (!this.options.allowMultiple || (!this.options.allowMultipleByClass && sw.hasClass(this.options.className))) + sw.dispose(); + }, this); + } + }, + setContent: function(html){ + if (this.win.getChildren().length>0) this.win.empty(); + if ($type(html) == "string") this.win.set('html', html); + else if ($(html)) this.win.adopt(html); + this.win.getElements('.'+this.options.closeClassName).each(function(el){ + el.addEvent('click', this.hide.bind(this)); + }, this); + this.win.getElements('.'+this.options.pinClassName).each(function(el){ + el.addEvent('click', this.togglepin.bind(this)); + }, this); + return this; + }, + position: function(){ + this.positioned = true; + this.win.setPosition({ + relativeTo: this.options.relativeTo, + position: this.options.position, + offset: this.options.offset, + edge: this.options.edge + }); + if (this.shim) this.shim.position(); + return this; + }, + pin: function(pin){ + if (!this.win.pin){ + dbug.log('you must include element.pin.js!'); + return this; + } + this.pinned = $pick(pin, true); + this.win.pin(pin); + return this; + }, + unpin: function(){ + return this.pin(false); + }, + togglepin: function(){ + return this.pin(!this.pinned); + }, + makeIframeShim: function(){ + if (!this.shim){ + var el = (this.options.iframeShimSelector)?this.win.getElement(this.options.iframeShimSelector):this.win; + this.shim = new IframeShim(el, { + display: false, + name: 'StickyWinShim' + }); + } + }, + showIframeShim: function(){ + if (this.options.useIframeShim){ + this.makeIframeShim(); + this.shim.show(); + } + }, + hideIframeShim: function(){ + if (this.shim) this.shim.hide(); + }, + destroy: function(){ + if (this.win) this.win.dispose(); + if (this.options.useIframeShim) this.shim.dispose(); + if ($('modalOverlay'))$('modalOverlay').dispose(); + } +}); + + +/* +Script: StickyWin.ui.js + +Creates an html holder for in-page popups using a default style. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ + +StickyWin.ui = function(caption, body, options){ + options = $extend({ + width: 300, + css: "div.DefaultStickyWin div.body{font-family:verdana; font-size:11px; line-height: 13px;}"+ + "div.DefaultStickyWin div.top_ul{background:url({%baseHref%}full.png) top left no-repeat; height:30px; width:15px; float:left}"+ + "div.DefaultStickyWin div.top_ur{position:relative; left:0px !important; left:-4px; background:url({%baseHref%}full.png) top right !important; height:30px; margin:0px 0px 0px 15px !important; margin-right:-4px; padding:0px}"+ + "div.DefaultStickyWin h1.caption{clear: none !important; margin:0px 5px 0px 0px !important; overflow: hidden; padding:0 !important; font-weight:bold; color:#555; font-size:14px !important; position:relative; top:8px !important; left:5px !important; float: left; height: 22px !important;}"+ + "div.DefaultStickyWin div.middle, div.DefaultStickyWin div.closeBody {background:url({%baseHref%}body.png) top left repeat-y; margin:0px 20px 0px 0px !important; margin-bottom: -3px; position: relative; top: 0px !important; top: -3px;}"+ + "div.DefaultStickyWin div.body{background:url({%baseHref%}body.png) top right repeat-y; padding:8px 30px 8px 0px !important; margin-left:5px !important; position:relative; right:-20px !important;}"+ + "div.DefaultStickyWin div.bottom{clear:both}"+ + "div.DefaultStickyWin div.bottom_ll{background:url({%baseHref%}full.png) bottom left no-repeat; width:15px; height:15px; float:left}"+ + "div.DefaultStickyWin div.bottom_lr{background:url({%baseHref%}full.png) bottom right; position:relative; left:0px !important; left:-4px; margin:0px 0px 0px 15px !important; margin-right:-4px; height:15px}"+ + "div.DefaultStickyWin div.closeButtons{text-align: center; background:url({%baseHref%}body.png) top right repeat-y; padding: 0px 30px 8px 0px; margin-left:5px; position:relative; right:-20px}"+ + "div.DefaultStickyWin a.button:hover{background:url({%baseHref%}big_button_over.gif) repeat-x}"+ + "div.DefaultStickyWin a.button {background:url({%baseHref%}big_button.gif) repeat-x; margin: 2px 8px 2px 8px; padding: 2px 12px; cursor:pointer; border: 1px solid #999 !important; text-decoration:none; color: #000 !important;}"+ + "div.DefaultStickyWin div.closeButton{width:13px; height:13px; background:url({%baseHref%}closebtn.gif) no-repeat; position: absolute; right: 0px; margin:10px 15px 0px 0px !important; cursor:pointer}"+ + "div.DefaultStickyWin div.dragHandle { width: 11px; height: 25px; position: relative; top: 5px; left: -3px; cursor: move; background: url({%baseHref%}drag_corner.gif); float: left;}", + cornerHandle: false, + cssClass: '', + baseHref: 'http://www.cnet.com/html/rb/assets/global/stickyWinHTML/', + buttons: [] +/* These options are deprecated: + closeTxt: false, + onClose: $empty, + confirmTxt: false, + onConfirm: $empty */ + }, options); + //legacy support + if (options.confirmTxt) options.buttons.push({text: options.confirmTxt, onClick: options.onConfirm || $empty}); + if (options.closeTxt) options.buttons.push({text: options.closeTxt, onClick: options.onClose || $empty}); + + new StyleWriter().createStyle(options.css.substitute({baseHref: options.baseHref}, /\\?\{%([^}]+)%\}/g), 'defaultStickyWinStyle'); + caption = $pick(caption, '%caption%'); + body = $pick(body, '%body%'); + var container = new Element('div').setStyle('width', options.width).addClass('DefaultStickyWin'); + if (options.cssClass) container.addClass(options.cssClass); + //header + var h1Caption = new Element('h1').addClass('caption').setStyle('width', (options.width.toInt()-(options.cornerHandle?70:60))); + + if ($(caption)) h1Caption.adopt(caption); + else h1Caption.set('html', caption); + + var bodyDiv = new Element('div').addClass('body'); + if ($(body)) bodyDiv.adopt(body); + else bodyDiv.set('html', body); + + var top_ur = new Element('div').addClass('top_ur').adopt( + new Element('div').addClass('closeButton').addClass('closeSticky') + ).adopt(h1Caption); + if (options.cornerHandle) new Element('div').addClass('dragHandle').inject(top_ur, 'top'); + else h1Caption.addClass('dragHandle'); + container.adopt( + new Element('div').addClass('top').adopt( + new Element('div').addClass('top_ul') + ).adopt(top_ur) + ); + //body + container.adopt(new Element('div').addClass('middle').adopt(bodyDiv)); + //close buttons + if (options.buttons.length > 0){ + var closeButtons = new Element('div').addClass('closeButtons'); + options.buttons.each(function(button){ + if (button.properties && button.properties.className){ + button.properties['class'] = button.properties.className; + delete button.properties.className; + } + var properties = $merge({'class': 'closeSticky'}, button.properties); + new Element('a').addEvent('click', + button.onClick || $empty).appendText( + button.text).inject(closeButtons).setProperties(properties).addClass('button'); + }); + container.adopt(new Element('div').addClass('closeBody').adopt(closeButtons)); + } + //footer + container.adopt( + new Element('div').addClass('bottom').adopt( + new Element('div').addClass('bottom_ll') + ).adopt( + new Element('div').addClass('bottom_lr') + ) + ); + return container; +}; + + +/* +Script: Waiter.js + +Adds a semi-transparent overlay over a dom element with a spinnin ajax icon. + +License: + http://www.clientcide.com/wiki/cnet-libraries#license +*/ +var Waiter = new Class({ + Implements: [Options, Events, Chain], + options: { + baseHref: 'http://www.cnet.com/html/rb/assets/global/waiter/', + containerProps: { + styles: { + position: 'absolute', + 'text-align': 'center' + }, + 'class':'waiterContainer' + }, + containerPosition: {}, + msg: false, + msgProps: { + styles: { + 'text-align': 'center', + fontWeight: 'bold' + }, + 'class':'waiterMsg' + }, + img: { + src: 'waiter.gif', + styles: { + width: 24, + height: 24 + }, + 'class':'waiterImg' + }, + layer:{ + styles: { + width: 0, + height: 0, + position: 'absolute', + zIndex: 999, + display: 'none', + opacity: 0.9, + background: '#fff' + }, + 'class': 'waitingDiv' + }, + useIframeShim: true, + fxOptions: {} +// iframeShimOptions: {}, +// onShow: $empty +// onHide: $empty + }, + initialize: function(target, options){ + this.target = $(target)||$(document.body); + this.setOptions(options); + this.waiterContainer = new Element('div', this.options.containerProps).inject(document.body); + if (this.options.msg){ + this.msgContainer = new Element('div', this.options.msgProps); + this.waiterContainer.adopt(this.msgContainer); + if (!$(this.options.msg)) this.msg = new Element('p').appendText(this.options.msg); + else this.msg = $(this.options.msg); + this.msgContainer.adopt(this.msg); + } + if (this.options.img) this.waiterImg = $(this.options.img.id) || new Element('img').inject(this.waiterContainer); + this.waiterOverlay = $(this.options.layer.id) || new Element('div').inject(document.body).adopt(this.waiterContainer); + this.waiterOverlay.set(this.options.layer); + try { + if (this.options.useIframeShim) this.shim = new IframeShim(this.waiterOverlay, this.options.iframeShimOptions); + } catch(e){ + dbug.log("Waiter attempting to use IframeShim but failed; did you include IframeShim? Error: ", e); + this.options.useIframeShim = false; + } + this.waiterFx = this.waiterFx || new Fx.Elements($$(this.waiterContainer, this.waiterOverlay), this.options.fxOptions); + }, + toggle: function(element, show){ + //the element or the default + element = $(element) || $(this.active) || $(this.target); + if (!$(element)) return this; + if (this.active && element != this.active) return this.stop(this.start.bind(this, element)); + //if it's not active or show is explicit + //or show is not explicitly set to false + //start the effect + if ((!this.active || show) && show !== false) this.start(element); + //else if it's active and show isn't explicitly set to true + //stop the effect + else if (this.active && !show) this.stop(); + return this; + }, + reset: function(){ + this.waiterFx.cancel().set({ + 0: { opacity:[0]}, + 1: { opacity:[0]} + }); + }, + start: function(element){ + this.reset(); + element = $(element) || $(this.target); + if (this.options.img){ + this.waiterImg.set($merge(this.options.img, { + src: this.options.baseHref + this.options.img.src + })); + } + + var start = function(){ + var dim = element.getComputedSize(); + this.active = element; + this.waiterOverlay.setStyles({ + width: this.options.layer.width||dim.totalWidth, + height: this.options.layer.height||dim.totalHeight, + display: 'block' + }).setPosition({ + relativeTo: element, + position: 'upperLeft' + }); + this.waiterContainer.setPosition({ + relativeTo: this.waiterOverlay + }); + if (this.options.useIframeShim) this.shim.show(); + this.waiterFx.start({ + 0: { opacity:[1] }, + 1: { opacity:[this.options.layer.styles.opacity]} + }).chain(function(){ + if (this.active == element) this.fireEvent('onShow', element); + this.callChain(); + }.bind(this)); + }.bind(this); + + if (this.active && this.active != element) this.stop(start); + else start(); + + return this; + }, + stop: function(callback){ + if (!this.active){ + if ($type(callback) == "function") callback.attempt(); + return this; + } + this.waiterFx.cancel(); + this.waiterFx.clearChain(); + //fade the waiter out + this.waiterFx.start({ + 0: { opacity:[0]}, + 1: { opacity:[0]} + }).chain(function(){ + this.active = null; + this.waiterOverlay.hide(); + if (this.options.useIframeShim) this.shim.hide(); + this.fireEvent('onHide', this.active); + this.callChain(); + this.clearChain(); + if ($type(callback) == "function") callback.attempt(); + }.bind(this)); + return this; + } +}); + +if (typeof Request != "undefined" && Request.HTML){ + Request.HTML = new Class({ + Extends: Request.HTML, + options: { + useWaiter: false, + waiterOptions: {}, + waiterTarget: false + }, + initialize: function(options){ + this._send = this.send; + this.send = function(options){ + if (this.waiter) this.waiter.start().chain(this._send.bind(this, options)); + else this._send(options); + return this; + }; + this.parent(options); + if (this.options.useWaiter && ($(this.options.update) || $(this.options.waiterTarget))){ + this.waiter = new Waiter(this.options.waiterTarget || this.options.update, this.options.waiterOptions); + ['onComplete', 'onException', 'onCancel'].each(function(event){ + this.addEvent(event, this.waiter.stop.bind(this.waiter)); + }, this); + } + } + }); +} + +function setCNETAssetBaseHref(baseHref){ + if (window.StickyWin && StickyWin.ui){ + var CGFstickyWinHTML = StickyWin.ui.bind(window); + StickyWin.ui = function(caption, body, options){ + return CGFstickyWinHTML(caption, body, $merge({ + baseHref: baseHref + '/stickyWinHTML/' + }, options)); + }; + if (StickyWin.alert){ + var CGFsimpleErrorPopup = StickyWin.alert.bind(window); + StickyWin.alert = function(msghdr, msg, base){ + return CGFsimpleErrorPopup(msghdr, msg, base||baseHref + "/simple.error.popup"); + }; + } + } + if (window.TagMaker){ + var store = {}; + var props = ['image', 'anchor', 'cnetVideo']; + props.each(function(prop){ + store[prop] = TagMaker[prop]; + }); + TagMaker = new Class({ + Extends: TagMaker, + options: { + baseHref: baseHref + '/tips/' + } + }); + $extend(TagMaker, store); + } + + if (window.ProductPicker){ + var store = {}; + var props = ['picklets', 'add', 'addAllThese', 'getPicklet']; + props.each(function(prop){ + store[prop] = ProductPicker[prop]; + }); + ProductPicker = new Class({ + Extends: ProductPicker, + options:{ + baseHref: baseHref + '/Picker' + } + }); + $extend(ProductPicker, store); + } + + if (window.Autocompleter){ + var AcCNET = function(orgClass){ + return { + Extends: orgClass, + options: { + baseHref: baseHref + '/autocompleter/' + } + }; + }; + Autocompleter.Base = new Class(AcCNET(Autocompleter.Base)); + if (Autocompleter.Ajax){ + ["Base", "Xhtml", "Json"].each(function(c){ + if (Autocompleter.Ajax[c]) Autocompleter.Ajax[c] = new Class(AcCNET(Autocompleter.Ajax[c])); + }); + } + if (Autocompleter.Local) Autocompleter.Local = new Class(AcCNET(Autocompleter.Local)); + if (Autocompleter.JsonP) Autocompleter.JsonP = new Class(AcCNET(Autocompleter.JsonP)); + } + + if (window.Lightbox){ + Lightbox = new Class({ + Extends: Lightbox, + options: { + assetBaseUrl: baseHref + '/slimbox/' + } + }); + } + + if (window.Waiter){ + Waiter = new Class({ + Extends: Waiter, + options: { + baseHref: baseHref + '/waiter/' + } + }); + } +}; \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/docs.css b/assets/mootools-core/Tests/assets/docs.css new file mode 100644 index 00000000..e09248c4 --- /dev/null +++ b/assets/mootools-core/Tests/assets/docs.css @@ -0,0 +1,290 @@ +/* +File: Style.css + Slick Style for MooTools Docs. + +License: + Copyright (c)2007 Valerio Proietti, . +*/ + +/* @group Reset */ + +* { + margin: 0; + padding: 0; +} + +#menu ul { + list-style: none; +} + +#submenu ul { + list-style-type: square; +} + +/* @end */ + +/* @group Base */ + + +body { + font: 11px/1.5 Lucida Grande, Helvetica, Arial, sans-serif; + background: #F3F1F1; + color: #41464D; +} + +body, #container { + width: 100%; +} + +a { + text-decoration:none; +} + +#title { + position: absolute; + top: 0; + left: 0; + width: 100%; + padding: 5px 0; + background: #aaa; + background: #41464D; + color: #F3F1F1; + height: 30px; +} + +#menu { + position: absolute; + width: 30%; + overflow-y: auto; + overflow-x: hidden; + top: 40px; + left: 0; + bottom: 0; + height: expression(document.body.clientHeight-40); +} + +#docs { + top: 40px; + position: relative; + overflow: auto; +} + +span.spc { + display: block; + height: 16px; +} + +#docs-wrapper, #menu-wrapper { + overflow: hidden; + padding: 4px 4px 0; + background: #fff; +} + +#docs-wrapper { + margin: 16px 16px 0 8px; +} + +#menu-wrapper { + margin: 16px 8px 0 16px; +} + +.success a:link, .success a:visited { + color: #657528; +} + +.exception a:link, .exception a:visited { + color: #B33F3F; +} + +a:link, a:visited { + color: #528CE0; +} + +a:hover, a:active { + cursor: pointer !important; +} + +#title h1 { + font: 25px/1.1 Arial, sans-serif; + font-weight: bolder; + margin: 1px 0 2px 20px; + text-shadow: 0 2px 2px rgba(0,0,0,0.4); +} + +#title h1 span { + color: #D2E0E6; +} + +#title a { + color: #fff; + text-decoration: none; + font-size: 14px; + position: relative; + top: -2px; +} + +#title ul li { + font-weight: bold; + font-size: 12px; + float: right; + margin: 10px 5px 0; +} + +#title ul { + margin-right: 20px; +} + +#menu h2 { + font-size: 14px; + background: #D0C8C8; + color: #8A7575; + margin-bottom: 4px; + padding: 2px 5px; +} + +br { + display: none; +} + +#menu h3 a { + display: block; +} + +#menu h3.selected { + background-color: #e2e5d2; +} + +#menu h3.selected a { + color: #657528; +} + +h1, h2, h3, h4, h5, h6 { + cursor: default; +} + +#menu h3 { + font-size: 12px; + padding: 3px 5px 1px; + background: #D2E0E6; + color: #528CE0; + margin-bottom: 4px; +} + +#submenu { + background: #CBCEBD; + color: #424D1A; + padding: 2px 30px; + max-height: 200px; + overflow: auto; + margin-bottom: 4px; +} + +#submenu a { + color: #424D1A; + display: block; +} + +#submenu a:hover { + text-decoration: underline; + color: #424D1A; + display: block; +} + +#submenu ul.subgroup { + padding-left: 20px; +} + +p { + color: #575d67; +} + +div#footer { + text-align: right; + padding: 10px 16px 0 0; +} + +div#footer p { + padding: 0; +} + +/* @end */ + + +/* @group Docs */ + +#docs p { + padding: 5px; + font-size: 12px; +} + +#docs p, #docs code, #docs li { + font-size: 12px; +} + +#docs h1, #docs h2, #docs h3, #docs h4, #docs h5, #docs h6 { + margin: 5px 0; + padding: 3px 5px 1px; + background: #ddd; +} + +#docs h1 { + margin: 25px 0 10px; + background: #D2E0E6; + color: #528CE0; +} + +#docs h1.first { + margin: 0 0 10px; +} + +#docs h2, #docs h3 { + margin: 10px 0; +} + +#docs h3 { + background: #D0C8C8; + color: #5d4f4f; +} + +#docs h2 { + color: #B33F3F; + background: #eed8d8; +} + +#docs ul, #docs ol { + margin-left: 20px; +} + +#docs ul { + list-style: square; +} + +#docs ul li p { + padding: 0px; +} + +#docs pre { + padding: 5px 7px; + margin: 5px 0; + background: #f5f5f5; + border: 1px solid #ddd; + color: #333; + overflow: auto; +} + +#docs h5, #docs h6 { + margin: 5px 0; + padding: 3px 5px 1px; + color: #ce4521; + background: #f0f0ee; +} + +#container #docs #docs-wrapper li strong { + color: #5a86a3; +} + +#container #docs #docs-wrapper li em { + color: #a56f49; +} + +/* @end */ diff --git a/assets/mootools-core/Tests/assets/empty_test.js b/assets/mootools-core/Tests/assets/empty_test.js new file mode 100644 index 00000000..8b7e0968 --- /dev/null +++ b/assets/mootools-core/Tests/assets/empty_test.js @@ -0,0 +1,14 @@ +//this is just a template for reference. +{ + tests: [ + { + title: "", //the title of the test + description: "", //a one liner description of the test + verify: "", //the question the user should answer "yes" to that signifies success + before: function(){}, //any code to execute when the test begins + post: function(){}, //any code to execute after the body is evaluated; if it returns false, the test fails + body: "" //any code you want the user to be able to see/modify; optional + } + ], + otherScripts: [] //other script that should be loaded for your test to work ("Selectors", "Request", etc) +} \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/fireDomReady.js b/assets/mootools-core/Tests/assets/fireDomReady.js new file mode 100644 index 00000000..75db00db --- /dev/null +++ b/assets/mootools-core/Tests/assets/fireDomReady.js @@ -0,0 +1,8 @@ +//this script is used in the test iframe to ensure that domready fires correctly when the body is updated with the test html +try { + if (typeof Browser != "undefined") Browser.loaded = true; + if (window.fireEvent) window.fireEvent('domready'); +} catch(e){ + dbug.log('domready not fired: ', e); +} +if (typeof IframeShim != "undefined") IframeShim.ready = true; \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/moobugger/bookmarklet.html b/assets/mootools-core/Tests/assets/moobugger/bookmarklet.html new file mode 100644 index 00000000..06b2aff2 --- /dev/null +++ b/assets/mootools-core/Tests/assets/moobugger/bookmarklet.html @@ -0,0 +1,46 @@ + + + + + + + bugger + + + + + + + + +
+

The MooBugger.

+

moobugger - bookmark it!

+
+ + + + \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/moobugger/debugger-iframe.js b/assets/mootools-core/Tests/assets/moobugger/debugger-iframe.js new file mode 100644 index 00000000..0d57f47e --- /dev/null +++ b/assets/mootools-core/Tests/assets/moobugger/debugger-iframe.js @@ -0,0 +1,372 @@ +/* +Script: Debugger.js + Creates Firebug style debugger for browsers without Firebug. + +License: + MIT-style license. +*/ + +var debug = { + + $nil: Function.empty, + + $init: function(){ + debug.loaded = false; + debug.$groups = {'keys': [], 'values': []}; + debug.$timers = {}; + }, + + $register: function(text){ + debug.$messages.remove(text); + debug.$messages.push(text); + debug.$midx = debug.$messages.length; + var toCookie = debug.$messages.join('|||').replace(/;/g, '%%%'); + if (toCookie.length >= 4096) toCookie = toCookie.substring(2048, 4049); + Cookie.set('mootools-debugger-history', toCookie, {duration: 10}); + }, + + $parse: function(args, separator, to_e, klass){ + separator = $pick(separator, ' '); + var chunks = []; + for (var i = 0, l = args.length; i < l; i++){ + if (args[i] === undefined){ + chunks.push({'type': 'undefined', 'value': 'undefined'}); + continue; + } + var argument = args[i]; + var type = parent.Moo.type(argument); + if (['boolean', false].contains(type)) argument = String(argument); + else if (type == 'collection') type = 'array'; + chunks.push({'type': type.toString(), 'value': argument}); + } + var holder = new Element('span'); + chunks.each(function(chunk, i){ + switch(chunk.type){ + case 'element': holder.adopt(debug.$element(chunk.value)); break; + case 'array': holder.adopt(new Element('span').setHTML('['), debug.$parse(chunk.value, ', ', true), new Element('span').setHTML(']')); break; + case 'object': + holder.adopt(new Element('span').setHTML('{')); + var x = 0; + var length = 0; + for (var len in chunk.value) length++; + for (var key in chunk.value){ + x++; + holder.adopt(new Element('span').setHTML('', key, '', ': '), debug.$parse([chunk.value[key]], '', true)); + if (x != length) holder.adopt(new Element('span').setHTML(', ')); + } + holder.adopt(new Element('span').setHTML('}')); + break; + default: new Element('span').addClass(chunk.type).appendText(chunk.value).inject(holder); + } + if (i != (chunks.length - 1)) holder.adopt(new Element('span').setHTML(separator)); + }); + if (to_e){ + return holder; + } else { + debug.$pre(holder, klass); + return debug.$nil; + } + }, + + $element: function(el){ + var oldbg = el.style.backgroundColor; + var oldfg = el.style.color; + + var link = new Element('a', {'href': '#'}).addEvents({ + + mouseenter: function(){ + el.style.backgroundColor = '#DBEAF0'; + el.style.color = '#757E8A'; + }, + + mouseleave: function(){ + el.style.backgroundColor = oldbg; + el.style.color = oldfg; + }, + + click: function(){ + return false; + } + + }); + var htm = ['<' + '' + Element.getTag(el) + '']; + ['id', 'className', 'name', 'href', 'title', 'rel', 'type'].each(function(attr){ + if (el[attr]) htm.push(attr + '="' + '' + el[attr] + '' + '"'); + }); + return link.setHTML(htm.join(' '), '>'); + }, + + $pre: function(content, klass){ + var pre = new Element('pre', {'class': klass || 'message'}); + if ($type(content) == "string") pre.appendText(content); + else pre.adopt(content); + pre.inject(debug.$groups.values.getLast()); + if (debug.loaded) debug._scroll.toBottom(); + return pre; + }, + + $log: function(args, separator, klass){ + separator = $pick(separator, ', '); + var sRegExp = /%[sdifo]/gi; + if ($type(args[0]) == 'string' && args[0].test(sRegExp)){ + separator = ''; + var logCollection = [], lastIndex = 0; + sRegExp.lastIndex = 0; + var token; + for (var i = 1; (i < args.length) && (token = sRegExp.exec(args[0])); i++){ + logCollection.push(args[0].substring(lastIndex, token.index), args[i]); + lastIndex = sRegExp.lastIndex; + } + sRegExp.lastIndex = 0; + if (!lastIndex) return debug.$parse(args); + logCollection.push(args[0].substring(lastIndex)); + args = logCollection; + } + debug.$parse(args, separator, false, klass); + return debug.$nil; + }, + + $special: function(obj, klass){ + if (obj.length == 1){ + var one = obj[0]; + var type = $type(one); + if ((type == 'object' && one.name && one.message) || (type == 'string')){ + var name, message; + + if (type == 'object'){ + name = one.name; + message = one.message; + } else if (type == 'string'){ + name = klass.capitalize(); + message = one; + } + + return debug.$pre(name + ': ' + message, klass); + } + } + return debug.$log([klass.capitalize() + ':'].concat(obj), ' ', klass); + }, + + $load: function(){ + debug.loaded = true; + debug.$messages = Cookie.get('mootools-debugger-history') || []; + debug.$messages = debug.$messages.length ? debug.$messages.replace(/%%%/g, ';').split('|||') : []; + debug.$midx = debug.$messages.length; + + debug._body = $('debug').setStyle('display', 'block'); + debug._messages = $('debug-messages'); + + debug.$groups.keys.push('$main$'); + debug.$groups.values.push(debug._messages); + + debug._input = $('debug-input'); + + debug._scroll = new Fx.Scroll(debug._messages, {duration: 300, wait: false}); + + debug._input.addEvent('keydown', debug.$key); + + debug._max = $('debug-button-max').addEvent('click', debug.$max); + + debug._min = $('debug-button-min').addEvent('click', debug.$min); + + debug._close = $('debug-button-close').addEvent('click', debug.$unload); + + debug._maxValue = 132; + debug._minValue = 18; + + var state = Cookie.get('mootools-debugger-state'); + if (state) debug[state](); + else debug.$max(); + + for (var i = 0, l = parent.debug.queue.length; i < l; i++){ + var kue = parent.debug.queue[i]; + debug[kue.name].apply(debug, kue.arguments); + } + + debug._scroll.toBottom(); + }, + + $max: function(){ + Cookie.set('mootools-debugger-state', '$max', {duration: 10}); + debug._messages.setStyles({ + 'height': debug._maxValue, + 'overflow': 'auto' + }); + debug._max.setStyle('display', 'none'); + debug._min.setStyle('display', 'block'); + debug.$pad(); + }, + + $min: function(){ + Cookie.set('mootools-debugger-state', '$min', {duration: 10}); + debug._messages.setStyles({ + 'height': debug._minValue, + 'overflow': 'hidden' + }); + debug._max.setStyle('display', 'block'); + debug._min.setStyle('display', 'none'); + debug.$pad(); + }, + + $pad: function(){ + parent.debug.iFrame.style.height = debug._body.offsetHeight + 'px'; + debug._messages.scrollTop = debug._messages.scrollHeight - debug._messages.offsetHeight; + parent.Moo.Debugger.reposition(); + }, + + $unload: function(){ + if (!debug.loaded) return; + debug.$init(); + parent.Moo.Debugger.unload(); + }, + + $focus: function(){ + debug._input.focus(); + }, + + $key: function(e){ + var value = debug._input.value; + + switch(e.key){ + case 'enter': + if (!value){ + return false; + } + debug._input.value = ''; + switch(value){ + case 'exit': debug.$unload(); return false; + case 'clear': case 'clr': debug._messages.empty(); return false; + } + + debug.$pre('>>> ' + value, 'logger'); + debug.$register(value); + if (value.indexOf('var ') == 0) value = value.substring(4, value.length); + if (value.charAt(value.length - 1) == ';') value = value.substring(0, value.length - 1); + if (value.indexOf('{') == 0) value = '(' + value + ')'; + + parent.Moo.Debugger.evaluate(value); + break; + + case 'up': + e.stop(); + var i = debug.$midx - 1; + if (debug.$messages[i]){ + debug._input.value = debug.$messages[i]; + debug.$midx = i; + } + break; + + case 'down': + e.stop(); + var j = debug.$midx + 1; + if (debug.$messages[j]){ + debug._input.value = debug.$messages[j]; + debug.$midx = j; + } else { + debug._input.value = ''; + debug.$midx = debug.$messages.length; + } + } + + return debug.$focus.delay(50); + }, + + /* + Property: log + sends a message to the debugger. + Arguments: + messages - any number of strings, objects, etc. to print out + Note: + The debugger will allow firebug style log messages: + %s - String + %d, %i - Integer (numeric formatting is not yet supported) + %f - Floating point number (numeric formatting is not yet supported) + %o - Object hyperlink + Example: + >console.log("the value of x is %s and this paragraph is %o", x, $('id')); + > the value of x is and this paragraph is

+ */ + + log: function(){ + return debug.$log($A(arguments)); + }, + + /* + Property: time + Starts a timer. + Argument: + name - the name of the timer + */ + + time: function(name){ + if (debug.$timers[name]){ + debug.error("a timer called " + name + ' already exists'); + } else { + debug.$pre(name + ' started', 'time'); + debug.$timers[name] = new Date().getTime(); + } + return debug.$nil; + }, + + /* + Property: timeEnd + Ends a timer and logs that value to the console. + Argument: + name - the name of the timer + */ + + timeEnd: function(name){ + if (debug.$timers[name]) debug.$pre(name + ' ended: ' + (new Date().getTime() - debug.$timers[name]) + ' ms', 'time'); + else debug.error("no such timer called " + name); + return debug.$nil; + }, + + group: function(name){ + if (debug.$groups.keys.contains(name)){ + debug.error('a group called ' + name + ' already exists'); + } else { + var pre = debug.$pre('Group: ' + name, 'group'); + var grp = new Element('div', {'class': 'group'}).inject(debug.$groups.values.getLast()); + pre.addEvent('click', function(){ + var none = (grp.getStyle('display') == 'none'); + var name = none ? 'block' : 'none'; + grp.setStyle('display', name); + this.toggleClass('group-closed'); + }); + debug.$groups.keys.push(name); + debug.$groups.values.push(grp); + } + return debug.$nil; + }, + + groupEnd: function(name){ + var idx = debug.$groups.keys.indexOf(name); + if (idx >= 0){ + debug.$groups.values.remove(debug.$groups.values[idx]); + debug.$groups.keys.remove(name); + } else { + debug.error('no such group called ' + name); + } + return debug.$nil; + }, + + error: function(){ + debug.$special($A(arguments), 'error'); + return debug.$nil; + }, + + warn: function(warning){ + debug.$special($A(arguments), 'warning'); + return debug.$nil; + }, + + info: function(){ + debug.$special($A(arguments), 'info'); + return debug.$nil; + } + +}; + +debug.$init(); + +window.addEvent('load', debug.$load); \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/moobugger/debugger.css b/assets/mootools-core/Tests/assets/moobugger/debugger.css new file mode 100644 index 00000000..ecc6991a --- /dev/null +++ b/assets/mootools-core/Tests/assets/moobugger/debugger.css @@ -0,0 +1,190 @@ +body { + margin: 0; + padding: 0; +} + +#debug { + display: none; + font-family: arial, helvetica; + width: 100%; + border-top: 1px solid #B9ACAC; + z-index: 9999; +} + +#debug-header { + height: 16px; + border-top: 1px solid #F3F1F1; + border-bottom: 1px solid #B9ACAC; + background: #DBD6D6; + text-align: right; + padding: 3px 7px 0; + font-size: 10px; + color: #B9ACAC; +} + +#debug-mootools-net:link, #debug-mootools-net:visited { + display: block; + float: left; + width: 14px; + height: 14px; + margin-top: -1px; + background: url(images/icon.png) no-repeat top left; +} + +#debug-mootools-net:hover, #debug-mootools-net:active { + background-position: bottom left; +} + +#debug-header span { + cursor: pointer; + width: 13px; + height: 13px; + display: block; + float: right; + margin-left: 5px; +} + +#debug-header b { + display: block; + clear: both; +} + +#debug-button-close { + background: url(images/close.png); +} + +#debug-button-max { + background: url(images/max.png); +} + +#debug-button-min { + background: url(images/min.png); +} + +#debug-messages { + height: 133px; + border-top: 1px solid #EEE; + overflow: auto; + background: #FFF url(images/mootools.png) no-repeat center center; +} + +#debug-messages pre { + white-space: normal; + padding: 3px 5px; + margin: 0; + font: 11px "Andale Mono", Monaco, "Courier New"; + border-bottom: 1px solid #ccc; + color: #444; + background-color: #FFF; +} + +#debug-messages pre.error { + background: #F0F0F0 url(images/error.png) no-repeat 5px 50%; + color: #da5d0b; + padding-left: 25px; +} + +#debug-messages pre.error span.string { + color: #da5d0b; +} + +#debug-messages pre.warning { + background: #F0F0F0 url(images/warning.png) no-repeat 5px 50%; + color: #ce7a2a; + padding-left: 25px; +} + +#debug-messages pre.warning span.string { + color: #ce7a2a; +} + +#debug-messages pre.info { + background: #F0F0F0 url(images/info.png) no-repeat 5px 50%; + color: #528CE0; + padding-left: 25px; +} + +#debug-messages pre.info span.string { + color: #528CE0; +} + +#debug-messages pre.time { + background: #F0F0F0 url(images/time.png) no-repeat 5px 50%; + color: #111; + padding-left: 25px; +} + +#debug-messages pre.group { + background: #f9f9f9 url(images/group-close.png) no-repeat 6px 50%; + color: #222; + padding-left: 25px; + cursor: pointer; +} + +#debug-messages pre.group-closed { + background-image: url(images/group-open.png); +} + +#debug-messages div.group { + padding: 2px 0 2px 10px; + background: #ccc; +} + +#debug-messages pre.logger { + color: #4373B8; +} + +#debug-input-area { + overflow: hidden; + border-top: 1px solid #B9ACAC; +} + +#debug-input { + width: 100% !important; + width: 90%; + color: #222; + font: 12px Andale Mono, Monaco, "Courier New"; + margin: 0; + border: 0; + padding: 4px 5px 3px 30px; + background: #fff url(images/lick.png) no-repeat 7px 63%; +} + +#debug-messages a:link, #debug-messages a:visited { + color: #333; + text-decoration: none; +} + +#debug-messages a:hover, #debug-messages a:active { + background-color: #757E8A; + color: #fff; +} + +#debug-messages a:hover span, #debug-messages a:active span { + color: #EECFCF; +} + +#debug-messages span.number { + color: #B33F3F; +} + +#debug-messages span.boolean { + color: #A652E0; +} + +#debug-messages span.undefined, #debug-messages span.false { + color: #888; + background-color: #eee; +} + +#debug-messages span.key { + color: #888; +} + +#debug-messages span.tag { + color: #528CE0; +} + +#debug-messages span.string { + color: #8B9E41; +} \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/moobugger/debugger.html b/assets/mootools-core/Tests/assets/moobugger/debugger.html new file mode 100644 index 00000000..60dd577a --- /dev/null +++ b/assets/mootools-core/Tests/assets/moobugger/debugger.html @@ -0,0 +1,25 @@ + + + + + debugger + + + + + +

+
+ + + + + +
+
+
+ +
+
+ + \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/moobugger/debugger.js b/assets/mootools-core/Tests/assets/moobugger/debugger.js new file mode 100644 index 00000000..6a760a73 --- /dev/null +++ b/assets/mootools-core/Tests/assets/moobugger/debugger.js @@ -0,0 +1,268 @@ +var Moo = { + + defined: function(obj){ + return (obj != undefined); + }, + + type: function(obj){ + if (!Moo.defined(obj)) return false; + var type = typeof obj; + if (type == 'object' && obj.nodeName){ + switch(obj.nodeType){ + case 1: return 'element'; + case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace'; + } + } + if (type == 'object' || type == 'function'){ + switch(obj.constructor){ + case Array: return 'array'; + case RegExp: return 'regexp'; + } + if (typeof obj.length == 'number'){ + if (obj.item) return 'collection'; + if (obj.callee) return 'arguments'; + } + } + return type; + } + +}; + +Moo.Client = { + Engine: {'name': 'unknown', 'version': ''}, + Platform: {}, + Features: {} +}; +Moo.Client.Features.xhr = !!(window.XMLHttpRequest); +Moo.Client.Features.xpath = !!(document.evaluate); + +if (window.opera) Moo.Client.Engine.name = 'opera'; +else if (window.ActiveXObject) Moo.Client.Engine = {'name': 'ie', 'version': (Moo.Client.Features.xhr) ? 7 : 6}; +else if (!navigator.taintEnabled) Moo.Client.Engine = {'name': 'webkit', 'version': (Moo.Client.Features.xpath) ? 420 : 419}; +else if (document.getBoxObjectFor != null) Moo.Client.Engine.name = 'gecko'; +Moo.Client.Engine[Moo.Client.Engine.name] = Moo.Client.Engine[Moo.Client.Engine.name + Moo.Client.Engine.version] = true; + +Moo.Client.Platform.name = navigator.platform.match(/(mac)|(win)|(linux)|(nix)/i) || ['Other']; +Moo.Client.Platform.name = Moo.Client.Platform.name[0].toLowerCase(); +Moo.Client.Platform[Moo.Client.Platform.name] = true; + +Moo.ViewPort = { + + getWidth: function(){ + if (Moo.Client.Engine.webkit419) return window.innerWidth; + if (Moo.Client.Engine.opera) return document.body.clientWidth; + return document.documentElement.clientWidth; + }, + + getHeight: function(){ + if (Moo.Client.Engine.webkit419) return window.innerHeight; + if (Moo.Client.Engine.opera) return document.body.clientHeight; + return document.documentElement.clientHeight; + }, + + getScrollWidth: function(){ + if (Moo.Client.Engine.ie) return Math.max(document.documentElement.offsetWidth, document.documentElement.scrollWidth); + if (Moo.Client.Engine.webkit) return document.body.scrollWidth; + return document.documentElement.scrollWidth; + }, + + getScrollHeight: function(){ + if (Moo.Client.Engine.ie) return Math.max(document.documentElement.offsetHeight, document.documentElement.scrollHeight); + if (Moo.Client.Engine.webkit) return document.body.scrollHeight; + return document.documentElement.scrollHeight; + }, + + getScrollLeft: function(){ + return window.pageXOffset || document.documentElement.scrollLeft; + }, + + getScrollTop: function(){ + return window.pageYOffset || document.documentElement.scrollTop; + } + +}; + +Moo.Element = { + + addEvent: function(element, type, fn){ + if (element.addEventListener) element.addEventListener(type, fn, false); + else element.attachEvent('on' + type, fn); + }, + + removeEvent: function(item, type, fn){ + if (item.removeEventListener) item.removeEventListener(type, fn, false); + else item.detachEvent('on' + type, fn); + }, + + remove: function(item){ + if (!item || !item.parentNode) return; + item.parentNode.removeChild(item); + } + +}; + +Moo.Array = { + + forEach: function(items, fn, bind){ + for (var i = 0, j = items.length; i < j; i++) fn.call(bind, items[i], i, items); + } + +}; + +Moo.String = { + + contains: function(item, string, s){ + return (s) ? (s + item + s).indexOf(s + string + s) > -1 : item.indexOf(string) > -1; + } + +}; + +Moo.Object = { + + add: function(item, properties){ + for (var property in properties){ + item[property] = properties[property]; + } + } + +}; + +var debug = debug || {}; +debug.queue = []; +debug.methods = ['log', 'time', 'timeEnd', 'group', 'groupEnd', 'warn', 'info', 'error']; + +Moo.Array.forEach(debug.methods, function(name){ + debug[name] = function(){ + debug.queue.push({'name': name, 'arguments': arguments}); + }; +}); + +Moo.Debugger = { + + load: function(){ + + debug.spacer = document.createElement('div'); + document.body.appendChild(debug.spacer); + + debug.iFrame = document.createElement('iframe'); + + debug.iFrame.frameBorder = 0; + + Moo.Object.add(debug.iFrame.style, { + 'border': 'none', + 'padding': 0, + 'margin': 0, + 'width': '100%', + 'position': 'fixed', + 'bottom': 0, + 'left': 0, + 'zIndex': 999999 + }); + + if (Moo.Client.Engine.ie) debug.iFrame.style.position = 'absolute'; + + debug.iFrame.id = debug.iFrame.name = 'debugger'; + debug.iFrame.src = (debug.local) ? debug.path + 'debugger.html' : 'javascript:parent.debug.htmlString'; + + + document.body.appendChild(debug.iFrame); + + Moo.Element.addEvent(debug.iFrame, 'load', Moo.Debugger.onFrameLoaded); + }, + + getPath: function(){ + var path = ''; + Moo.Array.forEach(document.getElementsByTagName('script'), function(script){ + if (!path && Moo.String.contains(script.src, '/') && Moo.String.contains(script.src, 'debugger.js')) path = script.src.substr(0, script.src.lastIndexOf('/')); + }); + return path + '/'; + }, + + onFrameLoaded: function(){ + debug.frame = window.frames['debugger']; + + Moo.Array.forEach(debug.methods, function(name){ + debug[name] = debug.frame.debug[name]; + }); + + Moo.Element.addEvent(window, 'resize', Moo.Debugger.reposition); + Moo.Element.addEvent(window, 'scroll', Moo.Debugger.reposition); + + Moo.Debugger.reposition(); + }, + + reposition: function(){ + debug.spacer.style.height = debug.iFrame.offsetHeight + 'px'; + var top = Moo.ViewPort.getHeight() - debug.iFrame.offsetHeight; + if (top < 0) return; + if (Moo.Client.Engine.ie6){ + top = Moo.ViewPort.getScrollTop() + top; + debug.iFrame.style.top = top + 'px'; + } + }, + + unload: function(){ + debug.queue = []; + Moo.Element.remove(debug.iFrame); + Moo.Element.remove(debug.spacer); + Moo.Element.remove(document.getElementById('debug-bookmarklet')); + }, + + evaluate: function(value){ + try { + var evaluation = eval(value); + if (evaluation !== debug.frame.debug.$nil){ + if (evaluation == window) evaluation = {'window': '[native code]'}; + if (evaluation == document) evaluation = {'document': '[native code]'}; + debug.frame.debug.$parse([evaluation]); + } + } catch(err){ + debug.frame.debug.error(err); + } + } + +}; + +window.$ = window.$ || function(id){ + return document.getElementById(id); +}; + +window.$$ = window.$$ || function(tag){ + return document.getElementsByTagName(tag); +}; + +if (!debug.path) debug.local = true; + +debug.path = debug.path || Moo.Debugger.getPath(); + +debug.htmlString = ' \ + \ + \ + \ + debugger \ + \ + \ + \ + \ + \ +
\ +
\ + \ + \ + \ + \ + \ +
\ +
\ +
\ + \ +
\ +
\ + \ +'; + +if (!window.console || !console.group){ + window.console = debug; + if (!debug.local) Moo.Debugger.load(); + else Moo.Element.addEvent(window, 'load', Moo.Debugger.load); +} \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/moobugger/images/close.png b/assets/mootools-core/Tests/assets/moobugger/images/close.png new file mode 100644 index 00000000..17fc775e Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/close.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/error.png b/assets/mootools-core/Tests/assets/moobugger/images/error.png new file mode 100644 index 00000000..2f8465e8 Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/error.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/group-close.png b/assets/mootools-core/Tests/assets/moobugger/images/group-close.png new file mode 100644 index 00000000..c2a86769 Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/group-close.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/group-open.png b/assets/mootools-core/Tests/assets/moobugger/images/group-open.png new file mode 100644 index 00000000..25b01b9d Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/group-open.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/icon.png b/assets/mootools-core/Tests/assets/moobugger/images/icon.png new file mode 100644 index 00000000..a22c633f Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/icon.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/info.png b/assets/mootools-core/Tests/assets/moobugger/images/info.png new file mode 100644 index 00000000..cd34f124 Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/info.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/lick.png b/assets/mootools-core/Tests/assets/moobugger/images/lick.png new file mode 100644 index 00000000..556e247f Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/lick.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/max.png b/assets/mootools-core/Tests/assets/moobugger/images/max.png new file mode 100644 index 00000000..a1ec4f39 Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/max.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/min.png b/assets/mootools-core/Tests/assets/moobugger/images/min.png new file mode 100644 index 00000000..e20b9256 Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/min.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/mootools.png b/assets/mootools-core/Tests/assets/moobugger/images/mootools.png new file mode 100644 index 00000000..e26a1dca Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/mootools.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/time.png b/assets/mootools-core/Tests/assets/moobugger/images/time.png new file mode 100644 index 00000000..4ec395bb Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/time.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/images/warning.png b/assets/mootools-core/Tests/assets/moobugger/images/warning.png new file mode 100644 index 00000000..0324a4c6 Binary files /dev/null and b/assets/mootools-core/Tests/assets/moobugger/images/warning.png differ diff --git a/assets/mootools-core/Tests/assets/moobugger/mootools.js b/assets/mootools-core/Tests/assets/moobugger/mootools.js new file mode 100644 index 00000000..2d117eb6 --- /dev/null +++ b/assets/mootools-core/Tests/assets/moobugger/mootools.js @@ -0,0 +1,57 @@ +//MooTools, My Object Oriented Javascript Tools. Copyright (c) 2006 Valerio Proietti, , MIT Style License. + +var MooTools={version:'1.2dev'};function $extend(){var args=arguments;if (!args[1])args=[this,args[0]];for(var property in args[1])args[0][property]=args[1][property];return args[0];};function $native(){for(var i=0,l=arguments.length;i-1:this.indexOf(string)>-1;},escapeRegExp:function(){return this.replace(/([.*+?^${}()|[\]\/\\])/g,'\\$1');}});Array.extend({rgbToHex:function(array){if (this.length<3)return false;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('');},hexToRgb:function(array){if (this.length!=3)return false;var rgb=[];for(var i=0;i<3;i++){rgb.push(parseInt((this[i].length==1)?this[i]+this[i]:this[i],16));} +return array?rgb:'rgb('+rgb.join(',')+')';}});Function.extend({create:function(options){var self=this;options=$merge({'bind':self,'arguments':null,'delay':false,'periodical':false,'attempt':false,'event':false},options);return function(event){var args=$splat(options.arguments)||arguments;if (options.event)args=[event||window.event].extend(args);var returns=function(){return self.apply($pick(options.bind,self),args);};if (options.delay)return setTimeout(returns,options.delay);if (options.periodical)return setInterval(returns,options.periodical);if (options.attempt)return $try(returns);return returns();};},pass:function(args,bind){return this.create({'arguments':args,'bind':bind});},attempt:function(args,bind){return this.create({'arguments':args,'bind':bind,'attempt':true})();},bind:function(bind,args,evt){return this.create({'bind':bind,'arguments':args,'event':evt});},delay:function(delay,bind,args){return this.create({'delay':delay,'bind':bind,'arguments':args})();},periodical:function(interval,bind,args){return this.create({'periodical':interval,'bind':bind,'arguments':args})();}});Function.empty=$empty;Number.extend({toInt:function(){return parseInt(this);},toFloat:function(){return parseFloat(this);},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){for(var i=0;i';} +el=document.createElement(el);} +el=$(el);return(!props||!el)?el:el.set(props);}});var Elements=new Class({initialize:function(elements){return(elements)?$extend(elements,this):this;}});Elements.extend=function(props){for(var prop in props){this.prototype[prop]=props[prop];this[prop]=$native.generic(prop);}};function $(el){if (!el)return null;if (el.htmlElement)return Garbage.collect(el);if ([window,document].contains(el))return el;var type=$type(el);if (type=='string'){el=document.getElementById(el);type=(el)?'element':false;} +if (type!='element')return null;if (el.htmlElement)return Garbage.collect(el);if (Element.$badTags.contains(el.tagName.toLowerCase()))return el;$extend(el,Element.prototype);el.htmlElement=$empty;return Garbage.collect(el);};document.getElementsBySelector=document.getElementsByTagName;function $$(){var elements=[];for(var i=0,j=arguments.length;i0&&fKey<13)this.key='f'+fKey;} +this.key=this.key||String.fromCharCode(this.code).toLowerCase();}else if (this.type.test(/(click|mouse|menu)/)){this.page={'x':event.pageX||event.clientX+document.documentElement.scrollLeft,'y':event.pageY||event.clientY+document.documentElement.scrollTop};this.client={'x':event.pageX?event.pageX-window.pageXOffset:event.clientX,'y':event.pageY?event.pageY-window.pageYOffset:event.clientY};this.rightClick=(event.which==3)||(event.button==2);switch(this.type){case'mouseover':this.relatedTarget=event.relatedTarget||event.fromElement;break;case'mouseout':this.relatedTarget=event.relatedTarget||event.toElement;} +if (this.fixRelatedTarget.create({'bind':this,'attempt':Client.Engine.gecko})()===false)this.relatedTarget=this.target;} +return this;},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;},fixRelatedTarget:function(){if (this.relatedTarget&&this.relatedTarget.nodeType==3)this.relatedTarget=this.relatedTarget.parentNode;}});Event.keys=new Abstract({'enter':13,'up':38,'down':40,'left':37,'right':39,'esc':27,'space':32,'backspace':8,'tab':9,'delete':46});Element.$eventMethods={addEvent:function(type,fn){this.$events=this.$events||{};this.$events[type]=this.$events[type]||{'keys':[],'values':[]};if (this.$events[type].keys.contains(fn))return this;this.$events[type].keys.push(fn);var realType=type;var custom=Element.Events[type];if (custom){if (custom.add)custom.add.call(this,fn);if (custom.map)fn=custom.map;if (custom.type)realType=custom.type;} +var defn=fn;var nativeEvent=Element.$nativeEvents[realType]||0;if (nativeEvent){if (nativeEvent==2){var self=this;defn=function(event){event=new Event(event);if (fn.call(self,event)===false)event.stop();};} +this.addListener(realType,defn);} +this.$events[type].values.push(defn);return this;},removeEvent:function(type,fn){if (!this.$events||!this.$events[type])return this;var pos=this.$events[type].keys.indexOf(fn);if (pos==-1)return this;var key=this.$events[type].keys.splice(pos,1)[0];var value=this.$events[type].values.splice(pos,1)[0];var custom=Element.Events[type];if (custom){if (custom.remove)custom.remove.call(this,fn);if (custom.type)type=custom.type;} +return(Element.$nativeEvents[type])?this.removeListener(type,value):this;},addEvents:function(source){return Element.$setMany(this,'addEvent',source);},removeEvents:function(type){if (!this.$events)return this;if (!type){for(var evType in this.$events)this.removeEvents(evType);this.$events=null;}else if (this.$events[type]){this.$events[type].keys.each(function(fn){this.removeEvent(type,fn);},this);this.$events[type]=null;} +return this;},fireEvent:function(type,args,delay){if (this.$events&&this.$events[type]){this.$events[type].keys.each(function(fn){fn.create({'bind':this,'delay':delay,'arguments':args})();},this);} +return this;},cloneEvents:function(from,type){if (!from.$events)return this;if (!type){for(var evType in from.$events)this.cloneEvents(from,evType);}else if (from.$events[type]){from.$events[type].keys.each(function(fn){this.addEvent(type,fn);},this);} +return this;}};window.extend(Element.$eventMethods);document.extend(Element.$eventMethods);Element.extend(Element.$eventMethods);Element.Events=new Abstract({'mouseenter':{type:'mouseover',map:function(event){if (event.relatedTarget!=this&&!this.hasChild(event.relatedTarget))this.fireEvent('mouseenter',event);}},'mouseleave':{type:'mouseout',map:function(event){if (event.relatedTarget!=this&&!this.hasChild(event.relatedTarget))this.fireEvent('mouseleave',event);}},'mousewheel':{type:(Client.Engine.gecko)?'DOMMouseScroll':'mousewheel'}});Element.$nativeEvents={'click':2,'dblclick':2,'mouseup':2,'mousedown':2,'mousewheel':2,'DOMMouseScroll':2,'mouseover':2,'mouseout':2,'mousemove':2,'keydown':2,'keypress':2,'keyup':2,'contextmenu':2,'submit':2,'load':1,'unload':1,'beforeunload':1,'resize':1,'move':1,'DOMContentLoaded':1,'focus':1,'blur':1,'change':1,'reset':1,'select':1,'error':1,'abort':1,'scroll':1};Element.extend({scrollTo:function(x,y){this.scrollLeft=x;this.scrollTop=y;},getSize:function(){return{'scroll':{'x':this.scrollLeft,'y':this.scrollTop},'size':{'x':this.offsetWidth,'y':this.offsetHeight},'scrollSize':{'x':this.scrollWidth,'y':this.scrollHeight}};},getPosition:function(overflown){overflown=overflown||[];var el=this,left=0,top=0;do{left+=el.offsetLeft||0;top+=el.offsetTop||0;el=el.offsetParent;}while(el);overflown.each(function(element){left-=element.scrollLeft||0;top-=element.scrollTop||0;});return{'x':left,'y':top};},getTop:function(overflown){return this.getPosition(overflown).y;},getLeft:function(overflown){return this.getPosition(overflown).x;},getCoordinates:function(overflown){var position=this.getPosition(overflown);var obj={'width':this.offsetWidth,'height':this.offsetHeight,'left':position.x,'top':position.y};obj.right=obj.left+obj.width;obj.bottom=obj.top+obj.height;return obj;}});window.extend({getWidth:function(){if (Client.Engine.webkit419)return this.innerWidth;if (Client.Engine.opera)return document.body.clientWidth;return document.documentElement.clientWidth;},getHeight:function(){if (Client.Engine.webkit419)return this.innerHeight;if (Client.Engine.opera)return document.body.clientHeight;return document.documentElement.clientHeight;},getScrollWidth:function(){if (Client.Engine.ie)return Math.max(document.documentElement.offsetWidth,document.documentElement.scrollWidth);if (Client.Engine.webkit)return document.body.scrollWidth;return document.documentElement.scrollWidth;},getScrollHeight:function(){if (Client.Engine.ie)return Math.max(document.documentElement.offsetHeight,document.documentElement.scrollHeight);if (Client.Engine.webkit)return document.body.scrollHeight;return document.documentElement.scrollHeight;},getScrollLeft:function(){return this.pageXOffset||document.documentElement.scrollLeft;},getScrollTop:function(){return this.pageYOffset||document.documentElement.scrollTop;},getSize:function(){return{'size':{'x':this.getWidth(),'y':this.getHeight()},'scrollSize':{'x':this.getScrollWidth(),'y':this.getScrollHeight()},'scroll':{'x':this.getScrollLeft(),'y':this.getScrollTop()}};},getPosition:function(){return{'x':0,'y':0};}});var Fx={};Fx.Base=new Class({options:{onStart:$empty,onComplete:$empty,onCancel:$empty,transition:function(p){return-(Math.cos(Math.PI*p)-1)/2;},duration:500,unit:'px',wait:true,fps:50},initialize:function(options){this.element=this.element||null;this.setOptions(options);if (this.options.initialize)this.options.initialize.call(this);},step:function(){var time=$time();if (time + + + + + + the moobugger + + + + + + + + + + +
+

The MooBugger.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+ + + + + + \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/mootools-1.2.js b/assets/mootools-core/Tests/assets/mootools-1.2.js new file mode 100644 index 00000000..25e33a59 --- /dev/null +++ b/assets/mootools-core/Tests/assets/mootools-1.2.js @@ -0,0 +1,341 @@ +//MooTools, , My Object Oriented (JavaScript) Tools. Copyright (c) 2006-2008 Valerio Proietti, , MIT Style License. + +var MooTools={version:"1.2.0",build:""};var Native=function(J){J=J||{};var F=J.afterImplement||function(){};var G=J.generics;G=(G!==false);var H=J.legacy; +var E=J.initialize;var B=J.protect;var A=J.name;var C=E||H;C.constructor=Native;C.$family={name:"native"};if (H&&E){C.prototype=H.prototype;}C.prototype.constructor=C; +if (A){var D=A.toLowerCase();C.prototype.$family={name:D};Native.typize(C,D);}var I=function(M,K,N,L){if (!B||L||!M.prototype[K]){M.prototype[K]=N;}if (G){Native.genericize(M,K,B); +}F.call(M,K,N);return M;};C.implement=function(L,K,N){if (typeof L=="string"){return I(this,L,K,N);}for(var M in L){I(this,M,L[M],K);}return this;};C.alias=function(M,K,N){if (typeof M=="string"){M=this.prototype[M]; +if (M){I(this,K,M,N);}}else{for(var L in M){this.alias(L,M[L],K);}}return this;};return C;};Native.implement=function(D,C){for(var B=0,A=D.length;B-1:this.indexOf(A)>-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(A){return A.charAt(1).toUpperCase();});},hyphenate:function(){return this.replace(/[A-Z]/g,function(A){return("-"+A.charAt(0).toLowerCase()); +});},capitalize:function(){return this.replace(/\b[a-z]/g,function(A){return A.toUpperCase();});},escapeRegExp:function(){return this.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1"); +},toInt:function(A){return parseInt(this,A||10);},toFloat:function(){return parseFloat(this);},hexToRgb:function(B){var A=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); +return(A)?A.slice(1).hexToRgb(B):null;},rgbToHex:function(B){var A=this.match(/\d{1,3}/g);return(A)?A.rgbToHex(B):null;},stripScripts:function(B){var A=""; +var C=this.replace(/]*>([\s\S]*?)<\/script>/gi,function(){A+=arguments[1]+"\n";return"";});if (B===true){$exec(A);}else{if ($type(B)=="function"){B(A,C); +}}return C;},substitute:function(A,B){return this.replace(B||(/\\?\{([^}]+)\}/g),function(D,C){if (D.charAt(0)=="\\"){return D.slice(1);}return(A[C]!=undefined)?A[C]:""; +});}});Hash.implement({has:Object.prototype.hasOwnProperty,keyOf:function(B){for(var A in this){if (this.hasOwnProperty(A)&&this[A]===B){return A;}}return null; +},hasValue:function(A){return(Hash.keyOf(this,A)!==null);},extend:function(A){Hash.each(A,function(C,B){Hash.set(this,B,C);},this);return this;},combine:function(A){Hash.each(A,function(C,B){Hash.include(this,B,C); +},this);return this;},erase:function(A){if (this.hasOwnProperty(A)){delete this[A];}return this;},get:function(A){return(this.hasOwnProperty(A))?this[A]:null; +},set:function(A,B){if (!this[A]||this.hasOwnProperty(A)){this[A]=B;}return this;},empty:function(){Hash.each(this,function(B,A){delete this[A];},this); +return this;},include:function(B,C){var A=this[B];if (A==undefined){this[B]=C;}return this;},map:function(B,C){var A=new Hash;Hash.each(this,function(E,D){A.set(D,B.call(C,E,D,this)); +},this);return A;},filter:function(B,C){var A=new Hash;Hash.each(this,function(E,D){if (B.call(C,E,D,this)){A.set(D,E);}},this);return A;},every:function(B,C){for(var A in this){if (this.hasOwnProperty(A)&&!B.call(C,this[A],A)){return false; +}}return true;},some:function(B,C){for(var A in this){if (this.hasOwnProperty(A)&&B.call(C,this[A],A)){return true;}}return false;},getKeys:function(){var A=[]; +Hash.each(this,function(C,B){A.push(B);});return A;},getValues:function(){var A=[];Hash.each(this,function(B){A.push(B);});return A;},toQueryString:function(A){var B=[]; +Hash.each(this,function(F,E){if (A){E=A+"["+E+"]";}var D;switch($type(F)){case"object":D=Hash.toQueryString(F,E);break;case"array":var C={};F.each(function(H,G){C[G]=H; +});D=Hash.toQueryString(C,E);break;default:D=E+"="+encodeURIComponent(F);}if (F!=undefined){B.push(D);}});return B.join("&");}});Hash.alias({keyOf:"indexOf",hasValue:"contains"}); +var Event=new Native({name:"Event",initialize:function(A,F){F=F||window;var K=F.document;A=A||F.event;if (A.$extended){return A;}this.$extended=true;var J=A.type; +var G=A.target||A.srcElement;while(G&&G.nodeType==3){G=G.parentNode;}if (J.test(/key/)){var B=A.which||A.keyCode;var M=Event.Keys.keyOf(B);if (J=="keydown"){var D=B-111; +if (D>0&&D<13){M="f"+D;}}M=M||String.fromCharCode(B).toLowerCase();}else{if (J.match(/(click|mouse|menu)/i)){K=(!K.compatMode||K.compatMode=="CSS1Compat")?K.html:K.body; +var I={x:A.pageX||A.clientX+K.scrollLeft,y:A.pageY||A.clientY+K.scrollTop};var C={x:(A.pageX)?A.pageX-F.pageXOffset:A.clientX,y:(A.pageY)?A.pageY-F.pageYOffset:A.clientY}; +if (J.match(/DOMMouseScroll|mousewheel/)){var H=(A.wheelDelta)?A.wheelDelta/120:-(A.detail||0)/3;}var E=(A.which==3)||(A.button==2);var L=null;if (J.match(/over|out/)){switch(J){case"mouseover":L=A.relatedTarget||A.fromElement; +break;case"mouseout":L=A.relatedTarget||A.toElement;}if (!(function(){while(L&&L.nodeType==3){L=L.parentNode;}return true;}).create({attempt:Browser.Engine.gecko})()){L=false; +}}}}return $extend(this,{event:A,type:J,page:I,client:C,rightClick:E,wheel:H,relatedTarget:L,target:G,code:B,key:M,shift:A.shiftKey,control:A.ctrlKey,alt:A.altKey,meta:A.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;}});var Class=new Native({name:"Class",initialize:function(B){B=B||{};var A=function(E){for(var D in this){this[D]=$unlink(this[D]); +}for(var F in Class.Mutators){if (!this[F]){continue;}Class.Mutators[F](this,this[F]);delete this[F];}this.constructor=A;if (E===$empty){return this;}var C=(this.initialize)?this.initialize.apply(this,arguments):this; +if (this.options&&this.options.initialize){this.options.initialize.call(this);}return C;};$extend(A,this);A.constructor=Class;A.prototype=B;return A;}}); +Class.implement({implement:function(){Class.Mutators.Implements(this.prototype,Array.slice(arguments));return this;}});Class.Mutators={Implements:function(A,B){$splat(B).each(function(C){$extend(A,($type(C)=="class")?new C($empty):C); +});},Extends:function(self,klass){var instance=new klass($empty);delete instance.parent;delete instance.parentOf;for(var key in instance){var current=self[key],previous=instance[key]; +if (current==undefined){self[key]=previous;continue;}var ctype=$type(current),ptype=$type(previous);if (ctype!=ptype){continue;}switch(ctype){case"function":if (!arguments.callee.caller){self[key]=eval("("+String(current).replace(/\bthis\.parent\(\s*(\))?/g,function(full,close){return"arguments.callee._parent_.call(this"+(close||", "); +})+")");}self[key]._parent_=previous;break;case"object":self[key]=$merge(previous,current);}}self.parent=function(){return arguments.callee.caller._parent_.apply(this,arguments); +};self.parentOf=function(descendant){return descendant._parent_.apply(this,Array.slice(arguments,1));};}};var Chain=new Class({chain:function(){this.$chain=(this.$chain||[]).extend(arguments); +return this;},callChain:function(){return(this.$chain&&this.$chain.length)?this.$chain.shift().apply(this,arguments):false;},clearChain:function(){if (this.$chain){this.$chain.empty(); +}return this;}});var Events=new Class({addEvent:function(C,B,A){C=Events.removeOn(C);if (B!=$empty){this.$events=this.$events||{};this.$events[C]=this.$events[C]||[]; +this.$events[C].include(B);if (A){B.internal=true;}}return this;},addEvents:function(A){for(var B in A){this.addEvent(B,A[B]);}return this;},fireEvent:function(C,B,A){C=Events.removeOn(C); +if (!this.$events||!this.$events[C]){return this;}this.$events[C].each(function(D){D.create({bind:this,delay:A,"arguments":B})();},this);return this;},removeEvent:function(B,A){B=Events.removeOn(B); +if (!this.$events||!this.$events[B]){return this;}if (!A.internal){this.$events[B].erase(A);}return this;},removeEvents:function(C){for(var D in this.$events){if (C&&C!=D){continue; +}var B=this.$events[D];for(var A=B.length;A--;A){this.removeEvent(D,B[A]);}}return this;}});Events.removeOn=function(A){return A.replace(/^on([A-Z])/,function(B,C){return C.toLowerCase(); +});};var Options=new Class({setOptions:function(){this.options=$merge.run([this.options].extend(arguments));if (!this.addEvent){return this;}for(var A in this.options){if ($type(this.options[A])!="function"||!(/^on[A-Z]/).test(A)){continue; +}this.addEvent(A,this.options[A]);delete this.options[A];}return this;}});Document.implement({newElement:function(A,B){if (Browser.Engine.trident&&B){["name","type","checked"].each(function(C){if (!B[C]){return ; +}A+=" "+C+'="'+B[C]+'"';if (C!="checked"){delete B[C];}});A="<"+A+">";}return $.element(this.createElement(A)).set(B);},newTextNode:function(A){return this.createTextNode(A); +},getDocument:function(){return this;},getWindow:function(){return this.defaultView||this.parentWindow;},purge:function(){var C=this.getElementsByTagName("*"); +for(var B=0,A=C.length;B1);A.each(function(E){var F=this.getElementsByTagName(E.trim());(B)?C.extend(F):C=F;},this);return new Elements(C,{ddup:B,cash:!D}); +}});Element.Storage={get:function(A){return(this[A]||(this[A]={}));}};Element.Inserters=new Hash({before:function(B,A){if (A.parentNode){A.parentNode.insertBefore(B,A); +}},after:function(B,A){if (!A.parentNode){return ;}var C=A.nextSibling;(C)?A.parentNode.insertBefore(B,C):A.parentNode.appendChild(B);},bottom:function(B,A){A.appendChild(B); +},top:function(B,A){var C=A.firstChild;(C)?A.insertBefore(B,C):A.appendChild(B);}});Element.Inserters.inside=Element.Inserters.bottom;Element.Inserters.each(function(C,B){var A=B.capitalize(); +Element.implement("inject"+A,function(D){C(this,$(D,true));return this;});Element.implement("grab"+A,function(D){C($(D,true),this);return this;});});Element.implement({getDocument:function(){return this.ownerDocument; +},getWindow:function(){return this.ownerDocument.getWindow();},getElementById:function(D,C){var B=this.ownerDocument.getElementById(D);if (!B){return null; +}for(var A=B.parentNode;A!=this;A=A.parentNode){if (!A){return null;}}return $.element(B,C);},set:function(D,B){switch($type(D)){case"object":for(var C in D){this.set(C,D[C]); +}break;case"string":var A=Element.Properties.get(D);(A&&A.set)?A.set.apply(this,Array.slice(arguments,1)):this.setProperty(D,B);}return this;},get:function(B){var A=Element.Properties.get(B); +return(A&&A.get)?A.get.apply(this,Array.slice(arguments,1)):this.getProperty(B);},erase:function(B){var A=Element.Properties.get(B);(A&&A.erase)?A.erase.apply(this,Array.slice(arguments,1)):this.removeProperty(B); +return this;},match:function(A){return(!A||Element.get(this,"tag")==A);},inject:function(B,A){Element.Inserters.get(A||"bottom")(this,$(B,true));return this; +},wraps:function(B,A){B=$(B,true);return this.replaces(B).grab(B,A);},grab:function(B,A){Element.Inserters.get(A||"bottom")($(B,true),this);return this; +},appendText:function(B,A){return this.grab(this.getDocument().newTextNode(B),A);},adopt:function(){Array.flatten(arguments).each(function(A){A=$(A,true); +if (A){this.appendChild(A);}},this);return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;},clone:function(D,C){switch($type(this)){case"element":var H={}; +for(var G=0,E=this.attributes.length;G1),cash:!G});}});Element.implement({match:function(B){if (!B){return true;}var D=Selectors.Utils.parseTagAndID(B); +var A=D[0],E=D[1];if (!Selectors.Filters.byID(this,E)||!Selectors.Filters.byTag(this,A)){return false;}var C=Selectors.Utils.parseSelector(B);return(C)?Selectors.Utils.filter(this,C,{}):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+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)}; +Selectors.Utils={chk:function(B,C){if (!C){return true;}var A=$uid(B);if (!C[A]){return C[A]=true;}return false;},parseNthArgument:function(F){if (Selectors.Cache.nth[F]){return Selectors.Cache.nth[F]; +}var C=F.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);if (!C){return false;}var E=parseInt(C[1]);var B=(E||E===0)?E:1;var D=C[2]||false;var A=parseInt(C[3])||0; +if (B!=0){A--;while(A<1){A+=B;}while(A>=B){A-=B;}}else{B=A;D="index";}switch(D){case"n":C={a:B,b:A,special:"n"};break;case"odd":C={a:2,b:0,special:"n"}; +break;case"even":C={a:2,b:1,special:"n"};break;case"first":C={a:0,special:"index"};break;case"last":C={special:"last-child"};break;case"only":C={special:"only-child"}; +break;default:C={a:(B-1),special:"index"};}return Selectors.Cache.nth[F]=C;},parseSelector:function(E){if (Selectors.Cache.parsed[E]){return Selectors.Cache.parsed[E]; +}var D,H={classes:[],pseudos:[],attributes:[]};while((D=Selectors.RegExps.combined.exec(E))){var I=D[1],G=D[2],F=D[3],B=D[4],C=D[5],J=D[6];if (I){H.classes.push(I); +}else{if (C){var A=Selectors.Pseudo.get(C);if (A){H.pseudos.push({parser:A,argument:J});}else{H.attributes.push({name:C,operator:"=",value:J});}}else{if (G){H.attributes.push({name:G,operator:F,value:B}); +}}}}if (!H.classes.length){delete H.classes;}if (!H.attributes.length){delete H.attributes;}if (!H.pseudos.length){delete H.pseudos;}if (!H.classes&&!H.attributes&&!H.pseudos){H=null; +}return Selectors.Cache.parsed[E]=H;},parseTagAndID:function(B){var A=B.match(Selectors.RegExps.tag);var C=B.match(Selectors.RegExps.id);return[(A)?A[1]:"*",(C)?C[1]:false]; +},filter:function(F,C,E){var D;if (C.classes){for(D=C.classes.length;D--;D){var G=C.classes[D];if (!Selectors.Filters.byClass(F,G)){return false;}}}if (C.attributes){for(D=C.attributes.length; +D--;D){var B=C.attributes[D];if (!Selectors.Filters.byAttribute(F,B.name,B.operator,B.value)){return false;}}}if (C.pseudos){for(D=C.pseudos.length;D--;D){var A=C.pseudos[D]; +if (!Selectors.Filters.byPseudo(F,A.parser,A.argument,E)){return false;}}}return true;},getByTagAndID:function(B,A,D){if (D){var C=(B.getElementById)?B.getElementById(D,true):Element.getElementById(B,D,true); +return(C&&Selectors.Filters.byTag(C,A))?[C]:[];}else{return B.getElementsByTagName(A);}},search:function(J,I,O){var B=[];var C=I.trim().replace(Selectors.RegExps.splitter,function(Z,Y,X){B.push(Y); +return":)"+X;}).split(":)");var K,F,E,V;for(var U=0,Q=C.length;U":function(H,G,I,A,F){var C=Selectors.Utils.getByTagAndID(G,I,A);for(var E=0,D=C.length;EA){return false; +}}return(C==A);},even:function(B,A){return Selectors.Pseudo["nth-child"].call(this,"2n+1",A);},odd:function(B,A){return Selectors.Pseudo["nth-child"].call(this,"2n",A); +}});Element.Events.domready={onAdd:function(A){if (Browser.loaded){A.call(this);}}};(function(){var B=function(){if (Browser.loaded){return ;}Browser.loaded=true; +window.fireEvent("domready");document.fireEvent("domready");};switch(Browser.Engine.name){case"webkit":(function(){(["loaded","complete"].contains(document.readyState))?B():arguments.callee.delay(50); +})();break;case"trident":var A=document.createElement("div");(function(){($try(function(){A.doScroll("left");return $(A).inject(document.body).set("html","temp").dispose(); +}))?B():arguments.callee.delay(50);})();break;default:window.addEvent("load",B);document.addEvent("DOMContentLoaded",B);}})();var JSON=new Hash({encode:function(B){switch($type(B)){case"string":return'"'+B.replace(/[\x00-\x1f\\"]/g,JSON.$replaceChars)+'"'; +case"array":return"["+String(B.map(JSON.encode).filter($defined))+"]";case"object":case"hash":var A=[];Hash.each(B,function(E,D){var C=JSON.encode(E);if (C){A.push(JSON.encode(D)+":"+C); +}});return"{"+A+"}";case"number":case"boolean":return String(B);case false:return"null";}return null;},$specialChars:{"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},$replaceChars:function(A){return JSON.$specialChars[A]||"\\u00"+Math.floor(A.charCodeAt()/16).toString(16)+(A.charCodeAt()%16).toString(16); +},decode:function(string,secure){if ($type(string)!="string"||!string.length){return null;}if (secure&&!(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"/g,""))){return null; +}return eval("("+string+")");}});Native.implement([Hash,Array,String,Number],{toJSON:function(){return JSON.encode(this);}});var Cookie=new Class({Implements:Options,options:{path:false,domain:false,duration:false,secure:false,document:document},initialize:function(B,A){this.key=B; +this.setOptions(A);},write:function(B){B=encodeURIComponent(B);if (this.options.domain){B+="; domain="+this.options.domain;}if (this.options.path){B+="; path="+this.options.path; +}if (this.options.duration){var A=new Date();A.setTime(A.getTime()+this.options.duration*24*60*60*1000);B+="; expires="+A.toGMTString();}if (this.options.secure){B+="; secure"; +}this.options.document.cookie=this.key+"="+B;return this;},read:function(){var A=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)"); +return(A)?decodeURIComponent(A[1]):null;},dispose:function(){new Cookie(this.key,$merge(this.options,{duration:-1})).write("");return this;}});Cookie.write=function(B,C,A){return new Cookie(B,A).write(C); +};Cookie.read=function(A){return new Cookie(A).read();};Cookie.dispose=function(B,A){return new Cookie(B,A).dispose();};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(L,M){this.instance="Swiff_"+$time();this.setOptions(M);M=this.options;var B=this.id=M.id||this.instance;var A=$(M.container);Swiff.CallBacks[this.instance]={}; +var E=M.params,G=M.vars,F=M.callBacks;var H=$extend({height:M.height,width:M.width},M.properties);var K=this;for(var D in F){Swiff.CallBacks[this.instance][D]=(function(N){return function(){return N.apply(K.object,arguments); +};})(F[D]);G[D]="Swiff.CallBacks."+this.instance+"."+D;}E.flashVars=Hash.toQueryString(G);if (Browser.Engine.trident){H.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"; +E.movie=L;}else{H.type="application/x-shockwave-flash";H.data=L;}var J=''; +}}J+="";this.object=((A)?A.empty():new Element("div")).set("html",J).firstChild;},replaces:function(A){A=$(A,true);A.parentNode.replaceChild(this.toElement(),A); +return this;},inject:function(A){$(A,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(''+__flash__argumentsToXML(arguments,2)+""); +return eval(rs);};var Fx=new Class({Implements:[Chain,Events,Options],options:{fps:50,unit:false,duration:500,link:"ignore",transition:function(A){return -(Math.cos(Math.PI*A)-1)/2; +}},initialize:function(A){this.subject=this.subject||this;this.setOptions(A);this.options.duration=Fx.Durations[this.options.duration]||this.options.duration.toInt(); +var B=this.options.wait;if (B===false){this.options.link="cancel";}},step:function(){var A=$time();if (A=(7-4*B)/11){C=-Math.pow((11-6*B-11*D)/4,2)+A*A; +break;}}return C;},Elastic:function(B,A){return Math.pow(2,10*--B)*Math.cos(20*B*Math.PI*(A[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(B,A){Fx.Transitions[B]=new Fx.Transition(function(C){return Math.pow(C,[A+2]); +});});var Request=new Class({Implements:[Chain,Events,Options],options:{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},initialize:function(A){this.xhr=new Browser.Request(); +this.setOptions(A);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));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();}this.xhr.onreadystatechange=$empty;},isSuccess:function(){return((this.status>=200)&&(this.status<300)); +},processScripts:function(A){if (this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return $exec(A);}return A.stripScripts(this.options.evalScripts); +},success:function(B,A){this.onSuccess(this.processScripts(B),A);},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(A,B){this.headers.set(A,B); +return this;},getHeader:function(A){return $try(function(){return this.xhr.getResponseHeader(A);}.bind(this));},check:function(A){if (!this.running){return true; +}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(A.bind(this,Array.slice(arguments,1)));return false;}return false; +},send:function(I){if (!this.check(arguments.callee,I)){return this;}this.running=true;var G=$type(I);if (G=="string"||G=="element"){I={data:I};}var D=this.options; +I=$extend({data:D.data,url:D.url,method:D.method},I);var E=I.data,B=I.url,A=I.method;switch($type(E)){case"element":E=$(E).toQueryString();break;case"object":case"hash":E=Hash.toQueryString(E); +}if (this.options.format){var H="format="+this.options.format;E=(E)?H+"&"+E:H;}if (this.options.emulation&&["put","delete"].contains(A)){var F="_method="+A; +E=(E)?F+"&"+E:F;A="post";}if (this.options.urlEncoded&&A=="post"){var C=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers.set("Content-type","application/x-www-form-urlencoded"+C); +}if (E&&A=="get"){B=B+(B.contains("?")?"&":"?")+E;E=null;}this.xhr.open(A.toUpperCase(),B,this.options.async);this.xhr.onreadystatechange=this.onStateChange.bind(this); +this.headers.each(function(K,J){if (!$try(function(){this.xhr.setRequestHeader(J,K);return true;}.bind(this))){this.fireEvent("exception",[J,K]);}},this); +this.fireEvent("request");this.xhr.send(E);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 A={}; +["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(B){A[B]=function(){var C=Array.link(arguments,{url:String.type,data:$defined}); +return this.send($extend(C,{method:B.toLowerCase()}));};});Request.implement(A);})();Element.Properties.send={set:function(A){var B=this.retrieve("send"); +if (B){B.cancel();}return this.eliminate("send").store("send:options",$extend({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")},A)); +},get:function(A){if (A||!this.retrieve("send")){if (A||!this.retrieve("send:options")){this.set("send",A);}this.store("send",new Request(this.retrieve("send:options"))); +}return this.retrieve("send");}};Element.implement({send:function(A){var B=this.get("send");B.send({data:this,url:A||B.options.url});return this;}});Request.HTML=new Class({Extends:Request,options:{update:false,evalScripts:true,filter:false},processHTML:function(C){var B=C.match(/]*>([\s\S]*?)<\/body>/i); +C=(B)?B[1]:C;var A=new Element("div");return $try(function(){var D=""+C+"",G;if (Browser.Engine.trident){G=new ActiveXObject("Microsoft.XMLDOM"); +G.async=false;G.loadXML(D);}else{G=new DOMParser().parseFromString(D,"text/xml");}D=G.getElementsByTagName("root")[0];for(var F=0,E=D.childNodes.length; +F. Copyright (c) 2006-2008 Valerio Proietti, , MIT Style License. + +Fx.Elements=new Class({Extends:Fx.CSS,initialize:function(B,A){this.elements=this.subject=$$(B);this.parent(A);},compute:function(G,H,I){var C={};for(var D in G){var A=G[D],E=H[D],F=C[D]={}; +for(var B in A){F[B]=this.parent(A[B],E[B],I);}}return C;},set:function(B){for(var C in B){var A=B[C];for(var D in A){this.render(this.elements[C],D,A[D],this.options.unit); +}}return this;},start:function(C){if (!this.check(arguments.callee,C)){return this;}var H={},I={};for(var D in C){var F=C[D],A=H[D]={},G=I[D]={};for(var B in F){var E=this.prepare(this.elements[D],B,F[B]); +A[B]=E.from;G[B]=E.to;}}return this.parent(H,I);}});var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,modifiers:{x:"left",y:"top"}},initialize:function(){var B=Array.link(arguments,{options:Object.type,element:$defined}); +this.element=$(B.element);this.document=this.element.getDocument();this.setOptions(B.options||{});var A=$type(this.options.handle);this.handles=(A=="array"||A=="collection")?$$(this.options.handle):$(this.options.handle)||this.element; +this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.Engine.trident)?"selectstart":"mousedown";this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:$lambda(false)}; +this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start); +return this;},start:function(C){if (this.options.preventDefault){C.preventDefault();}this.fireEvent("beforeStart",this.element);this.mouse.start=C.page; +var A=this.options.limit;this.limit={x:[],y:[]};for(var D in this.options.modifiers){if (!this.options.modifiers[D]){continue;}if (this.options.style){this.value.now[D]=this.element.getStyle(this.options.modifiers[D]).toInt(); +}else{this.value.now[D]=this.element[this.options.modifiers[D]];}if (this.options.invert){this.value.now[D]*=-1;}this.mouse.pos[D]=C.page[D]-this.value.now[D]; +if (A&&A[D]){for(var B=2;B--;B){if ($chk(A[D][B])){this.limit[D][B]=$lambda(A[D][B])();}}}}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(A){if (this.options.preventDefault){A.preventDefault(); +}var B=Math.round(Math.sqrt(Math.pow(A.page.x-this.mouse.start.x,2)+Math.pow(A.page.y-this.mouse.start.y,2)));if (B>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop}); +this.fireEvent("start",this.element).fireEvent("snap",this.element);}},drag:function(A){if (this.options.preventDefault){A.preventDefault();}this.mouse.now=A.page; +for(var B in this.options.modifiers){if (!this.options.modifiers[B]){continue;}this.value.now[B]=this.mouse.now[B]-this.mouse.pos[B];if (this.options.invert){this.value.now[B]*=-1; +}if (this.options.limit&&this.limit[B]){if ($chk(this.limit[B][1])&&(this.value.now[B]>this.limit[B][1])){this.value.now[B]=this.limit[B][1];}else{if ($chk(this.limit[B][0])&&(this.value.now[B]0));this.fireEvent(C?"background":"active",[this.togglers[D],E]); +for(var F in this.effects){B[D][F]=C?0:E[this.effects[F]];}},this);return this.start(B);}}); \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/posteditor.js b/assets/mootools-core/Tests/assets/posteditor.js new file mode 100644 index 00000000..9fae13db --- /dev/null +++ b/assets/mootools-core/Tests/assets/posteditor.js @@ -0,0 +1,453 @@ +/* +Script: postEditor.js + Using postEditor you can tabulate without losing your focus and maintain the tabsize in line brakes. + You can also use snippets like in TextMate. + +Dependencies: + + +Author: + Daniel Mota aka IceBeat, + +Contributors: + Sergio Álvarez aka Xergio, + Jordi Rivero aka Godsea, + +License: + MIT-style license. +*/ + +/* +Class: PostEditor + The base class of the postEditor. + +Arguments: + el - required. the textarea $(element) to apply postEditor. + next - optional. the $(element) to apply the next tab (shift+enter). + options - optional. The options object. + +Options: + snippets - optional, Snippets like in TextMate. + smartTypingPairs - optional, smartTypingPairs. + selections - optional, functions to execute with selections. +*/ + +var PostEditor = new Class({ + + tab: "\t", + + setOptions: function(options){ + this.options = $merge({ + snippets : {}, + smartTypingPairs : {}, + selections : {} + }, options || {}); + }, + + initialize: function(el, options){ + if (Browser.Engine.trident) return; + this.element = $(el); + this.setOptions(options); + this.styles = { + line_height: this.element.getStyle('line-height').toInt() || 14, + font_size: this.element.getStyle('font-size').toInt() || 11, + height: this.element.getStyle('height').toInt() + }; + this.autoTab = null; + this.ssKey = 0; + this.seKey = 0; + this.completion = null; + this.tabl = this.tab.length; + this.element.onkeypress = this.onKeyPress.bind(this); + }, + + changeSnippets: function(snippets){ + this.options.snippets = snippets || {}; + }, + + changeSmartTypingPairs: function(smartTypingPairs){ + this.options.smartTypingPairs = smartTypingPairs || {}; + }, + + changeSelections: function(selections){ + this.options.selections = selections || {}; + }, + + ss: function(){ + return this.element.selectionStart; + }, + + se: function(){ + return this.element.selectionEnd; + }, + + slice: function(start, end){ + return this.element.value.slice(start, end); + }, + + value: function(value){ + this.element.value = value.join(""); + }, + + getStart: function(rest){ + rest = rest ? rest.length : 0; + return this.slice(0, this.ss() - rest); + }, + + getEnd: function(rest){ + rest = rest ? rest.length : 0; + return this.element.value.slice(this.se()-rest); + }, + + selectRange: function(start,end){ + this.element.selectionStart = start; + this.element.selectionEnd = start+end; + }, + + focus: function(focus, type){ + if (type){ + this.scrollTop = this.element.scrollTop; + this.scrollLeft = this.element.scrollLeft; + } else { + this.element.scrollTop = this.scrollTop; + this.element.scrollLeft = this.scrollLeft; + } + if (focus) this.element.focus(); + }, + + updateScroll: function(){ + var lines = this.getStart().split("\n").length; + var height = (lines - Math.round(this.element.scrollTop/this.styles.line_height)) * this.styles.line_height; + height += this.styles.line_height; + if (height >= this.styles.height) this.element.scrollTop += this.styles.line_height; + this.focus(true, 1); + }, + + onKeyPress: function(e){ + if (this.filterByPairs(e)) return; + this.filterBySelect(e); + if (this.filterByTab(e)) return; + if ([13,9,8,46].contains(e.keyCode)) this.focus(false, true); + switch(e.keyCode){ + case 27: + this.completion = null; + this.autoTab = null; break; + case 39: this.onKeyRight(e); break; + case 13: this.onEnter(e); break; + case 9: this.onTab(e); break; + case 8: this.onBackspace(e); break; + case 46: this.onDelete(e); break; + } + if ([13,9,8,46].contains(e.keyCode)) this.focus(true, false); + }, + + filterByPairs: function(e){ + var charCode = String.fromCharCode(e.charCode); + var stpair = this.options.smartTypingPairs[charCode]; + if (stpair){ + if ($type(stpair) == 'string') stpair = {pair : stpair}; + if (!stpair.scope || this.scope(stpair.scope)){ + var ss = this.ss(), se = this.se(), start = this.getStart(); + if (ss == se){ + this.value([start,stpair.pair,this.getEnd()]); + this.selectRange(start.length,0); + } else { + e.preventDefault(); + this.ssKey = ss; + this.seKey = se; + this.value([start,charCode,this.slice(ss,se),stpair.pair,this.getEnd()]); + this.selectRange(ss+1,se-ss); + } + } + stpair = null; + return true; + } + return false; + }, + + filterBySelect: function(e){ + var charCode = String.fromCharCode(e.charCode); + if (e.ctrlKey && e.shiftKey){ + if ([0,1,2,3,4,5,6,7,8,9].contains(charCode)){ + var fn = this.options.selections[charCode]; + if (fn){ + var ss = this.ss(), se = this.se(), + sel = fn.apply(this, [this.slice(ss,se)]); + if (sel){ + var start = this.getStart(); + if ($type(sel) == 'array'){ + this.value([start,sel.join(""),this.getEnd()]); + this.selectRange(start.length+sel[0].length,sel[1].length); + } else { + if (sel.selection){ + if (sel.snippet){ + start = this.slice(0,sel.selection[0]); + var end = this.slice(sel.selection[1],this.element.value.length); + this.value([start,sel.snippet.join(""),end]); + this.selectRange(start.length+sel.snippet[0].length,sel.snippet[1].length); + } else { + this.selectRange(sel.selection[0],sel.selection[1]); + } + } else { + this.value([start,sel.snippet.join(""),this.getEnd()]); + this.selectRange(start.length+sel.snippet[0].length,sel.snippet[1].length); + } + } + } + } + } + } + }, + + filterByTab: function(e){ + if (this.autoTab){ + var ss = this.ss(); + var se = this.se() + var key = this.ssKey; + var end = this.seKey; + if (![key + 1,key,key - 1, end].contains(ss)){ + this.completion = null; + this.autoTab = null; + } + if (this.autoTab && [38, 39].contains(e.keyCode) && ss == se){ + this.completion = null; + this.autoTab = null; + } + this.ssKey = ss; + this.seKey = se; + } else { + this.ssKey = 0; + this.seKey = 0; + } + return false; + }, + + scope: function(scopes){ + var ss = this.ss(); + var text = this.getStart(); + for (var key in scopes){ + if (!key) return true; + var open = text.lastIndexOf(key); + if (open > -1){ + var close = this.slice(open + key.length, ss).lastIndexOf(scopes[key]); + if (close == -1) return true; + } + } + return false; + }, + + onKeyRight: function(e){ + var ss = this.ss(); + var se = this.se(); + var start = this.getStart(); + if (ss != se){ + e.preventDefault(); + this.selectRange(se, 0); + } + }, + + onEnter: function(e){ + this.updateScroll(); + var ss = this.ss(); + var se = this.se(); + var start = this.getStart(); + if (ss == se){ + var line = start.split("\n").pop(), + tab = line.match(/^\s+/gi); + if (tab){ + e.preventDefault(); + tab = tab.join(""); + this.value([start,"\n",tab,this.getEnd()]); + this.selectRange(ss + 1 + tab.length,0); + } + } + }, + + onBackspace: function(e){ + var ss = this.ss(); + var se = this.se(); + if (ss == se && this.slice(ss - this.tabl, ss) == this.tab){ + e.preventDefault(); + var start = this.getStart(this.tab), end = this.slice(ss, this.element.value.length); + if (start.match(/\n$/g) && end.match(/^\n/g)){ + this.value([start, this.slice(ss - 1, this.element.value.length)]); + } else { + this.value([start, end]); + } + this.selectRange(ss - this.tabl, 0); + } else if (ss == se){ + var charCode = this.slice(ss - 1, ss), + close = this.slice(ss,ss+1), + stpair = this.options.smartTypingPairs[charCode]; + if ($type(stpair) == 'string') stpair = {pair : stpair}; + if (stpair && stpair.pair == close){ + this.value([this.getStart(stpair.pair), this.slice(ss, this.element.value.length)]); + this.selectRange(ss,0); + } + } + }, + + onDelete: function(e){ + var ss = this.ss(), se = this.se(); + if (ss == se && this.slice(ss,ss+this.tabl) == this.tab){ + e.preventDefault(); + this.value([this.getStart(),this.slice(ss+this.tabl,this.element.value.length)]); + this.selectRange(ss,0); + } + }, + + onTab: function(e){ + e.preventDefault(); + var ss = this.ss(), se = this.se(), sel = this.slice(ss,se), text = this.getStart(); + if (this.filterCompletion(e, ss, se)) return; + if (this.filterAutoTab(e, ss, se)) return; + + if (ss != se && sel.indexOf("\n") != -1){ + var newsel = sel.replace(/\n/g,"\n" + this.tab); + this.value([text,this.tab,newsel,this.getEnd()]); + this.selectRange(ss + this.tabl,se + (this.tabl * sel.split("\n").length) - ss - this.tabl); + } else { + var snippetObj = null; + for (var key in this.options.snippets){ + var value = this.options.snippets[key]; + if ($type(value) == 'function') continue; + if (text.length-key.length==-1) continue; + if (text.length-key.length==text.lastIndexOf(key)){ + if ($type(value) == 'array') value = { snippet:value }; + snippetObj = Object.extend({},value); + break; + } + } + if (snippetObj && (!snippetObj.scope || this.scope(snippetObj.scope))){ + + if (snippetObj.command){ + var command = snippetObj.command.apply(this, [key]); + if ($type(command) == 'array') snippetObj.snippet = command; + else snippetObj = command; + } + + var snippet = snippetObj.snippet.copy(), tab = text.split("\n").pop().match(/^\s+/gi); + var start = this.getStart(snippetObj.key || key); + + if (tab){ + tab = tab.join(""); + snippet[0] = snippet[0].replace(/\n/g,"\n"+tab); + snippet[1] = snippet[1].replace(/\n/g,"\n"+tab); + snippet[2] = snippet[2].replace(/\n/g,"\n"+tab); + } + + this.value([start, snippet[0], snippet[1], snippet[2], this.getEnd()]); + + if (snippetObj.tab){ + + this.autoTab = { + tab: snippetObj.tab.copy(), + snippet: snippet.copy(), + start: snippetObj.start + }; + + var item = this.autoTab.tab.shift(); + this.autoTab.ss = snippet[1].indexOf(item); + + if (this.autoTab.ss > -1){ + this.autoTab.ssLast = start.length + snippet[0].length + this.autoTab.ss; + this.ssKey = this.autoTab.ssLast; + this.seKey = this.ssKey + item.length; + this.completion = null; + if (snippetObj.completion){ + this.autoTab.completion = snippetObj.completion; + this.autoTab.item = item; + this.autoTab.loop = true; + if (typeof snippetObj.loop == 'boolean') this.autoTab.loop = snippetObj.loop; + var completion = this.autoTab.completion[item]; + if (completion){ + var i = [item].extend(completion); + var a = completion.copy().extend(['']); + this.autoTab.index = item; + this.completion = a.associate(i); + } + } + this.selectRange(start.length + snippet[0].length + this.autoTab.ss, item.length); + + } else { + this.autoTab = null; + this.selectRange(start.length + snippet[0].length, snippet[1].length); + } + } else { + this.selectRange(start.length + snippet[0].length,snippet[1].length); + } + snippet = null; + } else { + this.value([text,this.tab,this.slice(ss, this.element.value.length)]); + if (ss == se) this.selectRange(ss + this.tabl,0); + else this.selectRange(ss + this.tabl,se - ss); + } + } + }, + + filterAutoTab: function(e,ss,se){ + if (this.autoTab){ + var length = this.autoTab.tab.length; + if (length){ + if (this.autoTab.ssLast <= ss){ + var item = this.autoTab.tab.shift(); + var next = this.slice(ss, ss + this.autoTab.snippet[1].length - this.autoTab.ss).indexOf(item); + if (length == 1 && !item){ + var end = this.autoTab.snippet[2].length; + if ($type(this.autoTab.start) == 'number') end = this.autoTab.start; + else if (this.autoTab.start) end = 0; + this.selectRange(se + this.getEnd().indexOf(this.autoTab.snippet[2])+end,0); + this.completion = null; + return true; + } else if (next > -1){ + this.autoTab.ss = next; + this.autoTab.ssLast = next + ss; + this.ssKey = this.autoTab.ssLast; + this.seKey = this.ssKey + item.length; + this.autoTab.item = item; + if (this.completion){ + var completion = this.autoTab.completion[item]; + if (completion){ + var i = [item].extend(completion); + var a = completion.copy().extend(['']); + this.autoTab.index = item; + this.completion = a.associate(i); + } else { + this.completion = null; + } + } + this.selectRange(ss + next,item.length); + return true; + } else { + this.onTab(e); + return true; + } + } + } + this.autoTab = null; + } + return false; + }, + + filterCompletion: function(e,ss,se){ + if (this.completion && ss == this.ssKey && se == this.seKey && this.autoTab.item.length == se - ss){ + var item = this.completion[this.autoTab.item]; + if (item){ + this.seKey = this.ssKey + item.length; + this.autoTab.item = item; + this.value([this.getStart(),item,this.getEnd()]); + this.selectRange(ss, item.length); + return true; + } else if (this.autoTab.loop){ + item = this.autoTab.index; + this.autoTab.item = item; + this.seKey = this.ssKey + item.length; + this.value([this.getStart(), item,this.getEnd()]); + this.selectRange(ss, item.length); + return true; + } + } + this.completion = null; + return false; + } +}); \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/radio.checked.gif b/assets/mootools-core/Tests/assets/radio.checked.gif new file mode 100644 index 00000000..7925deb3 Binary files /dev/null and b/assets/mootools-core/Tests/assets/radio.checked.gif differ diff --git a/assets/mootools-core/Tests/assets/radio.unchecked.gif b/assets/mootools-core/Tests/assets/radio.unchecked.gif new file mode 100644 index 00000000..60177298 Binary files /dev/null and b/assets/mootools-core/Tests/assets/radio.unchecked.gif differ diff --git a/assets/mootools-core/Tests/assets/showdown.js b/assets/mootools-core/Tests/assets/showdown.js new file mode 100644 index 00000000..d6b18745 --- /dev/null +++ b/assets/mootools-core/Tests/assets/showdown.js @@ -0,0 +1,1296 @@ +// +// showdown.js -- A javascript port of Markdown. +// +// Copyright (c) 2007 John Fraser. +// +// Original Markdown Copyright (c) 2004-2005 John Gruber +// +// +// Redistributable under a BSD-style open source license. +// See license.txt for more information. +// +// The full source distribution is at: +// +// A A L +// T C A +// T K B +// +// +// + +// +// Wherever possible, Showdown is a straight, line-by-line port +// of the Perl version of Markdown. +// +// This is not a normal parser design; it's basically just a +// series of string substitutions. It's hard to read and +// maintain this way, but keeping Showdown close to the original +// design makes it easier to port new features. +// +// More importantly, Showdown behaves like markdown.pl in most +// edge cases. So web applications can do client-side preview +// in Javascript, and then build identical HTML on the server. +// +// This port needs the new RegExp functionality of ECMA 262, +// 3rd Edition (i.e. Javascript 1.5). Most modern web browsers +// should do fine. Even with the new regular expression features, +// We do a lot of work to emulate Perl's regex functionality. +// The tricky changes in this file mostly have the "attacklab:" +// label. Major or self-explanatory changes don't. +// +// Smart diff tools like Araxis Merge will be able to match up +// this file with markdown.pl in a useful way. A little tweaking +// helps: in a copy of markdown.pl, replace "#" with "//" and +// replace "$text" with "text". Be sure to ignore whitespace +// and line endings. +// + + +// +// Showdown usage: +// +// var text = "Markdown *rocks*."; +// +// var converter = new Showdown.converter(); +// var html = converter.makeHtml(text); +// +// alert(html); +// +// Note: move the sample code to the bottom of this +// file before uncommenting it. +// + + +// +// Showdown namespace +// +var Showdown = {}; + +// +// converter +// +// Wraps all "globals" so that the only thing +// exposed is makeHtml(). +// +Showdown.converter = function(){ + +// +// Globals: +// + +// Global hashes, used by various utility routines +var g_urls; +var g_titles; +var g_html_blocks; + +// Used to track when we're inside an ordered or unordered list +// (see _ProcessListItems() for details): +var g_list_level = 0; + + +this.makeHtml = function(text){ +// +// Main function. The order in which other subs are called here is +// essential. Link and image substitutions need to happen before +// _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the +// and tags get encoded. +// + + // Clear the global hashes. If we don't clear these, you get conflicts + // from other articles when generating a page which contains more than + // one article (e.g. an index page that shows the N most recent + // articles): + g_urls = new Array(); + g_titles = new Array(); + g_html_blocks = new Array(); + + // attacklab: Replace ~ with ~T + // This lets us use tilde as an escape char to avoid md5 hashes + // The choice of character is arbitray; anything that isn't + // magic in Markdown will work. + text = text.replace(/~/g,"~T"); + + // attacklab: Replace $ with ~D + // RegExp interprets $ as a special character + // when it's in a replacement string + text = text.replace(/\$/g,"~D"); + + // Standardize line endings + text = text.replace(/\r\n/g,"\n"); // DOS to Unix + text = text.replace(/\r/g,"\n"); // Mac to Unix + + // Make sure text begins and ends with a couple of newlines: + text = "\n\n" + text + "\n\n"; + + // Convert all tabs to spaces. + text = _Detab(text); + + // Strip any lines consisting only of spaces and tabs. + // This makes subsequent regexen easier to write, because we can + // match consecutive blank lines with /\n+/ instead of something + // contorted like /[ \t]*\n+/ . + text = text.replace(/^[ \t]+$/mg,""); + + // Turn block-level HTML blocks into hash entries + text = _HashHTMLBlocks(text); + + // Strip link definitions, store in hashes. + text = _StripLinkDefinitions(text); + + text = _RunBlockGamut(text); + + text = _UnescapeSpecialChars(text); + + // attacklab: Restore dollar signs + text = text.replace(/~D/g,"$$"); + + // attacklab: Restore tildes + text = text.replace(/~T/g,"~"); + + return text; +} + + +var _StripLinkDefinitions = function(text){ +// +// Strips link definitions from text, stores the URLs and titles in +// hash references. +// + + // Link defs are in the form: ^[id]: url "optional title" + + /* + var text = text.replace(/ + ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1 + [ \t]* + \n? // maybe *one* newline + [ \t]* + ? // url = $2 + [ \t]* + \n? // maybe one newline + [ \t]* + (?: + (\n*) // any lines skipped = $3 attacklab: lookbehind removed + ["(] + (.+?) // title = $4 + [")] + [ \t]* + )? // title is optional + (?:\n+|$) + /gm, + function(){...}); + */ + var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm, + function (wholeMatch,m1,m2,m3,m4){ + m1 = m1.toLowerCase(); + g_urls[m1] = _EncodeAmpsAndAngles(m2); // Link IDs are case-insensitive + if (m3){ + // Oops, found blank lines, so it's not a title. + // Put back the parenthetical statement we stole. + return m3+m4; + } else if (m4){ + g_titles[m1] = m4.replace(/"/g,"""); + } + + // Completely remove the definition from the text + return ""; + } + ); + + return text; +} + + +var _HashHTMLBlocks = function(text){ + // attacklab: Double up blank lines to reduce lookaround + text = text.replace(/\n/g,"\n\n"); + + // Hashify HTML blocks: + // We only want to do this for block-level HTML tags, such as headers, + // lists, and tables. That's because we still want to wrap

s around + // "paragraphs" that are wrapped in non-block-level tags, such as anchors, + // phrase emphasis, and spans. The list of tags we're looking for is + // hard-coded: + var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del" + var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math" + + // First, look for nested blocks, e.g.: + //

+ //
+ // tags for inner block must be indented. + //
+ //
+ // + // The outermost tags must start at the left margin for this to match, and + // the inner nested divs must be indented. + // We need to do this before the next, more liberal match, because the next + // match will start at the first `
` and stop at the first `
`. + + // attacklab: This regex can be expensive when it fails. + /* + var text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_a) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*?\n // any number of lines, minimally matching + // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,hashElement); + + // + // Now match more liberally, simply from `\n` to `\n` + // + + /* + var text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_b) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*? // any number of lines, minimally matching + .* // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,hashElement); + + // Special case just for
. It was easier to make a special case than + // to make the other regex more complicated. + + /* + text = text.replace(/ + ( // save in $1 + \n\n // Starting after a blank line + [ ]{0,3} + (<(hr) // start tag = $2 + \b // word break + ([^<>])*? // + \/?>) // the matching end tag + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,hashElement); + + // Special case for standalone HTML comments: + + /* + text = text.replace(/ + ( // save in $1 + \n\n // Starting after a blank line + [ ]{0,3} // attacklab: g_tab_width - 1 + + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(\n\n[ ]{0,3}[ \t]*(?=\n{2,}))/g,hashElement); + + // PHP and ASP-style processor instructions ( and <%...%>) + + /* + text = text.replace(/ + (?: + \n\n // Starting after a blank line + ) + ( // save in $1 + [ ]{0,3} // attacklab: g_tab_width - 1 + (?: + <([?%]) // $2 + [^\r]*? + \2> + ) + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,hashElement); + + // attacklab: Undo double lines (see comment at top of this function) + text = text.replace(/\n\n/g,"\n"); + return text; +} + +var hashElement = function(wholeMatch,m1){ + var blockText = m1; + + // Undo double lines + blockText = blockText.replace(/\n\n/g,"\n"); + blockText = blockText.replace(/^\n/,""); + + // strip trailing blank lines + blockText = blockText.replace(/\n+$/g,""); + + // Replace the element text with a marker ("~KxK" where x is its key) + blockText = "\n\n~K" + (g_html_blocks.push(blockText)-1) + "K\n\n"; + + return blockText; +}; + +var _RunBlockGamut = function(text){ +// +// These are all the transformations that form block-level +// tags like paragraphs, headers, and list items. +// + text = _DoHeaders(text); + + // Do Horizontal Rules: + var key = hashBlock("
"); + text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key); + text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key); + text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key); + + text = _DoLists(text); + text = _DoCodeBlocks(text); + text = _DoBlockQuotes(text); + + // We already ran _HashHTMLBlocks() before, in Markdown(), but that + // was to escape raw HTML in the original Markdown source. This time, + // we're escaping the markup we've just created, so that we don't wrap + //

tags around block-level tags. + text = _HashHTMLBlocks(text); + text = _FormParagraphs(text); + + return text; +} + + +var _RunSpanGamut = function(text){ +// +// These are all the transformations that occur *within* block-level +// tags like paragraphs, headers, and list items. +// + + text = _DoCodeSpans(text); + text = _EscapeSpecialCharsWithinTagAttributes(text); + text = _EncodeBackslashEscapes(text); + + // Process anchor and image tags. Images must come first, + // because ![foo][f] looks like an anchor. + text = _DoImages(text); + text = _DoAnchors(text); + + // Make links out of things like `` + // Must come after _DoAnchors(), because you can use < and > + // delimiters in inline links like [this](). + text = _DoAutoLinks(text); + text = _EncodeAmpsAndAngles(text); + text = _DoItalicsAndBold(text); + + // Do hard breaks: + text = text.replace(/ +\n/g,"
\n"); + + return text; +} + +var _EscapeSpecialCharsWithinTagAttributes = function(text){ +// +// Within tags -- meaning between < and > -- encode [\ ` * _] so they +// don't conflict with their use in Markdown for code, italics and strong. +// + + // Build a regex to find HTML tags and comments. See Friedl's + // "Mastering Regular Expressions", 2nd Ed., pp. 200-201. + var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)/gi; + + text = text.replace(regex, function(wholeMatch){ + var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`"); + tag = escapeCharacters(tag,"\\`*_"); + return tag; + }); + + return text; +} + +var _DoAnchors = function(text){ +// +// Turn Markdown link shortcuts into XHTML
tags. +// + // + // First, handle reference-style links: [link text] [id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[] // or anything else + )* + ) + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + )()()()() // pad remaining backreferences + /g,_DoAnchors_callback); + */ + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeAnchorTag); + + // + // Next, inline-style links: [link text](url "optional title") + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[\]] // or anything else + ) + ) + \] + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + ? // href = $4 + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // Title = $7 + \6 // matching quote + [ \t]* // ignore any spaces/tabs between closing quote and ) + )? // title is optional + \) + ) + /g,writeAnchorTag); + */ + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag); + + // + // Last, handle reference-style shortcuts: [link text] + // These must come last in case you've also got [link test][1] + // or [link test](/foo) + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ([^\[\]]+) // link text = $2; can't contain '[' or ']' + \] + )()()()()() // pad rest of backreferences + /g, writeAnchorTag); + */ + text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag); + + return text; +} + +var writeAnchorTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7){ + if (m7 == undefined) m7 = ""; + var whole_match = m1; + var link_text = m2; + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (url == ""){ + if (link_id == ""){ + // lower-case and turn embedded newlines into spaces + link_id = link_text.toLowerCase().replace(/ ?\n/g," "); + } + url = "#"+link_id; + + if (g_urls[link_id] != undefined){ + url = g_urls[link_id]; + if (g_titles[link_id] != undefined){ + title = g_titles[link_id]; + } + } + else { + if (whole_match.search(/\(\s*\)$/m)>-1){ + // Special case for explicit empty url + url = ""; + } else { + return whole_match; + } + } + } + + url = escapeCharacters(url,"*_"); + var result = ""; + + return result; +} + + +var _DoImages = function(text){ +// +// Turn Markdown image shortcuts into tags. +// + + // + // First, handle reference-style labeled images: ![alt text][id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + )()()()() // pad rest of backreferences + /g,writeImageTag); + */ + text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeImageTag); + + // + // Next, handle inline images: ![alt text](url "optional title") + // Don't forget: encode * and _ + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + \s? // One optional whitespace character + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + ? // src url = $4 + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // title = $7 + \6 // matching quote + [ \t]* + )? // title is optional + \) + ) + /g,writeImageTag); + */ + text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeImageTag); + + return text; +} + +var writeImageTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7){ + var whole_match = m1; + var alt_text = m2; + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (!title) title = ""; + + if (url == ""){ + if (link_id == ""){ + // lower-case and turn embedded newlines into spaces + link_id = alt_text.toLowerCase().replace(/ ?\n/g," "); + } + url = "#"+link_id; + + if (g_urls[link_id] != undefined){ + url = g_urls[link_id]; + if (g_titles[link_id] != undefined){ + title = g_titles[link_id]; + } + } + else { + return whole_match; + } + } + + alt_text = alt_text.replace(/"/g,"""); + url = escapeCharacters(url,"*_"); + var result = "\""" + _RunSpanGamut(m1) + "");}); + + text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm, + function(matchFound,m1){return hashBlock("

" + _RunSpanGamut(m1) + "

");}); + + // atx-style headers: + // # Header 1 + // ## Header 2 + // ## Header 2 with closing hashes ## + // ... + // ###### Header 6 + // + + /* + text = text.replace(/ + ^(\#{1,6}) // $1 = string of #'s + [ \t]* + (.+?) // $2 = Header text + [ \t]* + \#* // optional closing #'s (not counted) + \n+ + /gm, function(){...}); + */ + + text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm, + function(wholeMatch,m1,m2){ + var h_level = m1.length; + return hashBlock("" + _RunSpanGamut(m2) + ""); + }); + + return text; +} + +// This declaration keeps Dojo compressor from outputting garbage: +var _ProcessListItems; + +var _DoLists = function(text){ +// +// Form HTML ordered (numbered) and unordered (bulleted) lists. +// + + // attacklab: add sentinel to hack around khtml/safari bug: + // http://bugs.webkit.org/show_bug.cgi?id=11231 + text += "~0"; + + // Re-usable pattern to match any entirel ul or ol list: + + /* + var whole_list = / + ( // $1 = whole list + ( // $2 + [ ]{0,3} // attacklab: g_tab_width - 1 + ([*+-]|\d+[.]) // $3 = first list item marker + [ \t]+ + ) + [^\r]+? + ( // $4 + ~0 // sentinel for workaround; should be $ + | + \n{2,} + (?=\S) + (?! // Negative lookahead for another list item marker + [ \t]* + (?:[*+-]|\d+[.])[ \t]+ + ) + ) + )/g + */ + var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; + + if (g_list_level){ + text = text.replace(whole_list,function(wholeMatch,m1,m2){ + var list = m1; + var list_type = (m2.search(/[*+-]/g)>-1) ? "ul" : "ol"; + + // Turn double returns into triple returns, so that we can make a + // paragraph for the last item in a list, if necessary: + list = list.replace(/\n{2,}/g,"\n\n\n");; + var result = _ProcessListItems(list); + + // Trim any trailing whitespace, to put the closing `` + // up on the preceding line, to get it past the current stupid + // HTML block parser. This is a hack to work around the terrible + // hack that is the HTML block parser. + result = result.replace(/\s+$/,""); + result = "<"+list_type+">" + result + "\n"; + return result; + }); + } else { + whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g; + text = text.replace(whole_list,function(wholeMatch,m1,m2,m3){ + var runup = m1; + var list = m2; + + var list_type = (m3.search(/[*+-]/g)>-1) ? "ul" : "ol"; + // Turn double returns into triple returns, so that we can make a + // paragraph for the last item in a list, if necessary: + var list = list.replace(/\n{2,}/g,"\n\n\n");; + var result = _ProcessListItems(list); + result = runup + "<"+list_type+">\n" + result + "\n"; + return result; + }); + } + + // attacklab: strip sentinel + text = text.replace(/~0/,""); + + return text; +} + +_ProcessListItems = function(list_str){ +// +// Process the contents of a single ordered or unordered list, splitting it +// into individual list items. +// + // The $g_list_level global keeps track of when we're inside a list. + // Each time we enter a list, we increment it; when we leave a list, + // we decrement. If it's zero, we're not in a list anymore. + // + // We do this because when we're not inside a list, we want to treat + // something like this: + // + // I recommend upgrading to version + // 8. Oops, now this line is treated + // as a sub-list. + // + // As a single paragraph, despite the fact that the second line starts + // with a digit-period-space sequence. + // + // Whereas when we're inside a list (or sub-list), that line will be + // treated as the start of a sub-list. What a kludge, huh? This is + // an aspect of Markdown's syntax that's hard to parse perfectly + // without resorting to mind-reading. Perhaps the solution is to + // change the syntax rules such that sub-lists must start with a + // starting cardinal number; e.g. "1." or "a.". + + g_list_level++; + + // trim trailing blank lines: + list_str = list_str.replace(/\n{2,}$/,"\n"); + + // attacklab: add sentinel to emulate \z + list_str += "~0"; + + /* + list_str = list_str.replace(/ + (\n)? // leading line = $1 + (^[ \t]*) // leading whitespace = $2 + ([*+-]|\d+[.]) [ \t]+ // list marker = $3 + ([^\r]+? // list item text = $4 + (\n{1,2})) + (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+)) + /gm, function(){...}); + */ + list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm, + function(wholeMatch,m1,m2,m3,m4){ + var item = m4; + var leading_line = m1; + var leading_space = m2; + + if (leading_line || (item.search(/\n{2,}/)>-1)){ + item = _RunBlockGamut(_Outdent(item)); + } + else { + // Recursion for sub-lists: + item = _DoLists(_Outdent(item)); + item = item.replace(/\n$/,""); // chomp(item) + item = _RunSpanGamut(item); + } + + return "
  • " + item + "
  • \n"; + } + ); + + // attacklab: strip sentinel + list_str = list_str.replace(/~0/g,""); + + g_list_level--; + return list_str; +} + + +var _DoCodeBlocks = function(text){ +// +// Process Markdown `
    ` blocks.
    +//  
    +
    +	/*
    +		text = text.replace(text,
    +			/(?:\n\n|^)
    +			(								// $1 = the code block -- one or more lines, starting with a space/tab
    +				(?:
    +					(?:[ ]{4}|\t)			// Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
    +					.*\n+
    +				)+
    +			)
    +			(\n*[ ]{0,3}[^ \t\n]|(?=~0))	// attacklab: g_tab_width
    +		/g,function(){...});
    +	*/
    +
    +	// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
    +	text += "~0";
    +	
    +	text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
    +		function(wholeMatch,m1,m2){
    +			var codeblock = m1;
    +			var nextChar = m2;
    +		
    +			codeblock = _EncodeCode( _Outdent(codeblock));
    +			codeblock = _Detab(codeblock);
    +			codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines
    +			codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace
    +
    +			codeblock = "
    " + codeblock + "\n
    "; + + return hashBlock(codeblock) + nextChar; + } + ); + + // attacklab: strip sentinel + text = text.replace(/~0/,""); + + return text; +} + +var hashBlock = function(text){ + text = text.replace(/(^\n+|\n+$)/g,""); + return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n"; +} + + +var _DoCodeSpans = function(text){ +// +// * Backtick quotes are used for spans. +// +// * You can use multiple backticks as the delimiters if you want to +// include literal backticks in the code span. So, this input: +// +// Just type ``foo `bar` baz`` at the prompt. +// +// Will translate to: +// +//

    Just type foo `bar` baz at the prompt.

    +// +// There's no arbitrary limit to the number of backticks you +// can use as delimters. If you need three consecutive backticks +// in your code, use four for delimiters, etc. +// +// * You can use spaces to get literal backticks at the edges: +// +// ... type `` `bar` `` ... +// +// Turns to: +// +// ... type `bar` ... +// + + /* + text = text.replace(/ + (^|[^\\]) // Character before opening ` can't be a backslash + (`+) // $2 = Opening run of ` + ( // $3 = The code block + [^\r]*? + [^`] // attacklab: work around lack of lookbehind + ) + \2 // Matching closer + (?!`) + /gm, function(){...}); + */ + + text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, + function(wholeMatch,m1,m2,m3,m4){ + var c = m3; + c = c.replace(/^([ \t]*)/g,""); // leading whitespace + c = c.replace(/[ \t]*$/g,""); // trailing whitespace + c = _EncodeCode(c); + return m1+""+c+""; + }); + + return text; +} + + +var _EncodeCode = function(text){ +// +// Encode/escape certain characters inside Markdown code runs. +// The point is that in code, these characters are literals, +// and lose their special Markdown meanings. +// + // Encode all ampersands; HTML entities are not + // entities within a Markdown code span. + text = text.replace(/&/g,"&"); + + // Do the angle bracket song and dance: + text = text.replace(//g,">"); + + // Now, escape characters that are magic in Markdown: + text = escapeCharacters(text,"\*_{}[]\\",false); + +// jj the line above breaks this: +//--- + +//* Item + +// 1. Subitem + +// special char: * +//--- + + return text; +} + + +var _DoItalicsAndBold = function(text){ + + // must go first: + text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, + "$2"); + + text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, + "$2"); + + return text; +} + + +var _DoBlockQuotes = function(text){ + + /* + text = text.replace(/ + ( // Wrap whole match in $1 + ( + ^[ \t]*>[ \t]? // '>' at the start of a line + .+\n // rest of the first line + (.+\n)* // subsequent consecutive lines + \n* // blanks + )+ + ) + /gm, function(){...}); + */ + + text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, + function(wholeMatch,m1){ + var bq = m1; + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + bq = bq.replace(/^[ \t]*>[ \t]?/gm,"~0"); // trim one level of quoting + + // attacklab: clean up hack + bq = bq.replace(/~0/g,""); + + bq = bq.replace(/^[ \t]+$/gm,""); // trim whitespace-only lines + bq = _RunBlockGamut(bq); // recurse + + bq = bq.replace(/(^|\n)/g,"$1 "); + // These leading spaces screw with
     content, so we need to fix that:
    +			bq = bq.replace(
    +					/(\s*
    [^\r]+?<\/pre>)/gm,
    +				function(wholeMatch,m1){
    +					var pre = m1;
    +					// attacklab: hack around Konqueror 3.5.4 bug:
    +					pre = pre.replace(/^  /mg,"~0");
    +					pre = pre.replace(/~0/g,"");
    +					return pre;
    +				});
    +			
    +			return hashBlock("
    \n" + bq + "\n
    "); + }); + return text; +} + + +var _FormParagraphs = function(text){ +// +// Params: +// $text - string to process with html

    tags +// + + // Strip leading and trailing lines: + text = text.replace(/^\n+/g,""); + text = text.replace(/\n+$/g,""); + + var grafs = text.split(/\n{2,}/g); + var grafsOut = new Array(); + + // + // Wrap

    tags. + // + var end = grafs.length; + for (var i=0; i= 0){ + grafsOut.push(str); + } + else if (str.search(/\S/) >= 0){ + str = _RunSpanGamut(str); + str = str.replace(/^([ \t]*)/g,"

    "); + str += "

    " + grafsOut.push(str); + } + + } + + // + // Unhashify HTML blocks + // + end = grafsOut.length; + for (var i=0; i= 0){ + var blockText = g_html_blocks[RegExp.$1]; + blockText = blockText.replace(/\$/g,"$$$$"); // Escape any dollar signs + grafsOut[i] = grafsOut[i].replace(/~K\d+K/,blockText); + } + } + + return grafsOut.join("\n\n"); +} + + +var _EncodeAmpsAndAngles = function(text){ +// Smart processing for ampersands and angle brackets that need to be encoded. + + // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: + // http://bumppo.net/projects/amputator/ + text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"); + + // Encode naked <'s + text = text.replace(/<(?![a-z\/?\$!])/gi,"<"); + + return text; +} + + +var _EncodeBackslashEscapes = function(text){ +// +// Parameter: String. +// Returns: The string, with after processing the following backslash +// escape sequences. +// + + // attacklab: The polite way to do this is with the new + // escapeCharacters() function: + // + // text = escapeCharacters(text,"\\",true); + // text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); + // + // ...but we're sidestepping its use of the (slow) RegExp constructor + // as an optimization for Firefox. This function gets called a LOT. + + text = text.replace(/\\(\\)/g,escapeCharacters_callback); + text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g,escapeCharacters_callback); + return text; +} + + +var _DoAutoLinks = function(text){ + + text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"
    $1"); + + // Email addresses: + + /* + text = text.replace(/ + < + (?:mailto:)? + ( + [-.\w]+ + \@ + [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+ + ) + > + /gi, _DoAutoLinks_callback()); + */ + text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, + function(wholeMatch,m1){ + return _EncodeEmailAddress( _UnescapeSpecialChars(m1) ); + } + ); + + return text; +} + + +var _EncodeEmailAddress = function(addr){ +// +// Input: an email address, e.g. "foo@example.com" +// +// Output: the email address as a mailto link, with each character +// of the address encoded as either a decimal or hex entity, in +// the hopes of foiling most address harvesting spam bots. E.g.: +// +// foo +// @example.com +// +// Based on a filter by Matthew Wickline, posted to the BBEdit-Talk +// mailing list: +// + + // attacklab: why can't javascript speak hex? + function char2hex(ch){ + var hexDigits = '0123456789ABCDEF'; + var dec = ch.charCodeAt(0); + return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15)); + } + + var encode = [ + function(ch){return "&#"+ch.charCodeAt(0)+";";}, + function(ch){return "&#x"+char2hex(ch)+";";}, + function(ch){return ch;} + ]; + + addr = "mailto:" + addr; + + addr = addr.replace(/./g, function(ch){ + if (ch == "@"){ + // this *must* be encoded. I insist. + ch = encode[Math.floor(Math.random()*2)](ch); + } else if (ch !=":"){ + // leave ':' alone (to spot mailto: later) + var r = Math.random(); + // roughly 10% raw, 45% hex, 45% dec + ch = ( + r > .9 ? encode[2](ch) : + r > .45 ? encode[1](ch) : + encode[0](ch) + ); + } + return ch; + }); + + addr = "" + addr + ""; + addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part + + return addr; +} + + +var _UnescapeSpecialChars = function(text){ +// +// Swap back in all the special characters we've hidden. +// + text = text.replace(/~E(\d+)E/g, + function(wholeMatch,m1){ + var charCodeToReplace = parseInt(m1); + return String.fromCharCode(charCodeToReplace); + } + ); + return text; +} + + +var _Outdent = function(text){ +// +// Remove one level of line-leading tabs or spaces +// + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + text = text.replace(/^(\t|[ ]{1,4})/gm,"~0"); // attacklab: g_tab_width + + // attacklab: clean up hack + text = text.replace(/~0/g,"") + + return text; +} + +var _Detab = function(text){ +// attacklab: Detab's completely rewritten for speed. +// In perl we could fix it by anchoring the regexp with \G. +// In javascript we're less fortunate. + + // expand first n-1 tabs + text = text.replace(/\t(?=\t)/g," "); // attacklab: g_tab_width + + // replace the nth with two sentinels + text = text.replace(/\t/g,"~A~B"); + + // use the sentinel to anchor our regex so it doesn't explode + text = text.replace(/~B(.+?)~A/g, + function(wholeMatch,m1,m2){ + var leadingText = m1; + var numSpaces = 4 - leadingText.length % 4; // attacklab: g_tab_width + + // there *must* be a better way to do this: + for (var i=0; i + +picker box + + + + +
    +

    caption

    +
    +
    + Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. +
    +
    +
    +
    + + + \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/stickyWinHTML/top.gif b/assets/mootools-core/Tests/assets/stickyWinHTML/top.gif new file mode 100644 index 00000000..815810cf Binary files /dev/null and b/assets/mootools-core/Tests/assets/stickyWinHTML/top.gif differ diff --git a/assets/mootools-core/Tests/assets/stickyWinHTML/top.png b/assets/mootools-core/Tests/assets/stickyWinHTML/top.png new file mode 100644 index 00000000..d90882b2 Binary files /dev/null and b/assets/mootools-core/Tests/assets/stickyWinHTML/top.png differ diff --git a/assets/mootools-core/Tests/assets/tests.css b/assets/mootools-core/Tests/assets/tests.css new file mode 100644 index 00000000..56a5cf71 --- /dev/null +++ b/assets/mootools-core/Tests/assets/tests.css @@ -0,0 +1,219 @@ +/* -- Clear Fix -- */ +.clearfix:after {content: "."; display: block; height: 0; clear: both; visibility: hidden;} +.clearfix {display: inline-table;} +/* Hides from IE-mac \*/ +* html .clearfix {height: 1%;} +.clearfix {display: block;} +/* End hide from IE-mac */ +body { + font-family: verdana; + font-size: 10px; + font: 11px/1.5 Lucida Grande, Helvetica, Arial, sans-serif; + background: #F3F1F1; + color: #41464D; +} +dl { + position: relative; +} + +#title { + width: 100%; + padding: 5px 0; + background: #aaa; + background: #41464D; + color: #F3F1F1; + height: 30px; +} +#title h1 { + font: 25px/1.1 Arial, sans-serif; + font-weight: bolder; + margin: 1px 0 2px 20px; + text-shadow: 0 2px 2px rgba(0,0,0,0.4); +} + +#title h1 span { + color: #D2E0E6; +} + +#title a { + color: #fff; + text-decoration: none; + font-size: 14px; + position: relative; + top: -2px; +} + +#testBox { + width: 1100px; + text-align: left; + position: relative; +} +#testFrameContainer { + float: left; + width: 403px; + margin-left: 10px; +} +#testFrame { + border: 1px solid black; + width: 400px; + height: 450px; + margin-top: 5px; +} +#script { + width: 400px; + float: left; + height: 600px; + overflow: auto; + border-bottom: 1px solid #ddd; + color: #000; + margin-top: 5px; + border-left: none; +} +#testLoader { + width: 200px; + float: left; +} +#testLoader dl { + margin: 4px 12px 0px 0px; + height: 577px; + overflow: auto; + width: 200px; +} +#testLoader dl * { + width: 170px; +} +#testLoader h4 { + margin: 4px 0px; +} +#testLoader dt { + margin: 4px 0px 3px; + padding: 2px 2px 2px 4px; + cursor: pointer; + background: #D2E0E6; + color: #528CE0; + font-size: 12px; + font-weight: bold; +} +#testLoader dt:hover { + color: #41464D; +} +#testLoader dd { + margin: 2px 0px 2px 2px; + padding: 2px 2px 2px 7px; + background: #D0C8C8; + color: #8A7575; + font-size: 12px; + font-weight: bold; + cursor: pointer; +} +#testLoader dd.selected, #testLoader dt.selected { + background-color: #fdfbd0; + color: #9b9828; +} +#tests .selected { + background-color: #fdfbd0 !important; +} +#testLoader .exception { + color: #B33F3F !important; + background: #EE9A9A !important; +} +#testLoader .success { + background-color: #CFE773 !important; + color: #657528 !important; +} +#runTest { + position: absolute; + right: 0px; +} +#testTemplate { + display: none; +} +#tests { + width: 370px; + padding-left: 10px; +} +#tests dt { + padding: 2px 8px 4px; + border-bottom: 1px solid #d0d0d0; + position: relative; +} +#tests dt b { + cursor: pointer; +} +dt button { + position: absolute; + right: 8px; + top: -2px; +} +#tests dd { + margin: 0px 7px 0px; + overflow: hidden; +} +textarea { + width: 342px; + padding: 4px; + height: 25px; +} +#testFrameContainer textarea { + width: 391px; + height: 100px; +} +div.handle { + width: 353px; + height: 4px; + position: relative; + top: -1px; + left: -1px; + border-top: #fff 1px solid; + border-left: #fff 1px solid; + border-right: #999 1px solid; + border-bottom: #999 1px solid; + background: #ccc; + cursor: n-resize; +} +#testFrameContainer div.handle { + width: 402px; +} + +div.handle:hover { + background: #fcfcfc; +} +#tests div.verify { + display: none; +} +#tests div.verify a.pass, #tests div.verify a.fail { + float: left; + display: block; + cursor: pointer; + padding: 2px 15px; + background: url(radio.unchecked.gif) 2px 1px no-repeat; +} +#tests div.passed div.verify a.pass, #tests div.failed div.verify a.fail { + background: url(radio.checked.gif) 2px 1px no-repeat; +} +#tests div.verify p { + margin-bottom: 0px; +} +#tests div.verify div.actions { + padding-left: 10px; +} +#tests div.testBlock { + border: 1px solid #d0d0d0; + background: #f5f5f5; + padding: 6px 0px 6px; + margin-bottom: 12px; +} +#tests div.passed { + background: #eafed8 +} +#tests div.failed { + background: #feede7; +} + +body.test_iframe { + background: #fff; +} + +body.test_iframe h1 { + font-size: 14px; +} \ No newline at end of file diff --git a/assets/mootools-core/Tests/assets/waiter/waiter.gif b/assets/mootools-core/Tests/assets/waiter/waiter.gif new file mode 100644 index 00000000..53dd589f Binary files /dev/null and b/assets/mootools-core/Tests/assets/waiter/waiter.gif differ diff --git a/assets/mootools-core/Tests/config.js b/assets/mootools-core/Tests/config.js new file mode 100644 index 00000000..bcde0e00 --- /dev/null +++ b/assets/mootools-core/Tests/config.js @@ -0,0 +1,14 @@ +UnitTester.site = 'MooTools Core'; +UnitTester.title = 'Unit Tests'; + +window.addEvent('load', function(){ + var sources = { + mootoolsCore: '../' + }; + + new UnitTester(sources, { + 'mootools-core': 'UserTests/' + }, { + autoplay: true + }); +}); diff --git a/assets/mootools-core/Tests/index.html b/assets/mootools-core/Tests/index.html new file mode 100644 index 00000000..a4ef7577 --- /dev/null +++ b/assets/mootools-core/Tests/index.html @@ -0,0 +1,70 @@ + + + + Unit Tester + + + + + + + + + + + + + +
    +

    +
    + readme » +
    + +

    +
    +
    +
    +
    +

    Load tests:

    +
    +
    +
    +
    + +
    + manual code entry: +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    {title}
    +
    +

    {description}

    + +
    +
    +

    {verify}

    +
    + yes + no +
    +
    +
    +
    + + \ No newline at end of file diff --git a/assets/mootools-core/Tests/readme.html b/assets/mootools-core/Tests/readme.html new file mode 100644 index 00000000..9cacd85f --- /dev/null +++ b/assets/mootools-core/Tests/readme.html @@ -0,0 +1,95 @@ + + + + MooTools Unit Test Framework Documentation + + + + + + + + + +
    +
    +

    + + MooTools Unit Test Framework Documentation +

    +
    +
    +
    + + +
    +
    + + diff --git a/assets/mootools-core/Tests/readme.md b/assets/mootools-core/Tests/readme.md new file mode 100644 index 00000000..6d8828f7 --- /dev/null +++ b/assets/mootools-core/Tests/readme.md @@ -0,0 +1,169 @@ +The MooTools Unit Test Framework +================================ + +### Author & Contact + +Aaron Newton (aaron [ at ] iminta <dot> com) + +### Download + +This framework can be downloaded from Google's svn servers: + +[http://code.google.com/p/clientside-test-framework][] + +Overview +-------- + +### Purpose + +MooTools ships with a version of JSSpec ([http://jania.pe.kr/aw/moin.cgi/JSSpec][]) and a series of Specs tests. This test framework is excellent at verifying that code that immediately produces an output is working. It can test, for example, that 2+2 does equal 4. + +It is not, however, very good at evaluating any type of code that has a delay between the execution of a code block and the production of a result. This includes Ajax requests, animations and other transitions, or interfaces that require a user to interact with the test (such as Drag). + +### The Unit Test Framework + +The MooTools Unit Test Framework aims to create an environment where developers can utilize test driven development patterns to develop their code as well as use those tests to regress their changes. Tests are easy to write and easy to verify by non-coders. Users are given a simple task ("Drag the box around") and a question to answer ("Can you drag it around?"). Answering yes marks the test as having passed. Answering no marks it as having failed. + + +### Environment + +The test framework itself is written with MooTools 1.2, but it can test any javascript code. It creates a "vanilla" iframe with only three javascript values defined: *dbug*, *$exec*, and *$LoadScript* (more on these in a bit). + +When a test is loaded, the dependencies for that test are loaded into the iframe synchronously along with the HTML portion of the test. This allows the developer to do several things: + + * Test the dependency map of their code base. This uses the MooTools scripts.json to map dependencies; more than one scripts.json can be used (so long as the file names are all unique - so only one "Core.js" please). + * Test only the code needed to run the test. Rather than including a full build of all their code, they can include on the parts that, in theory, are needed to run the test. + * Quickly introduce changes and test again. Developers can edit their source files and run the test again without reloading their browsers. + +### Running Tests + +The framework comes with a Firebug-like interface (Moobugger) for testing with browsers that are not equipped with with Firebug. Tests produce output into the debugger to show the user that test are loading and are ready. Additionally, tests themselves can send output directly to the debugger for the user to inspect. + +### User Entry + +The test framework allows for users to run their own code in the iframe via a text area under the test frame. This facilitates debugging the current test environment. The author of individual tests can also choose to expose a portion of or all of an individual test as editable code that the user can alter at test time. + +Authoring Tests +--------------- + +### tests.json + +The test framework loads a menu of available tests based on a file called tests.json found in the UserTests subdirectory. This subdirectory should mirror the Source directory of your repository, though it does not have to have directories for every directory in the Source directory. In other words, if you wish to only test on script in a repository that has several directories (Core, Request, Element, etc) you can only have the one you need (say, Request). + +*tests.json* describes the tests that should be loaded. + +#### Example + + { + "Foo":{ + "Bar": ['a','b','c'] + } + } + +#### File Mapping + +The above tests.json would load a menu with a "Foo" section and a test group called "Bar". Clicking on "Bar" would expand to show the tests for "a", "b", and "c". This would specifically test *Source/Foo/Bar.js* and load its dependencies as defined in *Source/scripts.json*. + +The actual javascript test file would therefore be located at *UserTests/Foo/Bar.a.js* and the HTML file for the test would be located at *UserTests/Foo/Bar.a.html*. + +### Single Tests vs. Break-outs + +Tests can be written as a single test file for a given script (as defined in Scripts.json) or as a series of tests. This is accomplished by naming conventions of the test files. If you give a test the name "all" then clicking the test name will not expand to show sub-tests but will instead just load the single test defined. + +#### Single Test in tests.json + + { + "Foo":{ + "Bar": ['all'] + } + } + +This would load *Source/Foo/Bar.js* and its dependencies just as before, but it would load *UserTests/Foo/Bar.all.js* and *Bar.all.html* instead of expanding a list of sub-tests. + +### Test Files + +Test files come in pairs: the javascript which is used to load the test and the accompanying HTML (which can be empty if no HTML is required, but must exist). + +#### HTML and paths + +The HTML can be anything. Note that its source location is that of the iframe's, which is the same path as the test suite. So if your test is at http://foo/tests/ then the iframe's base url is also at that location. You can use relative locations to refer to other files on your system (such as ../../bar.jpg) though it is not recommended as it makes your tests less portable. It is recommended that any assets that accompany your tests be located along side your test files. So if your test needs to reference "x.jpg" that you put it in the same location as the test files and refer to it as *UserTests/Foo/x.jpg*. + + +#### In-line JavaScript and domReady +HTML parts can contain in-line JavaScript inside of <script> tags. This code will be evaluated *after* your HTML body and dependencies have loaded. Note that this means that you cannot refer to *onload* in your inline code, as the document will already be loaded when your code is evaluated. You should assume that your inline code will be evaluated after the document is ready. *domReady* is fired manually for those dependencies that load that refer to it, but your inline code need not use it. + +#### Test Javascript Files + +Each test comes with HTML and a JavaScript configuration file. These files look like this: + + { + tests: [ + { + title: "Your Test Title", + description: "A brief description of this test.", + verify: "Verification question to ask the user - did the test work?", + before: function(){ + //code to execute when the user starts the test + }, + body: "//User editable JavaScript run after *before* and before *post*", + post: function(){ + //code to execute immediately after the *before* test above; + //if this returns a "falsy" value, the test will fail immediately + //before the user does anything else + } + } + ], + otherScripts: ["SomeOtherFileToLoad"] + } + +The *tests* array is an array of objects that contain test configurations. This allows you to pose more than one question to the user for a given test or to put more than one test in a given file. + +Each test has the following properties: + + * title - (*string*) the title of the test; this is displayed to the user before they run the test. + * description - (*string*) a brief (one sentence is best) description of the test; this is also displayed + before the test is run. + * verify - (*string*) a question that the user must answer after they run the test. The question must be + a yes/no question and answering it *yes* signals that the test succeeded. This is only displayed after + the user starts the test. + * before - (*function*; optional) this code is run immediately when the test is started. If it throw an error, the + test will fail immediately. + * body - (*string*; optional) this code is evaluated when the user runs the test after the *before* method if it is defined. This is user-editable so this string is displayed to them for them to change if they like. If this code throws an error the test + will fail immediately. + * post - (*function*; optional) this code is run immediately after the *body* code is evaluated (if it's defined). + If this code throws an error or returns a 'falsy' value the test will fail immediately. + +In addition to the tests, the test author can define additional scripts that should be loaded. This will include any missing dependencies for that script as well. This is useful if you're testing something that, say, doesn't require *Selector.js*, but you want to use *Selectors* for your test. This property is an array of script names assigned to the property *otherScripts*. + +Configuration +------------- + +The test framework must be configured for each environment in which it runs. All that is required is that the file *config.js* be altered for your environment. This amounts to initializing the *UnitTester* class with any options you choose to specify. + + window.addEvent('load', function(){ + new UnitTester(scripts, tests); + }); + +### Arguments + +1. sources - (*object*) a set of name/value pairs for the locations of scripts.json files for dependency mapping +2. tests - (*object*) a set of name/value pairs for the locations of tests.json files to load + +### Example + + window.addEvent('load', function(){ + new UnitTester({ + mootoolsCore: '../svn/Mootools/mootools-core', + mootoolsMore: '../svn/Mootools/mootools-more' + },{ + defaultTests: './UserTests/' + }); + }); + +Local Testing +------------- + +The framework is designed to work from the desktop or from a server, but it definitely works better from a server. Some browsers (FF3 in particular) won't allow you to request local files due to security settings. Safari will allow it and IE will prompt you to allow it. It is possible to work around this in FF3, but it's better to serve the tests from a server when possible. + +[http://jania.pe.kr/aw/moin.cgi/JSSpec]: http://jania.pe.kr/aw/moin.cgi/JSSpec +[http://code.google.com/p/clientside-test-framework]: http://code.google.com/p/clientside-test-framework \ No newline at end of file diff --git a/assets/mootools-core/Tests/test_frame.html b/assets/mootools-core/Tests/test_frame.html new file mode 100644 index 00000000..167474b4 --- /dev/null +++ b/assets/mootools-core/Tests/test_frame.html @@ -0,0 +1,43 @@ + + + + Unit Test Runner + + + + + + + + \ No newline at end of file diff --git a/assets/mootools-core/build.rb b/assets/mootools-core/build.rb new file mode 100755 index 00000000..8937f2a8 --- /dev/null +++ b/assets/mootools-core/build.rb @@ -0,0 +1,98 @@ +#!/usr/bin/env ruby + +# USAGE: +# +# Full: +# ./build.rb +# +# Fx.Tween, DomReady including all dependencies: +# ./build.rb Fx.Tween DomReady + +require 'rubygems' +require 'json' + +module MooTools + class Build + + attr_reader :included + attr_accessor :build_path + attr_accessor :dependency_path + + def initialize(path = File.dirname(__FILE__)) + @path = path + @scripts = [] + @included = [] + @data = {} + + @build_path ||= @path + '/mootools.js' + @dependency_path ||= @path + '/Source/scripts.json' + + json = JSON.load(File.read( dependency_path )) + json.each_pair do |folder, group| + group.each_pair do |script, properties| + @data[script] = {:folder => folder, :deps => properties["deps"]} + end + end + end + + def full_build + @data.each_key { |name| load_script name } + @string + end + + def load_script(name) + return if @included.index(name) || name == 'None'; + unless @data.key? name + puts "Script '#{name}' not found!" + throw :script_not_found + end + @included.push name + @data[name][:deps].each { |dep| load_script dep } + @string ||= "" + @string << File.read(@path + "/Source/#{@data[name][:folder]}/#{name}.js") << "\n" + end + + def build + @string ||= full_build + @string.sub!('%build%', build_number) + end + alias :to_s :build + + def build_number + ref = File.read(File.dirname(__FILE__) + '/.git/HEAD').chomp.match(/ref: (.*)/)[1] + return File.read(File.dirname(__FILE__) + "/.git/#{ref}").chomp + end + + def save(filename) + File.open(filename, 'w') { |fh| fh.write to_s } + end + + def save! + save build_path + end + + def self.build!(argv) + mootools = MooTools::Build.new + + catch :script_not_found do + if argv.length > 0 + argv.each { |script| mootools.load_script(script) } + else + mootools.full_build + end + end + + puts "MooTools Built '#{mootools.build_path}'" + print " Included Scripts:","\n " + puts mootools.included.join(" ") + mootools.save! + + end + + end +end +if __FILE__ == $0 + + MooTools::Build.build! ARGV + +end