From f461ea41c9557bfdd5258cbe9ed6119bc82d8185 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Sat, 21 Nov 2009 13:00:11 +0000 Subject: [PATCH 01/44] * Starting to work on the new specs for MooTools-Core --- {Specs => OldSpecs}/Assets/Scripts/Builder.js | 0 .../Assets/Scripts/DiffMatchPatch.js | 0 {Specs => OldSpecs}/Assets/Scripts/JSSpec.js | 0 .../Assets/Scripts/JSSpecSpecs.js | 0 {Specs => OldSpecs}/Assets/Styles/Specs.css | 0 {Specs => OldSpecs}/Class/Class.Extras.js | 0 {Specs => OldSpecs}/Class/Class.js | 0 {Specs => OldSpecs}/Core/Browser.js | 0 {Specs => OldSpecs}/Core/Core.js | 0 .../Element/Element.Dimensions.js | 0 {Specs => OldSpecs}/Element/Element.Style.js | 0 {Specs => OldSpecs}/Element/Element.js | 0 {Specs => OldSpecs}/Native/Array.js | 0 {Specs => OldSpecs}/Native/Function.js | 0 {Specs => OldSpecs}/Native/Hash.js | 0 {Specs => OldSpecs}/Native/Number.js | 0 {Specs => OldSpecs}/Native/String.js | 0 .../Plugins/Selectors.Children.js | 0 {Specs => OldSpecs}/Utilities/Color.js | 0 {Specs => OldSpecs}/Utilities/Selectors.js | 0 {Specs => OldSpecs}/Utilities/index.html | 0 {Specs => OldSpecs}/application.xml | 0 {Specs => OldSpecs}/demo.html | 0 OldSpecs/index.html | 45 + Specs/1.2public/Class/Class.Extras.js | 288 +++ Specs/1.2public/Class/Class.js | 274 +++ Specs/1.2public/Core/Browser.js | 40 + Specs/1.2public/Core/Core.js | 443 ++++ Specs/1.2public/Element/Element.Dimensions.js | 120 + Specs/1.2public/Element/Element.Style.js | 73 + Specs/1.2public/Element/Element.js | 1565 ++++++++++++ Specs/1.2public/Native/Array.js | 207 ++ Specs/1.2public/Native/Function.js | 155 ++ Specs/1.2public/Native/Hash.js | 203 ++ Specs/1.2public/Native/Number.js | 114 + Specs/1.2public/Native/String.js | 158 ++ .../1.2public/Utilities/Selectors.Children.js | 61 + Specs/MooToolsSpecLoader.js | 68 + Specs/SlickSpec/JSSpec.css | 245 ++ Specs/SlickSpec/JSSpec.js | 1553 ++++++++++++ Specs/SlickSpec/JSSpecHelpers.js | 308 +++ Specs/SlickSpec/diff_match_patch.js | 2136 +++++++++++++++++ Specs/SlickSpec/getgetter.js | 63 + Specs/SlickSpec/ie.css | 37 + Specs/SlickSpec/moobugger/bookmarklet.html | 46 + Specs/SlickSpec/moobugger/debugger-iframe.js | 386 +++ Specs/SlickSpec/moobugger/debugger.css | 190 ++ Specs/SlickSpec/moobugger/debugger.html | 25 + Specs/SlickSpec/moobugger/debugger.js | 284 +++ Specs/SlickSpec/moobugger/images/close.png | Bin 0 -> 508 bytes Specs/SlickSpec/moobugger/images/error.png | Bin 0 -> 671 bytes .../moobugger/images/group-close.png | Bin 0 -> 304 bytes .../SlickSpec/moobugger/images/group-open.png | Bin 0 -> 351 bytes Specs/SlickSpec/moobugger/images/icon.png | Bin 0 -> 647 bytes Specs/SlickSpec/moobugger/images/info.png | Bin 0 -> 674 bytes Specs/SlickSpec/moobugger/images/lick.png | Bin 0 -> 285 bytes Specs/SlickSpec/moobugger/images/max.png | Bin 0 -> 488 bytes Specs/SlickSpec/moobugger/images/min.png | Bin 0 -> 409 bytes Specs/SlickSpec/moobugger/images/mootools.png | Bin 0 -> 3769 bytes Specs/SlickSpec/moobugger/images/time.png | Bin 0 -> 616 bytes Specs/SlickSpec/moobugger/images/warning.png | Bin 0 -> 691 bytes Specs/SlickSpec/moobugger/test.html | 88 + Specs/SlickSpec/screen.css | 259 ++ Specs/SlickSpec/simple_request.js | 39 + Specs/SlickSpec/slickspec.css | 366 +++ Specs/index.html | 104 +- Specs/runner.html | 67 + 67 files changed, 9965 insertions(+), 45 deletions(-) rename {Specs => OldSpecs}/Assets/Scripts/Builder.js (100%) rename {Specs => OldSpecs}/Assets/Scripts/DiffMatchPatch.js (100%) rename {Specs => OldSpecs}/Assets/Scripts/JSSpec.js (100%) rename {Specs => OldSpecs}/Assets/Scripts/JSSpecSpecs.js (100%) rename {Specs => OldSpecs}/Assets/Styles/Specs.css (100%) rename {Specs => OldSpecs}/Class/Class.Extras.js (100%) rename {Specs => OldSpecs}/Class/Class.js (100%) rename {Specs => OldSpecs}/Core/Browser.js (100%) rename {Specs => OldSpecs}/Core/Core.js (100%) rename {Specs => OldSpecs}/Element/Element.Dimensions.js (100%) rename {Specs => OldSpecs}/Element/Element.Style.js (100%) rename {Specs => OldSpecs}/Element/Element.js (100%) rename {Specs => OldSpecs}/Native/Array.js (100%) rename {Specs => OldSpecs}/Native/Function.js (100%) rename {Specs => OldSpecs}/Native/Hash.js (100%) rename {Specs => OldSpecs}/Native/Number.js (100%) rename {Specs => OldSpecs}/Native/String.js (100%) rename {Specs => OldSpecs}/Plugins/Selectors.Children.js (100%) rename {Specs => OldSpecs}/Utilities/Color.js (100%) rename {Specs => OldSpecs}/Utilities/Selectors.js (100%) rename {Specs => OldSpecs}/Utilities/index.html (100%) rename {Specs => OldSpecs}/application.xml (100%) rename {Specs => OldSpecs}/demo.html (100%) create mode 100644 OldSpecs/index.html create mode 100644 Specs/1.2public/Class/Class.Extras.js create mode 100644 Specs/1.2public/Class/Class.js create mode 100644 Specs/1.2public/Core/Browser.js create mode 100644 Specs/1.2public/Core/Core.js create mode 100644 Specs/1.2public/Element/Element.Dimensions.js create mode 100644 Specs/1.2public/Element/Element.Style.js create mode 100644 Specs/1.2public/Element/Element.js create mode 100644 Specs/1.2public/Native/Array.js create mode 100644 Specs/1.2public/Native/Function.js create mode 100644 Specs/1.2public/Native/Hash.js create mode 100644 Specs/1.2public/Native/Number.js create mode 100644 Specs/1.2public/Native/String.js create mode 100644 Specs/1.2public/Utilities/Selectors.Children.js create mode 100644 Specs/MooToolsSpecLoader.js create mode 100755 Specs/SlickSpec/JSSpec.css create mode 100755 Specs/SlickSpec/JSSpec.js create mode 100644 Specs/SlickSpec/JSSpecHelpers.js create mode 100755 Specs/SlickSpec/diff_match_patch.js create mode 100644 Specs/SlickSpec/getgetter.js create mode 100644 Specs/SlickSpec/ie.css create mode 100644 Specs/SlickSpec/moobugger/bookmarklet.html create mode 100644 Specs/SlickSpec/moobugger/debugger-iframe.js create mode 100644 Specs/SlickSpec/moobugger/debugger.css create mode 100644 Specs/SlickSpec/moobugger/debugger.html create mode 100644 Specs/SlickSpec/moobugger/debugger.js create mode 100644 Specs/SlickSpec/moobugger/images/close.png create mode 100644 Specs/SlickSpec/moobugger/images/error.png create mode 100644 Specs/SlickSpec/moobugger/images/group-close.png create mode 100644 Specs/SlickSpec/moobugger/images/group-open.png create mode 100644 Specs/SlickSpec/moobugger/images/icon.png create mode 100644 Specs/SlickSpec/moobugger/images/info.png create mode 100644 Specs/SlickSpec/moobugger/images/lick.png create mode 100644 Specs/SlickSpec/moobugger/images/max.png create mode 100644 Specs/SlickSpec/moobugger/images/min.png create mode 100644 Specs/SlickSpec/moobugger/images/mootools.png create mode 100644 Specs/SlickSpec/moobugger/images/time.png create mode 100644 Specs/SlickSpec/moobugger/images/warning.png create mode 100644 Specs/SlickSpec/moobugger/test.html create mode 100644 Specs/SlickSpec/screen.css create mode 100644 Specs/SlickSpec/simple_request.js create mode 100755 Specs/SlickSpec/slickspec.css create mode 100644 Specs/runner.html diff --git a/Specs/Assets/Scripts/Builder.js b/OldSpecs/Assets/Scripts/Builder.js similarity index 100% rename from Specs/Assets/Scripts/Builder.js rename to OldSpecs/Assets/Scripts/Builder.js diff --git a/Specs/Assets/Scripts/DiffMatchPatch.js b/OldSpecs/Assets/Scripts/DiffMatchPatch.js similarity index 100% rename from Specs/Assets/Scripts/DiffMatchPatch.js rename to OldSpecs/Assets/Scripts/DiffMatchPatch.js diff --git a/Specs/Assets/Scripts/JSSpec.js b/OldSpecs/Assets/Scripts/JSSpec.js similarity index 100% rename from Specs/Assets/Scripts/JSSpec.js rename to OldSpecs/Assets/Scripts/JSSpec.js diff --git a/Specs/Assets/Scripts/JSSpecSpecs.js b/OldSpecs/Assets/Scripts/JSSpecSpecs.js similarity index 100% rename from Specs/Assets/Scripts/JSSpecSpecs.js rename to OldSpecs/Assets/Scripts/JSSpecSpecs.js diff --git a/Specs/Assets/Styles/Specs.css b/OldSpecs/Assets/Styles/Specs.css similarity index 100% rename from Specs/Assets/Styles/Specs.css rename to OldSpecs/Assets/Styles/Specs.css diff --git a/Specs/Class/Class.Extras.js b/OldSpecs/Class/Class.Extras.js similarity index 100% rename from Specs/Class/Class.Extras.js rename to OldSpecs/Class/Class.Extras.js diff --git a/Specs/Class/Class.js b/OldSpecs/Class/Class.js similarity index 100% rename from Specs/Class/Class.js rename to OldSpecs/Class/Class.js diff --git a/Specs/Core/Browser.js b/OldSpecs/Core/Browser.js similarity index 100% rename from Specs/Core/Browser.js rename to OldSpecs/Core/Browser.js diff --git a/Specs/Core/Core.js b/OldSpecs/Core/Core.js similarity index 100% rename from Specs/Core/Core.js rename to OldSpecs/Core/Core.js diff --git a/Specs/Element/Element.Dimensions.js b/OldSpecs/Element/Element.Dimensions.js similarity index 100% rename from Specs/Element/Element.Dimensions.js rename to OldSpecs/Element/Element.Dimensions.js diff --git a/Specs/Element/Element.Style.js b/OldSpecs/Element/Element.Style.js similarity index 100% rename from Specs/Element/Element.Style.js rename to OldSpecs/Element/Element.Style.js diff --git a/Specs/Element/Element.js b/OldSpecs/Element/Element.js similarity index 100% rename from Specs/Element/Element.js rename to OldSpecs/Element/Element.js diff --git a/Specs/Native/Array.js b/OldSpecs/Native/Array.js similarity index 100% rename from Specs/Native/Array.js rename to OldSpecs/Native/Array.js diff --git a/Specs/Native/Function.js b/OldSpecs/Native/Function.js similarity index 100% rename from Specs/Native/Function.js rename to OldSpecs/Native/Function.js diff --git a/Specs/Native/Hash.js b/OldSpecs/Native/Hash.js similarity index 100% rename from Specs/Native/Hash.js rename to OldSpecs/Native/Hash.js diff --git a/Specs/Native/Number.js b/OldSpecs/Native/Number.js similarity index 100% rename from Specs/Native/Number.js rename to OldSpecs/Native/Number.js diff --git a/Specs/Native/String.js b/OldSpecs/Native/String.js similarity index 100% rename from Specs/Native/String.js rename to OldSpecs/Native/String.js diff --git a/Specs/Plugins/Selectors.Children.js b/OldSpecs/Plugins/Selectors.Children.js similarity index 100% rename from Specs/Plugins/Selectors.Children.js rename to OldSpecs/Plugins/Selectors.Children.js diff --git a/Specs/Utilities/Color.js b/OldSpecs/Utilities/Color.js similarity index 100% rename from Specs/Utilities/Color.js rename to OldSpecs/Utilities/Color.js diff --git a/Specs/Utilities/Selectors.js b/OldSpecs/Utilities/Selectors.js similarity index 100% rename from Specs/Utilities/Selectors.js rename to OldSpecs/Utilities/Selectors.js diff --git a/Specs/Utilities/index.html b/OldSpecs/Utilities/index.html similarity index 100% rename from Specs/Utilities/index.html rename to OldSpecs/Utilities/index.html diff --git a/Specs/application.xml b/OldSpecs/application.xml similarity index 100% rename from Specs/application.xml rename to OldSpecs/application.xml diff --git a/Specs/demo.html b/OldSpecs/demo.html similarity index 100% rename from Specs/demo.html rename to OldSpecs/demo.html diff --git a/OldSpecs/index.html b/OldSpecs/index.html new file mode 100644 index 000000000..90b92cade --- /dev/null +++ b/OldSpecs/index.html @@ -0,0 +1,45 @@ + + + + + + MooTools Specs + + + + + + + + + + + + + diff --git a/Specs/1.2public/Class/Class.Extras.js b/Specs/1.2public/Class/Class.Extras.js new file mode 100644 index 000000000..493ed1224 --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Class/Class.js b/Specs/1.2public/Class/Class.js new file mode 100644 index 000000000..aa71d21ef --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Core/Browser.js b/Specs/1.2public/Core/Browser.js new file mode 100644 index 000000000..e78e9b03b --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Core/Core.js b/Specs/1.2public/Core/Core.js new file mode 100644 index 000000000..83d4c1b25 --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Element/Element.Dimensions.js b/Specs/1.2public/Element/Element.Dimensions.js new file mode 100644 index 000000000..760fb5f37 --- /dev/null +++ b/Specs/1.2public/Element/Element.Dimensions.js @@ -0,0 +1,120 @@ +/* +Script: Element.Dimensions.js + Specs for Element.Dimensions.js + +License: + MIT-style license. +*/ + +(function(){ + var div, relDiv, absDiv, scrollDiv, tallDiv; + window.addEvent('domready', function(){ + div = new Element('div', { + id: 'ElementDimensionsTest', + styles: { + width: 100, + height: 100, + margin: 2, + padding: 3, + border: '1px solid black', + visibility: 'hidden', + display: 'block', + position: 'absolute', + top: 100, + left: 100, + overflow: 'hidden', + zIndex: 1 + } + }).inject($(document.body)); + + relDiv = new Element('div', { + styles: { + width: 50, + height: 50, + margin: 5, + padding: 5, + border: '1px solid green', + visibility: 'hidden', + position: 'relative', + overflow: 'hidden' + } + }).inject(div); + + absDiv = new Element('div', { + styles: { + width: 10, + height: 10, + margin: 5, + padding: 5, + border: '1px solid red', + visibility: 'hidden', + position: 'absolute', + top: 10, + left: 10, + overflow: 'hidden' + } + }).inject(relDiv); + + scrollDiv = new Element('div', { + styles: { + width: 100, + height: 100, + overflow: 'scroll', + visibility: 'hidden', + position: 'absolute', + top: 0, + left: 0 + } + }).inject($(document.body)); + + tallDiv = new Element('div', { + styles: { + width: 200, + height: 200, + visibility: 'hidden' + } + }).inject(scrollDiv); + + }); + + describe('Element.getSize', { + + 'should measure the width and height of the element': function(){ + value_of(div.getSize()).should_be({x: 108, y: 108}); + } + + }); + + describe('Element.getPosition', { + + 'should measure the x and y position of the element': function(){ + value_of(div.getPosition()).should_be({x: 102, y: 102}); + } + + }); + + describe('Element.getCoordinates', { + + 'should return the coordinates relative to parent': function(){ + value_of(absDiv.getCoordinates(relDiv)).should_be({left:16, top:16, width:22, height:22, right:38, bottom:38}); + } + + }); + + describe('Element.getScrollSize', { + + 'should return the scrollSize': function(){ + value_of(scrollDiv.getScrollSize()).should_be({x:200, y:200}); + } + + }); + + describe('Element.scrollTo', { + + 'should scroll the element': function(){ + value_of(scrollDiv.scrollTo(20,20).getScroll()).should_be({x:20, y:20}); + } + + }); + +})(); diff --git a/Specs/1.2public/Element/Element.Style.js b/Specs/1.2public/Element/Element.Style.js new file mode 100644 index 000000000..95f85abec --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Element/Element.js b/Specs/1.2public/Element/Element.js new file mode 100644 index 000000000..b3eb17aa1 --- /dev/null +++ b/Specs/1.2public/Element/Element.js @@ -0,0 +1,1565 @@ +/* +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_match(/(font-size:12px;color:rgb\(255,255,255\))|(color:rgb\(255,255,255\);font-size:12px)/); + //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='); + }, + + "should return a query string ignoring submit, reset and file form Elements": function(){ + var form = new Element('form', { 'html': '' + + '' + + '' + + '' + + '' + + '' + }); + value_of(form.toQueryString()).should_be('input=checked&textarea=textarea-value'); + } + +}); + +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'); + + var div = new Element('div', {'html': + '' + }); + var input3 = div.getElement('select'); + value_of(input3.getProperty('type')).should_be('select-multiple'); + value_of(input3.getProperty('name')).should_be('test'); + }, + + '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(); + }, + + 'should setProperty defaultValue of an input Element': function(){ + var form = new Element('form'); + var defaultValue = new Element('input', {'type': 'text', 'value': '321'}).setProperty('defaultValue', '123'); + form.grab(defaultValue); + value_of(defaultValue.getProperty('value')).should_be('321'); + form.reset(); + value_of(defaultValue.getProperty('value')).should_be('123'); + } + +}); + +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', maxlenght: 10 }); + readonly.removeProperty('readonly'); + readonly.removeProperty('maxlength'); + var props = readonly.getProperties('type', 'readonly', 'maxlength'); + value_of(props).should_be({ type: 'text', readonly: false, maxlength: Browser.Engine.webkit ? 524288 : 0}); + } + +}); + +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/Specs/1.2public/Native/Array.js b/Specs/1.2public/Native/Array.js new file mode 100644 index 000000000..37d28e6bb --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Native/Function.js b/Specs/1.2public/Native/Function.js new file mode 100644 index 000000000..61a5dd1be --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Native/Hash.js b/Specs/1.2public/Native/Hash.js new file mode 100644 index 000000000..ff75a33b1 --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Native/Number.js b/Specs/1.2public/Native/Number.js new file mode 100644 index 000000000..3ccdf1893 --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Native/String.js b/Specs/1.2public/Native/String.js new file mode 100644 index 000000000..caa540006 --- /dev/null +++ b/Specs/1.2public/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/Specs/1.2public/Utilities/Selectors.Children.js b/Specs/1.2public/Utilities/Selectors.Children.js new file mode 100644 index 000000000..9ed2d258e --- /dev/null +++ b/Specs/1.2public/Utilities/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/Specs/MooToolsSpecLoader.js b/Specs/MooToolsSpecLoader.js new file mode 100644 index 000000000..c17adaa47 --- /dev/null +++ b/Specs/MooToolsSpecLoader.js @@ -0,0 +1,68 @@ +var Sets = { + + '1.2public': [ + 'Core/Core.js', 'Core/Browser.js', + 'Native/Array.js', 'Native/String.js', 'Native/Function.js', 'Native/Number.js', 'Native/Hash.js', + 'Class/Class.js', 'Class/Class.Extras.js', + 'Element/Element.js', 'Element/Element.Style.js', 'Element/Element.Dimensions.js', + 'Utilities/Selectors.Children.js' + ], + + '1.2private': [ + + ] + +}; + +var runSpecs = (function(){ + +// Uses String.parseQueryString from MooTools-More +// TODO Needs compat for other browsers +var parseQueryString = function(string){ + var vars = string.split(/[&;]/), res = {}; + if (vars.length) vars.forEach(function(val){ + var index = val.indexOf('='), + keys = index < 0 ? [''] : val.substr(0, index).match(/[^\]\[]+/g), + value = decodeURIComponent(val.substr(index + 1)), + obj = res; + keys.forEach(function(key, i){ + var current = obj[key]; + if(i < keys.length - 1) + obj = obj[key] = current || {}; + else if(current && current._type == 'Array') // JSSpec prototyping + current.push(value); + else + obj[key] = current != undefined ? [current, value] : value; + }); + }); + return res; +}; + +var getSpecs = function(queryString){ + queryString = parseQueryString(queryString); + + var requestedSpecs = [], + specs = queryString.specs; + + (specs && specs._type == 'Array' ? specs : [specs]).forEach(function(spec){ + if (Sets[spec] && requestedSpecs.indexOf(spec) == -1) requestedSpecs.push(spec); + }); + + return requestedSpecs; +}; + +var loadSpecs = function(obj){ + for (var i = 0; i < obj.length; i++){ + SpecNames.push(obj[i]); + + var specs = Sets[obj[i]]; + for (var j = 0; j < specs.length; j++){ + document.write('<\/script>'); + } + } +}; + +var requestedSpecs = getSpecs(document.location.search.substr(1)); +loadSpecs(requestedSpecs); + +}); \ No newline at end of file diff --git a/Specs/SlickSpec/JSSpec.css b/Specs/SlickSpec/JSSpec.css new file mode 100755 index 000000000..0f43a51db --- /dev/null +++ b/Specs/SlickSpec/JSSpec.css @@ -0,0 +1,245 @@ +@CHARSET "UTF-8"; + +/* -------------------- + * @Layout + */ + +html { + overflow: hidden; +} + +body, #jsspec_container { + overflow: hidden; + padding: 0; + margin: 0; + width: 100%; + height: 100%; + background-color: white; +} + +#title { + padding: 0; + margin: 0; + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 40px; + overflow: hidden; +} + +#list { + padding: 0; + margin: 0; + position: absolute; + top: 40px; + left: 0px; + bottom: 0px; + overflow: auto; + width: 250px; + _height:expression(document.body.clientHeight-40); +} + +#log { + padding: 0; + margin: 0; + position: absolute; + top: 40px; + left: 250px; + right: 0px; + bottom: 0px; + overflow: auto; + _height:expression(document.body.clientHeight-40); + _width:expression(document.body.clientWidth-250); +} + +/*iPhone*/ +@media only screen and (max-device-width: 480px) { + #list { + overflow: visible; + } + + #log { + overflow: visible; + } +} + + +/* -------------------- + * @Decorations and colors + */ +* { + padding: 0; + margin: 0; + font-family: "Lucida Grande", Helvetica, sans-serif; +} + +li { + list-style: none; +} + +/* hiding subtitles */ +h2 { + display: none; +} + +/* title section */ +div#title { + padding: 0em 0.5em; +} + +div#title h1 { + font-size: 1.5em; + float: left; +} + +div#title ul li { + float: left; + padding: 0.5em 0em 0.5em 0.75em; +} + +div#title p { + float:right; + margin-right:1em; + font-size: 0.75em; +} + +/* spec container */ +ul.specs { + margin: 0.5em; +} +ul.specs li { + margin-bottom: 0.1em; +} + +/* spec title */ +ul.specs li h3 { + font-weight: bold; + font-size: 0.75em; + padding: 0.2em 1em; + cursor: pointer; + _cursor: hand; +} + +/* example container */ +ul.examples li { + border-style: solid; + border-width: 0px 0px 1px 5px; + margin: 0.2em 0em 0.2em 1em; +} + +/* example title */ +ul.examples li h4 { + font-weight: normal; + font-size: 0.75em; + margin-left: 1em; +} + +pre.examples-code { + margin: 0.5em 2em; + padding: 0.5em; + background: white; + border: solid 1px #CCC; + font-size: 10px; + font-family: "Panic Sans", "Monaco", monospace !important; +} + +/* example explaination */ +ul.examples li div { + padding: 1em 2em; + font-size: 0.75em; +} + +/* styles for ongoing, success, failure, error */ +div.success, div.success a { + color: #FFFFFF; + background-color: #65C400; +} + +li.ongoing li.success pre.examples-code, +li pre.examples-code { + display:none !important; +} +li.exception pre.examples-code, +li.ongoing pre.examples-code { + display:block !important; +} + +ul.specs li.success h3, ul.specs li.success h3 a { + color: #FFFFFF; + background-color: #65C400; +} + +ul.examples li.success, ul.examples li.success a { + color: #3D7700; + background-color: #DBFFB4; + border-color: #65C400; +} + +div.exception, div.exception a { + color: #FFFFFF; + background-color: #C20000; +} + +ul.specs li.exception h3, ul.specs li.exception h3 a { + color: #FFFFFF; + background-color: #C20000; +} + +ul.examples li.exception, ul.examples li.exception a { + color: #C20000; + background-color: #FFFBD3; + border-color: #C20000; +} + +div.ongoing, div.ongoing a { + color: #000000; + background-color: #FFFF80; +} + +ul.specs li.ongoing h3, ul.specs li.ongoing h3 a { + color: #000000; + background-color: #FFFF80; +} + +ul.examples li.ongoing, ul.examples li.ongoing a { + color: #000000; + background-color: #FFFF80; + border-color: #DDDD00; +} + + + +/* -------------------- + * values + */ +.number_value, .string_value, .regexp_value, .boolean_value, .dom_value { + font-family: monospace; + color: blue; +} +.object_value, .array_value { + line-height: 2em; + padding: 0.1em 0.2em; + margin: 0.1em 0; +} +.date_value { + font-family: monospace; + color: olive; +} +.undefined_value, .null_value { + font-style: italic; + color: blue; +} +.dom_attr_name { +} +.dom_attr_value { + color: red; +} +.dom_path { + font-size: 0.75em; + color: gray; +} +strong { + font-weight: normal; + background-color: #FFC6C6; +} diff --git a/Specs/SlickSpec/JSSpec.js b/Specs/SlickSpec/JSSpec.js new file mode 100755 index 000000000..0b2e15b72 --- /dev/null +++ b/Specs/SlickSpec/JSSpec.js @@ -0,0 +1,1553 @@ +/** + * JSSpec + * + * Copyright 2007 Alan Kang + * - mailto:jania902@gmail.com + * - http://jania.pe.kr + * + * http://jania.pe.kr/aw/moin.cgi/JSSpec + * + * Dependencies: + * - diff_match_patch.js ( http://code.google.com/p/google-diff-match-patch ) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * Namespace + */ + +var baseQueryString = window.location.search.replace(/&?rerun=.*?(&|$)/ig,'').replace(/&$/,''); +if (!baseQueryString) baseQueryString = '?'; else baseQueryString += '&'; + +var JSSpec = { + specs: [], + + EMPTY_FUNCTION: function() {}, + + Browser: { + // By Rendering Engines + Trident: navigator.appName === "Microsoft Internet Explorer", + Webkit: navigator.userAgent.indexOf('AppleWebKit/') > -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) { + window._curExecutor = self; + + result = self.target(); + self.onSuccess(self, result); + } 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 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

', + '' + ].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'); + if (links) links = links.getElementsByTagName('A'); + else return; + 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/Specs/SlickSpec/JSSpecHelpers.js b/Specs/SlickSpec/JSSpecHelpers.js new file mode 100644 index 000000000..9b17ede7f --- /dev/null +++ b/Specs/SlickSpec/JSSpecHelpers.js @@ -0,0 +1,308 @@ +function $try(){ + for (var i = 0, l = arguments.length; i < l; i++){ + try { + return arguments[i](); + } catch(e){} + } + return null; +}; + +Function.prototype._type = "Function"; + +String.escapeSingle = String.escapeSingle || function escapeSingle(string){ + return (''+string).replace(/(?=[\\\n'])/g,'\\'); +}; + + +var global = this; +global.context = this; +var specs, spec, it, its; +var descriptionParent = ''; +var uniquespecs = {}; + +function Describe(description,specBuilder){ + // Backup existing object so we don't override it + var old_specs = specs; + specs = spec = it = its = {}; + + // Inherit the before and afters of your forefathers + if (old_specs) { + if (old_specs.before ) specs.before = old_specs.before; + if (old_specs.before_all ) specs.before_all = old_specs.before_all; + if (old_specs.before_each ) specs.before_each = old_specs.before_each; + if (old_specs.after ) specs.after = old_specs.after; + if (old_specs.after_all ) specs.after_all = old_specs.after_all; + if (old_specs.after_each ) specs.after_each = old_specs.after_each; + } + + // Inherit the description of your forefathers + description = descriptionParent + (descriptionParent ? ': ' : '') + String(description); + var old_descriptionParent = descriptionParent; + descriptionParent = description; + + // Build the spec object + specBuilder(specs,global.context); + + // Create the tests and go! + var spec_count = 0; + var specnames = []; + for (var specname in specs){ + if (/^(before|after)[_ ](all|each)$/.test(specname)) continue; + if (!specs[specname]) continue; + spec_count++; + specnames.push(description+specname); + } + if (spec_count && !uniquespecs[specnames]){ + describe(description, specs); + uniquespecs[specnames] = true; + } + + // Reset + descriptionParent = old_descriptionParent; + specs = spec = it = its = old_specs; +}; + + +global.mocks = {}; +var Mock = (function(){ + + function Mock(mockName, testBuilder){ + if (mockName && !testBuilder) throw new Error("Invalid mockName, Mock syntax: `new Mock(/mockName/, function(specs, window){})`"); + + if (Object.prototype.toString.call(mockName) != '[object RegExp]') + mockName = new RegExp(mockName); + + this.mockName = mockName; + this.testBuilder = testBuilder; + Mock.mocks.push(this); + }; + + Mock.mocks = []; + + Mock.prototype.run = function(){ + var globalContextOld = global.context; + for (var mockName in global.mocks) if (this.mockName.test(mockName)) { + + global.context = global.mocks[mockName]; + for (var i = 0, l = global.willDefineEverywhere.length; i < l; i++) { + try { + global.willDefineEverywhere[i](global.context); + } finally { + continue; + } + } + Describe(mockName,this.testBuilder); + + } + global.context = globalContextOld; + }; + + Mock.register = function(name, window){ + clearTimeout(Mock.register.delay); + global.mocks[name] = window; + Mock.register.delay = setTimeout(Mock.register.done, 1000); + }; + + Mock.register.done = function(){ + for (var i=0; i < Mock.mocks.length; i++){ + try { + Mock.mocks[i].run(); + } finally { + continue; + } + } + + global.runSpecs(); + }; + + + return Mock; +})(); + +Mock.Request = function(mockName, url){ + if (!this instanceof Mock.Request) throw new Error('Mock.Request is not callable directly. Must use `new Mock.Request`'); + + this.mockName = mockName; + this.url = url; + + var self = this; + this.callback = function(html, xml){ + Mock.register(self.mockName +': '+ String(self.url).replace(/^.*\//,''), newFakeWinFromDoc(xml)); + }; + this.rq = new SimpleRequest(); + this.rq.send(this.url, this.callback); +}; + +global.willDefineEverywhere = []; +Mock.defineEverywhere = function(definer){ + global.willDefineEverywhere.push(definer); +} + +var TODO = function(){ throw "TODO: This test has not be written yet"; }; + +if(typeof JSSpec == 'undefined') var JSSpec = {}; +if(!JSSpec.Browser) JSSpec.Browser = {}; +JSSpec.Browser.NativeConsole = !!(('console' in this) && ('log' in console) && ('toString' in console.log) && console.log.toString().match(/\[native code\]/)); +JSSpec.Browser.Trident = (JSSpec.Browser.Trident && !JSSpec.Browser.NativeConsole); + +// Stop the normal JSSpec onload from firing yet +var runSpecs_actually = window.onload; +// console.time('runSpecs'); +var runSpecs = function(){ + // console.timeEnd('runSpecs'); + // console.time('runSpecs'); + // console.log('runSpecs'); + clearTimeout(global.runSpecs_timer); + global.runSpecs_timer = setTimeout(runSpecs_actually, 1000); +}; +window.onload = function(){ + window.loaded = true; + // setTimeout(runSpecs, 100); +}; + + +// XML +// from http://www.webreference.com/programming/javascript/definitive2/ +/** + * Create a new Document object. If no arguments are specified, + * the document will be empty. If a root tag is specified, the document + * will contain that single root tag. If the root tag has a namespace + * prefix, the second argument must specify the URL that identifies the + * namespace. + */ +var newXMLDocument = (document.implementation && document.implementation.createDocument) +? function(rootTagName, namespaceURL){ + return document.implementation.createDocument(namespaceURL||'', rootTagName||'', null); +} +: function(rootTagName, namespaceURL){ + if (!rootTagName) rootTagName = ""; + if (!namespaceURL) namespaceURL = ""; + // This is the IE way to do it + // Create an empty document as an ActiveX object + // If there is no root element, this is all we have to do + var doc = new ActiveXObject("MSXML2.DOMDocument"); + // If there is a root tag, initialize the document + if (rootTagName) { + // Look for a namespace prefix + var prefix = ""; + var tagname = rootTagName; + var p = rootTagName.indexOf(':'); + if (p != -1) { + prefix = rootTagName.substring(0, p); + tagname = rootTagName.substring(p+1); + } + // If we have a namespace, we must have a namespace prefix + // If we don't have a namespace, we discard any prefix + if (namespaceURL) { + if (!prefix) prefix = "a0"; // What Firefox uses + } + else prefix = ""; + // Create the root element (with optional namespace) as a + // string of text + var text = "<" + (prefix?(prefix+":"):"") + tagname + + (namespaceURL + ?(" xmlns:" + prefix + '="' + namespaceURL +'"') + :"") + + "/>"; + // And parse that text into the empty document + doc.loadXML(text); + } + return doc; +}; + +/** + * Synchronously load the XML document at the specified URL and + * return it as a Document object + */ +var loadXML = function(url) { + // Create a new document with the previously defined function + var xmldoc = newXMLDocument(); + xmldoc.async = false; // We want to load synchronously + xmldoc.load(url); // Load and parse + return xmldoc; // Return the document +}; + +/** + * Parse the XML document contained in the string argument and return + * a Document object that represents it. + */ +var parseXML = (function(){ + + // Mozilla, Firefox, and related browsers + if (typeof DOMParser != "undefined") + return function(rawXML){ + return (new DOMParser()).parseFromString(rawXML, "application/xml"); + }; + + // Internet Explorer. + if (typeof ActiveXObject != "undefined") + return function(rawXML){ + var xmlDocument = new ActiveXObject("Microsoft.XMLDOM"); + xmlDocument.async = false; + xmlDocument.loadXML(rawXML); + + if (xmlDocument.parseError && xmlDocument.parseError.errorCode) + xmlDocument.loadXML(rawXML.replace(/]*?>/i,'')); + + if (xmlDocument.parseError && xmlDocument.parseError.errorCode) + throw new Error(['' + ,("Error code: " + xmlDocument.parseError.errorCode) + ,("Error reason: " + xmlDocument.parseError.reason) + ,("Error line: " + xmlDocument.parseError.line) + ,rawXML + ].join('\n')); + + return xmlDocument; + }; + + // As a last resort, try loading the document from a data: URL + // This is supposed to work in Safari. Thanks to Manos Batsis and + // his Sarissa library (sarissa.sourceforge.net) for this technique. + return function(rawXML){ + var url = "data:text/xml;charset=utf-8," + encodeURIComponent(rawXML); + var request = new XMLHttpRequest(); + request.open("GET", url, false); + request.send(null); + return request.responseXML; + }; + +})(); + + +function getXML(url,mime){ + if (!mime && url && /\.(svg|xml|xhtml)/i.test(url)) + mime = 'text/xml'; + + var request; + if (XMLHttpRequest != undefined) + request = new XMLHttpRequest(); + else + request = new ActiveXObject("Microsoft.XMLHTTP"); + + request.open("GET", url, false); + if (mime && request.overrideMimeType) request.overrideMimeType(mime); + request.send(null); + return request; + return request.responseXML || parseXML(request.responseText); + +}; + + +function newFakeWinFromDoc(document){ + var fakeWin = { fake:true }; + fakeWin.document = document; + // fakeWin.document = getXML('/test/tools/MooTools_Logo.svg'); + // fakeWin.document = loadXML('tools/MooTools_Logo.svg'); + // fakeWin.document = document.getElementById('svg_logo_data_island').document; + // fakeWin.document = parseXML(''); + + fakeWin.SELECT = function(context, expression){ + return global.SELECT.call(fakeWin, context, expression); + }; + // if (fakeWin.document) fakeWin.document.search = function(expression){ + // return SELECT(fakeWin.document, expression); + // }; + + return fakeWin; +}; + diff --git a/Specs/SlickSpec/diff_match_patch.js b/Specs/SlickSpec/diff_match_patch.js new file mode 100755 index 000000000..67af5832f --- /dev/null +++ b/Specs/SlickSpec/diff_match_patch.js @@ -0,0 +1,2136 @@ +/* +curl -s http://google-diff-match-patch.googlecode.com/svn/trunk/javascript/diff_match_patch_uncompressed.js #*/ +/** + * Diff Match and Patch + * + * Copyright 2006 Google Inc. + * http://code.google.com/p/google-diff-match-patch/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Computes the difference between two texts to create a patch. + * Applies the patch onto another text, allowing for errors. + * @author fraser@google.com (Neil Fraser) + */ + +/** + * Class containing the diff, match and patch methods. + * @constructor + */ +function diff_match_patch() { + + // Defaults. + // Redefine these in your program to override the defaults. + + // Number of seconds to map a diff before giving up (0 for infinity). + this.Diff_Timeout = 1.0; + // Cost of an empty edit operation in terms of edit characters. + this.Diff_EditCost = 4; + // The size beyond which the double-ended diff activates. + // Double-ending is twice as fast, but less accurate. + this.Diff_DualThreshold = 32; + // At what point is no match declared (0.0 = perfection, 1.0 = very loose). + this.Match_Threshold = 0.5; + // How far to search for a match (0 = exact location, 1000+ = broad match). + // A match this many characters away from the expected location will add + // 1.0 to the score (0.0 is a perfect match). + this.Match_Distance = 1000; + // When deleting a large block of text (over ~64 characters), how close does + // the contents have to match the expected contents. (0.0 = perfection, + // 1.0 = very loose). Note that Match_Threshold controls how closely the + // end points of a delete need to match. + this.Patch_DeleteThreshold = 0.5; + // Chunk size for context length. + this.Patch_Margin = 4; + + /** + * Compute the number of bits in an int. + * The normal answer for JavaScript is 32. + * @return {number} Max bits + */ + function getMaxBits() { + var maxbits = 0; + var oldi = 1; + var newi = 2; + while (oldi != newi) { + maxbits++; + oldi = newi; + newi = newi << 1; + } + return maxbits; + } + // How many bits in a number? + this.Match_MaxBits = getMaxBits(); +} + + +// DIFF FUNCTIONS + + +/** + * The data structure representing a diff is an array of tuples: + * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']] + * which means: delete 'Hello', add 'Goodbye' and keep ' world.' + */ +var DIFF_DELETE = -1; +var DIFF_INSERT = 1; +var DIFF_EQUAL = 0; + + +/** + * Find the differences between two texts. Simplifies the problem by stripping + * any common prefix or suffix off the texts before diffing. + * @param {string} text1 Old string to be diffed. + * @param {string} text2 New string to be diffed. + * @param {boolean} opt_checklines Optional speedup flag. If present and false, + * then don't run a line-level diff first to identify the changed areas. + * Defaults to true, which does a faster, slightly less optimal diff + * @return {Array.>} Array of diff tuples. + */ +diff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines) { + // Check for equality (speedup) + if (text1 == text2) { + return [[DIFF_EQUAL, text1]]; + } + + if (typeof opt_checklines == 'undefined') { + opt_checklines = true; + } + var checklines = opt_checklines; + + // Trim off common prefix (speedup) + var commonlength = this.diff_commonPrefix(text1, text2); + var commonprefix = text1.substring(0, commonlength); + text1 = text1.substring(commonlength); + text2 = text2.substring(commonlength); + + // Trim off common suffix (speedup) + 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); + + // Compute the diff on the middle block + var diffs = this.diff_compute(text1, text2, checklines); + + // Restore the prefix and suffix + if (commonprefix) { + diffs.unshift([DIFF_EQUAL, commonprefix]); + } + if (commonsuffix) { + diffs.push([DIFF_EQUAL, commonsuffix]); + } + this.diff_cleanupMerge(diffs); + return diffs; +}; + + +/** + * Find the differences between two texts. Assumes that the texts do not + * have any common prefix or suffix. + * @param {string} text1 Old string to be diffed. + * @param {string} text2 New string to be diffed. + * @param {boolean} checklines Speedup flag. If false, then don't run a + * line-level diff first to identify the changed areas. + * If true, then run a faster, slightly less optimal diff + * @return {Array.>} Array of diff tuples. + * @private + */ +diff_match_patch.prototype.diff_compute = function(text1, text2, checklines) { + var diffs; + + if (!text1) { + // Just add some text (speedup) + return [[DIFF_INSERT, text2]]; + } + + if (!text2) { + // Just delete some text (speedup) + 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) { + // Shorter text is inside the longer text (speedup) + diffs = [[DIFF_INSERT, longtext.substring(0, i)], + [DIFF_EQUAL, shorttext], + [DIFF_INSERT, longtext.substring(i + shorttext.length)]]; + // Swap insertions for deletions if diff is reversed. + if (text1.length > text2.length) { + diffs[0][0] = diffs[2][0] = DIFF_DELETE; + } + return diffs; + } + longtext = shorttext = null; // Garbage collect + + // Check to see if the problem can be split in two. + var hm = this.diff_halfMatch(text1, text2); + if (hm) { + // A half-match was found, sort out the return data. + 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]; + // Send both pairs off for separate processing. + var diffs_a = this.diff_main(text1_a, text2_a, checklines); + var diffs_b = this.diff_main(text1_b, text2_b, checklines); + // Merge the results. + return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b); + } + + // Perform a real diff. + if (checklines && (text1.length < 100 || text2.length < 100)) { + // Too trivial for the overhead. + checklines = false; + } + var linearray; + if (checklines) { + // Scan the text on a line-by-line basis first. + var a = this.diff_linesToChars(text1, text2); + text1 = a[0]; + text2 = a[1]; + linearray = a[2]; + } + diffs = this.diff_map(text1, text2); + if (!diffs) { + // No acceptable result. + diffs = [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; + } + if (checklines) { + // Convert the diff back to original text. + this.diff_charsToLines(diffs, linearray); + // Eliminate freak matches (e.g. blank lines) + this.diff_cleanupSemantic(diffs); + + // Rediff any replacement blocks, this time character-by-character. + // Add a dummy entry at the end. + diffs.push([DIFF_EQUAL, '']); + var pointer = 0; + var count_delete = 0; + var count_insert = 0; + var text_delete = ''; + var text_insert = ''; + while (pointer < diffs.length) { + switch (diffs[pointer][0]) { + case DIFF_INSERT: + count_insert++; + text_insert += diffs[pointer][1]; + break; + case DIFF_DELETE: + count_delete++; + text_delete += diffs[pointer][1]; + break; + case DIFF_EQUAL: + // Upon reaching an equality, check for prior redundancies. + if (count_delete >= 1 && count_insert >= 1) { + // Delete the offending records and add the merged ones. + 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 = ''; + break; + } + pointer++; + } + diffs.pop(); // Remove the dummy entry at the end. + } + return diffs; +}; + + +/** + * Split two texts into an array of strings. Reduce the texts to a string of + * hashes where each Unicode character represents one line. + * @param {string} text1 First string. + * @param {string} text2 Second string. + * @return {Array.>} Three element Array, containing the + * encoded text1, the encoded text2 and the array of unique strings. The + * zeroth element of the array of unique strings is intentionally blank. + * @private + */ +diff_match_patch.prototype.diff_linesToChars = function(text1, text2) { + var lineArray = []; // e.g. lineArray[4] == 'Hello\n' + var lineHash = {}; // e.g. lineHash['Hello\n'] == 4 + + // '\x00' is a valid character, but various debuggers don't like it. + // So we'll insert a junk entry to avoid generating a null character. + lineArray[0] = ''; + + /** + * Split a text into an array of strings. Reduce the texts to a string of + * hashes where each Unicode character represents one line. + * Modifies linearray and linehash through being a closure. + * @param {string} text String to encode + * @return {string} Encoded string + * @private + */ + function diff_linesToCharsMunge(text) { + var chars = ''; + // Walk the text, pulling out a substring for each line. + // text.split('\n') would would temporarily double our memory footprint. + // Modifying text would create many large strings to garbage collect. + var lineStart = 0; + var lineEnd = -1; + // Keeping our own length variable is faster than looking it up. + var lineArrayLength = lineArray.length; + while (lineEnd < text.length - 1) { + lineEnd = text.indexOf('\n', lineStart); + if (lineEnd == -1) { + lineEnd = text.length - 1; + } + var line = text.substring(lineStart, lineEnd + 1); + lineStart = lineEnd + 1; + + if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : + (lineHash[line] !== undefined)) { + chars += String.fromCharCode(lineHash[line]); + } else { + chars += String.fromCharCode(lineArrayLength); + lineHash[line] = lineArrayLength; + lineArray[lineArrayLength++] = line; + } + } + return chars; + } + + var chars1 = diff_linesToCharsMunge(text1); + var chars2 = diff_linesToCharsMunge(text2); + return [chars1, chars2, lineArray]; +}; + + +/** + * Rehydrate the text in a diff from a string of line hashes to real lines of + * text. + * @param {Array.>} diffs Array of diff tuples. + * @param {Array.} lineArray Array of unique strings. + * @private + */ +diff_match_patch.prototype.diff_charsToLines = function(diffs, lineArray) { + for (var x = 0; x < diffs.length; x++) { + var chars = diffs[x][1]; + var text = []; + for (var y = 0; y < chars.length; y++) { + text[y] = lineArray[chars.charCodeAt(y)]; + } + diffs[x][1] = text.join(''); + } +}; + + +/** + * Explore the intersection points between the two texts. + * @param {string} text1 Old string to be diffed. + * @param {string} text2 New string to be diffed. + * @return {Array.>?} Array of diff tuples or null if no + * diff available. + * @private + */ +diff_match_patch.prototype.diff_map = function(text1, text2) { + // Don't run for too long. + var ms_end = (new Date()).getTime() + this.Diff_Timeout * 1000; + // Cache the text lengths to prevent multiple calls. + var text1_length = text1.length; + var text2_length = text2.length; + var max_d = text1_length + text2_length - 1; + var doubleEnd = this.Diff_DualThreshold * 2 < max_d; + var v_map1 = []; + var v_map2 = []; + var v1 = {}; + var v2 = {}; + v1[1] = 0; + v2[1] = 0; + var x, y; + var footstep; // Used to track overlapping paths. + var footsteps = {}; + var done = false; + // Safari 1.x doesn't have hasOwnProperty + var hasOwnProperty = !!(footsteps.hasOwnProperty); + // If the total number of characters is odd, then the front path will collide + // with the reverse path. + var front = (text1_length + text2_length) % 2; + for (var d = 0; d < max_d; d++) { + // Bail out if timeout reached. + if (this.Diff_Timeout > 0 && (new Date()).getTime() > ms_end) { + return null; + } + + // Walk the front path one step. + v_map1[d] = {}; + for (var k = -d; k <= d; k += 2) { + if (k == -d || k != d && v1[k - 1] < v1[k + 1]) { + x = v1[k + 1]; + } else { + x = v1[k - 1] + 1; + } + y = x - k; + if (doubleEnd) { + footstep = x + ',' + y; + if (front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : + (footsteps[footstep] !== undefined))) { + done = true; + } + if (!front) { + footsteps[footstep] = d; + } + } + while (!done && x < text1_length && y < text2_length && + text1.charAt(x) == text2.charAt(y)) { + x++; + y++; + if (doubleEnd) { + footstep = x + ',' + y; + if (front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : + (footsteps[footstep] !== undefined))) { + done = true; + } + if (!front) { + footsteps[footstep] = d; + } + } + } + v1[k] = x; + v_map1[d][x + ',' + y] = true; + if (x == text1_length && y == text2_length) { + // Reached the end in single-path mode. + return this.diff_path1(v_map1, text1, text2); + } else if (done) { + // Front path ran over reverse path. + v_map2 = v_map2.slice(0, footsteps[footstep] + 1); + var a = this.diff_path1(v_map1, text1.substring(0, x), + text2.substring(0, y)); + return a.concat(this.diff_path2(v_map2, text1.substring(x), + text2.substring(y))); + } + } + + if (doubleEnd) { + // Walk the reverse path one step. + v_map2[d] = {}; + for (var k = -d; k <= d; k += 2) { + if (k == -d || k != d && v2[k - 1] < v2[k + 1]) { + x = v2[k + 1]; + } else { + x = v2[k - 1] + 1; + } + y = x - k; + footstep = (text1_length - x) + ',' + (text2_length - y); + if (!front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : + (footsteps[footstep] !== undefined))) { + done = true; + } + if (front) { + footsteps[footstep] = d; + } + while (!done && x < text1_length && y < text2_length && + text1.charAt(text1_length - x - 1) == + text2.charAt(text2_length - y - 1)) { + x++; + y++; + footstep = (text1_length - x) + ',' + (text2_length - y); + if (!front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : + (footsteps[footstep] !== undefined))) { + done = true; + } + if (front) { + footsteps[footstep] = d; + } + } + v2[k] = x; + v_map2[d][x + ',' + y] = true; + if (done) { + // Reverse path ran over front path. + v_map1 = v_map1.slice(0, footsteps[footstep] + 1); + var a = this.diff_path1(v_map1, text1.substring(0, text1_length - x), + text2.substring(0, text2_length - y)); + return a.concat(this.diff_path2(v_map2, + text1.substring(text1_length - x), + text2.substring(text2_length - y))); + } + } + } + } + // Number of diffs equals number of characters, no commonality at all. + return null; +}; + + +/** + * Work from the middle back to the start to determine the path. + * @param {Array.} v_map Array of paths. + * @param {string} text1 Old string fragment to be diffed. + * @param {string} text2 New string fragment to be diffed. + * @return {Array.>} Array of diff tuples. + * @private + */ +diff_match_patch.prototype.diff_path1 = function(v_map, text1, text2) { + var path = []; + var x = text1.length; + var y = text2.length; + /** @type {number?} */ + 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[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 (text1.charAt(x) != text2.charAt(y)) { + // throw new Error('No diagonal. Can\'t happen. (diff_path1)'); + //} + 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; +}; + + +/** + * Work from the middle back to the end to determine the path. + * @param {Array.} v_map Array of paths. + * @param {string} text1 Old string fragment to be diffed. + * @param {string} text2 New string fragment to be diffed. + * @return {Array.>} Array of diff tuples. + * @private + */ +diff_match_patch.prototype.diff_path2 = function(v_map, text1, text2) { + var path = []; + var pathLength = 0; + var x = text1.length; + var y = text2.length; + /** @type {number?} */ + 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[pathLength - 1][1] += text1.charAt(text1.length - x - 1); + } else { + path[pathLength++] = + [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[pathLength - 1][1] += text2.charAt(text2.length - y - 1); + } else { + path[pathLength++] = + [DIFF_INSERT, text2.charAt(text2.length - y - 1)]; + } + last_op = DIFF_INSERT; + break; + } else { + x--; + y--; + //if (text1.charAt(text1.length - x - 1) != + // text2.charAt(text2.length - y - 1)) { + // throw new Error('No diagonal. Can\'t happen. (diff_path2)'); + //} + if (last_op === DIFF_EQUAL) { + path[pathLength - 1][1] += text1.charAt(text1.length - x - 1); + } else { + path[pathLength++] = + [DIFF_EQUAL, text1.charAt(text1.length - x - 1)]; + } + last_op = DIFF_EQUAL; + } + } + } + return path; +}; + + +/** + * Determine the common prefix of two strings + * @param {string} text1 First string. + * @param {string} text2 Second string. + * @return {number} The number of characters common to the start of each + * string. + */ +diff_match_patch.prototype.diff_commonPrefix = function(text1, text2) { + // Quick check for common null cases. + if (!text1 || !text2 || text1.charCodeAt(0) !== text2.charCodeAt(0)) { + return 0; + } + // Binary search. + // Performance analysis: http://neil.fraser.name/news/2007/10/09/ + var pointermin = 0; + var pointermax = Math.min(text1.length, text2.length); + var pointermid = pointermax; + var pointerstart = 0; + while (pointermin < pointermid) { + if (text1.substring(pointerstart, pointermid) == + text2.substring(pointerstart, pointermid)) { + pointermin = pointermid; + pointerstart = pointermin; + } else { + pointermax = pointermid; + } + pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); + } + return pointermid; +}; + + +/** + * Determine the common suffix of two strings + * @param {string} text1 First string. + * @param {string} text2 Second string. + * @return {number} The number of characters common to the end of each string. + */ +diff_match_patch.prototype.diff_commonSuffix = function(text1, text2) { + // Quick check for common null cases. + if (!text1 || !text2 || text1.charCodeAt(text1.length - 1) !== + text2.charCodeAt(text2.length - 1)) { + return 0; + } + // Binary search. + // Performance analysis: http://neil.fraser.name/news/2007/10/09/ + var pointermin = 0; + var pointermax = Math.min(text1.length, text2.length); + var pointermid = pointermax; + var pointerend = 0; + while (pointermin < pointermid) { + if (text1.substring(text1.length - pointermid, text1.length - pointerend) == + text2.substring(text2.length - pointermid, text2.length - pointerend)) { + pointermin = pointermid; + pointerend = pointermin; + } else { + pointermax = pointermid; + } + pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); + } + return pointermid; +}; + + +/** + * Do the two texts share a substring which is at least half the length of the + * longer text? + * @param {string} text1 First string. + * @param {string} text2 Second string. + * @return {Array.?} Five element Array, containing the prefix of + * text1, the suffix of text1, the prefix of text2, the suffix of + * text2 and the common middle. Or null if there was no match. + */ +diff_match_patch.prototype.diff_halfMatch = function(text1, text2) { + var longtext = text1.length > text2.length ? text1 : text2; + var shorttext = text1.length > text2.length ? text2 : text1; + if (longtext.length < 10 || shorttext.length < 1) { + return null; // Pointless. + } + var dmp = this; // 'this' becomes 'window' in a closure. + + /** + * Does a substring of shorttext exist within longtext such that the substring + * is at least half the length of longtext? + * Closure, but does not reference any external variables. + * @param {string} longtext Longer string. + * @param {string} shorttext Shorter string. + * @param {number} i Start index of quarter length substring within longtext + * @return {Array.?} Five element Array, containing the prefix of + * longtext, the suffix of longtext, the prefix of shorttext, the suffix + * of shorttext and the common middle. Or null if there was no match. + * @private + */ + function diff_halfMatchI(longtext, shorttext, i) { + // Start with a 1/4 length substring at position i as a seed. + 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 < suffixLength + prefixLength) { + best_common = shorttext.substring(j - suffixLength, j) + + shorttext.substring(j, j + prefixLength); + best_longtext_a = longtext.substring(0, i - suffixLength); + best_longtext_b = longtext.substring(i + prefixLength); + best_shorttext_a = shorttext.substring(0, j - suffixLength); + best_shorttext_b = shorttext.substring(j + prefixLength); + } + } + 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; + } + } + + // First check if the second quarter is the seed for a half-match. + var hm1 = diff_halfMatchI(longtext, shorttext, + Math.ceil(longtext.length / 4)); + // Check again based on the third quarter. + 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 { + // Both matched. Select the longest. + hm = hm1[4].length > hm2[4].length ? hm1 : hm2; + } + + // A half-match was found, sort out the return data. + 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]; +}; + + +/** + * Reduce the number of edits by eliminating semantically trivial equalities. + * @param {Array.>} diffs Array of diff tuples. + */ +diff_match_patch.prototype.diff_cleanupSemantic = function(diffs) { + var changes = false; + var equalities = []; // Stack of indices where equalities are found. + var equalitiesLength = 0; // Keeping our own length var is faster in JS. + var lastequality = null; // Always equal to equalities[equalitiesLength-1][1] + var pointer = 0; // Index of current position. + // Number of characters that changed prior to the equality. + var length_changes1 = 0; + // Number of characters that changed after the equality. + var length_changes2 = 0; + while (pointer < diffs.length) { + if (diffs[pointer][0] == DIFF_EQUAL) { // equality found + equalities[equalitiesLength++] = pointer; + length_changes1 = length_changes2; + length_changes2 = 0; + lastequality = diffs[pointer][1]; + } else { // an insertion or deletion + length_changes2 += diffs[pointer][1].length; + if (lastequality !== null && (lastequality.length <= length_changes1) && + (lastequality.length <= length_changes2)) { + // Duplicate record + diffs.splice(equalities[equalitiesLength - 1], 0, + [DIFF_DELETE, lastequality]); + // Change second copy to insert. + diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; + // Throw away the equality we just deleted. + equalitiesLength--; + // Throw away the previous equality (it needs to be reevaluated). + equalitiesLength--; + pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; + length_changes1 = 0; // Reset the counters. + length_changes2 = 0; + lastequality = null; + changes = true; + } + } + pointer++; + } + if (changes) { + this.diff_cleanupMerge(diffs); + } + this.diff_cleanupSemanticLossless(diffs); +}; + + +/** + * Look for single edits surrounded on both sides by equalities + * which can be shifted sideways to align the edit to a word boundary. + * e.g: The cat came. -> The cat came. + * @param {Array.>} diffs Array of diff tuples. + */ +diff_match_patch.prototype.diff_cleanupSemanticLossless = function(diffs) { + // Define some regex patterns for matching boundaries. + var punctuation = /[^a-zA-Z0-9]/; + var whitespace = /\s/; + var linebreak = /[\r\n]/; + var blanklineEnd = /\n\r?\n$/; + var blanklineStart = /^\r?\n\r?\n/; + + /** + * Given two strings, compute a score representing whether the internal + * boundary falls on logical boundaries. + * Scores range from 5 (best) to 0 (worst). + * Closure, makes reference to regex patterns defined above. + * @param {string} one First string + * @param {string} two Second string + * @return {number} The score. + */ + function diff_cleanupSemanticScore(one, two) { + if (!one || !two) { + // Edges are the best. + return 5; + } + + // Each port of this function behaves slightly differently due to + // subtle differences in each language's definition of things like + // 'whitespace'. Since this function's purpose is largely cosmetic, + // the choice has been made to use each language's native features + // rather than force total conformity. + var score = 0; + // One point for non-alphanumeric. + if (one.charAt(one.length - 1).match(punctuation) || + two.charAt(0).match(punctuation)) { + score++; + // Two points for whitespace. + if (one.charAt(one.length - 1).match(whitespace) || + two.charAt(0).match(whitespace)) { + score++; + // Three points for line breaks. + if (one.charAt(one.length - 1).match(linebreak) || + two.charAt(0).match(linebreak)) { + score++; + // Four points for blank lines. + if (one.match(blanklineEnd) || two.match(blanklineStart)) { + score++; + } + } + } + } + return score; + } + + var pointer = 1; + // Intentionally ignore the first and last element (don't need checking). + while (pointer < diffs.length - 1) { + if (diffs[pointer - 1][0] == DIFF_EQUAL && + diffs[pointer + 1][0] == DIFF_EQUAL) { + // This is a single edit surrounded by equalities. + var equality1 = diffs[pointer - 1][1]; + var edit = diffs[pointer][1]; + var equality2 = diffs[pointer + 1][1]; + + // First, shift the edit as far left as possible. + var commonOffset = this.diff_commonSuffix(equality1, edit); + if (commonOffset) { + var commonString = edit.substring(edit.length - commonOffset); + equality1 = equality1.substring(0, equality1.length - commonOffset); + edit = commonString + edit.substring(0, edit.length - commonOffset); + equality2 = commonString + equality2; + } + + // Second, step character by character right, looking for the best fit. + var bestEquality1 = equality1; + var bestEdit = edit; + var bestEquality2 = equality2; + var bestScore = diff_cleanupSemanticScore(equality1, edit) + + diff_cleanupSemanticScore(edit, equality2); + while (edit.charAt(0) === equality2.charAt(0)) { + equality1 += edit.charAt(0); + edit = edit.substring(1) + equality2.charAt(0); + equality2 = equality2.substring(1); + var score = diff_cleanupSemanticScore(equality1, edit) + + diff_cleanupSemanticScore(edit, equality2); + // The >= encourages trailing rather than leading whitespace on edits. + if (score >= bestScore) { + bestScore = score; + bestEquality1 = equality1; + bestEdit = edit; + bestEquality2 = equality2; + } + } + + if (diffs[pointer - 1][1] != bestEquality1) { + // We have an improvement, save it back to the diff. + if (bestEquality1) { + diffs[pointer - 1][1] = bestEquality1; + } else { + diffs.splice(pointer - 1, 1); + pointer--; + } + diffs[pointer][1] = bestEdit; + if (bestEquality2) { + diffs[pointer + 1][1] = bestEquality2; + } else { + diffs.splice(pointer + 1, 1); + pointer--; + } + } + } + pointer++; + } +}; + + +/** + * Reduce the number of edits by eliminating operationally trivial equalities. + * @param {Array.>} diffs Array of diff tuples. + */ +diff_match_patch.prototype.diff_cleanupEfficiency = function(diffs) { + var changes = false; + var equalities = []; // Stack of indices where equalities are found. + var equalitiesLength = 0; // Keeping our own length var is faster in JS. + var lastequality = ''; // Always equal to equalities[equalitiesLength-1][1] + var pointer = 0; // Index of current position. + // Is there an insertion operation before the last equality. + var pre_ins = false; + // Is there a deletion operation before the last equality. + var pre_del = false; + // Is there an insertion operation after the last equality. + var post_ins = false; + // Is there a deletion operation after the last equality. + var post_del = false; + while (pointer < diffs.length) { + if (diffs[pointer][0] == DIFF_EQUAL) { // equality found + if (diffs[pointer][1].length < this.Diff_EditCost && + (post_ins || post_del)) { + // Candidate found. + equalities[equalitiesLength++] = pointer; + pre_ins = post_ins; + pre_del = post_del; + lastequality = diffs[pointer][1]; + } else { + // Not a candidate, and can never become one. + equalitiesLength = 0; + lastequality = ''; + } + post_ins = post_del = false; + } else { // an insertion or deletion + if (diffs[pointer][0] == DIFF_DELETE) { + post_del = true; + } else { + post_ins = true; + } + /* + * Five types to be split: + * ABXYCD + * AXCD + * ABXC + * AXCD + * ABXC + */ + if (lastequality && ((pre_ins && pre_del && post_ins && post_del) || + ((lastequality.length < this.Diff_EditCost / 2) && + (pre_ins + pre_del + post_ins + post_del) == 3))) { + // Duplicate record + diffs.splice(equalities[equalitiesLength - 1], 0, + [DIFF_DELETE, lastequality]); + // Change second copy to insert. + diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; + equalitiesLength--; // Throw away the equality we just deleted; + lastequality = ''; + if (pre_ins && pre_del) { + // No changes made which could affect previous entry, keep going. + post_ins = post_del = true; + equalitiesLength = 0; + } else { + equalitiesLength--; // Throw away the previous equality; + pointer = equalitiesLength > 0 ? + equalities[equalitiesLength - 1] : -1; + post_ins = post_del = false; + } + changes = true; + } + } + pointer++; + } + + if (changes) { + this.diff_cleanupMerge(diffs); + } +}; + + +/** + * Reorder and merge like edit sections. Merge equalities. + * Any edit section can move as long as it doesn't cross an equality. + * @param {Array.>} diffs Array of diff tuples. + */ +diff_match_patch.prototype.diff_cleanupMerge = function(diffs) { + diffs.push([DIFF_EQUAL, '']); // Add a dummy entry at the end. + var pointer = 0; + var count_delete = 0; + var count_insert = 0; + var text_delete = ''; + var text_insert = ''; + var commonlength; + while (pointer < diffs.length) { + switch (diffs[pointer][0]) { + case DIFF_INSERT: + count_insert++; + text_insert += diffs[pointer][1]; + pointer++; + break; + case DIFF_DELETE: + count_delete++; + text_delete += diffs[pointer][1]; + pointer++; + break; + case DIFF_EQUAL: + // Upon reaching an equality, check for prior redundancies. + if (count_delete !== 0 || count_insert !== 0) { + if (count_delete !== 0 && count_insert !== 0) { + // Factor out any common prefixies. + commonlength = this.diff_commonPrefix(text_insert, text_delete); + if (commonlength !== 0) { + if ((pointer - count_delete - count_insert) > 0 && + 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); + } + // Factor out any common suffixies. + 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); + } + } + // Delete the offending records and add the merged ones. + 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) { + // Merge this equality with the previous one. + diffs[pointer - 1][1] += diffs[pointer][1]; + diffs.splice(pointer, 1); + } else { + pointer++; + } + count_insert = 0; + count_delete = 0; + text_delete = ''; + text_insert = ''; + break; + } + } + if (diffs[diffs.length - 1][1] === '') { + diffs.pop(); // Remove the dummy entry at the end. + } + + // Second pass: look for single edits surrounded on both sides by equalities + // which can be shifted sideways to eliminate an equality. + // e.g: ABAC -> ABAC + var changes = false; + pointer = 1; + // Intentionally ignore the first and last element (don't need checking). + while (pointer < diffs.length - 1) { + if (diffs[pointer - 1][0] == DIFF_EQUAL && + diffs[pointer + 1][0] == DIFF_EQUAL) { + // This is a single edit surrounded by equalities. + if (diffs[pointer][1].substring(diffs[pointer][1].length - + diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) { + // Shift the edit over the previous equality. + diffs[pointer][1] = diffs[pointer - 1][1] + + diffs[pointer][1].substring(0, diffs[pointer][1].length - + diffs[pointer - 1][1].length); + diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; + diffs.splice(pointer - 1, 1); + changes = true; + } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) == + diffs[pointer + 1][1]) { + // Shift the edit over the next equality. + diffs[pointer - 1][1] += diffs[pointer + 1][1]; + diffs[pointer][1] = + diffs[pointer][1].substring(diffs[pointer + 1][1].length) + + diffs[pointer + 1][1]; + diffs.splice(pointer + 1, 1); + changes = true; + } + } + pointer++; + } + // If shifts were made, the diff needs reordering and another shift sweep. + if (changes) { + this.diff_cleanupMerge(diffs); + } +}; + + +/** + * loc is a location in text1, compute and return the equivalent location in + * text2. + * e.g. 'The cat' vs 'The big cat', 1->1, 5->8 + * @param {Array.>} diffs Array of diff tuples. + * @param {number} loc Location within text1. + * @return {number} Location within text2. + */ +diff_match_patch.prototype.diff_xIndex = function(diffs, loc) { + var chars1 = 0; + var chars2 = 0; + var last_chars1 = 0; + var last_chars2 = 0; + var x; + for (x = 0; x < diffs.length; x++) { + if (diffs[x][0] !== DIFF_INSERT) { // Equality or deletion. + chars1 += diffs[x][1].length; + } + if (diffs[x][0] !== DIFF_DELETE) { // Equality or insertion. + chars2 += diffs[x][1].length; + } + if (chars1 > loc) { // Overshot the location. + break; + } + last_chars1 = chars1; + last_chars2 = chars2; + } + // Was the location was deleted? + if (diffs.length != x && diffs[x][0] === DIFF_DELETE) { + return last_chars2; + } + // Add the remaining character length. + return last_chars2 + (loc - last_chars1); +}; + + +/** + * Convert a diff array into a pretty HTML report. + * @param {Array.>} diffs Array of diff tuples. + * @return {string} HTML representation. + */ +diff_match_patch.prototype.diff_prettyHtml = function(diffs) { + var html = []; + var i = 0; + for (var x = 0; x < diffs.length; x++) { + var op = diffs[x][0]; // Operation (insert, delete, equal) + var data = diffs[x][1]; // Text of change. + var text = data.replace(/&/g, '&').replace(//g, '>').replace(/\n/g, '¶
'); + switch (op) { + case DIFF_INSERT: + html[x] = '' + + text + ''; + break; + case DIFF_DELETE: + html[x] = '' + + text + ''; + break; + case DIFF_EQUAL: + html[x] = '' + text + ''; + break; + } + if (op !== DIFF_DELETE) { + i += data.length; + } + } + return html.join(''); +}; + + +/** + * Compute and return the source text (all equalities and deletions). + * @param {Array.>} diffs Array of diff tuples. + * @return {string} Source text. + */ +diff_match_patch.prototype.diff_text1 = function(diffs) { + var text = []; + for (var x = 0; x < diffs.length; x++) { + if (diffs[x][0] !== DIFF_INSERT) { + text[x] = diffs[x][1]; + } + } + return text.join(''); +}; + + +/** + * Compute and return the destination text (all equalities and insertions). + * @param {Array.>} diffs Array of diff tuples. + * @return {string} Destination text. + */ +diff_match_patch.prototype.diff_text2 = function(diffs) { + var text = []; + for (var x = 0; x < diffs.length; x++) { + if (diffs[x][0] !== DIFF_DELETE) { + text[x] = diffs[x][1]; + } + } + return text.join(''); +}; + + +/** + * Compute the Levenshtein distance; the number of inserted, deleted or + * substituted characters. + * @param {Array.>} diffs Array of diff tuples. + * @return {number} Number of changes. + */ +diff_match_patch.prototype.diff_levenshtein = function(diffs) { + var levenshtein = 0; + var insertions = 0; + var deletions = 0; + for (var x = 0; x < diffs.length; x++) { + var op = diffs[x][0]; + var data = diffs[x][1]; + switch (op) { + case DIFF_INSERT: + insertions += data.length; + break; + case DIFF_DELETE: + deletions += data.length; + break; + case DIFF_EQUAL: + // A deletion and an insertion is one substitution. + levenshtein += Math.max(insertions, deletions); + insertions = 0; + deletions = 0; + break; + } + } + levenshtein += Math.max(insertions, deletions); + return levenshtein; +}; + + +/** + * Crush the diff into an encoded string which describes the operations + * required to transform text1 into text2. + * E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'. + * Operations are tab-separated. Inserted text is escaped using %xx notation. + * @param {Array.>} diffs Array of diff tuples. + * @return {string} Delta text. + */ +diff_match_patch.prototype.diff_toDelta = function(diffs) { + var text = []; + for (var x = 0; x < diffs.length; x++) { + switch (diffs[x][0]) { + case DIFF_INSERT: + text[x] = '+' + encodeURI(diffs[x][1]); + break; + case DIFF_DELETE: + text[x] = '-' + diffs[x][1].length; + break; + case DIFF_EQUAL: + text[x] = '=' + diffs[x][1].length; + break; + } + } + // Opera doesn't know how to encode char 0. + return text.join('\t').replace(/\x00/g, '%00').replace(/%20/g, ' '); +}; + + +/** + * Given the original text1, and an encoded string which describes the + * operations required to transform text1 into text2, compute the full diff. + * @param {string} text1 Source string for the diff. + * @param {string} delta Delta text. + * @return {Array.>} Array of diff tuples. + * @throws {Error} If invalid input. + */ +diff_match_patch.prototype.diff_fromDelta = function(text1, delta) { + var diffs = []; + var diffsLength = 0; // Keeping our own length var is faster in JS. + var pointer = 0; // Cursor in text1 + // Opera doesn't know how to decode char 0. + delta = delta.replace(/%00/g, '\0'); + var tokens = delta.split(/\t/g); + for (var x = 0; x < tokens.length; x++) { + // Each token begins with a one character parameter which specifies the + // operation of this token (delete, insert, equality). + var param = tokens[x].substring(1); + switch (tokens[x].charAt(0)) { + case '+': + try { + diffs[diffsLength++] = [DIFF_INSERT, decodeURI(param)]; + } catch (ex) { + // Malformed URI sequence. + throw new Error('Illegal escape in diff_fromDelta: ' + param); + } + break; + case '-': + // Fall through. + case '=': + var n = parseInt(param, 10); + if (isNaN(n) || n < 0) { + throw new Error('Invalid number in diff_fromDelta: ' + param); + } + var text = text1.substring(pointer, pointer += n); + if (tokens[x].charAt(0) == '=') { + diffs[diffsLength++] = [DIFF_EQUAL, text]; + } else { + diffs[diffsLength++] = [DIFF_DELETE, text]; + } + break; + default: + // Blank tokens are ok (from a trailing \t). + // Anything else is an error. + if (tokens[x]) { + throw new Error('Invalid diff operation in diff_fromDelta: ' + + tokens[x]); + } + } + } + if (pointer != text1.length) { + throw new Error('Delta length (' + pointer + + ') does not equal source text length (' + text1.length + ').'); + } + return diffs; +}; + + +// MATCH FUNCTIONS + + +/** + * Locate the best instance of 'pattern' in 'text' near 'loc'. + * @param {string} text The text to search. + * @param {string} pattern The pattern to search for. + * @param {number} loc The location to search around. + * @return {number} Best match index or -1. + */ +diff_match_patch.prototype.match_main = function(text, pattern, loc) { + loc = Math.max(0, Math.min(loc, text.length)); + if (text == pattern) { + // Shortcut (potentially not guaranteed by the algorithm) + return 0; + } else if (!text.length) { + // Nothing to match. + return -1; + } else if (text.substring(loc, loc + pattern.length) == pattern) { + // Perfect match at the perfect spot! (Includes case of null pattern) + return loc; + } else { + // Do a fuzzy compare. + return this.match_bitap(text, pattern, loc); + } +}; + + +/** + * Locate the best instance of 'pattern' in 'text' near 'loc' using the + * Bitap algorithm. + * @param {string} text The text to search. + * @param {string} pattern The pattern to search for. + * @param {number} loc The location to search around. + * @return {number} Best match index or -1. + * @private + */ +diff_match_patch.prototype.match_bitap = function(text, pattern, loc) { + if (pattern.length > this.Match_MaxBits) { + throw new Error('Pattern too long for this browser.'); + } + + // Initialise the alphabet. + var s = this.match_alphabet(pattern); + + var dmp = this; // 'this' becomes 'window' in a closure. + + /** + * Compute and return the score for a match with e errors and x location. + * Accesses loc and pattern through being a closure. + * @param {number} e Number of errors in match. + * @param {number} x Location of match. + * @return {number} Overall score for match (0.0 = good, 1.0 = bad). + * @private + */ + function match_bitapScore(e, x) { + var accuracy = e / pattern.length; + var proximity = Math.abs(loc - x); + if (!dmp.Match_Distance) { + // Dodge divide by zero error. + return proximity ? 1.0 : accuracy; + } + return accuracy + (proximity / dmp.Match_Distance); + } + + // Highest score beyond which we give up. + var score_threshold = this.Match_Threshold; + // Is there a nearby exact match? (speedup) + var best_loc = text.indexOf(pattern, loc); + if (best_loc != -1) { + score_threshold = Math.min(match_bitapScore(0, best_loc), score_threshold); + } + // What about in the other direction? (speedup) + best_loc = text.lastIndexOf(pattern, loc + pattern.length); + if (best_loc != -1) { + score_threshold = Math.min(match_bitapScore(0, best_loc), score_threshold); + } + + // Initialise the bit arrays. + var matchmask = 1 << (pattern.length - 1); + best_loc = -1; + + var bin_min, bin_mid; + var bin_max = pattern.length + text.length; + var last_rd; + for (var d = 0; d < pattern.length; d++) { + // Scan for the best match; each iteration allows for one more error. + // Run a binary search to determine how far from 'loc' we can stray at this + // error level. + bin_min = 0; + bin_mid = bin_max; + while (bin_min < bin_mid) { + if (match_bitapScore(d, loc + bin_mid) <= score_threshold) { + bin_min = bin_mid; + } else { + bin_max = bin_mid; + } + bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min); + } + // Use the result from this iteration as the maximum for the next. + bin_max = bin_mid; + var start = Math.max(1, loc - bin_mid + 1); + var finish = Math.min(loc + bin_mid, text.length) + pattern.length; + + var rd = Array(finish + 2); + rd[finish + 1] = (1 << d) - 1; + for (var j = finish; j >= start; j--) { + // The alphabet (s) is a sparse hash, so the following line generates + // warnings. + var charMatch = s[text.charAt(j - 1)]; + if (d === 0) { // First pass: exact match. + rd[j] = ((rd[j + 1] << 1) | 1) & charMatch; + } else { // Subsequent passes: fuzzy match. + rd[j] = ((rd[j + 1] << 1) | 1) & charMatch | + (((last_rd[j + 1] | last_rd[j]) << 1) | 1) | + last_rd[j + 1]; + } + if (rd[j] & matchmask) { + var score = match_bitapScore(d, j - 1); + // This match will almost certainly be better than any existing match. + // But check anyway. + if (score <= score_threshold) { + // Told you so. + score_threshold = score; + best_loc = j - 1; + if (best_loc > loc) { + // When passing loc, don't exceed our current distance from loc. + start = Math.max(1, 2 * loc - best_loc); + } else { + // Already passed loc, downhill from here on in. + break; + } + } + } + } + // No hope for a (better) match at greater error levels. + if (match_bitapScore(d + 1, loc) > score_threshold) { + break; + } + last_rd = rd; + } + return best_loc; +}; + + +/** + * Initialise the alphabet for the Bitap algorithm. + * @param {string} pattern The text to encode. + * @return {Object} Hash of character locations. + * @private + */ +diff_match_patch.prototype.match_alphabet = function(pattern) { + var s = {}; + for (var i = 0; i < pattern.length; i++) { + s[pattern.charAt(i)] = 0; + } + for (var i = 0; i < pattern.length; i++) { + s[pattern.charAt(i)] |= 1 << (pattern.length - i - 1); + } + return s; +}; + + +// PATCH FUNCTIONS + + +/** + * Increase the context until it is unique, + * but don't let the pattern expand beyond Match_MaxBits. + * @param {patch_obj} patch The patch to grow. + * @param {string} text Source text. + * @private + */ +diff_match_patch.prototype.patch_addContext = function(patch, text) { + var pattern = text.substring(patch.start2, patch.start2 + patch.length1); + var padding = 0; + while (text.indexOf(pattern) != text.lastIndexOf(pattern) && + pattern.length < this.Match_MaxBits - this.Patch_Margin - + this.Patch_Margin) { + padding += this.Patch_Margin; + pattern = text.substring(patch.start2 - padding, + patch.start2 + patch.length1 + padding); + } + // Add one chunk for good luck. + padding += this.Patch_Margin; + // Add the prefix. + var prefix = text.substring(patch.start2 - padding, patch.start2); + if (prefix) { + patch.diffs.unshift([DIFF_EQUAL, prefix]); + } + // Add the suffix. + var suffix = text.substring(patch.start2 + patch.length1, + patch.start2 + patch.length1 + padding); + if (suffix) { + patch.diffs.push([DIFF_EQUAL, suffix]); + } + + // Roll back the start points. + patch.start1 -= prefix.length; + patch.start2 -= prefix.length; + // Extend the lengths. + patch.length1 += prefix.length + suffix.length; + patch.length2 += prefix.length + suffix.length; +}; + + +/** + * Compute a list of patches to turn text1 into text2. + * Use diffs if provided, otherwise compute it ourselves. + * There are four ways to call this function, depending on what data is + * available to the caller: + * Method 1: + * a = text1, b = text2 + * Method 2: + * a = diffs + * Method 3 (optimal): + * a = text1, b = diffs + * Method 4 (deprecated, use method 3): + * a = text1, b = text2, c = diffs + * + * @param {string|Array.>} a text1 (methods 1,3,4) or + * Array of diff tuples for text1 to text2 (method 2). + * @param {string|Array.>} opt_b text2 (methods 1,4) or + * Array of diff tuples for text1 to text2 (method 3) or undefined (method 2). + * @param {string|Array.>} opt_c Array of diff tuples for + * text1 to text2 (method 4) or undefined (methods 1,2,3). + * @return {Array.} Array of patch objects. + */ +diff_match_patch.prototype.patch_make = function(a, opt_b, opt_c) { + var text1, diffs; + if (typeof a == 'string' && typeof opt_b == 'string' && + typeof opt_c == 'undefined') { + // Method 1: text1, text2 + // Compute diffs from text1 and text2. + text1 = a; + diffs = this.diff_main(text1, opt_b, true); + if (diffs.length > 2) { + this.diff_cleanupSemantic(diffs); + this.diff_cleanupEfficiency(diffs); + } + } else if (typeof a == 'object' && typeof opt_b == 'undefined' && + typeof opt_c == 'undefined') { + // Method 2: diffs + // Compute text1 from diffs. + diffs = a; + text1 = this.diff_text1(diffs); + } else if (typeof a == 'string' && typeof opt_b == 'object' && + typeof opt_c == 'undefined') { + // Method 3: text1, diffs + text1 = a; + diffs = opt_b; + } else if (typeof a == 'string' && typeof opt_b == 'string' && + typeof opt_c == 'object') { + // Method 4: text1, text2, diffs + // text2 is not used. + text1 = a; + diffs = opt_c; + } else { + throw new Error('Unknown call format to patch_make.'); + } + + if (diffs.length === 0) { + return []; // Get rid of the null case. + } + var patches = []; + var patch = new patch_obj(); + var patchDiffLength = 0; // Keeping our own length var is faster in JS. + var char_count1 = 0; // Number of characters into the text1 string. + var char_count2 = 0; // Number of characters into the text2 string. + // Start with text1 (prepatch_text) and apply the diffs until we arrive at + // text2 (postpatch_text). We recreate the patches one by one to determine + // context info. + var prepatch_text = text1; + var postpatch_text = text1; + for (var x = 0; x < diffs.length; x++) { + var diff_type = diffs[x][0]; + var diff_text = diffs[x][1]; + + if (!patchDiffLength && diff_type !== DIFF_EQUAL) { + // A new patch starts here. + patch.start1 = char_count1; + patch.start2 = char_count2; + } + + switch (diff_type) { + case DIFF_INSERT: + patch.diffs[patchDiffLength++] = diffs[x]; + patch.length2 += diff_text.length; + postpatch_text = postpatch_text.substring(0, char_count2) + diff_text + + postpatch_text.substring(char_count2); + break; + case DIFF_DELETE: + patch.length1 += diff_text.length; + patch.diffs[patchDiffLength++] = diffs[x]; + postpatch_text = postpatch_text.substring(0, char_count2) + + postpatch_text.substring(char_count2 + + diff_text.length); + break; + case DIFF_EQUAL: + if (diff_text.length <= 2 * this.Patch_Margin && + patchDiffLength && diffs.length != x + 1) { + // Small equality inside a patch. + patch.diffs[patchDiffLength++] = diffs[x]; + patch.length1 += diff_text.length; + patch.length2 += diff_text.length; + } else if (diff_text.length >= 2 * this.Patch_Margin) { + // Time for a new patch. + if (patchDiffLength) { + this.patch_addContext(patch, prepatch_text); + patches.push(patch); + patch = new patch_obj(); + patchDiffLength = 0; + // Unlike Unidiff, our patch lists have a rolling context. + // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff + // Update prepatch text & pos to reflect the application of the + // just completed patch. + prepatch_text = postpatch_text; + char_count1 = char_count2; + } + } + break; + } + + // Update the current character count. + if (diff_type !== DIFF_INSERT) { + char_count1 += diff_text.length; + } + if (diff_type !== DIFF_DELETE) { + char_count2 += diff_text.length; + } + } + // Pick up the leftover patch if not empty. + if (patchDiffLength) { + this.patch_addContext(patch, prepatch_text); + patches.push(patch); + } + + return patches; +}; + + +/** + * Given an array of patches, return another array that is identical. + * @param {Array.} patches Array of patch objects. + * @return {Array.} Array of patch objects. + */ +diff_match_patch.prototype.patch_deepCopy = function(patches) { + // Making deep copies is hard in JavaScript. + var patchesCopy = []; + for (var x = 0; x < patches.length; x++) { + var patch = patches[x]; + var patchCopy = new patch_obj(); + patchCopy.diffs = []; + for (var y = 0; y < patch.diffs.length; y++) { + patchCopy.diffs[y] = patch.diffs[y].slice(); + } + patchCopy.start1 = patch.start1; + patchCopy.start2 = patch.start2; + patchCopy.length1 = patch.length1; + patchCopy.length2 = patch.length2; + patchesCopy[x] = patchCopy; + } + return patchesCopy; +}; + + +/** + * Merge a set of patches onto the text. Return a patched text, as well + * as a list of true/false values indicating which patches were applied. + * @param {Array.} patches Array of patch objects. + * @param {string} text Old text. + * @return {Array.>} Two element Array, containing the + * new text and an array of boolean values. + */ +diff_match_patch.prototype.patch_apply = function(patches, text) { + if (patches.length == 0) { + return [text, []]; + } + + // Deep copy the patches so that no changes are made to originals. + patches = this.patch_deepCopy(patches); + + var nullPadding = this.patch_addPadding(patches); + text = nullPadding + text + nullPadding; + + this.patch_splitMax(patches); + // delta keeps track of the offset between the expected and actual location + // of the previous patch. If there are patches expected at positions 10 and + // 20, but the first patch was found at 12, delta is 2 and the second patch + // has an effective expected position of 22. + var delta = 0; + var results = []; + for (var x = 0; x < patches.length; x++) { + var expected_loc = patches[x].start2 + delta; + var text1 = this.diff_text1(patches[x].diffs); + var start_loc; + var end_loc = -1; + if (text1.length > this.Match_MaxBits) { + // patch_splitMax will only provide an oversized pattern in the case of + // a monster delete. + start_loc = this.match_main(text, text1.substring(0, this.Match_MaxBits), + expected_loc); + if (start_loc != -1) { + end_loc = this.match_main(text, + text1.substring(text1.length - this.Match_MaxBits), + expected_loc + text1.length - this.Match_MaxBits); + if (end_loc == -1 || start_loc >= end_loc) { + // Can't find valid trailing context. Drop this patch. + start_loc = -1; + } + } + } else { + start_loc = this.match_main(text, text1, expected_loc); + } + if (start_loc == -1) { + // No match found. :( + results[x] = false; + // Subtract the delta for this failed patch from subsequent patches. + delta -= patches[x].length2 - patches[x].length1; + } else { + // Found a match. :) + results[x] = true; + delta = start_loc - expected_loc; + var text2; + if (end_loc == -1) { + text2 = text.substring(start_loc, start_loc + text1.length); + } else { + text2 = text.substring(start_loc, end_loc + this.Match_MaxBits); + } + if (text1 == text2) { + // Perfect match, just shove the replacement text in. + text = text.substring(0, start_loc) + + this.diff_text2(patches[x].diffs) + + text.substring(start_loc + text1.length); + } else { + // Imperfect match. Run a diff to get a framework of equivalent + // indices. + var diffs = this.diff_main(text1, text2, false); + if (text1.length > this.Match_MaxBits && + this.diff_levenshtein(diffs) / text1.length > + this.Patch_DeleteThreshold) { + // The end points match, but the content is unacceptably bad. + results[x] = false; + } else { + this.diff_cleanupSemanticLossless(diffs); + var index1 = 0; + var index2; + for (var y = 0; y < patches[x].diffs.length; y++) { + var mod = patches[x].diffs[y]; + if (mod[0] !== DIFF_EQUAL) { + index2 = this.diff_xIndex(diffs, index1); + } + if (mod[0] === DIFF_INSERT) { // Insertion + text = text.substring(0, start_loc + index2) + mod[1] + + text.substring(start_loc + index2); + } else if (mod[0] === DIFF_DELETE) { // Deletion + text = text.substring(0, start_loc + index2) + + text.substring(start_loc + this.diff_xIndex(diffs, + index1 + mod[1].length)); + } + if (mod[0] !== DIFF_DELETE) { + index1 += mod[1].length; + } + } + } + } + } + } + // Strip the padding off. + text = text.substring(nullPadding.length, text.length - nullPadding.length); + return [text, results]; +}; + + +/** + * Add some padding on text start and end so that edges can match something. + * Intended to be called only from within patch_apply. + * @param {Array.} patches Array of patch objects. + * @return {string} The padding string added to each side. + */ +diff_match_patch.prototype.patch_addPadding = function(patches) { + var paddingLength = this.Patch_Margin; + var nullPadding = ''; + for (var x = 1; x <= paddingLength; x++) { + nullPadding += String.fromCharCode(x); + } + + // Bump all the patches forward. + for (var x = 0; x < patches.length; x++) { + patches[x].start1 += paddingLength; + patches[x].start2 += paddingLength; + } + + // Add some padding on start of first diff. + var patch = patches[0]; + var diffs = patch.diffs; + if (diffs.length == 0 || diffs[0][0] != DIFF_EQUAL) { + // Add nullPadding equality. + diffs.unshift([DIFF_EQUAL, nullPadding]); + patch.start1 -= paddingLength; // Should be 0. + patch.start2 -= paddingLength; // Should be 0. + patch.length1 += paddingLength; + patch.length2 += paddingLength; + } else if (paddingLength > diffs[0][1].length) { + // Grow first equality. + var extraLength = paddingLength - diffs[0][1].length; + diffs[0][1] = nullPadding.substring(diffs[0][1].length) + diffs[0][1]; + patch.start1 -= extraLength; + patch.start2 -= extraLength; + patch.length1 += extraLength; + patch.length2 += extraLength; + } + + // Add some padding on end of last diff. + patch = patches[patches.length - 1]; + diffs = patch.diffs; + if (diffs.length == 0 || diffs[diffs.length - 1][0] != DIFF_EQUAL) { + // Add nullPadding equality. + diffs.push([DIFF_EQUAL, nullPadding]); + patch.length1 += paddingLength; + patch.length2 += paddingLength; + } else if (paddingLength > diffs[diffs.length - 1][1].length) { + // Grow last equality. + var extraLength = paddingLength - diffs[diffs.length - 1][1].length; + diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength); + patch.length1 += extraLength; + patch.length2 += extraLength; + } + + return nullPadding; +}; + + +/** + * Look through the patches and break up any which are longer than the maximum + * limit of the match algorithm. + * @param {Array.} patches Array of patch objects. + */ +diff_match_patch.prototype.patch_splitMax = function(patches) { + for (var x = 0; x < patches.length; x++) { + if (patches[x].length1 > this.Match_MaxBits) { + var bigpatch = patches[x]; + // Remove the big old patch. + 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) { + // Create one of several smaller patches. + 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 < patch_size - this.Patch_Margin) { + var diff_type = bigpatch.diffs[0][0]; + var diff_text = bigpatch.diffs[0][1]; + if (diff_type === DIFF_INSERT) { + // Insertions are harmless. + patch.length2 += diff_text.length; + start2 += diff_text.length; + patch.diffs.push(bigpatch.diffs.shift()); + empty = false; + } else if (diff_type === DIFF_DELETE && patch.diffs.length == 1 && + patch.diffs[0][0] == DIFF_EQUAL && + diff_text.length > 2 * patch_size) { + // This is a large deletion. Let it pass in one chunk. + patch.length1 += diff_text.length; + start1 += diff_text.length; + empty = false; + patch.diffs.push([diff_type, diff_text]); + bigpatch.diffs.shift(); + } else { + // Deletion or equality. Only take as much as we can stomach. + diff_text = diff_text.substring(0, patch_size - patch.length1 - + this.Patch_Margin); + patch.length1 += diff_text.length; + start1 += diff_text.length; + if (diff_type === DIFF_EQUAL) { + patch.length2 += diff_text.length; + start2 += diff_text.length; + } else { + empty = false; + } + patch.diffs.push([diff_type, diff_text]); + if (diff_text == bigpatch.diffs[0][1]) { + bigpatch.diffs.shift(); + } else { + bigpatch.diffs[0][1] = + bigpatch.diffs[0][1].substring(diff_text.length); + } + } + } + // Compute the head context for the next patch. + precontext = this.diff_text2(patch.diffs); + precontext = + precontext.substring(precontext.length - this.Patch_Margin); + // Append the end context for this patch. + var postcontext = this.diff_text1(bigpatch.diffs) + .substring(0, this.Patch_Margin); + if (postcontext !== '') { + patch.length1 += postcontext.length; + patch.length2 += postcontext.length; + if (patch.diffs.length !== 0 && + patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL) { + patch.diffs[patch.diffs.length - 1][1] += postcontext; + } else { + patch.diffs.push([DIFF_EQUAL, postcontext]); + } + } + if (!empty) { + patches.splice(++x, 0, patch); + } + } + } + } +}; + + +/** + * Take a list of patches and return a textual representation. + * @param {Array.} patches Array of patch objects. + * @return {string} Text representation of patches. + */ +diff_match_patch.prototype.patch_toText = function(patches) { + var text = []; + for (var x = 0; x < patches.length; x++) { + text[x] = patches[x]; + } + return text.join(''); +}; + + +/** + * Parse a textual representation of patches and return a list of patch objects. + * @param {string} textline Text representation of patches. + * @return {Array.} Array of patch objects. + * @throws {Error} If invalid input. + */ +diff_match_patch.prototype.patch_fromText = function(textline) { + var patches = []; + if (!textline) { + return patches; + } + // Opera doesn't know how to decode char 0. + textline = textline.replace(/%00/g, '\0'); + var text = textline.split('\n'); + var textPointer = 0; + while (textPointer < text.length) { + var m = text[textPointer].match(/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/); + if (!m) { + throw new Error('Invalid patch string: ' + text[textPointer]); + } + var patch = new patch_obj(); + patches.push(patch); + patch.start1 = parseInt(m[1], 10); + if (m[2] === '') { + patch.start1--; + patch.length1 = 1; + } else if (m[2] == '0') { + patch.length1 = 0; + } else { + patch.start1--; + patch.length1 = parseInt(m[2], 10); + } + + patch.start2 = parseInt(m[3], 10); + if (m[4] === '') { + patch.start2--; + patch.length2 = 1; + } else if (m[4] == '0') { + patch.length2 = 0; + } else { + patch.start2--; + patch.length2 = parseInt(m[4], 10); + } + textPointer++; + + while (textPointer < text.length) { + var sign = text[textPointer].charAt(0); + try { + var line = decodeURI(text[textPointer].substring(1)); + } catch (ex) { + // Malformed URI sequence. + throw new Error('Illegal escape in patch_fromText: ' + line); + } + if (sign == '-') { + // Deletion. + patch.diffs.push([DIFF_DELETE, line]); + } else if (sign == '+') { + // Insertion. + patch.diffs.push([DIFF_INSERT, line]); + } else if (sign == ' ') { + // Minor equality. + patch.diffs.push([DIFF_EQUAL, line]); + } else if (sign == '@') { + // Start of next patch. + break; + } else if (sign === '') { + // Blank line? Whatever. + } else { + // WTF? + throw new Error('Invalid patch mode "' + sign + '" in: ' + line); + } + textPointer++; + } + } + return patches; +}; + + +/** + * Class representing one patch operation. + * @constructor + */ +function patch_obj() { + /** @type {Array.>} */ + this.diffs = []; + /** @type {number?} */ + this.start1 = null; + /** @type {number?} */ + this.start2 = null; + /** @type {number} */ + this.length1 = 0; + /** @type {number} */ + this.length2 = 0; +} + + +/** + * Emmulate GNU diff's format. + * Header: @@ -382,8 +481,9 @@ + * Indicies are printed as 1-based, not 0-based. + * @return {string} The GNU diff string. + */ +patch_obj.prototype.toString = function() { + var coords1, coords2; + if (this.length1 === 0) { + coords1 = this.start1 + ',0'; + } else if (this.length1 == 1) { + coords1 = this.start1 + 1; + } else { + coords1 = (this.start1 + 1) + ',' + this.length1; + } + if (this.length2 === 0) { + coords2 = this.start2 + ',0'; + } else if (this.length2 == 1) { + coords2 = this.start2 + 1; + } else { + coords2 = (this.start2 + 1) + ',' + this.length2; + } + var text = ['@@ -' + coords1 + ' +' + coords2 + ' @@\n']; + var op; + // Escape the body of the patch with %xx notation. + for (var x = 0; x < this.diffs.length; x++) { + switch (this.diffs[x][0]) { + case DIFF_INSERT: + op = '+'; + break; + case DIFF_DELETE: + op = '-'; + break; + case DIFF_EQUAL: + op = ' '; + break; + } + text[x + 1] = op + encodeURI(this.diffs[x][1]) + '\n'; + } + // Opera doesn't know how to encode char 0. + return text.join('').replace(/\x00/g, '%00').replace(/%20/g, ' '); +}; + + +// Export these global variables so that they survive Google's JS compiler. +window['diff_match_patch'] = diff_match_patch; +window['patch_obj'] = patch_obj; +window['DIFF_DELETE'] = DIFF_DELETE; +window['DIFF_INSERT'] = DIFF_INSERT; +window['DIFF_EQUAL'] = DIFF_EQUAL; + diff --git a/Specs/SlickSpec/getgetter.js b/Specs/SlickSpec/getgetter.js new file mode 100644 index 000000000..5e8dddc21 --- /dev/null +++ b/Specs/SlickSpec/getgetter.js @@ -0,0 +1,63 @@ +// -*- Mode: JavaScript; tab-width: 4; -*- + +(function(){ + + window.scripts_to_get = parent.scripts_to_get || window.location.search.match(/\bscript=(.*?\.js)/gi) || ['http://mootools.github.com/slick/slick.js','bootstrap/slick.slickspec.js']; + + for (var i=0, scriptsrc; scriptsrc = scripts_to_get[i]; i++){ + + scripts_to_get[i] = scriptsrc = decodeURIComponent(scriptsrc.replace(/^(&?script=)+/,'')); + + scriptsrc.replace(/^(?!=http|\/)/,'../'); + + var written; + if (document.write){ + try { + document.write('<\/script>'); + written = true; + } catch(e){ + written = false; + } + } + + if (!written && document.documentElement.nodeName == 'HTML'){ + var script = document.createElement('script'); + script.setAttribute('src', scriptsrc); + script.setAttribute('type', 'text/javascript'); + document.documentElement.appendChild(script); + } + + // else evalRemote(scriptsrc); + + if (/\bbootstrap\b/.test(scriptsrc)) scripts_to_get.splice(i,1); + + } + + this.frameworkName = scripts_to_get[0].replace(/^.*\//,''); + + // function evalRemote(url){ + // if (!(/^(\/|http:)/).test(url) && /\bmocks\b/.test(document.location.href)) url = '../' + url; + // + // var code = getResource(url); + // + // try { + // globalEval(code); + // } catch(e){ + // try{console.log(e);}catch(e){}; + // } + // }; + // + // function getResource(url) { + // if (!(XMLHttpRequest || ActiveXObject)) return false; + // request = (XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); + // if (!request) return false; + // request.open("GET", url + '?' + Math.random().toString(32), false); + // // try { + // request.send(null); + // // } catch(e){} + // + // if (request.status != 200) return false; + // return request.responseText; + // } + // +})(); diff --git a/Specs/SlickSpec/ie.css b/Specs/SlickSpec/ie.css new file mode 100644 index 000000000..94c336e15 --- /dev/null +++ b/Specs/SlickSpec/ie.css @@ -0,0 +1,37 @@ +/* +curl -s http://tripledoubleyou.subtlegradient.com/c/blueprint/ie.css #*/ +/* ----------------------------------------------------------------------- + + + Blueprint CSS Framework 0.9 + http://blueprintcss.org + + * Copyright (c) 2007-Present. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* ie.css */ +body {text-align:center;} +.container {text-align:left;} +* html .column, * html div.span-1, * html div.span-2, * html div.span-3, * html div.span-4, * html div.span-5, * html div.span-6, * html div.span-7, * html div.span-8, * html div.span-9, * html div.span-10, * html div.span-11, * html div.span-12, * html div.span-13, * html div.span-14, * html div.span-15, * html div.span-16, * html div.span-17, * html div.span-18, * html div.span-19, * html div.span-20, * html div.span-21, * html div.span-22, * html div.span-23, * html div.span-24 {display:inline;overflow-x:hidden;} +* html legend {margin:0px -8px 16px 0;padding:0;} +sup {vertical-align:text-top;} +sub {vertical-align:text-bottom;} +html>body p code {*white-space:normal;} +hr {margin:-8px auto 11px;} +img {-ms-interpolation-mode:bicubic;} +.clearfix, .container {display:inline-block;} +* html .clearfix, * html .container {height:1%;} +fieldset {padding-top:0;} +textarea {overflow:auto;} +input.text, input.title, textarea {background-color:#fff;border:1px solid #bbb;} +input.text:focus, input.title:focus {border-color:#666;} +input.text, input.title, textarea, select {margin:0.5em 0;} +input.checkbox, input.radio {position:relative;top:.25em;} +form.inline div, form.inline p {vertical-align:middle;} +form.inline label {position:relative;top:-0.25em;} +form.inline input.checkbox, form.inline input.radio, form.inline input.button, form.inline button {margin:0.5em 0;} +button, input.button {position:relative;top:0.25em;} diff --git a/Specs/SlickSpec/moobugger/bookmarklet.html b/Specs/SlickSpec/moobugger/bookmarklet.html new file mode 100644 index 000000000..06b2aff2c --- /dev/null +++ b/Specs/SlickSpec/moobugger/bookmarklet.html @@ -0,0 +1,46 @@ + + + + + + + bugger + + + + + + + + +
+

The MooBugger.

+

moobugger - bookmark it!

+
+ + + + \ No newline at end of file diff --git a/Specs/SlickSpec/moobugger/debugger-iframe.js b/Specs/SlickSpec/moobugger/debugger-iframe.js new file mode 100644 index 000000000..a30d1d8f9 --- /dev/null +++ b/Specs/SlickSpec/moobugger/debugger-iframe.js @@ -0,0 +1,386 @@ +/* +Script: Debugger.js + Creates Firebug style debugger for browsers without Firebug. + +License: + MIT-style license. +*/ + +var FOR_IN_MAX = 20; + +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': + try{ + 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(', ')); + if (x > FOR_IN_MAX){ + holder.adopt(new Element('span').setHTML('and '+ (length - x) +' more properties…')); + break; + } + } + holder.adopt(new Element('span').setHTML('}')); + }catch(e){ + new Element('span').addClass(chunk.type).appendText(chunk.value).inject(holder); + } + 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 el_style = el.style; + if (!el_style) el_style = {}; + + 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/Specs/SlickSpec/moobugger/debugger.css b/Specs/SlickSpec/moobugger/debugger.css new file mode 100644 index 000000000..ecc6991a8 --- /dev/null +++ b/Specs/SlickSpec/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/Specs/SlickSpec/moobugger/debugger.html b/Specs/SlickSpec/moobugger/debugger.html new file mode 100644 index 000000000..60dd577a7 --- /dev/null +++ b/Specs/SlickSpec/moobugger/debugger.html @@ -0,0 +1,25 @@ + + + + + debugger + + + + + +

+
+ + + + + +
+
+
+ +
+
+ + \ No newline at end of file diff --git a/Specs/SlickSpec/moobugger/debugger.js b/Specs/SlickSpec/moobugger/debugger.js new file mode 100644 index 000000000..166b72d11 --- /dev/null +++ b/Specs/SlickSpec/moobugger/debugger.js @@ -0,0 +1,284 @@ +var Moo = { + + defined: function(obj){ + return (obj != undefined); + }, + + type: function(obj){ + if (obj == null) return false; + 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){ + var i = 0; + for (var property in properties){ + item[property] = properties[property]; + if (i++ > 10) break; + } + } + +}; + +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(){ + + document.documentElement.className = document.documentElement.className + ' moobugger'; + + debug.spacer = document.createElement('div'); + debug.spacer.className = 'debug-spacer'; + 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 = []; + document.documentElement.className = document.documentElement.className.replace(/ ?moobugger ?/,' '); + Moo.Element.remove(debug.iFrame); + Moo.Element.remove(debug.spacer); + Moo.Element.remove(document.getElementById('debug-bookmarklet')); + }, + + evaluate: function(value){ + try { + var evaluation = value; + if (typeof value == 'string') + evaluation = eval(value); + if (evaluation !== debug.frame.debug.$nil){ + if (evaluation == window) evaluation = {'window': '[native code]'}; + if (evaluation.nodeType === 9) 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); +} + +if (!window.onerror) +window.onerror = function(error, url, line){ + console.error({error:error, url:url, line:line}); + return true; +} + diff --git a/Specs/SlickSpec/moobugger/images/close.png b/Specs/SlickSpec/moobugger/images/close.png new file mode 100644 index 0000000000000000000000000000000000000000..17fc775e803c88b6131986b1bac4c02e9814a13b GIT binary patch literal 508 zcmV2|(*&;8E%F1u)e#ssF7JV&46$O|x`;-B?knMO4A8J`OsC%yy;W`)Nyu9lU97kI!_ z4PY!=Vp##p_=>1re=V`FLLCNFUjW{oVN}dTNm!JH;M4|+yZRwKrLYX6lSJ)`qPx85 z4ti57xW5X)QVQ zkEc!!5IfwLQ_2j@cUBQ6fm7vh)`YI8^d?e?_Zd;*tE2h0xmE6RYdN!lzoh70uWr09 y4G$d=J!2MGOFu~HAT$#S@c)Vt&Ix=Xn4C0000M5skAD!Pd7bWugDE?fo|x)DT0K`T;(mex-+1Wb)d zrO=qqB=etn-lx-&y74iGVcxyx+&lLk0h^CN@DTh2uX|?^41!Hy?TPD$6N1;aU}!A0 zXFQ%v4pE*^D-=GxS^AoptYeYlsw=QT6bX^p-CbAqPF+01q!=7WA$bPT@qpz^$WGs$ z9?jJ*Q=ZJpf=ljv-QRUJb^p$U+R8&;n5AOk-;hUue{dK+Er{&-^sUiv@&yXCczfQd zAO??Kns}fG*Py?93BenHRVjmMO^AUA?3E%|Pba#2wvEIWK0kS7;wP8&AK4`xXHo>( z+zW`ID9q9q^xa%U@5v0T)dC6mVdb)L5+RHwA}2V96TPv7w9isj!E}Srg0)tJs;X$J z8m#IHm_h%m>9EZ@Lhq>~5zr-VK-N6-!Fw9>qd?{jSCF!Xcn2H0e|>xd4g z&=?QL*#HkVYsf9J=)+0W-_xh^ujT${a?^cpnEbZ@0|0E3`{(kt{~Q1S002ovPDHLk FV1g+>H|+ob literal 0 HcmV?d00001 diff --git a/Specs/SlickSpec/moobugger/images/group-close.png b/Specs/SlickSpec/moobugger/images/group-close.png new file mode 100644 index 0000000000000000000000000000000000000000..c2a8676938c598b1ac53426ca7b7f4fa9e285374 GIT binary patch literal 304 zcmV-00nh%4P)2He#l-g4l~c8sV<%UUgmfT5GDR zikNdQgh1Z=w{z|Zz#wd`C1VT$0+1kt;ceS`WC1Wj2m`{kQYxFU?|XX20ODsL2+Op1 zf7kth2w?m;j?}hovGF|5G)>b5Knr;Vk{zAqKV10TgbUCPJmsvepv_ zX?3@4WIB!`zC#v(z~0H8A1Pd#ApIP&{O_;v6<`49$5oy&TJhZg0000&AY z;G?eVuQW~XT5F1;h?IKuF*8|fzl|}CMrOcSmQj)<1k*4K4($8h!O(FWcd#%hK!9Pw zy{al_$n)Ht=Xp{bqjO>LMH>JisYcgzIS@$@PdLP_X&RpAnYV3wt7TcZZCea})82)$ zKJ(v@{=+>OFrXiLnkM(wb=@zh^{W8`7e(PrsD>!ZGE|qf1_S%m`E9K08bAbEecl-c xFje)?^U^@RCwBA{Qv(y137>NL@+WkVwLPF zE%gObn_&F1?rugDjkv)7fB)c`-hTLC4Wzh$_#24NgiqtYfB(Sv;j?GjU32GNXv)pi zYA-DOkJrZ5{Cr=KCJ^9cXBPl!(qv|0It>-$!m6<;C&%~i-@kBY^7HTcbm zAL}zSQ8b~0Z{NR%f&&y39k5WXNlirwMY!T0KSKK!FW!bE^b@YJG9dw{rim+7fHeIC zVz^tu8q4G2aB7;edNqb7cy#>v^Ji1n;>9eVzkUq`vO#*Y| z?LR7*2DcHPrn}d!Wv*MW04`SA)dg}HBca@pxpv+>I48cakm2XgpR@l%{5GAa+>usQ z#ULOeGW-4O*Qp&vMPNf&a5?k#)vFA!-0|bvHxN#p*VDs*(~lrcx2{~tTsdc8_vl%q>^&t@q)WpHT0r4YP z(}fF}izZIQ&=i-S&!DKGF&h{QndrG=+V%72GZ*ytV`xeMMuC!+7T5;#+yS!fe^F#4 zI9Xgddlt+FVG#Srj~}yuN|>?v6*+e>Xd4-U*-6F43@X~%*lj`%l*^}2{|Dv{Fb1*l h*@QDO6RQazzyRdMdkwE%pN9Yd002ovPDHLkV1fXqEhhi~ literal 0 HcmV?d00001 diff --git a/Specs/SlickSpec/moobugger/images/info.png b/Specs/SlickSpec/moobugger/images/info.png new file mode 100644 index 0000000000000000000000000000000000000000..cd34f124d7597a9a631eae83fc3ef32a7bb65e06 GIT binary patch literal 674 zcmV;T0$u%yP)1=kPP^UX0`=`AI_Y%ph@+NwUim|1Jjz;8cI> z$#b1O;pVzl+XhRnWM}8&AKzelaFXKrVu2FqAywC1i9URA{miXK(F1N+upN>@iyHeedqoQLb@}&nVaj)d4WS_QbNo`T!#I-@4%Ulp8P%Y^Y^dBso?Bqu zF~H|RXKM}ex&_k$6y1av2)0m@f^#DZIg3eo6B;K_v#^}z`2FH2Vv#0#vhJQ~RLsdK zs77g;#?nG+I;)uAmgOe>*w7$J5)^q8D;d56(v_)g6WP`6gfmqKXLmsXc9RMmz^s;)ar#yNwcP(qt{1;0lm8K50QeIJM%|0PkpKVy07*qo IM6N<$f-pTY+yDRo literal 0 HcmV?d00001 diff --git a/Specs/SlickSpec/moobugger/images/lick.png b/Specs/SlickSpec/moobugger/images/lick.png new file mode 100644 index 0000000000000000000000000000000000000000..556e247fa0a42d74c9babd5560d3c6540c3ce513 GIT binary patch literal 285 zcmV+&0pk9NP)ooZ1~Et# z2LYzP|Ni*_F#{BDN^V^150W5N90V9aL|n~ke_Bm6Qp6d(^OyJn z8Jl2E{`LJ+=P)c!mct+Sh4 zylCDr472-Y=IzXpi389>6n0|_mZKp^Qw@MXCj>y%;c!~3!~WU2Xi!Wjr41-%;s9nO z3shqez|RjC+_b~3orsm9vN}7yF0>PA z@OPrrU(u`N$&*M7uz#H?F78EuNU9aKG|M;q9fCwq3t1`&H+^Drt0?#2jl5DVDXD%* z5-B5pkM4uwud&B;Gv^9t1`i_5v68k_30-5K{jt%QEImidbXsG(6>OrSzeQjkHAkBfnYg_(f~P1nEw z|E2%@`CHA+$)*bAMzH{GNS2cnVvrK!XW(RKWnf}Lvj(Q|-+zWbfB*RcneHq=Cy5I3 zapKhg0w6gS1}07*(~Jq^2Ub>Qyc&=-0s#*T$oY&w80f6eAR@?vRq>nmUl`W!y$I*C zz!+b?d|_Z^`ioW5hYz0^KD>X!ARs7$s%iJhyI_ewzkg%Z$im8sX%h&*Od{wvV8p%t z&+wlp#jGsM-@%%IF+KP9@4w)9AOxgD`LBSy&jd^w^_(1R>w%iS;?l^*%KR0W0M0s^ zs~rV$&oKV~4_3$w#9lyb1jM{JEcy(@=YV({K!5=No<3iWc~NV%00000NkvXXu0mjf DN9efU literal 0 HcmV?d00001 diff --git a/Specs/SlickSpec/moobugger/images/mootools.png b/Specs/SlickSpec/moobugger/images/mootools.png new file mode 100644 index 0000000000000000000000000000000000000000..e26a1dca57b83b930f106eb9799a8297bc790339 GIT binary patch literal 3769 zcmV;q4o2~bP)Eu%qO?>jic(ROO2tKKQItwWsjM_?P%4!MrD8EO z5GoBDC@UKX8#Xi$c=my8$j%|(;5g3AIrq+eZ>_l>T=Mhg&7HaTeCO|;J2Pi`dYU{u zW(yuZd}#aC>Y%L-+Gx-Qvkt7St<8O%6@IEbJXDwp+805)7qq>l?#vU@!{cdu60{Ez zh}i?nc{FHW2CdQ))5D`Y=m^?-LF-KTtS9pOn?d{B6Vt<^JP6&?B?+JP1+5tQyE|wn zJuy8zN{a@Q|)tu zHjaLWXeO(7-|)QaaGqx!g`o9gTwS9wGNy~r*8|MuearJ*qM5?ri~QXu~|NhK!`4h<>i4-*M%<*Et|1E1`p~2XIcI zP>BA`7Uj*1<3qx1rkT>EmW*SWoX3K8A>lI~5Uxku3agfcNs#3P&Lv?!uBkgmyukOj zCuld68n+vL&bRE31?qIrjtEx!S0&+}Mf77#ZyS7PMbJLNPaCU!0!ptS9LuEtdyac! za=(OoOfwSmA>(}PAY{2Oe?-7uED&?46 zuqxG#go(+rJEK1yaNb?e?$E-lfwvI{YxG~9gRtT<Fz<^JA`nHW%}Pi`!q?;D#|1T-5}PP9Bw90?5W7#jTnTk5?ymA+?*)k_rX%u zm7qUXGT$V`QjPTdpdEA8m=HsMg;2^Rc)(3(|XKRh8V(#}{GSBe73x(8?<;otV zGVIRIiPzv#--3oJHCQWt2rGK34E^z>FN`EGx)5(^Fh4_S6jNN~xRq%x!##4m`3eO4 zV}Up>FojSd&8@vFShzUW#PSeq(0Txxf>8D$(?R4(>xx5vN&9({#eny7_^C$ z&_%0sIsdRT_P=Y6JU5n^r5tz0iTN#=?JXOK_||!2ydt^HJl+POZl)x0mP063IO=Z_ zlXjMpmq41}w(L^6!Y@(sPKGSE?bnP@fv;qcb$Lt=L#>7hB#BLkUX zMRgT(IuS{-tU_$MO&KC_w)Xv$FhWz3#|rn)^ki0*UDqEJvONTYAoann^(NaG^RuA+ z5$xvnhlD^_10Li}IM?r?(M~uZ$oinIgz%(gR`1}LcQTIAg4fQtPI5n`uS<^N^M#~a z5I1%2nuJNuTJ%4lAX8Y~vJlp8Ace5Yg0_XSv#+EiNvvbD{l~GiYZ4fMVjbT{Ps!#|?*eh7CAtY*s4DYc&hr-)| zu{H5z3b0O++;nDKujC~r%~5N{9AC(|){U_-Ex@BryV5ZvWMq$`J%5-wVdrzB@g&?i{UniM70B*?~t6mq4ZUWh-#Jjb8l zSv(={CdBMl4vds_x~x2pNpbOK!Q2LRqd7tj}2o_tR>P8y6=jp6my31sdkchIac+U~2g=`TqcF0h>MW5Va0SmVN-1GdC;WiiW5%z{G! zT2$sfTXM$h8aFKMJPnTKNu%sE-p`nWm|Z&_qY2m8WJ%008!TNrmsQ@<%5}y6flwok ziRr5FnYHZlGWXdje15-#1efl?RTY-DsN3c4pd|t+3x?My$t-&pnxqw1nQ@g+yDMTA z4cw|Mmw4PjD>fRC#6^8)mw_^HRXo2f(FEfD;=f;<{x zPEvB=wv>?RbVL&E-0*n1*o%2Un46@hQ?xrWCR};+YRY)Wy^*i8Je>+95wz~7WVu|& zmm%Jxe0wC1lG*MLzP_zFV<2fa!+Apjn8vA-!n`iXNlqrm=Z01=?`sCS1PjeBY*OJ$ zn*-U8TI6MlFr=O`UgKBcIKC`bW;f~hPc0{NABb%V-bZNjtRKGCZ-nH_5ScB>v|1)E z?g-~SnIoP)L*_eoc+JoDRRe7GE(yn+O^7e+h4HgVg8d9~O0~Ny(v+WTV!BHF*zDTx z2067ZW(_o!?S4R>&~FXn&G4B@QnF?b=@;c21d?Z!DN1FJta$!r=#B8PU*zy8&RAIL z)o=~7lnA?*#|+(Ajmw{vm)Ssak;c|6V*XawFynX^g1pHo=j|AbJ z4<&F{;qG5?Xe}jW*hBJ?%xcm$cq@ z!9tddT z%xgtk6=cuCMR*XJoh)6H?-3d-q?;gwUn%8jFXej<6|XUF5yA@+T;RMI#(5etlzY*} zmHjQmm@W~0t_!;&gC*{d$M+So+qRZP%twm3W3s$OZt7wsY=;-ZF7#i^&>zp+tCU`; z)ufPF7vs{LLCUEl^1F^P8wCLvcR=t-XuwA$m`Fb7ZhGI4(;#@Lt1?x_nJi)mtkZ$m+hIKIblT+b#b!PhDK zi5Rx-@*&KZWC&amlao+i#$r~E9giYbPDA3(s0zeJjSk#csievzvsH>vBiLTn_T_Q~Ehc_Fw$`MG+rgO(UkO_)W)a?kF!dT(_Rxjk!sB_c zTpH`klg*p5dDr!chu=XytRprUZX3h5+2)Ipb9lq3O9>N06oSep(p0*58 zn2_r+wzmzGTAO0NC1SE+I~Ox1m9U)Ba?g!4IjBNLXh4X8v^P2+44#YgBneAD+@dgb zzZ$=XPbQD<_3I=3V^Xq6_8}TCC9I{#4|bj#(Xl-%Kz0>i1$bYHh(GYz z!$TWx)KF<&P@9%_Xd~q-?3Ca#%ugcmZV!~uf|$qgqCoC@WWHrBjIUEehN{}yS}$hL zC|tZUyhIo+bAMChJ}cf4xtBE&kBZl#uR$3|Ue#Q9L?-L*9MWwe;c++>Ui>{~DMDf% zrzewBY{jleT;?p?L@d3YH6av2Lr@r zl2I~Tv-QOEn62PM6_*$C?vCh^TLV2VJ2Z`<*~0d^xVSmf)6;&6JZ59u-i26_;96cl zT*>coSpci~0$HqCyU5#kVtUM0VlsH|XVP<*3Wyu69_sCam_GUAF`L2lyPP2nGrl9R joQuiLllHCgKLG{+fRlZkYU|z%00000NkvXXu0mjfc;PBv literal 0 HcmV?d00001 diff --git a/Specs/SlickSpec/moobugger/images/time.png b/Specs/SlickSpec/moobugger/images/time.png new file mode 100644 index 0000000000000000000000000000000000000000..4ec395bb357e95049d83b1c45c47b221188143a9 GIT binary patch literal 616 zcmV-u0+;=XP)`Btfnm>{IlnXWpBWDRTpSvYCZJvEXA0U8O-0jwzj$5*JO~DZ*O5r%*6;UUpH3%k zFc^HVR;wSI&E{A1@AL;QpaIPqkH<5qRO-3I;Q(2dLDMwgI1Wam5#;mvx5Z-dHQxJ4 zFt5YrSSl|Ygt223UsaJ$_QjYelP`zE zA(YEy*zI-8EEiNqaAA%;L991cIV+wD-PR6rC(7KJWOr&Bl{ zj|}d1yUgeF`JNF&mAmqIJP%i^6)1|rqEWiD*$fJW0^8ecHgLIIU^bhu|5RnK*UL2H znRKqIrmE@?Q+YxFISmE_d!5oFqrJsq0qiNX+wD7qe=rdBEfE%-PUj6ppn{NIJOdm8 z;CY@!$02yvXf!^MI$oEcV$VKfsy5UYJ?kQf(kH#GR_lGOR(plV8*=?Ka@f;H*qU3D z$rPfg+3)ufX7s7k>3l)|_V1DV-;m4t_cG+a1Q-B^`vZz?fXXQV0000t+Ue1gR+{YC8OO*txphWUc9IHDM-goja5BcG+BBke$92q?G z71N^^hoa|}Pf?sIV7UUj$B)*X-gfZP5zU)LG4l{+E)G+T!zg_Q+t7ge=FUh@^()WS zNn@PiO#!-2bYSb=L;cru-*@O=o`A7xSXvs~%0rU9uvb#xem8=_`u0HfV1=hkeoKOwA+Pr;&5unQ-YG}21mToY> z?E(d-V45aMIg4(dCmX%j(qXd|)c8G3f+@G$F*IgdKj7FJl}RQ^fv)LrB$@(~$X+N9 z!m*ZN8(O)W0<@MAsdxV3=623Ba#9hj3Vl28()+~Zf@CAmMfO4wYC0DaT@|GoV=tD5 z%~%q0kQ!mo&8CX;W1ScrjS!^Le;(XNrOwXd`5XI+V9GfsGFaK;eDl;cdLn#1%~;nE zZJb3%YZ|iK1r~C_nNyJ*S-iaeF|HG%%asMNZ_Mz??%bl!=Vm)tErT3TAbXT@QO^4k zlDE|1-S=>uVhf@z|E%0#7;W3Ppx3hwO^m$x1;pOQaeH72ugPEhd*%MO + + + + + + 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/Specs/SlickSpec/screen.css b/Specs/SlickSpec/screen.css new file mode 100644 index 000000000..8a8ea9158 --- /dev/null +++ b/Specs/SlickSpec/screen.css @@ -0,0 +1,259 @@ +/* +curl -s http://tripledoubleyou.subtlegradient.com/c/blueprint/screen.css #*/ +/* ----------------------------------------------------------------------- + + + Blueprint CSS Framework 0.9 + http://blueprintcss.org + + * Copyright (c) 2007-Present. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* reset.css */ +html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;} +body {line-height:1.5;} +table {border-collapse:separate;border-spacing:0;} +caption, th, td {text-align:left;font-weight:normal;} +table, td, th {vertical-align:middle;} +blockquote:before, blockquote:after, q:before, q:after {content:"";} +blockquote, q {quotes:"" "";} +a img {border:none;} + +/* typography.css */ +html {font-size:100.01%;} +body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;} +h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;} +h1 {font-size:3em;line-height:1;margin-bottom:0.5em;} +h2 {font-size:2em;margin-bottom:0.75em;} +h3 {font-size:1.5em;line-height:1;margin-bottom:1em;} +h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;} +h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;} +h6 {font-size:1em;font-weight:bold;} +h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;} +p {margin:0 0 1.5em;} +p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;} +p img.right {float:right;margin:1.5em 0 1.5em 1.5em;} +a:focus, a:hover {color:#000;} +a {color:#009;text-decoration:underline;} +blockquote {margin:1.5em;color:#666;font-style:italic;} +strong {font-weight:bold;} +em, dfn {font-style:italic;} +dfn {font-weight:bold;} +sup, sub {line-height:0;} +abbr, acronym {border-bottom:1px dotted #666;} +address {margin:0 0 1.5em;font-style:italic;} +del {color:#666;} +pre {margin:1.5em 0;white-space:pre;} +pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;} +li ul, li ol {margin:0;} +ul, ol {margin:0 1.5em 1.5em 0;padding-left:3.333em;} +ul {list-style-type:disc;} +ol {list-style-type:decimal;} +dl {margin:0 0 1.5em 0;} +dl dt {font-weight:bold;} +dd {margin-left:1.5em;} +table {margin-bottom:1.4em;width:100%;} +th {font-weight:bold;} +thead th {background:#c3d9ff;} +th, td, caption {padding:4px 10px 4px 5px;} +tr.even td {background:#e5ecf9;} +tfoot {font-style:italic;} +caption {background:#eee;} +.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;} +.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;} +.hide {display:none;} +.quiet {color:#666;} +.loud {color:#000;} +.highlight {background:#ff0;} +.added {background:#060;color:#fff;} +.removed {background:#900;color:#fff;} +.first {margin-left:0;padding-left:0;} +.last {margin-right:0;padding-right:0;} +.top {margin-top:0;padding-top:0;} +.bottom {margin-bottom:0;padding-bottom:0;} + +/* forms.css */ +label {font-weight:bold;} +fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;} +legend {font-weight:bold;font-size:1.2em;} +input[type=text], input[type=password], input.text, input.title, textarea, select {background-color:#fff;border:1px solid #bbb;} +input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus, select:focus {border-color:#666;} +input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;} +input.text, input.title {width:300px;padding:5px;} +input.title {font-size:1.5em;} +textarea {width:390px;height:250px;padding:5px;} +input[type=checkbox], input[type=radio], input.checkbox, input.radio {position:relative;top:.25em;} +form.inline {line-height:3;} +form.inline p {margin-bottom:0;} +.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;} +.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;} +.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;} +.success {background:#E6EFC2;color:#264409;border-color:#C6D880;} +.error a {color:#8a1f11;} +.notice a {color:#514721;} +.success a {color:#264409;} + +/* grid.css */ +.container {width:950px;margin:0 auto;} +.showgrid {background:url(src/grid.png);} +.column, div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 {float:left;margin-right:10px;} +.last, div.last {margin-right:0;} +.span-1 {width:30px;} +.span-2 {width:70px;} +.span-3 {width:110px;} +.span-4 {width:150px;} +.span-5 {width:190px;} +.span-6 {width:230px;} +.span-7 {width:270px;} +.span-8 {width:310px;} +.span-9 {width:350px;} +.span-10 {width:390px;} +.span-11 {width:430px;} +.span-12 {width:470px;} +.span-13 {width:510px;} +.span-14 {width:550px;} +.span-15 {width:590px;} +.span-16 {width:630px;} +.span-17 {width:670px;} +.span-18 {width:710px;} +.span-19 {width:750px;} +.span-20 {width:790px;} +.span-21 {width:830px;} +.span-22 {width:870px;} +.span-23 {width:910px;} +.span-24, div.span-24 {width:950px;margin-right:0;} +input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 {border-left-width:1px!important;border-right-width:1px!important;padding-left:5px!important;padding-right:5px!important;} +input.span-1, textarea.span-1 {width:18px!important;} +input.span-2, textarea.span-2 {width:58px!important;} +input.span-3, textarea.span-3 {width:98px!important;} +input.span-4, textarea.span-4 {width:138px!important;} +input.span-5, textarea.span-5 {width:178px!important;} +input.span-6, textarea.span-6 {width:218px!important;} +input.span-7, textarea.span-7 {width:258px!important;} +input.span-8, textarea.span-8 {width:298px!important;} +input.span-9, textarea.span-9 {width:338px!important;} +input.span-10, textarea.span-10 {width:378px!important;} +input.span-11, textarea.span-11 {width:418px!important;} +input.span-12, textarea.span-12 {width:458px!important;} +input.span-13, textarea.span-13 {width:498px!important;} +input.span-14, textarea.span-14 {width:538px!important;} +input.span-15, textarea.span-15 {width:578px!important;} +input.span-16, textarea.span-16 {width:618px!important;} +input.span-17, textarea.span-17 {width:658px!important;} +input.span-18, textarea.span-18 {width:698px!important;} +input.span-19, textarea.span-19 {width:738px!important;} +input.span-20, textarea.span-20 {width:778px!important;} +input.span-21, textarea.span-21 {width:818px!important;} +input.span-22, textarea.span-22 {width:858px!important;} +input.span-23, textarea.span-23 {width:898px!important;} +input.span-24, textarea.span-24 {width:938px!important;} +.append-1 {padding-right:40px;} +.append-2 {padding-right:80px;} +.append-3 {padding-right:120px;} +.append-4 {padding-right:160px;} +.append-5 {padding-right:200px;} +.append-6 {padding-right:240px;} +.append-7 {padding-right:280px;} +.append-8 {padding-right:320px;} +.append-9 {padding-right:360px;} +.append-10 {padding-right:400px;} +.append-11 {padding-right:440px;} +.append-12 {padding-right:480px;} +.append-13 {padding-right:520px;} +.append-14 {padding-right:560px;} +.append-15 {padding-right:600px;} +.append-16 {padding-right:640px;} +.append-17 {padding-right:680px;} +.append-18 {padding-right:720px;} +.append-19 {padding-right:760px;} +.append-20 {padding-right:800px;} +.append-21 {padding-right:840px;} +.append-22 {padding-right:880px;} +.append-23 {padding-right:920px;} +.prepend-1 {padding-left:40px;} +.prepend-2 {padding-left:80px;} +.prepend-3 {padding-left:120px;} +.prepend-4 {padding-left:160px;} +.prepend-5 {padding-left:200px;} +.prepend-6 {padding-left:240px;} +.prepend-7 {padding-left:280px;} +.prepend-8 {padding-left:320px;} +.prepend-9 {padding-left:360px;} +.prepend-10 {padding-left:400px;} +.prepend-11 {padding-left:440px;} +.prepend-12 {padding-left:480px;} +.prepend-13 {padding-left:520px;} +.prepend-14 {padding-left:560px;} +.prepend-15 {padding-left:600px;} +.prepend-16 {padding-left:640px;} +.prepend-17 {padding-left:680px;} +.prepend-18 {padding-left:720px;} +.prepend-19 {padding-left:760px;} +.prepend-20 {padding-left:800px;} +.prepend-21 {padding-left:840px;} +.prepend-22 {padding-left:880px;} +.prepend-23 {padding-left:920px;} +div.border {padding-right:4px;margin-right:5px;border-right:1px solid #eee;} +div.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #eee;} +.pull-1 {margin-left:-40px;} +.pull-2 {margin-left:-80px;} +.pull-3 {margin-left:-120px;} +.pull-4 {margin-left:-160px;} +.pull-5 {margin-left:-200px;} +.pull-6 {margin-left:-240px;} +.pull-7 {margin-left:-280px;} +.pull-8 {margin-left:-320px;} +.pull-9 {margin-left:-360px;} +.pull-10 {margin-left:-400px;} +.pull-11 {margin-left:-440px;} +.pull-12 {margin-left:-480px;} +.pull-13 {margin-left:-520px;} +.pull-14 {margin-left:-560px;} +.pull-15 {margin-left:-600px;} +.pull-16 {margin-left:-640px;} +.pull-17 {margin-left:-680px;} +.pull-18 {margin-left:-720px;} +.pull-19 {margin-left:-760px;} +.pull-20 {margin-left:-800px;} +.pull-21 {margin-left:-840px;} +.pull-22 {margin-left:-880px;} +.pull-23 {margin-left:-920px;} +.pull-24 {margin-left:-960px;} +.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;} +.push-1 {margin:0 -40px 1.5em 40px;} +.push-2 {margin:0 -80px 1.5em 80px;} +.push-3 {margin:0 -120px 1.5em 120px;} +.push-4 {margin:0 -160px 1.5em 160px;} +.push-5 {margin:0 -200px 1.5em 200px;} +.push-6 {margin:0 -240px 1.5em 240px;} +.push-7 {margin:0 -280px 1.5em 280px;} +.push-8 {margin:0 -320px 1.5em 320px;} +.push-9 {margin:0 -360px 1.5em 360px;} +.push-10 {margin:0 -400px 1.5em 400px;} +.push-11 {margin:0 -440px 1.5em 440px;} +.push-12 {margin:0 -480px 1.5em 480px;} +.push-13 {margin:0 -520px 1.5em 520px;} +.push-14 {margin:0 -560px 1.5em 560px;} +.push-15 {margin:0 -600px 1.5em 600px;} +.push-16 {margin:0 -640px 1.5em 640px;} +.push-17 {margin:0 -680px 1.5em 680px;} +.push-18 {margin:0 -720px 1.5em 720px;} +.push-19 {margin:0 -760px 1.5em 760px;} +.push-20 {margin:0 -800px 1.5em 800px;} +.push-21 {margin:0 -840px 1.5em 840px;} +.push-22 {margin:0 -880px 1.5em 880px;} +.push-23 {margin:0 -920px 1.5em 920px;} +.push-24 {margin:0 -960px 1.5em 960px;} +.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:right;position:relative;} +.prepend-top {margin-top:1.5em;} +.append-bottom {margin-bottom:1.5em;} +.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;} +hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;} +hr.space {background:#fff;color:#fff;visibility:hidden;} +.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;} +.clearfix, .container {display:block;} +.clear {clear:both;} diff --git a/Specs/SlickSpec/simple_request.js b/Specs/SlickSpec/simple_request.js new file mode 100644 index 000000000..f6ed56d14 --- /dev/null +++ b/Specs/SlickSpec/simple_request.js @@ -0,0 +1,39 @@ +var SimpleRequest = (function(){ + + function SimpleRequest(){ + this.initialize(); + }; + SimpleRequest.prototype = { + + initialize: function(){ + this.xhr = this.createXHR(); + }, + + createXHR: function(){ + // return ('XMLHttpRequest' in window)? new XMLHttpRequest(): new ActiveXObject('MSXML2.XMLHTTP'); + return ('XMLHttpRequest' in window)? new XMLHttpRequest(): new ActiveXObject('Microsoft.XMLHTTP'); + }, + + stateChange: function(fn){ + if(this.xhr.readyState == 4 && this.xhr.status == 200){ + fn.apply(this, [this.xhr.responseText, this.getXML()]); + } + }, + + getXML: function(){ + if (this.xhr.responseXML && this.xhr.responseXML.documentElement) + return this.xhr.responseXML; + return parseXML(this.xhr.responseText); + }, + + send: function(url, fn){ + var self = this; + this.xhr.onreadystatechange = function(){ self.stateChange(fn); }; + this.xhr.open('get', url + '?n=' + (new Date()).getTime(), true); + this.xhr.send(null); + } + + }; + + return SimpleRequest; +})(); diff --git a/Specs/SlickSpec/slickspec.css b/Specs/SlickSpec/slickspec.css new file mode 100755 index 000000000..936076505 --- /dev/null +++ b/Specs/SlickSpec/slickspec.css @@ -0,0 +1,366 @@ +@CHARSET "UTF-8"; + +/* -------------------- +* @Layout +*/ + + +#slickspec_logo { + position: absolute; + top: 0px; + left: 0px; + z-index: 9999; + padding:0.5em 0.75em; + color: #fff; + + font-size: 20px; + line-height: 20px; + + font-weight: normal; +} +#slickspec_logo a, +#slickspec_logo a:link, +#slickspec_logo a:visited { + color: #fff; + text-decoration: none; +} +#slickspec_logo a:hover { + color: #000; +} + +#jsspec_container{padding-top:3em !important;} +#framework_name { + position: absolute; + top: 42px; + right: 0px; + z-index: 1; + padding:0.5em 0.75em; + color: #000; + + font-size: 20px; + line-height: 20px; + + font-weight: normal; +} +#framework_name a, +#framework_name a:link, +#framework_name a:visited { + color: #fff; + text-decoration: none; +} +#framework_name a:hover { + color: #000; +} + + +#copyright{ + position: fixed; + bottom: 0px; + right: 0px; + z-index: 1000; + font-size: 10px; + padding:0.5em 0.75em; + background-color: #fff; + background-color: rgba(255,255,255,0.9); + + -webkit-border-top-left-radius: 6px; +} +* html #copyright { + position: absolute; + bottom: auto; + top: expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.clientHeight)); +} +html.moobugger #copyright{ + bottom: 180px; +} + + +html { + overflow-x: hidden; + overflow-y: scroll; +} + +iframe {display:none;} +iframe#debugger {display:block !important;} +iframe#debugger{ position: fixed !important; bottom: 0; top: auto; } +* html iframe#debugger{position:absolute !important;bottom:auto;top:expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.clientHeight));} + +.debug-spacer {display:none;} + +/*Make position:fixed work in IE6!*/ + +* html,* html body /* IE6 Fixed Position Jitter Fix */ {background-image:url(about:blank);background-attachment:fixed;} + +#slickspec_logo, +.fixed-top /* position fixed Top */ {position: fixed ; bottom: auto ; top: 0px ; } +* html #slickspec_logo, +* html .fixed-top /* IE6 position fixed Top */ {position: absolute ; bottom: auto ; top: expression(eval(document.documentElement.scrollTop)) ; } +.fixed-bottom /* position fixed Bottom */ {position: fixed ; bottom: 0px ; top: auto ; } +* html .fixed-bottom /* IE6 position fixed Bottom */ {position: absolute ; bottom: auto ; top: expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.clientHeight)) ; } +.fixed-left /* position fixed Left */ {position: fixed ; right: auto ; left: 0px ; } +* html .fixed-left /* IE6 position fixed Left */ {position: absolute ; right: auto ; left: expression(eval(document.documentElement.scrollLeft)) ; } +.fixed-right /* position fixed right */ {position: fixed ; right: 0px ; left: auto ; } +* html .fixed-right /* IE6 position fixed right */ {position: absolute ; right: auto ; left: expression(eval(document.documentElement.scrollWidth-this.clientWidth)) ; } + + + +body, #jsspec_container { + padding: 0; + margin: 0; + background-color: #FFFFFF; +} + +#jsspec_container { + padding-bottom:180px; +} + +#title { + padding: 0 !important; + margin: 0 !important; + height: 40px !important; + overflow: hidden !important; + + position: fixed; + _position: absolute; + top: 0px; + _top: expression(eval(document.documentElement.scrollTop)); + left: 0px; + _left: expression(eval(document.documentElement.scrollLeft)); + width: 100%; + _width: expression(eval(document.documentElement.clientWidth)); + + z-index: 1000; +} + +#title { + border-bottom:2px solid #fff; +} + +#list { + overflow: auto; + + position: fixed; + top: 0px; + left: 0px; + bottom: 0px; + background: #eee; + + margin-top:42px; + + width: 250px; +} +* html #list{ + position: absolute; + bottom: auto; + top: expression(eval(document.documentElement.scrollTop)); + height: expression(eval(document.documentElement.clientHeight - 42)); +} +html.moobugger #list{ + bottom: 180px; +} +* html.moobugger #list{ + bottom: auto; + height: expression(eval(document.documentElement.clientHeight - 42 - 180)); +} + +#log { + position:relative; + overflow: hidden; + + padding: 0; + margin: 0; + margin-top: 42px; + margin-left: 250px; +} + +/*iPhone*/ +@media only screen and (max-device-width: 480px) { + #list { + overflow: visible; + } + + #log { + overflow: visible; + } +} + + +/* -------------------- +* @Decorations and colors +*/ +* { + padding: 0; + margin: 0; + font-family: "Lucida Grande", Helvetica, sans-serif; +} + +li { + list-style: none; +} + +/* hiding subtitles */ +h2 { + display: none; +} + +/* title section */ +div#title { + padding: 0em 0.5em; +} + +div#title h1 { + float: right; + padding: 0.25em 0.75em; + font-size: 16px; +} +div#title h1:before{ + content:"powered by "; + font-size: 9px; + font-style: italic; + color:#fff; +} + +div#title ul { + position: absolute; + top: 0px; + left: 0px; + margin-left:120px; +} +div#title ul li { + font-size: 12px; + float: left; + padding: 0.75em 0em 0.5em 0.75em; + max-width: 14em; +} + +div#title p { + float:right; + padding: 0.5em 0em 0.5em 0.75em; + font-size: 10px; +} + +/* spec container */ +ul.specs { + margin: 0.5em; +} +ul.specs li { + margin-bottom: 0.1em; + position:relative; +} + +/* spec title */ +ul.specs li h3 { + font-weight: bold; + font-size: 11px; + line-height: 13px; + padding: 0.5em 0.75em; + cursor: pointer; + _cursor: hand; +} +ul.specs li h3 a { + text-decoration: none; +} +ul.specs li h3 a:hover { + text-decoration: underline; +} + +/* example container */ +ul.examples li { + background-color: #eee; + color: #999; + + border-style: solid; + border-width: 0px 0px 1px 5px; + margin: 0.2em 0em 0.2em 1em; +} + +/* example title */ +ul.examples li h4 { + font-weight: normal; + font-size: 12px; + margin-left: 1em; +} + +pre.examples-code { + background: #FFFFFF; + border: solid 1px #CCC; + + margin: 0.5em 2em; +} +pre.examples-code code { + display:block; + + padding: 0.5em; + _padding-right: 0; + _padding-left: 0; + + white-space: pre; + _width:100%; + + font-size: 10px; + font-family: "Panic Sans", "Monaco", monospace !important; + overflow-x: auto; + + scrollbar-base-color: #FFF; + scrollbar-arrow-color: #FFF; + scrollbar-track-color: #FFF; + scrollbar-3dlight-color: #eee; + scrollbar-highlight-color: #eee; + scrollbar-face-color: #eee; + scrollbar-shadow-color: #eee; + scrollbar-darkshadow-color: #FFF; +} + +/* example explaination */ +ul.examples li div { + padding: 1em 2em; + font-size: 11px; +} + +/* styles for ongoing, success, failure, error */ +ul.specs li h3, ul.specs li h3 a { color: #666; background-color: #fff; } + +div.success, div.success a { color: #FFFFFF; background-color: #6C6; } +div.exception, div.exception a { color: #FFFFFF; background-color: #C30; } + +ul.specs li.success h3, ul.specs li.success h3 a { color: #FFFFFF; background-color: #6C6; } +ul.examples li.success, ul.examples li.success a { color: #363; background-color: #CFC; border-color: #6C6; } + +ul.specs li.exception h3, ul.specs li.exception h3 a { color: #FFFFFF; background-color: #C30; } +ul.examples li.exception, ul.examples li.exception a { color: #C30; background-color: #FFC; border-color: #C30; } +div.ongoing, div.ongoing a { color: #330; background-color: #FF9; } + +ul.specs li.ongoing h3, ul.specs li.ongoing h3 a { color: #330; background-color: #FF9; } +ul.examples li.ongoing, ul.examples li.ongoing a { color: #330; background-color: #FF9; border-color: #CC0; } + + + +/* -------------------- +* values +*/ +.number_value, .string_value, .regexp_value, .boolean_value, .dom_value { + font-family: monospace; + color: blue; +} +.object_value, .array_value { + line-height: 2em; + padding: 0.1em 0.2em; + margin: 0.1em 0; +} +.date_value { + font-family: monospace; + color: olive; +} +.undefined_value, .null_value { + font-style: italic; + color: blue; +} +.dom_attr_name { +} +.dom_attr_value { + color: red; +} +.dom_path { + font-size: 11px; + color: gray; +} diff --git a/Specs/index.html b/Specs/index.html index 90b92cade..d76bdb418 100644 --- a/Specs/index.html +++ b/Specs/index.html @@ -1,45 +1,59 @@ - - - - - - MooTools Specs - - - - - - - - - - - - - + + + + SlickSpec for MooTools + + + + + +
+ +

SlickSpec alpha for MooTools-Core

+ + + +
+ + \ No newline at end of file diff --git a/Specs/runner.html b/Specs/runner.html new file mode 100644 index 000000000..4cc0e6a04 --- /dev/null +++ b/Specs/runner.html @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +SlickSpec Select +

SlickSpec

+ +

+ + + From a90072d9f61202da7539bc594d862c09bccf7b55 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Sat, 21 Nov 2009 13:30:54 +0000 Subject: [PATCH 02/44] * SlickSpecs work now --- .../1.2public/Utilities/Selectors.Children.js | 61 ------------------- Specs/MooToolsSpecLoader.js | 2 +- Specs/runner.html | 1 + 3 files changed, 2 insertions(+), 62 deletions(-) delete mode 100644 Specs/1.2public/Utilities/Selectors.Children.js diff --git a/Specs/1.2public/Utilities/Selectors.Children.js b/Specs/1.2public/Utilities/Selectors.Children.js deleted file mode 100644 index 9ed2d258e..000000000 --- a/Specs/1.2public/Utilities/Selectors.Children.js +++ /dev/null @@ -1,61 +0,0 @@ -/* -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/Specs/MooToolsSpecLoader.js b/Specs/MooToolsSpecLoader.js index c17adaa47..7398e398a 100644 --- a/Specs/MooToolsSpecLoader.js +++ b/Specs/MooToolsSpecLoader.js @@ -14,7 +14,7 @@ var Sets = { }; -var runSpecs = (function(){ +var loadSpecs = (function(){ // Uses String.parseQueryString from MooTools-More // TODO Needs compat for other browsers diff --git a/Specs/runner.html b/Specs/runner.html index 4cc0e6a04..72d46a757 100644 --- a/Specs/runner.html +++ b/Specs/runner.html @@ -55,6 +55,7 @@ var SpecNames = [], Name = 'MooTools-Core-1.2'; +loadSpecs(); runSpecs(); From 38109ab15be229bc72af40e0c3d16fdae7cac319 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Sat, 21 Nov 2009 14:56:16 +0000 Subject: [PATCH 03/44] * Removing the old specs --- OldSpecs/Assets/Scripts/Builder.js | 39 - OldSpecs/Assets/Scripts/DiffMatchPatch.js | 1 - OldSpecs/Assets/Scripts/JSSpec.js | 1552 -------------------- OldSpecs/Assets/Scripts/JSSpecSpecs.js | 140 -- OldSpecs/Assets/Styles/Specs.css | 293 ---- OldSpecs/Class/Class.Extras.js | 288 ---- OldSpecs/Class/Class.js | 274 ---- OldSpecs/Core/Browser.js | 40 - OldSpecs/Core/Core.js | 443 ------ OldSpecs/Element/Element.Dimensions.js | 120 -- OldSpecs/Element/Element.Style.js | 73 - OldSpecs/Element/Element.js | 1565 --------------------- OldSpecs/Native/Array.js | 207 --- OldSpecs/Native/Function.js | 155 -- OldSpecs/Native/Hash.js | 203 --- OldSpecs/Native/Number.js | 114 -- OldSpecs/Native/String.js | 158 --- OldSpecs/Plugins/Selectors.Children.js | 61 - OldSpecs/Utilities/Color.js | 62 - OldSpecs/Utilities/Selectors.js | 17 - OldSpecs/Utilities/index.html | 17 - OldSpecs/application.xml | 16 - OldSpecs/demo.html | 14 - OldSpecs/index.html | 45 - 24 files changed, 5897 deletions(-) delete mode 100644 OldSpecs/Assets/Scripts/Builder.js delete mode 100755 OldSpecs/Assets/Scripts/DiffMatchPatch.js delete mode 100755 OldSpecs/Assets/Scripts/JSSpec.js delete mode 100644 OldSpecs/Assets/Scripts/JSSpecSpecs.js delete mode 100644 OldSpecs/Assets/Styles/Specs.css delete mode 100644 OldSpecs/Class/Class.Extras.js delete mode 100644 OldSpecs/Class/Class.js delete mode 100644 OldSpecs/Core/Browser.js delete mode 100644 OldSpecs/Core/Core.js delete mode 100644 OldSpecs/Element/Element.Dimensions.js delete mode 100644 OldSpecs/Element/Element.Style.js delete mode 100644 OldSpecs/Element/Element.js delete mode 100644 OldSpecs/Native/Array.js delete mode 100644 OldSpecs/Native/Function.js delete mode 100644 OldSpecs/Native/Hash.js delete mode 100644 OldSpecs/Native/Number.js delete mode 100644 OldSpecs/Native/String.js delete mode 100644 OldSpecs/Plugins/Selectors.Children.js delete mode 100644 OldSpecs/Utilities/Color.js delete mode 100644 OldSpecs/Utilities/Selectors.js delete mode 100644 OldSpecs/Utilities/index.html delete mode 100644 OldSpecs/application.xml delete mode 100644 OldSpecs/demo.html delete mode 100644 OldSpecs/index.html diff --git a/OldSpecs/Assets/Scripts/Builder.js b/OldSpecs/Assets/Scripts/Builder.js deleted file mode 100644 index aa9fac6c8..000000000 --- a/OldSpecs/Assets/Scripts/Builder.js +++ /dev/null @@ -1,39 +0,0 @@ -/* -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 = { - includeFiles: function(path, files){ - switch(typeof files){ - case 'object': - if( files.constructor == Array ){ - for(var i=0; i< files.length; i++){ - this.includeJs(path + files[i]); - } - } - else{ - for(key in files){ - this.includeFiles(path + key + '/', files[key]); - } - } - break; - case 'string': - this.includeJs(path + files); - } - }, - - includeJs: function(filePath){ - document.writeln(''.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/OldSpecs/Plugins/Selectors.Children.js b/OldSpecs/Plugins/Selectors.Children.js deleted file mode 100644 index 8f7a43c28..000000000 --- a/OldSpecs/Plugins/Selectors.Children.js +++ /dev/null @@ -1,61 +0,0 @@ -/* -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/OldSpecs/Utilities/Color.js b/OldSpecs/Utilities/Color.js deleted file mode 100644 index 205ea874d..000000000 --- a/OldSpecs/Utilities/Color.js +++ /dev/null @@ -1,62 +0,0 @@ -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/OldSpecs/Utilities/Selectors.js b/OldSpecs/Utilities/Selectors.js deleted file mode 100644 index cd52e5f15..000000000 --- a/OldSpecs/Utilities/Selectors.js +++ /dev/null @@ -1,17 +0,0 @@ -/* -Script: Selectors.js - Specs for Selectors.js - -License: - MIT-style license. -*/ - -describe('Utilities.Selectors', { - - 'should not return comment nodes': function(){ - var div = new Element('div'); - div.appendChild(document.createComment('')); - value_of(div.getElements('*').length).should_be(0); - } - -}); diff --git a/OldSpecs/Utilities/index.html b/OldSpecs/Utilities/index.html deleted file mode 100644 index bfb493aad..000000000 --- a/OldSpecs/Utilities/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - Selectors Sample Document - - - - - - diff --git a/OldSpecs/application.xml b/OldSpecs/application.xml deleted file mode 100644 index 94e21e3f1..000000000 --- a/OldSpecs/application.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - net.mootools.specs - Specs - v1 - - Specs/index.html - true - 900 - 500 - 50 - 50 - 200 100 - - diff --git a/OldSpecs/demo.html b/OldSpecs/demo.html deleted file mode 100644 index 769a774c4..000000000 --- a/OldSpecs/demo.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - JSSpec Sample Specs - - - - - - - - - - \ No newline at end of file diff --git a/OldSpecs/index.html b/OldSpecs/index.html deleted file mode 100644 index 90b92cade..000000000 --- a/OldSpecs/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - MooTools Specs - - - - - - - - - - - - - From 3e04bb3e306b59f9cd1110c39d284ef807a21b28 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Sat, 21 Nov 2009 14:56:40 +0000 Subject: [PATCH 04/44] * New Events and Options specs for 1.2 (backported from 2.0) --- Specs/1.2public/Class/Class.Extras.js | 280 +++++++++++++++++--------- 1 file changed, 186 insertions(+), 94 deletions(-) diff --git a/Specs/1.2public/Class/Class.Extras.js b/Specs/1.2public/Class/Class.Extras.js index 493ed1224..f03a2eabe 100644 --- a/Specs/1.2public/Class/Class.Extras.js +++ b/Specs/1.2public/Class/Class.Extras.js @@ -119,116 +119,208 @@ describe("Chain Class", { }); +Hash.each({ -describe("Events Class", { - - "before all": function(){ - Local.EventsTest = new Class({ - Implements: Events, - - called: 0, - - initialize: function(){ - this.called = 0; - } - }); + element: function(){ + return new Element('div'); }, + + mixin: function(){ + return new Events(); + } - "before each": function(){ - Local.called = 0; - Local.fn = function(){ - return Local.called++; - }; - }, +}, function(createObject, type){ + describe('Events API: ' + type.capitalize(), { + + 'before each': function(){ + Local.called = 0; + Local.fn = function(){ + return Local.called++; + }; + }, + + 'should add an Event to the Class': function(){ + var object = createObject(); + + object.addEvent('event', Local.fn).fireEvent('event'); + + value_of(Local.called).should_be(1); + }, + + 'should add multiple Events to the Class': function(){ + createObject().addEvents({ + event1: Local.fn, + event2: Local.fn + }).fireEvent('event1').fireEvent('event2'); + + value_of(Local.called).should_be(2); + }, + + // TODO 2.0only + /*'should be able to remove event during firing': function(){ + createObject().addEvent('event', Local.fn).addEvent('event', function(){ + Local.fn(); + this.removeEvent('event', arguments.callee); + }).addEvent('event', function(){ Local.fn(); }).fireEvent('event').fireEvent('event'); + + value_of(Local.called).should_be(5); + },*/ + + 'should add a protected event': function(){ + var object = createObject(); + + //TODO 2.0; 1.2 intentionally has a different API + if (type == 'element'){ + value_of(1).should_be(1); + return; + } + + var protectedFn = (function(){ Local.fn(); }); + + object.addEvent('protected', protectedFn, true).removeEvent('protected', protectedFn).fireEvent('protected'); + + value_of(Local.called).should_be(1); + }, + + 'should remove a specific method for an event': function(){ + var object = createObject(); + var x = 0, fn = function(){ x++; }; + + object.addEvent('event', Local.fn).addEvent('event', fn).removeEvent('event', Local.fn).fireEvent('event'); + + value_of(x).should_be(1); + value_of(Local.called).should_be(0); + }, + + 'should remove an event and its methods': function(){ + var object = createObject(); + var x = 0, fn = function(){ x++; }; + + object.addEvent('event', Local.fn).addEvent('event', fn).removeEvents('event').fireEvent('event'); + + value_of(x).should_be(0); + value_of(Local.called).should_be(0); + }, + + 'should remove all events': function(){ + var object = createObject(); + var x = 0, fn = function(){ x++; }; + + object.addEvent('event1', Local.fn).addEvent('event2', fn).removeEvents(); + object.fireEvent('event1').fireEvent('event2'); + + value_of(x).should_be(0); + value_of(Local.called).should_be(0); + }, + + 'should remove events with an object': function(){ + var object = createObject(); + var events = { + event1: Local.fn, + event2: Local.fn + }; + + object.addEvent('event1', function(){ Local.fn(); }).addEvents(events).fireEvent('event1'); + value_of(Local.called).should_be(2); + + object.removeEvents(events); + object.fireEvent('event1'); + value_of(Local.called).should_be(3); + + object.fireEvent('event2'); + value_of(Local.called).should_be(3); + }, + + 'should remove an event immediately': function(){ + var object = createObject(); + + var methods = []; + + var three = function(){ + methods.push(3); + }; + + object.addEvent('event', function(){ + methods.push(1); + this.removeEvent('event', three); + }).addEvent('event', function(){ + methods.push(2); + }).addEvent('event', three); + + object.fireEvent('event'); + value_of(methods).should_be([1, 2]); + + object.fireEvent('event'); + value_of(methods).should_be([1, 2, 1, 2]); + } + }); +}); - "should add an Event to the Class": function(){ - var myTest = new Local.EventsTest(); - myTest.addEvent("event", Local.fn); +describe("Options Class", { - var events = myTest.$events; - var myEvent = events["event"]; - value_of(myEvent).should_not_be(undefined); - value_of(myEvent.contains(Local.fn)).should_be_true(); - }, + "before all": function(){ + Local.OptionsTest = new Class({ + Implements: [Options, Events], + + options: { + a: 1, + b: 2 + }, - "should add multiple Events to the Class": function(){ - var myTest = new Local.EventsTest(); - myTest.addEvents({ - "event1": Local.fn, - "event2": Local.fn + initialize: function(options){ + this.setOptions(options); + } }); - - 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 set options": function(){ + var myTest = new Local.OptionsTest({a: 1, b: 3}); + value_of(myTest.options).should_not_be(undefined); }, - "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"); + "should override default options": function(){ + 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); + } - 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(); +describe("Options Class w/ Events", { - var events = myTest.$events; - value_of(events["event1"].length).should_be(0); - value_of(events["event2"].length).should_be(0); + "before all": function(){ + Local.OptionsTest = new Class({ + Implements: [Options, Events], + + options: { + onEvent1: function(){ + return true; + }, + onEvent2: function(){ + return false; + } + }, + + initialize: function(options){ + this.setOptions(options); + } + }); }, + + "should add events in the options object if class has implemented the Events class": function(){ + var myTest = new Local.OptionsTest({ + onEvent2: function(){ + return true; + }, + + onEvent3: function(){ + return true; + } + }); - "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); + value_of(myTest.$events.event1.length).should_be(1); + value_of(myTest.$events.event2.length).should_be(1); + value_of(myTest.$events.event3.length).should_be(1); } }); From 55f02c3bb7d89e3ac2aacc74c3b9dc8b77ff297e Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Sat, 21 Nov 2009 14:57:15 +0000 Subject: [PATCH 05/44] * Starting to separate specs --- Specs/1.2private/Core/Browser.js | 8 ++++ Specs/1.2private/Core/Core.js | 77 ++++++++++++++++++++++++++++++++ Specs/1.2public/Class/Class.js | 7 +-- Specs/1.2public/Core/Browser.js | 2 +- Specs/1.2public/Core/Core.js | 74 +----------------------------- Specs/MooToolsSpecLoader.js | 1 + 6 files changed, 91 insertions(+), 78 deletions(-) create mode 100644 Specs/1.2private/Core/Browser.js create mode 100644 Specs/1.2private/Core/Core.js diff --git a/Specs/1.2private/Core/Browser.js b/Specs/1.2private/Core/Browser.js new file mode 100644 index 000000000..e29ff716b --- /dev/null +++ b/Specs/1.2private/Core/Browser.js @@ -0,0 +1,8 @@ +/* +Script: Browser.js + Private Specs for Browser.js 1.2 + +License: + MIT-style license. +*/ + diff --git a/Specs/1.2private/Core/Core.js b/Specs/1.2private/Core/Core.js new file mode 100644 index 000000000..bbcc13e46 --- /dev/null +++ b/Specs/1.2private/Core/Core.js @@ -0,0 +1,77 @@ +/* +Script: Core.js + Private Specs for Core.js 1.2 + +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 (private)', { + + '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(); + } + +}); + +})(); \ No newline at end of file diff --git a/Specs/1.2public/Class/Class.js b/Specs/1.2public/Class/Class.js index aa71d21ef..bdd3a0c67 100644 --- a/Specs/1.2public/Class/Class.js +++ b/Specs/1.2public/Class/Class.js @@ -209,9 +209,7 @@ describe('Class creation', { } //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(){ + /*"should access the proper parent when it is overwritten after instantiation": function(){ var Dog = new Class({ Extends: Animal, say: function(){ @@ -232,8 +230,7 @@ describe('Class creation', { value_of(spot.say()).should_be('NEW:animal:say:spot'); value_of(rover.say()).should_be('NEW:animal:say:rover'); - } - */ + }*/ }); diff --git a/Specs/1.2public/Core/Browser.js b/Specs/1.2public/Core/Browser.js index e78e9b03b..fe146dde1 100644 --- a/Specs/1.2public/Core/Browser.js +++ b/Specs/1.2public/Core/Browser.js @@ -1,6 +1,6 @@ /* Script: Browser.js - Specs for Browser.js + Public Specs for Browser.js 1.2 License: MIT-style license. diff --git a/Specs/1.2public/Core/Core.js b/Specs/1.2public/Core/Core.js index 83d4c1b25..05dd5c539 100644 --- a/Specs/1.2public/Core/Core.js +++ b/Specs/1.2public/Core/Core.js @@ -1,79 +1,11 @@ /* Script: Core.js - Examples for Core.js + Public Specs for Core.js 1.2 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(){ @@ -438,6 +370,4 @@ describe('$unlink', { value_of(copy.get('a')).should_be('two'); } -}); - -})(); \ No newline at end of file +}); \ No newline at end of file diff --git a/Specs/MooToolsSpecLoader.js b/Specs/MooToolsSpecLoader.js index 7398e398a..a8496775d 100644 --- a/Specs/MooToolsSpecLoader.js +++ b/Specs/MooToolsSpecLoader.js @@ -9,6 +9,7 @@ var Sets = { ], '1.2private': [ + 'Core/Core.js', 'Core/Browser.js', ] From 55f5042e9a94ee9e1774420da2331119b8397dbf Mon Sep 17 00:00:00 2001 From: Jan Kassens Date: Sun, 22 Nov 2009 14:31:16 +0000 Subject: [PATCH 06/44] clearChain specs --- Specs/1.2public/Class/Class.Extras.js | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Specs/1.2public/Class/Class.Extras.js b/Specs/1.2public/Class/Class.Extras.js index f03a2eabe..3e79b56ba 100644 --- a/Specs/1.2public/Class/Class.Extras.js +++ b/Specs/1.2public/Class/Class.Extras.js @@ -51,6 +51,34 @@ describe("Chain Class", { value_of(arr).should_be(["0Aa", "1Bb"]); }, + "should clearChain and remove all functions from it": function(){ + var called; + var fn = function(){ + called = true; + }; + + var chain = new Local.Chain(); + chain.chain(fn, fn, fn, fn); + + chain.callChain(); + value_of(called).should_be_true(); + called = false; + + chain.callChain(); + value_of(called).should_be_true(); + called = false; + + chain.clearChain(); + + chain.callChain(); + value_of(called).should_be_false(); + called = false; + + chain.callChain(); + value_of(called).should_be_false(); + called = false; + }, + "should chain any number of functions": function(){ var chain = new Local.Chain(); var arr = []; From 72a751ca05dc54d8d2d271e62843a5892d32f021 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Sun, 22 Nov 2009 14:47:17 +0000 Subject: [PATCH 07/44] * Class.Extras specs --- Specs/1.2public/Class/Class.Extras.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Specs/1.2public/Class/Class.Extras.js b/Specs/1.2public/Class/Class.Extras.js index f03a2eabe..7de75c470 100644 --- a/Specs/1.2public/Class/Class.Extras.js +++ b/Specs/1.2public/Class/Class.Extras.js @@ -286,7 +286,7 @@ describe("Options Class", { }); -describe("Options Class w/ Events", { +describe("Options Class with Events", { "before all": function(){ Local.OptionsTest = new Class({ @@ -372,9 +372,9 @@ describe("Options Class", { }); 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); + value_of(events.event1.length).should_be(1); + value_of(events.event1.length).should_be(1); + value_of(events.event1.length).should_be(1); } }); \ No newline at end of file From 14b9857dc345a0135ef524c75ef599c83e489588 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Sun, 22 Nov 2009 14:48:40 +0000 Subject: [PATCH 08/44] * ClearChain cleanups --- Specs/1.2public/Class/Class.Extras.js | 62 +++++++++++++++------------ 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/Specs/1.2public/Class/Class.Extras.js b/Specs/1.2public/Class/Class.Extras.js index 2943b18ea..e58562e9c 100644 --- a/Specs/1.2public/Class/Class.Extras.js +++ b/Specs/1.2public/Class/Class.Extras.js @@ -51,34 +51,6 @@ describe("Chain Class", { value_of(arr).should_be(["0Aa", "1Bb"]); }, - "should clearChain and remove all functions from it": function(){ - var called; - var fn = function(){ - called = true; - }; - - var chain = new Local.Chain(); - chain.chain(fn, fn, fn, fn); - - chain.callChain(); - value_of(called).should_be_true(); - called = false; - - chain.callChain(); - value_of(called).should_be_true(); - called = false; - - chain.clearChain(); - - chain.callChain(); - value_of(called).should_be_false(); - called = false; - - chain.callChain(); - value_of(called).should_be_false(); - called = false; - }, - "should chain any number of functions": function(){ var chain = new Local.Chain(); var arr = []; @@ -143,6 +115,40 @@ describe("Chain Class", { bar.callChain(); value_of(foo.val).should_be('FOO'); value_of(bar.val).should_be('BAR'); + }, + + "should be able to clear the chain": function(){ + var called; + var fn = function(){ + called = true; + }; + + var chain = new Local.Chain(); + chain.chain(fn, fn, fn, fn); + + chain.callChain(); + value_of(called).should_be_true(); + called = false; + + chain.clearChain(); + + chain.callChain(); + value_of(called).should_be_false(); + called = false; + }, + + "should be able to clear the chain from within": function(){ + var foo = new Local.Chain(); + + var test = 0; + foo.chain(function(){ + test++; + foo.clearChain(); + }).chain(function(){ + test++; + }).callChain(); + + value_of(test).should_be(1); } }); From c6a673e167aadec906a3517bfdc958b152e39c07 Mon Sep 17 00:00:00 2001 From: Jan Kassens Date: Sun, 22 Nov 2009 14:52:33 +0000 Subject: [PATCH 09/44] adding simple $H spec --- Specs/1.2public/Core/Core.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Specs/1.2public/Core/Core.js b/Specs/1.2public/Core/Core.js index 05dd5c539..3c3515e0e 100644 --- a/Specs/1.2public/Core/Core.js +++ b/Specs/1.2public/Core/Core.js @@ -370,4 +370,13 @@ describe('$unlink', { value_of(copy.get('a')).should_be('two'); } -}); \ No newline at end of file +}); + +describe('$H', { + + "should create a new hash": function(){ + var hash = $H({}); + value_of($type(hash)).should_be('hash'); + } + +}); From 88b96ceb97fda3b1ed4b6356a2f93b728ba312c0 Mon Sep 17 00:00:00 2001 From: Jan Kassens Date: Sun, 22 Nov 2009 15:12:39 +0000 Subject: [PATCH 10/44] adding Hash.getLength specs --- Specs/1.2public/Core/Core.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Specs/1.2public/Core/Core.js b/Specs/1.2public/Core/Core.js index 3c3515e0e..37fef6fc4 100644 --- a/Specs/1.2public/Core/Core.js +++ b/Specs/1.2public/Core/Core.js @@ -372,6 +372,28 @@ describe('$unlink', { }); +describe('Hash.getLength', { + + "should return the number of items in it": function(){ + var hash = new Hash({}); + value_of(hash.getLength()).should_be(0); + hash.set('mootools', 'awesome'); + hash.milk = 'yummy'; + value_of(hash.getLength()).should_be(2); + }, + + "should not fail when length is set": function(){ + var hash = new Hash({'length': 10}); + value_of(hash.getLength()).should_be(1); + }, + + "should work as a generic on objects": function(){ + value_of(Hash.getLength({})).should_be(0); + value_of(Hash.getLength({'': '', '0': '0', 'length': 99})).should_be(3); + } + +}); + describe('$H', { "should create a new hash": function(){ From b100a4da8ecb5491ebfb83c56e5c1af122e96b96 Mon Sep 17 00:00:00 2001 From: Aaron Newton Date: Tue, 17 Nov 2009 14:25:41 -0800 Subject: [PATCH 11/44] fixing https://mootools.lighthouseapp.com/projects/24057/tickets/146; adding links to Element.Measure in the Element.Dimensions docs. --- Docs/Element/Element.Dimensions.md | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Docs/Element/Element.Dimensions.md b/Docs/Element/Element.Dimensions.md index 28670766e..a25b705eb 100644 --- a/Docs/Element/Element.Dimensions.md +++ b/Docs/Element/Element.Dimensions.md @@ -3,10 +3,10 @@ Native: Element {#Element} Custom Native to allow all of its methods to be used with any DOM element via the dollar function [$][]. -### Note: +### Notes: -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. +* 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. +* If you need to measure the properties of elements that are not displayed (either their display style is none or one of their parents display style is none), you will need to use [Element.measure][] to expose it. ### Credits: @@ -59,7 +59,9 @@ The following method is also available on the Window object. var size = myElement.getSize(); alert("The element is "+size.x+" pixels wide and "+size.y+"pixels high."); +### Note: +If you need to measure the properties of elements that are not displayed (either their display style is none or one of their parents display style is none), you will need to use [Element.measure][] to expose it. Element Method: getScrollSize {#Element:getScrollSize} @@ -85,6 +87,9 @@ The following method is also available on the Window object. - [MDC Element:scrollLeft][], [MDC Element:scrollTop][], [MDC Element:offsetWidth][], [MDC Element:offsetHeight][], [MDC Element:scrollWidth][], [MDC Element:scrollHeight][] +### Note: + +If you need to measure the properties of elements that are not displayed (either their display style is none or one of their parents display style is none), you will need to use [Element.measure][] to expose it. Element Method: getScroll {#Element:getScroll} @@ -106,6 +111,9 @@ The following method is also available on the Window object. var scroll = $('myElement').getScroll(); alert('My element is scrolled down ' + scroll.y + 'px'); //alerts 'My element is scrolled down to 620px' +### Note: + +If you need to measure the properties of elements that are not displayed (either their display style is none or one of their parents display style is none), you will need to use [Element.measure][] to expose it. Element Method: getPosition {#Element:getPosition} -------------------------------------------------- @@ -132,6 +140,10 @@ relative - (Element, defaults to the document) If set, the position will be rela - [QuirksMode: Find position](http://www.quirksmode.org/js/findpos.html) +### Note: + +If you need to measure the properties of elements that are not displayed (either their display style is none or one of their parents display style is none), you will need to use [Element.measure][] to expose it. + Element Method: setPosition {#Element:setPosition} -------------------------------------------------- @@ -189,6 +201,9 @@ relative - (*element*, optional) if set, the position will be relative to this e [Element:getPosition](#Element:getPosition) +### Note: + +If you need to measure the properties of elements that are not displayed (either their display style is none or one of their parents display style is none), you will need to use [Element.measure][] to expose it. Element Method: getOffsetParent {#Element:getOffsetParent} ---------------------------------------------------------- @@ -209,4 +224,5 @@ Returns the parent of the element that is positioned, if there is one. [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 +[MDC Element:scrollHeight]: http://developer.mozilla.org/en/docs/DOM:element.scrollHeight +[Element.measure]: /more/Element/Element.Measure \ No newline at end of file From 26d7310e257d72b9e684d415e3b98d39d6b32ce1 Mon Sep 17 00:00:00 2001 From: Aaron Newton Date: Wed, 25 Nov 2009 08:39:50 -0800 Subject: [PATCH 12/44] adding event to the list of strings that returns --- Docs/Core/Core.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Core/Core.md b/Docs/Core/Core.md index dd36eb037..5f6b1fe0c 100644 --- a/Docs/Core/Core.md +++ b/Docs/Core/Core.md @@ -417,6 +417,7 @@ Returns the type of object that matches the element passed in. * '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. +* 'event' - (*string*) If object is an event. * false - (*boolean*) If object is undefined, null, NaN or none of the above. ### Example: From 0ce655fd56ac23848091fe6ecd80355c73d5ec8a Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Fri, 27 Nov 2009 02:41:53 +0100 Subject: [PATCH 13/44] * Separating the Loader and the Sets --- Specs/1.2public/Class/Class.Extras.js | 2 +- Specs/1.2public/Class/Class.js | 7 ++- Specs/1.2public/Core/Core.js | 6 +- Specs/1.2public/Utilities/Cookie.js | 17 +++++ Specs/Sets.js | 15 +++++ Specs/SlickSpec/JSSpec.css | 0 Specs/SlickSpec/JSSpec.js | 0 .../Loader.js} | 19 +----- Specs/SlickSpec/diff_match_patch.js | 0 Specs/SlickSpec/getgetter.js | 63 ------------------- Specs/SlickSpec/slickspec.css | 0 Specs/runner.html | 6 +- 12 files changed, 46 insertions(+), 89 deletions(-) create mode 100644 Specs/1.2public/Utilities/Cookie.js create mode 100644 Specs/Sets.js mode change 100755 => 100644 Specs/SlickSpec/JSSpec.css mode change 100755 => 100644 Specs/SlickSpec/JSSpec.js rename Specs/{MooToolsSpecLoader.js => SlickSpec/Loader.js} (76%) mode change 100755 => 100644 Specs/SlickSpec/diff_match_patch.js delete mode 100644 Specs/SlickSpec/getgetter.js mode change 100755 => 100644 Specs/SlickSpec/slickspec.css diff --git a/Specs/1.2public/Class/Class.Extras.js b/Specs/1.2public/Class/Class.Extras.js index e58562e9c..a877cb9cf 100644 --- a/Specs/1.2public/Class/Class.Extras.js +++ b/Specs/1.2public/Class/Class.Extras.js @@ -1,6 +1,6 @@ /* Script: Class.Extras.js - Specs for Class.Extras.js + Public specs for Class.Extras.js License: MIT-style license. diff --git a/Specs/1.2public/Class/Class.js b/Specs/1.2public/Class/Class.js index bdd3a0c67..91c431e52 100644 --- a/Specs/1.2public/Class/Class.js +++ b/Specs/1.2public/Class/Class.js @@ -207,9 +207,10 @@ describe('Class creation', { 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(){ + + /* + * TODO: 2.0 + "should access the proper parent when it is overwritten after instantiation": function(){ var Dog = new Class({ Extends: Animal, say: function(){ diff --git a/Specs/1.2public/Core/Core.js b/Specs/1.2public/Core/Core.js index 37fef6fc4..cc158069d 100644 --- a/Specs/1.2public/Core/Core.js +++ b/Specs/1.2public/Core/Core.js @@ -239,6 +239,10 @@ describe('$time', { 'should return a timestamp': function(){ value_of(Number.type($time())).should_be_true(); + }, + + 'should be within a reasonable range': function(){ + value_of($time() < 1e13 && $time() > 1e12).should_be_true(); } }); @@ -328,7 +332,7 @@ describe('$type', { 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'); }, diff --git a/Specs/1.2public/Utilities/Cookie.js b/Specs/1.2public/Utilities/Cookie.js new file mode 100644 index 000000000..856a892f0 --- /dev/null +++ b/Specs/1.2public/Utilities/Cookie.js @@ -0,0 +1,17 @@ +/* +Script: Core.js + Public Specs for Core.js 1.2 + +License: + MIT-style license. +*/ + +describe('Cookie', { + + "should set a cookie": function(){ + Cookie.write('test', 1); + + + } + +}); \ No newline at end of file diff --git a/Specs/Sets.js b/Specs/Sets.js new file mode 100644 index 000000000..7bdd4348f --- /dev/null +++ b/Specs/Sets.js @@ -0,0 +1,15 @@ +var Sets = { + + '1.2public': [ + 'Core/Core.js', 'Core/Browser.js', + 'Native/Array.js', 'Native/String.js', 'Native/Function.js', 'Native/Number.js', 'Native/Hash.js', + 'Class/Class.js', 'Class/Class.Extras.js', + 'Element/Element.js', 'Element/Element.Style.js', 'Element/Element.Dimensions.js', + ], + + '1.2private': [ + 'Core/Core.js', 'Core/Browser.js', + + ] + +}; \ No newline at end of file diff --git a/Specs/SlickSpec/JSSpec.css b/Specs/SlickSpec/JSSpec.css old mode 100755 new mode 100644 diff --git a/Specs/SlickSpec/JSSpec.js b/Specs/SlickSpec/JSSpec.js old mode 100755 new mode 100644 diff --git a/Specs/MooToolsSpecLoader.js b/Specs/SlickSpec/Loader.js similarity index 76% rename from Specs/MooToolsSpecLoader.js rename to Specs/SlickSpec/Loader.js index a8496775d..5fd3517a4 100644 --- a/Specs/MooToolsSpecLoader.js +++ b/Specs/SlickSpec/Loader.js @@ -1,21 +1,4 @@ -var Sets = { - - '1.2public': [ - 'Core/Core.js', 'Core/Browser.js', - 'Native/Array.js', 'Native/String.js', 'Native/Function.js', 'Native/Number.js', 'Native/Hash.js', - 'Class/Class.js', 'Class/Class.Extras.js', - 'Element/Element.js', 'Element/Element.Style.js', 'Element/Element.Dimensions.js', - 'Utilities/Selectors.Children.js' - ], - - '1.2private': [ - 'Core/Core.js', 'Core/Browser.js', - - ] - -}; - -var loadSpecs = (function(){ +var loadSpecs = (function(Sets){ // Uses String.parseQueryString from MooTools-More // TODO Needs compat for other browsers diff --git a/Specs/SlickSpec/diff_match_patch.js b/Specs/SlickSpec/diff_match_patch.js old mode 100755 new mode 100644 diff --git a/Specs/SlickSpec/getgetter.js b/Specs/SlickSpec/getgetter.js deleted file mode 100644 index 5e8dddc21..000000000 --- a/Specs/SlickSpec/getgetter.js +++ /dev/null @@ -1,63 +0,0 @@ -// -*- Mode: JavaScript; tab-width: 4; -*- - -(function(){ - - window.scripts_to_get = parent.scripts_to_get || window.location.search.match(/\bscript=(.*?\.js)/gi) || ['http://mootools.github.com/slick/slick.js','bootstrap/slick.slickspec.js']; - - for (var i=0, scriptsrc; scriptsrc = scripts_to_get[i]; i++){ - - scripts_to_get[i] = scriptsrc = decodeURIComponent(scriptsrc.replace(/^(&?script=)+/,'')); - - scriptsrc.replace(/^(?!=http|\/)/,'../'); - - var written; - if (document.write){ - try { - document.write('<\/script>'); - written = true; - } catch(e){ - written = false; - } - } - - if (!written && document.documentElement.nodeName == 'HTML'){ - var script = document.createElement('script'); - script.setAttribute('src', scriptsrc); - script.setAttribute('type', 'text/javascript'); - document.documentElement.appendChild(script); - } - - // else evalRemote(scriptsrc); - - if (/\bbootstrap\b/.test(scriptsrc)) scripts_to_get.splice(i,1); - - } - - this.frameworkName = scripts_to_get[0].replace(/^.*\//,''); - - // function evalRemote(url){ - // if (!(/^(\/|http:)/).test(url) && /\bmocks\b/.test(document.location.href)) url = '../' + url; - // - // var code = getResource(url); - // - // try { - // globalEval(code); - // } catch(e){ - // try{console.log(e);}catch(e){}; - // } - // }; - // - // function getResource(url) { - // if (!(XMLHttpRequest || ActiveXObject)) return false; - // request = (XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); - // if (!request) return false; - // request.open("GET", url + '?' + Math.random().toString(32), false); - // // try { - // request.send(null); - // // } catch(e){} - // - // if (request.status != 200) return false; - // return request.responseText; - // } - // -})(); diff --git a/Specs/SlickSpec/slickspec.css b/Specs/SlickSpec/slickspec.css old mode 100755 new mode 100644 diff --git a/Specs/runner.html b/Specs/runner.html index 72d46a757..0150db0f1 100644 --- a/Specs/runner.html +++ b/Specs/runner.html @@ -10,6 +10,7 @@ + @@ -48,14 +49,13 @@ - - + From 22f28048ac927152564710b699688b7e89b0db12 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Wed, 2 Dec 2009 20:02:52 +0100 Subject: [PATCH 14/44] * Removing Specs --- Specs/1.2private/Core/Browser.js | 8 - Specs/1.2private/Core/Core.js | 77 - Specs/1.2public/Class/Class.Extras.js | 414 ---- Specs/1.2public/Class/Class.js | 272 --- Specs/1.2public/Core/Browser.js | 40 - Specs/1.2public/Core/Core.js | 408 ---- Specs/1.2public/Element/Element.Dimensions.js | 120 - Specs/1.2public/Element/Element.Style.js | 73 - Specs/1.2public/Element/Element.js | 1565 ------------ Specs/1.2public/Native/Array.js | 207 -- Specs/1.2public/Native/Function.js | 155 -- Specs/1.2public/Native/Hash.js | 203 -- Specs/1.2public/Native/Number.js | 114 - Specs/1.2public/Native/String.js | 158 -- Specs/1.2public/Utilities/Cookie.js | 17 - Specs/Sets.js | 15 - Specs/SlickSpec/JSSpec.css | 245 -- Specs/SlickSpec/JSSpec.js | 1553 ------------ Specs/SlickSpec/JSSpecHelpers.js | 308 --- Specs/SlickSpec/Loader.js | 52 - Specs/SlickSpec/diff_match_patch.js | 2136 ----------------- Specs/SlickSpec/ie.css | 37 - Specs/SlickSpec/moobugger/bookmarklet.html | 46 - Specs/SlickSpec/moobugger/debugger-iframe.js | 386 --- Specs/SlickSpec/moobugger/debugger.css | 190 -- Specs/SlickSpec/moobugger/debugger.html | 25 - Specs/SlickSpec/moobugger/debugger.js | 284 --- Specs/SlickSpec/moobugger/images/close.png | Bin 508 -> 0 bytes Specs/SlickSpec/moobugger/images/error.png | Bin 671 -> 0 bytes .../moobugger/images/group-close.png | Bin 304 -> 0 bytes .../SlickSpec/moobugger/images/group-open.png | Bin 351 -> 0 bytes Specs/SlickSpec/moobugger/images/icon.png | Bin 647 -> 0 bytes Specs/SlickSpec/moobugger/images/info.png | Bin 674 -> 0 bytes Specs/SlickSpec/moobugger/images/lick.png | Bin 285 -> 0 bytes Specs/SlickSpec/moobugger/images/max.png | Bin 488 -> 0 bytes Specs/SlickSpec/moobugger/images/min.png | Bin 409 -> 0 bytes Specs/SlickSpec/moobugger/images/mootools.png | Bin 3769 -> 0 bytes Specs/SlickSpec/moobugger/images/time.png | Bin 616 -> 0 bytes Specs/SlickSpec/moobugger/images/warning.png | Bin 691 -> 0 bytes Specs/SlickSpec/moobugger/test.html | 88 - Specs/SlickSpec/screen.css | 259 -- Specs/SlickSpec/simple_request.js | 39 - Specs/SlickSpec/slickspec.css | 366 --- Specs/index.html | 59 - Specs/runner.html | 68 - 45 files changed, 9987 deletions(-) delete mode 100644 Specs/1.2private/Core/Browser.js delete mode 100644 Specs/1.2private/Core/Core.js delete mode 100644 Specs/1.2public/Class/Class.Extras.js delete mode 100644 Specs/1.2public/Class/Class.js delete mode 100644 Specs/1.2public/Core/Browser.js delete mode 100644 Specs/1.2public/Core/Core.js delete mode 100644 Specs/1.2public/Element/Element.Dimensions.js delete mode 100644 Specs/1.2public/Element/Element.Style.js delete mode 100644 Specs/1.2public/Element/Element.js delete mode 100644 Specs/1.2public/Native/Array.js delete mode 100644 Specs/1.2public/Native/Function.js delete mode 100644 Specs/1.2public/Native/Hash.js delete mode 100644 Specs/1.2public/Native/Number.js delete mode 100644 Specs/1.2public/Native/String.js delete mode 100644 Specs/1.2public/Utilities/Cookie.js delete mode 100644 Specs/Sets.js delete mode 100644 Specs/SlickSpec/JSSpec.css delete mode 100644 Specs/SlickSpec/JSSpec.js delete mode 100644 Specs/SlickSpec/JSSpecHelpers.js delete mode 100644 Specs/SlickSpec/Loader.js delete mode 100644 Specs/SlickSpec/diff_match_patch.js delete mode 100644 Specs/SlickSpec/ie.css delete mode 100644 Specs/SlickSpec/moobugger/bookmarklet.html delete mode 100644 Specs/SlickSpec/moobugger/debugger-iframe.js delete mode 100644 Specs/SlickSpec/moobugger/debugger.css delete mode 100644 Specs/SlickSpec/moobugger/debugger.html delete mode 100644 Specs/SlickSpec/moobugger/debugger.js delete mode 100644 Specs/SlickSpec/moobugger/images/close.png delete mode 100644 Specs/SlickSpec/moobugger/images/error.png delete mode 100644 Specs/SlickSpec/moobugger/images/group-close.png delete mode 100644 Specs/SlickSpec/moobugger/images/group-open.png delete mode 100644 Specs/SlickSpec/moobugger/images/icon.png delete mode 100644 Specs/SlickSpec/moobugger/images/info.png delete mode 100644 Specs/SlickSpec/moobugger/images/lick.png delete mode 100644 Specs/SlickSpec/moobugger/images/max.png delete mode 100644 Specs/SlickSpec/moobugger/images/min.png delete mode 100644 Specs/SlickSpec/moobugger/images/mootools.png delete mode 100644 Specs/SlickSpec/moobugger/images/time.png delete mode 100644 Specs/SlickSpec/moobugger/images/warning.png delete mode 100644 Specs/SlickSpec/moobugger/test.html delete mode 100644 Specs/SlickSpec/screen.css delete mode 100644 Specs/SlickSpec/simple_request.js delete mode 100644 Specs/SlickSpec/slickspec.css delete mode 100644 Specs/index.html delete mode 100644 Specs/runner.html diff --git a/Specs/1.2private/Core/Browser.js b/Specs/1.2private/Core/Browser.js deleted file mode 100644 index e29ff716b..000000000 --- a/Specs/1.2private/Core/Browser.js +++ /dev/null @@ -1,8 +0,0 @@ -/* -Script: Browser.js - Private Specs for Browser.js 1.2 - -License: - MIT-style license. -*/ - diff --git a/Specs/1.2private/Core/Core.js b/Specs/1.2private/Core/Core.js deleted file mode 100644 index bbcc13e46..000000000 --- a/Specs/1.2private/Core/Core.js +++ /dev/null @@ -1,77 +0,0 @@ -/* -Script: Core.js - Private Specs for Core.js 1.2 - -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 (private)', { - - '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(); - } - -}); - -})(); \ No newline at end of file diff --git a/Specs/1.2public/Class/Class.Extras.js b/Specs/1.2public/Class/Class.Extras.js deleted file mode 100644 index a877cb9cf..000000000 --- a/Specs/1.2public/Class/Class.Extras.js +++ /dev/null @@ -1,414 +0,0 @@ -/* -Script: Class.Extras.js - Public 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'); - }, - - "should be able to clear the chain": function(){ - var called; - var fn = function(){ - called = true; - }; - - var chain = new Local.Chain(); - chain.chain(fn, fn, fn, fn); - - chain.callChain(); - value_of(called).should_be_true(); - called = false; - - chain.clearChain(); - - chain.callChain(); - value_of(called).should_be_false(); - called = false; - }, - - "should be able to clear the chain from within": function(){ - var foo = new Local.Chain(); - - var test = 0; - foo.chain(function(){ - test++; - foo.clearChain(); - }).chain(function(){ - test++; - }).callChain(); - - value_of(test).should_be(1); - } - -}); - -Hash.each({ - - element: function(){ - return new Element('div'); - }, - - mixin: function(){ - return new Events(); - } - -}, function(createObject, type){ - describe('Events API: ' + type.capitalize(), { - - 'before each': function(){ - Local.called = 0; - Local.fn = function(){ - return Local.called++; - }; - }, - - 'should add an Event to the Class': function(){ - var object = createObject(); - - object.addEvent('event', Local.fn).fireEvent('event'); - - value_of(Local.called).should_be(1); - }, - - 'should add multiple Events to the Class': function(){ - createObject().addEvents({ - event1: Local.fn, - event2: Local.fn - }).fireEvent('event1').fireEvent('event2'); - - value_of(Local.called).should_be(2); - }, - - // TODO 2.0only - /*'should be able to remove event during firing': function(){ - createObject().addEvent('event', Local.fn).addEvent('event', function(){ - Local.fn(); - this.removeEvent('event', arguments.callee); - }).addEvent('event', function(){ Local.fn(); }).fireEvent('event').fireEvent('event'); - - value_of(Local.called).should_be(5); - },*/ - - 'should add a protected event': function(){ - var object = createObject(); - - //TODO 2.0; 1.2 intentionally has a different API - if (type == 'element'){ - value_of(1).should_be(1); - return; - } - - var protectedFn = (function(){ Local.fn(); }); - - object.addEvent('protected', protectedFn, true).removeEvent('protected', protectedFn).fireEvent('protected'); - - value_of(Local.called).should_be(1); - }, - - 'should remove a specific method for an event': function(){ - var object = createObject(); - var x = 0, fn = function(){ x++; }; - - object.addEvent('event', Local.fn).addEvent('event', fn).removeEvent('event', Local.fn).fireEvent('event'); - - value_of(x).should_be(1); - value_of(Local.called).should_be(0); - }, - - 'should remove an event and its methods': function(){ - var object = createObject(); - var x = 0, fn = function(){ x++; }; - - object.addEvent('event', Local.fn).addEvent('event', fn).removeEvents('event').fireEvent('event'); - - value_of(x).should_be(0); - value_of(Local.called).should_be(0); - }, - - 'should remove all events': function(){ - var object = createObject(); - var x = 0, fn = function(){ x++; }; - - object.addEvent('event1', Local.fn).addEvent('event2', fn).removeEvents(); - object.fireEvent('event1').fireEvent('event2'); - - value_of(x).should_be(0); - value_of(Local.called).should_be(0); - }, - - 'should remove events with an object': function(){ - var object = createObject(); - var events = { - event1: Local.fn, - event2: Local.fn - }; - - object.addEvent('event1', function(){ Local.fn(); }).addEvents(events).fireEvent('event1'); - value_of(Local.called).should_be(2); - - object.removeEvents(events); - object.fireEvent('event1'); - value_of(Local.called).should_be(3); - - object.fireEvent('event2'); - value_of(Local.called).should_be(3); - }, - - 'should remove an event immediately': function(){ - var object = createObject(); - - var methods = []; - - var three = function(){ - methods.push(3); - }; - - object.addEvent('event', function(){ - methods.push(1); - this.removeEvent('event', three); - }).addEvent('event', function(){ - methods.push(2); - }).addEvent('event', three); - - object.fireEvent('event'); - value_of(methods).should_be([1, 2]); - - object.fireEvent('event'); - value_of(methods).should_be([1, 2, 1, 2]); - } - }); -}); - -describe("Options Class", { - - "before all": function(){ - Local.OptionsTest = new Class({ - Implements: [Options, Events], - - options: { - a: 1, - b: 2 - }, - - initialize: function(options){ - this.setOptions(options); - } - }); - }, - - "should set options": function(){ - var myTest = new Local.OptionsTest({a: 1, b: 3}); - value_of(myTest.options).should_not_be(undefined); - }, - - "should override default options": function(){ - 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); - } - -}); - -describe("Options Class with Events", { - - "before all": function(){ - Local.OptionsTest = new Class({ - Implements: [Options, Events], - - options: { - onEvent1: function(){ - return true; - }, - onEvent2: function(){ - return false; - } - }, - - initialize: function(options){ - this.setOptions(options); - } - }); - }, - - "should add events in the options object if class has implemented the Events class": function(){ - var myTest = new Local.OptionsTest({ - onEvent2: function(){ - return true; - }, - - onEvent3: function(){ - return true; - } - }); - - value_of(myTest.$events.event1.length).should_be(1); - value_of(myTest.$events.event2.length).should_be(1); - value_of(myTest.$events.event3.length).should_be(1); - } - -}); - -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.event1.length).should_be(1); - value_of(events.event1.length).should_be(1); - } - -}); \ No newline at end of file diff --git a/Specs/1.2public/Class/Class.js b/Specs/1.2public/Class/Class.js deleted file mode 100644 index 91c431e52..000000000 --- a/Specs/1.2public/Class/Class.js +++ /dev/null @@ -1,272 +0,0 @@ -/* -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'); - } - - /* - * TODO: 2.0 - "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/Specs/1.2public/Core/Browser.js b/Specs/1.2public/Core/Browser.js deleted file mode 100644 index fe146dde1..000000000 --- a/Specs/1.2public/Core/Browser.js +++ /dev/null @@ -1,40 +0,0 @@ -/* -Script: Browser.js - Public Specs for Browser.js 1.2 - -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/Specs/1.2public/Core/Core.js b/Specs/1.2public/Core/Core.js deleted file mode 100644 index cc158069d..000000000 --- a/Specs/1.2public/Core/Core.js +++ /dev/null @@ -1,408 +0,0 @@ -/* -Script: Core.js - Public Specs for Core.js 1.2 - -License: - MIT-style license. -*/ - -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(); - }, - - 'should be within a reasonable range': function(){ - value_of($time() < 1e13 && $time() > 1e12).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'); - } - -}); - -describe('Hash.getLength', { - - "should return the number of items in it": function(){ - var hash = new Hash({}); - value_of(hash.getLength()).should_be(0); - hash.set('mootools', 'awesome'); - hash.milk = 'yummy'; - value_of(hash.getLength()).should_be(2); - }, - - "should not fail when length is set": function(){ - var hash = new Hash({'length': 10}); - value_of(hash.getLength()).should_be(1); - }, - - "should work as a generic on objects": function(){ - value_of(Hash.getLength({})).should_be(0); - value_of(Hash.getLength({'': '', '0': '0', 'length': 99})).should_be(3); - } - -}); - -describe('$H', { - - "should create a new hash": function(){ - var hash = $H({}); - value_of($type(hash)).should_be('hash'); - } - -}); diff --git a/Specs/1.2public/Element/Element.Dimensions.js b/Specs/1.2public/Element/Element.Dimensions.js deleted file mode 100644 index 760fb5f37..000000000 --- a/Specs/1.2public/Element/Element.Dimensions.js +++ /dev/null @@ -1,120 +0,0 @@ -/* -Script: Element.Dimensions.js - Specs for Element.Dimensions.js - -License: - MIT-style license. -*/ - -(function(){ - var div, relDiv, absDiv, scrollDiv, tallDiv; - window.addEvent('domready', function(){ - div = new Element('div', { - id: 'ElementDimensionsTest', - styles: { - width: 100, - height: 100, - margin: 2, - padding: 3, - border: '1px solid black', - visibility: 'hidden', - display: 'block', - position: 'absolute', - top: 100, - left: 100, - overflow: 'hidden', - zIndex: 1 - } - }).inject($(document.body)); - - relDiv = new Element('div', { - styles: { - width: 50, - height: 50, - margin: 5, - padding: 5, - border: '1px solid green', - visibility: 'hidden', - position: 'relative', - overflow: 'hidden' - } - }).inject(div); - - absDiv = new Element('div', { - styles: { - width: 10, - height: 10, - margin: 5, - padding: 5, - border: '1px solid red', - visibility: 'hidden', - position: 'absolute', - top: 10, - left: 10, - overflow: 'hidden' - } - }).inject(relDiv); - - scrollDiv = new Element('div', { - styles: { - width: 100, - height: 100, - overflow: 'scroll', - visibility: 'hidden', - position: 'absolute', - top: 0, - left: 0 - } - }).inject($(document.body)); - - tallDiv = new Element('div', { - styles: { - width: 200, - height: 200, - visibility: 'hidden' - } - }).inject(scrollDiv); - - }); - - describe('Element.getSize', { - - 'should measure the width and height of the element': function(){ - value_of(div.getSize()).should_be({x: 108, y: 108}); - } - - }); - - describe('Element.getPosition', { - - 'should measure the x and y position of the element': function(){ - value_of(div.getPosition()).should_be({x: 102, y: 102}); - } - - }); - - describe('Element.getCoordinates', { - - 'should return the coordinates relative to parent': function(){ - value_of(absDiv.getCoordinates(relDiv)).should_be({left:16, top:16, width:22, height:22, right:38, bottom:38}); - } - - }); - - describe('Element.getScrollSize', { - - 'should return the scrollSize': function(){ - value_of(scrollDiv.getScrollSize()).should_be({x:200, y:200}); - } - - }); - - describe('Element.scrollTo', { - - 'should scroll the element': function(){ - value_of(scrollDiv.scrollTo(20,20).getScroll()).should_be({x:20, y:20}); - } - - }); - -})(); diff --git a/Specs/1.2public/Element/Element.Style.js b/Specs/1.2public/Element/Element.Style.js deleted file mode 100644 index 95f85abec..000000000 --- a/Specs/1.2public/Element/Element.Style.js +++ /dev/null @@ -1,73 +0,0 @@ -/* -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/Specs/1.2public/Element/Element.js b/Specs/1.2public/Element/Element.js deleted file mode 100644 index b3eb17aa1..000000000 --- a/Specs/1.2public/Element/Element.js +++ /dev/null @@ -1,1565 +0,0 @@ -/* -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_match(/(font-size:12px;color:rgb\(255,255,255\))|(color:rgb\(255,255,255\);font-size:12px)/); - //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='); - }, - - "should return a query string ignoring submit, reset and file form Elements": function(){ - var form = new Element('form', { 'html': '' + - '' + - '' + - '' + - '' + - '' - }); - value_of(form.toQueryString()).should_be('input=checked&textarea=textarea-value'); - } - -}); - -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'); - - var div = new Element('div', {'html': - '' - }); - var input3 = div.getElement('select'); - value_of(input3.getProperty('type')).should_be('select-multiple'); - value_of(input3.getProperty('name')).should_be('test'); - }, - - '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(); - }, - - 'should setProperty defaultValue of an input Element': function(){ - var form = new Element('form'); - var defaultValue = new Element('input', {'type': 'text', 'value': '321'}).setProperty('defaultValue', '123'); - form.grab(defaultValue); - value_of(defaultValue.getProperty('value')).should_be('321'); - form.reset(); - value_of(defaultValue.getProperty('value')).should_be('123'); - } - -}); - -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', maxlenght: 10 }); - readonly.removeProperty('readonly'); - readonly.removeProperty('maxlength'); - var props = readonly.getProperties('type', 'readonly', 'maxlength'); - value_of(props).should_be({ type: 'text', readonly: false, maxlength: Browser.Engine.webkit ? 524288 : 0}); - } - -}); - -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/Specs/1.2public/Native/Array.js b/Specs/1.2public/Native/Array.js deleted file mode 100644 index 37d28e6bb..000000000 --- a/Specs/1.2public/Native/Array.js +++ /dev/null @@ -1,207 +0,0 @@ -/* -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/Specs/1.2public/Native/Function.js b/Specs/1.2public/Native/Function.js deleted file mode 100644 index 61a5dd1be..000000000 --- a/Specs/1.2public/Native/Function.js +++ /dev/null @@ -1,155 +0,0 @@ -/* -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/Specs/1.2public/Native/Hash.js b/Specs/1.2public/Native/Hash.js deleted file mode 100644 index ff75a33b1..000000000 --- a/Specs/1.2public/Native/Hash.js +++ /dev/null @@ -1,203 +0,0 @@ -/* -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/Specs/1.2public/Native/Number.js b/Specs/1.2public/Native/Number.js deleted file mode 100644 index 3ccdf1893..000000000 --- a/Specs/1.2public/Native/Number.js +++ /dev/null @@ -1,114 +0,0 @@ -/* -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/Specs/1.2public/Native/String.js b/Specs/1.2public/Native/String.js deleted file mode 100644 index caa540006..000000000 --- a/Specs/1.2public/Native/String.js +++ /dev/null @@ -1,158 +0,0 @@ -/* -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/Specs/1.2public/Utilities/Cookie.js b/Specs/1.2public/Utilities/Cookie.js deleted file mode 100644 index 856a892f0..000000000 --- a/Specs/1.2public/Utilities/Cookie.js +++ /dev/null @@ -1,17 +0,0 @@ -/* -Script: Core.js - Public Specs for Core.js 1.2 - -License: - MIT-style license. -*/ - -describe('Cookie', { - - "should set a cookie": function(){ - Cookie.write('test', 1); - - - } - -}); \ No newline at end of file diff --git a/Specs/Sets.js b/Specs/Sets.js deleted file mode 100644 index 7bdd4348f..000000000 --- a/Specs/Sets.js +++ /dev/null @@ -1,15 +0,0 @@ -var Sets = { - - '1.2public': [ - 'Core/Core.js', 'Core/Browser.js', - 'Native/Array.js', 'Native/String.js', 'Native/Function.js', 'Native/Number.js', 'Native/Hash.js', - 'Class/Class.js', 'Class/Class.Extras.js', - 'Element/Element.js', 'Element/Element.Style.js', 'Element/Element.Dimensions.js', - ], - - '1.2private': [ - 'Core/Core.js', 'Core/Browser.js', - - ] - -}; \ No newline at end of file diff --git a/Specs/SlickSpec/JSSpec.css b/Specs/SlickSpec/JSSpec.css deleted file mode 100644 index 0f43a51db..000000000 --- a/Specs/SlickSpec/JSSpec.css +++ /dev/null @@ -1,245 +0,0 @@ -@CHARSET "UTF-8"; - -/* -------------------- - * @Layout - */ - -html { - overflow: hidden; -} - -body, #jsspec_container { - overflow: hidden; - padding: 0; - margin: 0; - width: 100%; - height: 100%; - background-color: white; -} - -#title { - padding: 0; - margin: 0; - position: absolute; - top: 0px; - left: 0px; - width: 100%; - height: 40px; - overflow: hidden; -} - -#list { - padding: 0; - margin: 0; - position: absolute; - top: 40px; - left: 0px; - bottom: 0px; - overflow: auto; - width: 250px; - _height:expression(document.body.clientHeight-40); -} - -#log { - padding: 0; - margin: 0; - position: absolute; - top: 40px; - left: 250px; - right: 0px; - bottom: 0px; - overflow: auto; - _height:expression(document.body.clientHeight-40); - _width:expression(document.body.clientWidth-250); -} - -/*iPhone*/ -@media only screen and (max-device-width: 480px) { - #list { - overflow: visible; - } - - #log { - overflow: visible; - } -} - - -/* -------------------- - * @Decorations and colors - */ -* { - padding: 0; - margin: 0; - font-family: "Lucida Grande", Helvetica, sans-serif; -} - -li { - list-style: none; -} - -/* hiding subtitles */ -h2 { - display: none; -} - -/* title section */ -div#title { - padding: 0em 0.5em; -} - -div#title h1 { - font-size: 1.5em; - float: left; -} - -div#title ul li { - float: left; - padding: 0.5em 0em 0.5em 0.75em; -} - -div#title p { - float:right; - margin-right:1em; - font-size: 0.75em; -} - -/* spec container */ -ul.specs { - margin: 0.5em; -} -ul.specs li { - margin-bottom: 0.1em; -} - -/* spec title */ -ul.specs li h3 { - font-weight: bold; - font-size: 0.75em; - padding: 0.2em 1em; - cursor: pointer; - _cursor: hand; -} - -/* example container */ -ul.examples li { - border-style: solid; - border-width: 0px 0px 1px 5px; - margin: 0.2em 0em 0.2em 1em; -} - -/* example title */ -ul.examples li h4 { - font-weight: normal; - font-size: 0.75em; - margin-left: 1em; -} - -pre.examples-code { - margin: 0.5em 2em; - padding: 0.5em; - background: white; - border: solid 1px #CCC; - font-size: 10px; - font-family: "Panic Sans", "Monaco", monospace !important; -} - -/* example explaination */ -ul.examples li div { - padding: 1em 2em; - font-size: 0.75em; -} - -/* styles for ongoing, success, failure, error */ -div.success, div.success a { - color: #FFFFFF; - background-color: #65C400; -} - -li.ongoing li.success pre.examples-code, -li pre.examples-code { - display:none !important; -} -li.exception pre.examples-code, -li.ongoing pre.examples-code { - display:block !important; -} - -ul.specs li.success h3, ul.specs li.success h3 a { - color: #FFFFFF; - background-color: #65C400; -} - -ul.examples li.success, ul.examples li.success a { - color: #3D7700; - background-color: #DBFFB4; - border-color: #65C400; -} - -div.exception, div.exception a { - color: #FFFFFF; - background-color: #C20000; -} - -ul.specs li.exception h3, ul.specs li.exception h3 a { - color: #FFFFFF; - background-color: #C20000; -} - -ul.examples li.exception, ul.examples li.exception a { - color: #C20000; - background-color: #FFFBD3; - border-color: #C20000; -} - -div.ongoing, div.ongoing a { - color: #000000; - background-color: #FFFF80; -} - -ul.specs li.ongoing h3, ul.specs li.ongoing h3 a { - color: #000000; - background-color: #FFFF80; -} - -ul.examples li.ongoing, ul.examples li.ongoing a { - color: #000000; - background-color: #FFFF80; - border-color: #DDDD00; -} - - - -/* -------------------- - * values - */ -.number_value, .string_value, .regexp_value, .boolean_value, .dom_value { - font-family: monospace; - color: blue; -} -.object_value, .array_value { - line-height: 2em; - padding: 0.1em 0.2em; - margin: 0.1em 0; -} -.date_value { - font-family: monospace; - color: olive; -} -.undefined_value, .null_value { - font-style: italic; - color: blue; -} -.dom_attr_name { -} -.dom_attr_value { - color: red; -} -.dom_path { - font-size: 0.75em; - color: gray; -} -strong { - font-weight: normal; - background-color: #FFC6C6; -} diff --git a/Specs/SlickSpec/JSSpec.js b/Specs/SlickSpec/JSSpec.js deleted file mode 100644 index 0b2e15b72..000000000 --- a/Specs/SlickSpec/JSSpec.js +++ /dev/null @@ -1,1553 +0,0 @@ -/** - * JSSpec - * - * Copyright 2007 Alan Kang - * - mailto:jania902@gmail.com - * - http://jania.pe.kr - * - * http://jania.pe.kr/aw/moin.cgi/JSSpec - * - * Dependencies: - * - diff_match_patch.js ( http://code.google.com/p/google-diff-match-patch ) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/** - * Namespace - */ - -var baseQueryString = window.location.search.replace(/&?rerun=.*?(&|$)/ig,'').replace(/&$/,''); -if (!baseQueryString) baseQueryString = '?'; else baseQueryString += '&'; - -var JSSpec = { - specs: [], - - EMPTY_FUNCTION: function() {}, - - Browser: { - // By Rendering Engines - Trident: navigator.appName === "Microsoft Internet Explorer", - Webkit: navigator.userAgent.indexOf('AppleWebKit/') > -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) { - window._curExecutor = self; - - result = self.target(); - self.onSuccess(self, result); - } 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'); - if (links) links = links.getElementsByTagName('A'); - else return; - 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/Specs/SlickSpec/JSSpecHelpers.js b/Specs/SlickSpec/JSSpecHelpers.js deleted file mode 100644 index 9b17ede7f..000000000 --- a/Specs/SlickSpec/JSSpecHelpers.js +++ /dev/null @@ -1,308 +0,0 @@ -function $try(){ - for (var i = 0, l = arguments.length; i < l; i++){ - try { - return arguments[i](); - } catch(e){} - } - return null; -}; - -Function.prototype._type = "Function"; - -String.escapeSingle = String.escapeSingle || function escapeSingle(string){ - return (''+string).replace(/(?=[\\\n'])/g,'\\'); -}; - - -var global = this; -global.context = this; -var specs, spec, it, its; -var descriptionParent = ''; -var uniquespecs = {}; - -function Describe(description,specBuilder){ - // Backup existing object so we don't override it - var old_specs = specs; - specs = spec = it = its = {}; - - // Inherit the before and afters of your forefathers - if (old_specs) { - if (old_specs.before ) specs.before = old_specs.before; - if (old_specs.before_all ) specs.before_all = old_specs.before_all; - if (old_specs.before_each ) specs.before_each = old_specs.before_each; - if (old_specs.after ) specs.after = old_specs.after; - if (old_specs.after_all ) specs.after_all = old_specs.after_all; - if (old_specs.after_each ) specs.after_each = old_specs.after_each; - } - - // Inherit the description of your forefathers - description = descriptionParent + (descriptionParent ? ': ' : '') + String(description); - var old_descriptionParent = descriptionParent; - descriptionParent = description; - - // Build the spec object - specBuilder(specs,global.context); - - // Create the tests and go! - var spec_count = 0; - var specnames = []; - for (var specname in specs){ - if (/^(before|after)[_ ](all|each)$/.test(specname)) continue; - if (!specs[specname]) continue; - spec_count++; - specnames.push(description+specname); - } - if (spec_count && !uniquespecs[specnames]){ - describe(description, specs); - uniquespecs[specnames] = true; - } - - // Reset - descriptionParent = old_descriptionParent; - specs = spec = it = its = old_specs; -}; - - -global.mocks = {}; -var Mock = (function(){ - - function Mock(mockName, testBuilder){ - if (mockName && !testBuilder) throw new Error("Invalid mockName, Mock syntax: `new Mock(/mockName/, function(specs, window){})`"); - - if (Object.prototype.toString.call(mockName) != '[object RegExp]') - mockName = new RegExp(mockName); - - this.mockName = mockName; - this.testBuilder = testBuilder; - Mock.mocks.push(this); - }; - - Mock.mocks = []; - - Mock.prototype.run = function(){ - var globalContextOld = global.context; - for (var mockName in global.mocks) if (this.mockName.test(mockName)) { - - global.context = global.mocks[mockName]; - for (var i = 0, l = global.willDefineEverywhere.length; i < l; i++) { - try { - global.willDefineEverywhere[i](global.context); - } finally { - continue; - } - } - Describe(mockName,this.testBuilder); - - } - global.context = globalContextOld; - }; - - Mock.register = function(name, window){ - clearTimeout(Mock.register.delay); - global.mocks[name] = window; - Mock.register.delay = setTimeout(Mock.register.done, 1000); - }; - - Mock.register.done = function(){ - for (var i=0; i < Mock.mocks.length; i++){ - try { - Mock.mocks[i].run(); - } finally { - continue; - } - } - - global.runSpecs(); - }; - - - return Mock; -})(); - -Mock.Request = function(mockName, url){ - if (!this instanceof Mock.Request) throw new Error('Mock.Request is not callable directly. Must use `new Mock.Request`'); - - this.mockName = mockName; - this.url = url; - - var self = this; - this.callback = function(html, xml){ - Mock.register(self.mockName +': '+ String(self.url).replace(/^.*\//,''), newFakeWinFromDoc(xml)); - }; - this.rq = new SimpleRequest(); - this.rq.send(this.url, this.callback); -}; - -global.willDefineEverywhere = []; -Mock.defineEverywhere = function(definer){ - global.willDefineEverywhere.push(definer); -} - -var TODO = function(){ throw "TODO: This test has not be written yet"; }; - -if(typeof JSSpec == 'undefined') var JSSpec = {}; -if(!JSSpec.Browser) JSSpec.Browser = {}; -JSSpec.Browser.NativeConsole = !!(('console' in this) && ('log' in console) && ('toString' in console.log) && console.log.toString().match(/\[native code\]/)); -JSSpec.Browser.Trident = (JSSpec.Browser.Trident && !JSSpec.Browser.NativeConsole); - -// Stop the normal JSSpec onload from firing yet -var runSpecs_actually = window.onload; -// console.time('runSpecs'); -var runSpecs = function(){ - // console.timeEnd('runSpecs'); - // console.time('runSpecs'); - // console.log('runSpecs'); - clearTimeout(global.runSpecs_timer); - global.runSpecs_timer = setTimeout(runSpecs_actually, 1000); -}; -window.onload = function(){ - window.loaded = true; - // setTimeout(runSpecs, 100); -}; - - -// XML -// from http://www.webreference.com/programming/javascript/definitive2/ -/** - * Create a new Document object. If no arguments are specified, - * the document will be empty. If a root tag is specified, the document - * will contain that single root tag. If the root tag has a namespace - * prefix, the second argument must specify the URL that identifies the - * namespace. - */ -var newXMLDocument = (document.implementation && document.implementation.createDocument) -? function(rootTagName, namespaceURL){ - return document.implementation.createDocument(namespaceURL||'', rootTagName||'', null); -} -: function(rootTagName, namespaceURL){ - if (!rootTagName) rootTagName = ""; - if (!namespaceURL) namespaceURL = ""; - // This is the IE way to do it - // Create an empty document as an ActiveX object - // If there is no root element, this is all we have to do - var doc = new ActiveXObject("MSXML2.DOMDocument"); - // If there is a root tag, initialize the document - if (rootTagName) { - // Look for a namespace prefix - var prefix = ""; - var tagname = rootTagName; - var p = rootTagName.indexOf(':'); - if (p != -1) { - prefix = rootTagName.substring(0, p); - tagname = rootTagName.substring(p+1); - } - // If we have a namespace, we must have a namespace prefix - // If we don't have a namespace, we discard any prefix - if (namespaceURL) { - if (!prefix) prefix = "a0"; // What Firefox uses - } - else prefix = ""; - // Create the root element (with optional namespace) as a - // string of text - var text = "<" + (prefix?(prefix+":"):"") + tagname + - (namespaceURL - ?(" xmlns:" + prefix + '="' + namespaceURL +'"') - :"") + - "/>"; - // And parse that text into the empty document - doc.loadXML(text); - } - return doc; -}; - -/** - * Synchronously load the XML document at the specified URL and - * return it as a Document object - */ -var loadXML = function(url) { - // Create a new document with the previously defined function - var xmldoc = newXMLDocument(); - xmldoc.async = false; // We want to load synchronously - xmldoc.load(url); // Load and parse - return xmldoc; // Return the document -}; - -/** - * Parse the XML document contained in the string argument and return - * a Document object that represents it. - */ -var parseXML = (function(){ - - // Mozilla, Firefox, and related browsers - if (typeof DOMParser != "undefined") - return function(rawXML){ - return (new DOMParser()).parseFromString(rawXML, "application/xml"); - }; - - // Internet Explorer. - if (typeof ActiveXObject != "undefined") - return function(rawXML){ - var xmlDocument = new ActiveXObject("Microsoft.XMLDOM"); - xmlDocument.async = false; - xmlDocument.loadXML(rawXML); - - if (xmlDocument.parseError && xmlDocument.parseError.errorCode) - xmlDocument.loadXML(rawXML.replace(/]*?>/i,'')); - - if (xmlDocument.parseError && xmlDocument.parseError.errorCode) - throw new Error(['' - ,("Error code: " + xmlDocument.parseError.errorCode) - ,("Error reason: " + xmlDocument.parseError.reason) - ,("Error line: " + xmlDocument.parseError.line) - ,rawXML - ].join('\n')); - - return xmlDocument; - }; - - // As a last resort, try loading the document from a data: URL - // This is supposed to work in Safari. Thanks to Manos Batsis and - // his Sarissa library (sarissa.sourceforge.net) for this technique. - return function(rawXML){ - var url = "data:text/xml;charset=utf-8," + encodeURIComponent(rawXML); - var request = new XMLHttpRequest(); - request.open("GET", url, false); - request.send(null); - return request.responseXML; - }; - -})(); - - -function getXML(url,mime){ - if (!mime && url && /\.(svg|xml|xhtml)/i.test(url)) - mime = 'text/xml'; - - var request; - if (XMLHttpRequest != undefined) - request = new XMLHttpRequest(); - else - request = new ActiveXObject("Microsoft.XMLHTTP"); - - request.open("GET", url, false); - if (mime && request.overrideMimeType) request.overrideMimeType(mime); - request.send(null); - return request; - return request.responseXML || parseXML(request.responseText); - -}; - - -function newFakeWinFromDoc(document){ - var fakeWin = { fake:true }; - fakeWin.document = document; - // fakeWin.document = getXML('/test/tools/MooTools_Logo.svg'); - // fakeWin.document = loadXML('tools/MooTools_Logo.svg'); - // fakeWin.document = document.getElementById('svg_logo_data_island').document; - // fakeWin.document = parseXML(''); - - fakeWin.SELECT = function(context, expression){ - return global.SELECT.call(fakeWin, context, expression); - }; - // if (fakeWin.document) fakeWin.document.search = function(expression){ - // return SELECT(fakeWin.document, expression); - // }; - - return fakeWin; -}; - diff --git a/Specs/SlickSpec/Loader.js b/Specs/SlickSpec/Loader.js deleted file mode 100644 index 5fd3517a4..000000000 --- a/Specs/SlickSpec/Loader.js +++ /dev/null @@ -1,52 +0,0 @@ -var loadSpecs = (function(Sets){ - -// Uses String.parseQueryString from MooTools-More -// TODO Needs compat for other browsers -var parseQueryString = function(string){ - var vars = string.split(/[&;]/), res = {}; - if (vars.length) vars.forEach(function(val){ - var index = val.indexOf('='), - keys = index < 0 ? [''] : val.substr(0, index).match(/[^\]\[]+/g), - value = decodeURIComponent(val.substr(index + 1)), - obj = res; - keys.forEach(function(key, i){ - var current = obj[key]; - if(i < keys.length - 1) - obj = obj[key] = current || {}; - else if(current && current._type == 'Array') // JSSpec prototyping - current.push(value); - else - obj[key] = current != undefined ? [current, value] : value; - }); - }); - return res; -}; - -var getSpecs = function(queryString){ - queryString = parseQueryString(queryString); - - var requestedSpecs = [], - specs = queryString.specs; - - (specs && specs._type == 'Array' ? specs : [specs]).forEach(function(spec){ - if (Sets[spec] && requestedSpecs.indexOf(spec) == -1) requestedSpecs.push(spec); - }); - - return requestedSpecs; -}; - -var loadSpecs = function(obj){ - for (var i = 0; i < obj.length; i++){ - SpecNames.push(obj[i]); - - var specs = Sets[obj[i]]; - for (var j = 0; j < specs.length; j++){ - document.write('<\/script>'); - } - } -}; - -var requestedSpecs = getSpecs(document.location.search.substr(1)); -loadSpecs(requestedSpecs); - -}); \ No newline at end of file diff --git a/Specs/SlickSpec/diff_match_patch.js b/Specs/SlickSpec/diff_match_patch.js deleted file mode 100644 index 67af5832f..000000000 --- a/Specs/SlickSpec/diff_match_patch.js +++ /dev/null @@ -1,2136 +0,0 @@ -/* -curl -s http://google-diff-match-patch.googlecode.com/svn/trunk/javascript/diff_match_patch_uncompressed.js #*/ -/** - * Diff Match and Patch - * - * Copyright 2006 Google Inc. - * http://code.google.com/p/google-diff-match-patch/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Computes the difference between two texts to create a patch. - * Applies the patch onto another text, allowing for errors. - * @author fraser@google.com (Neil Fraser) - */ - -/** - * Class containing the diff, match and patch methods. - * @constructor - */ -function diff_match_patch() { - - // Defaults. - // Redefine these in your program to override the defaults. - - // Number of seconds to map a diff before giving up (0 for infinity). - this.Diff_Timeout = 1.0; - // Cost of an empty edit operation in terms of edit characters. - this.Diff_EditCost = 4; - // The size beyond which the double-ended diff activates. - // Double-ending is twice as fast, but less accurate. - this.Diff_DualThreshold = 32; - // At what point is no match declared (0.0 = perfection, 1.0 = very loose). - this.Match_Threshold = 0.5; - // How far to search for a match (0 = exact location, 1000+ = broad match). - // A match this many characters away from the expected location will add - // 1.0 to the score (0.0 is a perfect match). - this.Match_Distance = 1000; - // When deleting a large block of text (over ~64 characters), how close does - // the contents have to match the expected contents. (0.0 = perfection, - // 1.0 = very loose). Note that Match_Threshold controls how closely the - // end points of a delete need to match. - this.Patch_DeleteThreshold = 0.5; - // Chunk size for context length. - this.Patch_Margin = 4; - - /** - * Compute the number of bits in an int. - * The normal answer for JavaScript is 32. - * @return {number} Max bits - */ - function getMaxBits() { - var maxbits = 0; - var oldi = 1; - var newi = 2; - while (oldi != newi) { - maxbits++; - oldi = newi; - newi = newi << 1; - } - return maxbits; - } - // How many bits in a number? - this.Match_MaxBits = getMaxBits(); -} - - -// DIFF FUNCTIONS - - -/** - * The data structure representing a diff is an array of tuples: - * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']] - * which means: delete 'Hello', add 'Goodbye' and keep ' world.' - */ -var DIFF_DELETE = -1; -var DIFF_INSERT = 1; -var DIFF_EQUAL = 0; - - -/** - * Find the differences between two texts. Simplifies the problem by stripping - * any common prefix or suffix off the texts before diffing. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {boolean} opt_checklines Optional speedup flag. If present and false, - * then don't run a line-level diff first to identify the changed areas. - * Defaults to true, which does a faster, slightly less optimal diff - * @return {Array.>} Array of diff tuples. - */ -diff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines) { - // Check for equality (speedup) - if (text1 == text2) { - return [[DIFF_EQUAL, text1]]; - } - - if (typeof opt_checklines == 'undefined') { - opt_checklines = true; - } - var checklines = opt_checklines; - - // Trim off common prefix (speedup) - var commonlength = this.diff_commonPrefix(text1, text2); - var commonprefix = text1.substring(0, commonlength); - text1 = text1.substring(commonlength); - text2 = text2.substring(commonlength); - - // Trim off common suffix (speedup) - 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); - - // Compute the diff on the middle block - var diffs = this.diff_compute(text1, text2, checklines); - - // Restore the prefix and suffix - if (commonprefix) { - diffs.unshift([DIFF_EQUAL, commonprefix]); - } - if (commonsuffix) { - diffs.push([DIFF_EQUAL, commonsuffix]); - } - this.diff_cleanupMerge(diffs); - return diffs; -}; - - -/** - * Find the differences between two texts. Assumes that the texts do not - * have any common prefix or suffix. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {boolean} checklines Speedup flag. If false, then don't run a - * line-level diff first to identify the changed areas. - * If true, then run a faster, slightly less optimal diff - * @return {Array.>} Array of diff tuples. - * @private - */ -diff_match_patch.prototype.diff_compute = function(text1, text2, checklines) { - var diffs; - - if (!text1) { - // Just add some text (speedup) - return [[DIFF_INSERT, text2]]; - } - - if (!text2) { - // Just delete some text (speedup) - 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) { - // Shorter text is inside the longer text (speedup) - diffs = [[DIFF_INSERT, longtext.substring(0, i)], - [DIFF_EQUAL, shorttext], - [DIFF_INSERT, longtext.substring(i + shorttext.length)]]; - // Swap insertions for deletions if diff is reversed. - if (text1.length > text2.length) { - diffs[0][0] = diffs[2][0] = DIFF_DELETE; - } - return diffs; - } - longtext = shorttext = null; // Garbage collect - - // Check to see if the problem can be split in two. - var hm = this.diff_halfMatch(text1, text2); - if (hm) { - // A half-match was found, sort out the return data. - 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]; - // Send both pairs off for separate processing. - var diffs_a = this.diff_main(text1_a, text2_a, checklines); - var diffs_b = this.diff_main(text1_b, text2_b, checklines); - // Merge the results. - return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b); - } - - // Perform a real diff. - if (checklines && (text1.length < 100 || text2.length < 100)) { - // Too trivial for the overhead. - checklines = false; - } - var linearray; - if (checklines) { - // Scan the text on a line-by-line basis first. - var a = this.diff_linesToChars(text1, text2); - text1 = a[0]; - text2 = a[1]; - linearray = a[2]; - } - diffs = this.diff_map(text1, text2); - if (!diffs) { - // No acceptable result. - diffs = [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; - } - if (checklines) { - // Convert the diff back to original text. - this.diff_charsToLines(diffs, linearray); - // Eliminate freak matches (e.g. blank lines) - this.diff_cleanupSemantic(diffs); - - // Rediff any replacement blocks, this time character-by-character. - // Add a dummy entry at the end. - diffs.push([DIFF_EQUAL, '']); - var pointer = 0; - var count_delete = 0; - var count_insert = 0; - var text_delete = ''; - var text_insert = ''; - while (pointer < diffs.length) { - switch (diffs[pointer][0]) { - case DIFF_INSERT: - count_insert++; - text_insert += diffs[pointer][1]; - break; - case DIFF_DELETE: - count_delete++; - text_delete += diffs[pointer][1]; - break; - case DIFF_EQUAL: - // Upon reaching an equality, check for prior redundancies. - if (count_delete >= 1 && count_insert >= 1) { - // Delete the offending records and add the merged ones. - 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 = ''; - break; - } - pointer++; - } - diffs.pop(); // Remove the dummy entry at the end. - } - return diffs; -}; - - -/** - * Split two texts into an array of strings. Reduce the texts to a string of - * hashes where each Unicode character represents one line. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {Array.>} Three element Array, containing the - * encoded text1, the encoded text2 and the array of unique strings. The - * zeroth element of the array of unique strings is intentionally blank. - * @private - */ -diff_match_patch.prototype.diff_linesToChars = function(text1, text2) { - var lineArray = []; // e.g. lineArray[4] == 'Hello\n' - var lineHash = {}; // e.g. lineHash['Hello\n'] == 4 - - // '\x00' is a valid character, but various debuggers don't like it. - // So we'll insert a junk entry to avoid generating a null character. - lineArray[0] = ''; - - /** - * Split a text into an array of strings. Reduce the texts to a string of - * hashes where each Unicode character represents one line. - * Modifies linearray and linehash through being a closure. - * @param {string} text String to encode - * @return {string} Encoded string - * @private - */ - function diff_linesToCharsMunge(text) { - var chars = ''; - // Walk the text, pulling out a substring for each line. - // text.split('\n') would would temporarily double our memory footprint. - // Modifying text would create many large strings to garbage collect. - var lineStart = 0; - var lineEnd = -1; - // Keeping our own length variable is faster than looking it up. - var lineArrayLength = lineArray.length; - while (lineEnd < text.length - 1) { - lineEnd = text.indexOf('\n', lineStart); - if (lineEnd == -1) { - lineEnd = text.length - 1; - } - var line = text.substring(lineStart, lineEnd + 1); - lineStart = lineEnd + 1; - - if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : - (lineHash[line] !== undefined)) { - chars += String.fromCharCode(lineHash[line]); - } else { - chars += String.fromCharCode(lineArrayLength); - lineHash[line] = lineArrayLength; - lineArray[lineArrayLength++] = line; - } - } - return chars; - } - - var chars1 = diff_linesToCharsMunge(text1); - var chars2 = diff_linesToCharsMunge(text2); - return [chars1, chars2, lineArray]; -}; - - -/** - * Rehydrate the text in a diff from a string of line hashes to real lines of - * text. - * @param {Array.>} diffs Array of diff tuples. - * @param {Array.} lineArray Array of unique strings. - * @private - */ -diff_match_patch.prototype.diff_charsToLines = function(diffs, lineArray) { - for (var x = 0; x < diffs.length; x++) { - var chars = diffs[x][1]; - var text = []; - for (var y = 0; y < chars.length; y++) { - text[y] = lineArray[chars.charCodeAt(y)]; - } - diffs[x][1] = text.join(''); - } -}; - - -/** - * Explore the intersection points between the two texts. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @return {Array.>?} Array of diff tuples or null if no - * diff available. - * @private - */ -diff_match_patch.prototype.diff_map = function(text1, text2) { - // Don't run for too long. - var ms_end = (new Date()).getTime() + this.Diff_Timeout * 1000; - // Cache the text lengths to prevent multiple calls. - var text1_length = text1.length; - var text2_length = text2.length; - var max_d = text1_length + text2_length - 1; - var doubleEnd = this.Diff_DualThreshold * 2 < max_d; - var v_map1 = []; - var v_map2 = []; - var v1 = {}; - var v2 = {}; - v1[1] = 0; - v2[1] = 0; - var x, y; - var footstep; // Used to track overlapping paths. - var footsteps = {}; - var done = false; - // Safari 1.x doesn't have hasOwnProperty - var hasOwnProperty = !!(footsteps.hasOwnProperty); - // If the total number of characters is odd, then the front path will collide - // with the reverse path. - var front = (text1_length + text2_length) % 2; - for (var d = 0; d < max_d; d++) { - // Bail out if timeout reached. - if (this.Diff_Timeout > 0 && (new Date()).getTime() > ms_end) { - return null; - } - - // Walk the front path one step. - v_map1[d] = {}; - for (var k = -d; k <= d; k += 2) { - if (k == -d || k != d && v1[k - 1] < v1[k + 1]) { - x = v1[k + 1]; - } else { - x = v1[k - 1] + 1; - } - y = x - k; - if (doubleEnd) { - footstep = x + ',' + y; - if (front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : - (footsteps[footstep] !== undefined))) { - done = true; - } - if (!front) { - footsteps[footstep] = d; - } - } - while (!done && x < text1_length && y < text2_length && - text1.charAt(x) == text2.charAt(y)) { - x++; - y++; - if (doubleEnd) { - footstep = x + ',' + y; - if (front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : - (footsteps[footstep] !== undefined))) { - done = true; - } - if (!front) { - footsteps[footstep] = d; - } - } - } - v1[k] = x; - v_map1[d][x + ',' + y] = true; - if (x == text1_length && y == text2_length) { - // Reached the end in single-path mode. - return this.diff_path1(v_map1, text1, text2); - } else if (done) { - // Front path ran over reverse path. - v_map2 = v_map2.slice(0, footsteps[footstep] + 1); - var a = this.diff_path1(v_map1, text1.substring(0, x), - text2.substring(0, y)); - return a.concat(this.diff_path2(v_map2, text1.substring(x), - text2.substring(y))); - } - } - - if (doubleEnd) { - // Walk the reverse path one step. - v_map2[d] = {}; - for (var k = -d; k <= d; k += 2) { - if (k == -d || k != d && v2[k - 1] < v2[k + 1]) { - x = v2[k + 1]; - } else { - x = v2[k - 1] + 1; - } - y = x - k; - footstep = (text1_length - x) + ',' + (text2_length - y); - if (!front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : - (footsteps[footstep] !== undefined))) { - done = true; - } - if (front) { - footsteps[footstep] = d; - } - while (!done && x < text1_length && y < text2_length && - text1.charAt(text1_length - x - 1) == - text2.charAt(text2_length - y - 1)) { - x++; - y++; - footstep = (text1_length - x) + ',' + (text2_length - y); - if (!front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : - (footsteps[footstep] !== undefined))) { - done = true; - } - if (front) { - footsteps[footstep] = d; - } - } - v2[k] = x; - v_map2[d][x + ',' + y] = true; - if (done) { - // Reverse path ran over front path. - v_map1 = v_map1.slice(0, footsteps[footstep] + 1); - var a = this.diff_path1(v_map1, text1.substring(0, text1_length - x), - text2.substring(0, text2_length - y)); - return a.concat(this.diff_path2(v_map2, - text1.substring(text1_length - x), - text2.substring(text2_length - y))); - } - } - } - } - // Number of diffs equals number of characters, no commonality at all. - return null; -}; - - -/** - * Work from the middle back to the start to determine the path. - * @param {Array.} v_map Array of paths. - * @param {string} text1 Old string fragment to be diffed. - * @param {string} text2 New string fragment to be diffed. - * @return {Array.>} Array of diff tuples. - * @private - */ -diff_match_patch.prototype.diff_path1 = function(v_map, text1, text2) { - var path = []; - var x = text1.length; - var y = text2.length; - /** @type {number?} */ - 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[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 (text1.charAt(x) != text2.charAt(y)) { - // throw new Error('No diagonal. Can\'t happen. (diff_path1)'); - //} - 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; -}; - - -/** - * Work from the middle back to the end to determine the path. - * @param {Array.} v_map Array of paths. - * @param {string} text1 Old string fragment to be diffed. - * @param {string} text2 New string fragment to be diffed. - * @return {Array.>} Array of diff tuples. - * @private - */ -diff_match_patch.prototype.diff_path2 = function(v_map, text1, text2) { - var path = []; - var pathLength = 0; - var x = text1.length; - var y = text2.length; - /** @type {number?} */ - 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[pathLength - 1][1] += text1.charAt(text1.length - x - 1); - } else { - path[pathLength++] = - [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[pathLength - 1][1] += text2.charAt(text2.length - y - 1); - } else { - path[pathLength++] = - [DIFF_INSERT, text2.charAt(text2.length - y - 1)]; - } - last_op = DIFF_INSERT; - break; - } else { - x--; - y--; - //if (text1.charAt(text1.length - x - 1) != - // text2.charAt(text2.length - y - 1)) { - // throw new Error('No diagonal. Can\'t happen. (diff_path2)'); - //} - if (last_op === DIFF_EQUAL) { - path[pathLength - 1][1] += text1.charAt(text1.length - x - 1); - } else { - path[pathLength++] = - [DIFF_EQUAL, text1.charAt(text1.length - x - 1)]; - } - last_op = DIFF_EQUAL; - } - } - } - return path; -}; - - -/** - * Determine the common prefix of two strings - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {number} The number of characters common to the start of each - * string. - */ -diff_match_patch.prototype.diff_commonPrefix = function(text1, text2) { - // Quick check for common null cases. - if (!text1 || !text2 || text1.charCodeAt(0) !== text2.charCodeAt(0)) { - return 0; - } - // Binary search. - // Performance analysis: http://neil.fraser.name/news/2007/10/09/ - var pointermin = 0; - var pointermax = Math.min(text1.length, text2.length); - var pointermid = pointermax; - var pointerstart = 0; - while (pointermin < pointermid) { - if (text1.substring(pointerstart, pointermid) == - text2.substring(pointerstart, pointermid)) { - pointermin = pointermid; - pointerstart = pointermin; - } else { - pointermax = pointermid; - } - pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); - } - return pointermid; -}; - - -/** - * Determine the common suffix of two strings - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {number} The number of characters common to the end of each string. - */ -diff_match_patch.prototype.diff_commonSuffix = function(text1, text2) { - // Quick check for common null cases. - if (!text1 || !text2 || text1.charCodeAt(text1.length - 1) !== - text2.charCodeAt(text2.length - 1)) { - return 0; - } - // Binary search. - // Performance analysis: http://neil.fraser.name/news/2007/10/09/ - var pointermin = 0; - var pointermax = Math.min(text1.length, text2.length); - var pointermid = pointermax; - var pointerend = 0; - while (pointermin < pointermid) { - if (text1.substring(text1.length - pointermid, text1.length - pointerend) == - text2.substring(text2.length - pointermid, text2.length - pointerend)) { - pointermin = pointermid; - pointerend = pointermin; - } else { - pointermax = pointermid; - } - pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); - } - return pointermid; -}; - - -/** - * Do the two texts share a substring which is at least half the length of the - * longer text? - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {Array.?} Five element Array, containing the prefix of - * text1, the suffix of text1, the prefix of text2, the suffix of - * text2 and the common middle. Or null if there was no match. - */ -diff_match_patch.prototype.diff_halfMatch = function(text1, text2) { - var longtext = text1.length > text2.length ? text1 : text2; - var shorttext = text1.length > text2.length ? text2 : text1; - if (longtext.length < 10 || shorttext.length < 1) { - return null; // Pointless. - } - var dmp = this; // 'this' becomes 'window' in a closure. - - /** - * Does a substring of shorttext exist within longtext such that the substring - * is at least half the length of longtext? - * Closure, but does not reference any external variables. - * @param {string} longtext Longer string. - * @param {string} shorttext Shorter string. - * @param {number} i Start index of quarter length substring within longtext - * @return {Array.?} Five element Array, containing the prefix of - * longtext, the suffix of longtext, the prefix of shorttext, the suffix - * of shorttext and the common middle. Or null if there was no match. - * @private - */ - function diff_halfMatchI(longtext, shorttext, i) { - // Start with a 1/4 length substring at position i as a seed. - 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 < suffixLength + prefixLength) { - best_common = shorttext.substring(j - suffixLength, j) + - shorttext.substring(j, j + prefixLength); - best_longtext_a = longtext.substring(0, i - suffixLength); - best_longtext_b = longtext.substring(i + prefixLength); - best_shorttext_a = shorttext.substring(0, j - suffixLength); - best_shorttext_b = shorttext.substring(j + prefixLength); - } - } - 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; - } - } - - // First check if the second quarter is the seed for a half-match. - var hm1 = diff_halfMatchI(longtext, shorttext, - Math.ceil(longtext.length / 4)); - // Check again based on the third quarter. - 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 { - // Both matched. Select the longest. - hm = hm1[4].length > hm2[4].length ? hm1 : hm2; - } - - // A half-match was found, sort out the return data. - 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]; -}; - - -/** - * Reduce the number of edits by eliminating semantically trivial equalities. - * @param {Array.>} diffs Array of diff tuples. - */ -diff_match_patch.prototype.diff_cleanupSemantic = function(diffs) { - var changes = false; - var equalities = []; // Stack of indices where equalities are found. - var equalitiesLength = 0; // Keeping our own length var is faster in JS. - var lastequality = null; // Always equal to equalities[equalitiesLength-1][1] - var pointer = 0; // Index of current position. - // Number of characters that changed prior to the equality. - var length_changes1 = 0; - // Number of characters that changed after the equality. - var length_changes2 = 0; - while (pointer < diffs.length) { - if (diffs[pointer][0] == DIFF_EQUAL) { // equality found - equalities[equalitiesLength++] = pointer; - length_changes1 = length_changes2; - length_changes2 = 0; - lastequality = diffs[pointer][1]; - } else { // an insertion or deletion - length_changes2 += diffs[pointer][1].length; - if (lastequality !== null && (lastequality.length <= length_changes1) && - (lastequality.length <= length_changes2)) { - // Duplicate record - diffs.splice(equalities[equalitiesLength - 1], 0, - [DIFF_DELETE, lastequality]); - // Change second copy to insert. - diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; - // Throw away the equality we just deleted. - equalitiesLength--; - // Throw away the previous equality (it needs to be reevaluated). - equalitiesLength--; - pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; - length_changes1 = 0; // Reset the counters. - length_changes2 = 0; - lastequality = null; - changes = true; - } - } - pointer++; - } - if (changes) { - this.diff_cleanupMerge(diffs); - } - this.diff_cleanupSemanticLossless(diffs); -}; - - -/** - * Look for single edits surrounded on both sides by equalities - * which can be shifted sideways to align the edit to a word boundary. - * e.g: The cat came. -> The cat came. - * @param {Array.>} diffs Array of diff tuples. - */ -diff_match_patch.prototype.diff_cleanupSemanticLossless = function(diffs) { - // Define some regex patterns for matching boundaries. - var punctuation = /[^a-zA-Z0-9]/; - var whitespace = /\s/; - var linebreak = /[\r\n]/; - var blanklineEnd = /\n\r?\n$/; - var blanklineStart = /^\r?\n\r?\n/; - - /** - * Given two strings, compute a score representing whether the internal - * boundary falls on logical boundaries. - * Scores range from 5 (best) to 0 (worst). - * Closure, makes reference to regex patterns defined above. - * @param {string} one First string - * @param {string} two Second string - * @return {number} The score. - */ - function diff_cleanupSemanticScore(one, two) { - if (!one || !two) { - // Edges are the best. - return 5; - } - - // Each port of this function behaves slightly differently due to - // subtle differences in each language's definition of things like - // 'whitespace'. Since this function's purpose is largely cosmetic, - // the choice has been made to use each language's native features - // rather than force total conformity. - var score = 0; - // One point for non-alphanumeric. - if (one.charAt(one.length - 1).match(punctuation) || - two.charAt(0).match(punctuation)) { - score++; - // Two points for whitespace. - if (one.charAt(one.length - 1).match(whitespace) || - two.charAt(0).match(whitespace)) { - score++; - // Three points for line breaks. - if (one.charAt(one.length - 1).match(linebreak) || - two.charAt(0).match(linebreak)) { - score++; - // Four points for blank lines. - if (one.match(blanklineEnd) || two.match(blanklineStart)) { - score++; - } - } - } - } - return score; - } - - var pointer = 1; - // Intentionally ignore the first and last element (don't need checking). - while (pointer < diffs.length - 1) { - if (diffs[pointer - 1][0] == DIFF_EQUAL && - diffs[pointer + 1][0] == DIFF_EQUAL) { - // This is a single edit surrounded by equalities. - var equality1 = diffs[pointer - 1][1]; - var edit = diffs[pointer][1]; - var equality2 = diffs[pointer + 1][1]; - - // First, shift the edit as far left as possible. - var commonOffset = this.diff_commonSuffix(equality1, edit); - if (commonOffset) { - var commonString = edit.substring(edit.length - commonOffset); - equality1 = equality1.substring(0, equality1.length - commonOffset); - edit = commonString + edit.substring(0, edit.length - commonOffset); - equality2 = commonString + equality2; - } - - // Second, step character by character right, looking for the best fit. - var bestEquality1 = equality1; - var bestEdit = edit; - var bestEquality2 = equality2; - var bestScore = diff_cleanupSemanticScore(equality1, edit) + - diff_cleanupSemanticScore(edit, equality2); - while (edit.charAt(0) === equality2.charAt(0)) { - equality1 += edit.charAt(0); - edit = edit.substring(1) + equality2.charAt(0); - equality2 = equality2.substring(1); - var score = diff_cleanupSemanticScore(equality1, edit) + - diff_cleanupSemanticScore(edit, equality2); - // The >= encourages trailing rather than leading whitespace on edits. - if (score >= bestScore) { - bestScore = score; - bestEquality1 = equality1; - bestEdit = edit; - bestEquality2 = equality2; - } - } - - if (diffs[pointer - 1][1] != bestEquality1) { - // We have an improvement, save it back to the diff. - if (bestEquality1) { - diffs[pointer - 1][1] = bestEquality1; - } else { - diffs.splice(pointer - 1, 1); - pointer--; - } - diffs[pointer][1] = bestEdit; - if (bestEquality2) { - diffs[pointer + 1][1] = bestEquality2; - } else { - diffs.splice(pointer + 1, 1); - pointer--; - } - } - } - pointer++; - } -}; - - -/** - * Reduce the number of edits by eliminating operationally trivial equalities. - * @param {Array.>} diffs Array of diff tuples. - */ -diff_match_patch.prototype.diff_cleanupEfficiency = function(diffs) { - var changes = false; - var equalities = []; // Stack of indices where equalities are found. - var equalitiesLength = 0; // Keeping our own length var is faster in JS. - var lastequality = ''; // Always equal to equalities[equalitiesLength-1][1] - var pointer = 0; // Index of current position. - // Is there an insertion operation before the last equality. - var pre_ins = false; - // Is there a deletion operation before the last equality. - var pre_del = false; - // Is there an insertion operation after the last equality. - var post_ins = false; - // Is there a deletion operation after the last equality. - var post_del = false; - while (pointer < diffs.length) { - if (diffs[pointer][0] == DIFF_EQUAL) { // equality found - if (diffs[pointer][1].length < this.Diff_EditCost && - (post_ins || post_del)) { - // Candidate found. - equalities[equalitiesLength++] = pointer; - pre_ins = post_ins; - pre_del = post_del; - lastequality = diffs[pointer][1]; - } else { - // Not a candidate, and can never become one. - equalitiesLength = 0; - lastequality = ''; - } - post_ins = post_del = false; - } else { // an insertion or deletion - if (diffs[pointer][0] == DIFF_DELETE) { - post_del = true; - } else { - post_ins = true; - } - /* - * Five types to be split: - * ABXYCD - * AXCD - * ABXC - * AXCD - * ABXC - */ - if (lastequality && ((pre_ins && pre_del && post_ins && post_del) || - ((lastequality.length < this.Diff_EditCost / 2) && - (pre_ins + pre_del + post_ins + post_del) == 3))) { - // Duplicate record - diffs.splice(equalities[equalitiesLength - 1], 0, - [DIFF_DELETE, lastequality]); - // Change second copy to insert. - diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; - equalitiesLength--; // Throw away the equality we just deleted; - lastequality = ''; - if (pre_ins && pre_del) { - // No changes made which could affect previous entry, keep going. - post_ins = post_del = true; - equalitiesLength = 0; - } else { - equalitiesLength--; // Throw away the previous equality; - pointer = equalitiesLength > 0 ? - equalities[equalitiesLength - 1] : -1; - post_ins = post_del = false; - } - changes = true; - } - } - pointer++; - } - - if (changes) { - this.diff_cleanupMerge(diffs); - } -}; - - -/** - * Reorder and merge like edit sections. Merge equalities. - * Any edit section can move as long as it doesn't cross an equality. - * @param {Array.>} diffs Array of diff tuples. - */ -diff_match_patch.prototype.diff_cleanupMerge = function(diffs) { - diffs.push([DIFF_EQUAL, '']); // Add a dummy entry at the end. - var pointer = 0; - var count_delete = 0; - var count_insert = 0; - var text_delete = ''; - var text_insert = ''; - var commonlength; - while (pointer < diffs.length) { - switch (diffs[pointer][0]) { - case DIFF_INSERT: - count_insert++; - text_insert += diffs[pointer][1]; - pointer++; - break; - case DIFF_DELETE: - count_delete++; - text_delete += diffs[pointer][1]; - pointer++; - break; - case DIFF_EQUAL: - // Upon reaching an equality, check for prior redundancies. - if (count_delete !== 0 || count_insert !== 0) { - if (count_delete !== 0 && count_insert !== 0) { - // Factor out any common prefixies. - commonlength = this.diff_commonPrefix(text_insert, text_delete); - if (commonlength !== 0) { - if ((pointer - count_delete - count_insert) > 0 && - 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); - } - // Factor out any common suffixies. - 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); - } - } - // Delete the offending records and add the merged ones. - 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) { - // Merge this equality with the previous one. - diffs[pointer - 1][1] += diffs[pointer][1]; - diffs.splice(pointer, 1); - } else { - pointer++; - } - count_insert = 0; - count_delete = 0; - text_delete = ''; - text_insert = ''; - break; - } - } - if (diffs[diffs.length - 1][1] === '') { - diffs.pop(); // Remove the dummy entry at the end. - } - - // Second pass: look for single edits surrounded on both sides by equalities - // which can be shifted sideways to eliminate an equality. - // e.g: ABAC -> ABAC - var changes = false; - pointer = 1; - // Intentionally ignore the first and last element (don't need checking). - while (pointer < diffs.length - 1) { - if (diffs[pointer - 1][0] == DIFF_EQUAL && - diffs[pointer + 1][0] == DIFF_EQUAL) { - // This is a single edit surrounded by equalities. - if (diffs[pointer][1].substring(diffs[pointer][1].length - - diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) { - // Shift the edit over the previous equality. - diffs[pointer][1] = diffs[pointer - 1][1] + - diffs[pointer][1].substring(0, diffs[pointer][1].length - - diffs[pointer - 1][1].length); - diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; - diffs.splice(pointer - 1, 1); - changes = true; - } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) == - diffs[pointer + 1][1]) { - // Shift the edit over the next equality. - diffs[pointer - 1][1] += diffs[pointer + 1][1]; - diffs[pointer][1] = - diffs[pointer][1].substring(diffs[pointer + 1][1].length) + - diffs[pointer + 1][1]; - diffs.splice(pointer + 1, 1); - changes = true; - } - } - pointer++; - } - // If shifts were made, the diff needs reordering and another shift sweep. - if (changes) { - this.diff_cleanupMerge(diffs); - } -}; - - -/** - * loc is a location in text1, compute and return the equivalent location in - * text2. - * e.g. 'The cat' vs 'The big cat', 1->1, 5->8 - * @param {Array.>} diffs Array of diff tuples. - * @param {number} loc Location within text1. - * @return {number} Location within text2. - */ -diff_match_patch.prototype.diff_xIndex = function(diffs, loc) { - var chars1 = 0; - var chars2 = 0; - var last_chars1 = 0; - var last_chars2 = 0; - var x; - for (x = 0; x < diffs.length; x++) { - if (diffs[x][0] !== DIFF_INSERT) { // Equality or deletion. - chars1 += diffs[x][1].length; - } - if (diffs[x][0] !== DIFF_DELETE) { // Equality or insertion. - chars2 += diffs[x][1].length; - } - if (chars1 > loc) { // Overshot the location. - break; - } - last_chars1 = chars1; - last_chars2 = chars2; - } - // Was the location was deleted? - if (diffs.length != x && diffs[x][0] === DIFF_DELETE) { - return last_chars2; - } - // Add the remaining character length. - return last_chars2 + (loc - last_chars1); -}; - - -/** - * Convert a diff array into a pretty HTML report. - * @param {Array.>} diffs Array of diff tuples. - * @return {string} HTML representation. - */ -diff_match_patch.prototype.diff_prettyHtml = function(diffs) { - var html = []; - var i = 0; - for (var x = 0; x < diffs.length; x++) { - var op = diffs[x][0]; // Operation (insert, delete, equal) - var data = diffs[x][1]; // Text of change. - var text = data.replace(/&/g, '&').replace(//g, '>').replace(/\n/g, '¶
'); - switch (op) { - case DIFF_INSERT: - html[x] = '' + - text + ''; - break; - case DIFF_DELETE: - html[x] = '' + - text + ''; - break; - case DIFF_EQUAL: - html[x] = '' + text + ''; - break; - } - if (op !== DIFF_DELETE) { - i += data.length; - } - } - return html.join(''); -}; - - -/** - * Compute and return the source text (all equalities and deletions). - * @param {Array.>} diffs Array of diff tuples. - * @return {string} Source text. - */ -diff_match_patch.prototype.diff_text1 = function(diffs) { - var text = []; - for (var x = 0; x < diffs.length; x++) { - if (diffs[x][0] !== DIFF_INSERT) { - text[x] = diffs[x][1]; - } - } - return text.join(''); -}; - - -/** - * Compute and return the destination text (all equalities and insertions). - * @param {Array.>} diffs Array of diff tuples. - * @return {string} Destination text. - */ -diff_match_patch.prototype.diff_text2 = function(diffs) { - var text = []; - for (var x = 0; x < diffs.length; x++) { - if (diffs[x][0] !== DIFF_DELETE) { - text[x] = diffs[x][1]; - } - } - return text.join(''); -}; - - -/** - * Compute the Levenshtein distance; the number of inserted, deleted or - * substituted characters. - * @param {Array.>} diffs Array of diff tuples. - * @return {number} Number of changes. - */ -diff_match_patch.prototype.diff_levenshtein = function(diffs) { - var levenshtein = 0; - var insertions = 0; - var deletions = 0; - for (var x = 0; x < diffs.length; x++) { - var op = diffs[x][0]; - var data = diffs[x][1]; - switch (op) { - case DIFF_INSERT: - insertions += data.length; - break; - case DIFF_DELETE: - deletions += data.length; - break; - case DIFF_EQUAL: - // A deletion and an insertion is one substitution. - levenshtein += Math.max(insertions, deletions); - insertions = 0; - deletions = 0; - break; - } - } - levenshtein += Math.max(insertions, deletions); - return levenshtein; -}; - - -/** - * Crush the diff into an encoded string which describes the operations - * required to transform text1 into text2. - * E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'. - * Operations are tab-separated. Inserted text is escaped using %xx notation. - * @param {Array.>} diffs Array of diff tuples. - * @return {string} Delta text. - */ -diff_match_patch.prototype.diff_toDelta = function(diffs) { - var text = []; - for (var x = 0; x < diffs.length; x++) { - switch (diffs[x][0]) { - case DIFF_INSERT: - text[x] = '+' + encodeURI(diffs[x][1]); - break; - case DIFF_DELETE: - text[x] = '-' + diffs[x][1].length; - break; - case DIFF_EQUAL: - text[x] = '=' + diffs[x][1].length; - break; - } - } - // Opera doesn't know how to encode char 0. - return text.join('\t').replace(/\x00/g, '%00').replace(/%20/g, ' '); -}; - - -/** - * Given the original text1, and an encoded string which describes the - * operations required to transform text1 into text2, compute the full diff. - * @param {string} text1 Source string for the diff. - * @param {string} delta Delta text. - * @return {Array.>} Array of diff tuples. - * @throws {Error} If invalid input. - */ -diff_match_patch.prototype.diff_fromDelta = function(text1, delta) { - var diffs = []; - var diffsLength = 0; // Keeping our own length var is faster in JS. - var pointer = 0; // Cursor in text1 - // Opera doesn't know how to decode char 0. - delta = delta.replace(/%00/g, '\0'); - var tokens = delta.split(/\t/g); - for (var x = 0; x < tokens.length; x++) { - // Each token begins with a one character parameter which specifies the - // operation of this token (delete, insert, equality). - var param = tokens[x].substring(1); - switch (tokens[x].charAt(0)) { - case '+': - try { - diffs[diffsLength++] = [DIFF_INSERT, decodeURI(param)]; - } catch (ex) { - // Malformed URI sequence. - throw new Error('Illegal escape in diff_fromDelta: ' + param); - } - break; - case '-': - // Fall through. - case '=': - var n = parseInt(param, 10); - if (isNaN(n) || n < 0) { - throw new Error('Invalid number in diff_fromDelta: ' + param); - } - var text = text1.substring(pointer, pointer += n); - if (tokens[x].charAt(0) == '=') { - diffs[diffsLength++] = [DIFF_EQUAL, text]; - } else { - diffs[diffsLength++] = [DIFF_DELETE, text]; - } - break; - default: - // Blank tokens are ok (from a trailing \t). - // Anything else is an error. - if (tokens[x]) { - throw new Error('Invalid diff operation in diff_fromDelta: ' + - tokens[x]); - } - } - } - if (pointer != text1.length) { - throw new Error('Delta length (' + pointer + - ') does not equal source text length (' + text1.length + ').'); - } - return diffs; -}; - - -// MATCH FUNCTIONS - - -/** - * Locate the best instance of 'pattern' in 'text' near 'loc'. - * @param {string} text The text to search. - * @param {string} pattern The pattern to search for. - * @param {number} loc The location to search around. - * @return {number} Best match index or -1. - */ -diff_match_patch.prototype.match_main = function(text, pattern, loc) { - loc = Math.max(0, Math.min(loc, text.length)); - if (text == pattern) { - // Shortcut (potentially not guaranteed by the algorithm) - return 0; - } else if (!text.length) { - // Nothing to match. - return -1; - } else if (text.substring(loc, loc + pattern.length) == pattern) { - // Perfect match at the perfect spot! (Includes case of null pattern) - return loc; - } else { - // Do a fuzzy compare. - return this.match_bitap(text, pattern, loc); - } -}; - - -/** - * Locate the best instance of 'pattern' in 'text' near 'loc' using the - * Bitap algorithm. - * @param {string} text The text to search. - * @param {string} pattern The pattern to search for. - * @param {number} loc The location to search around. - * @return {number} Best match index or -1. - * @private - */ -diff_match_patch.prototype.match_bitap = function(text, pattern, loc) { - if (pattern.length > this.Match_MaxBits) { - throw new Error('Pattern too long for this browser.'); - } - - // Initialise the alphabet. - var s = this.match_alphabet(pattern); - - var dmp = this; // 'this' becomes 'window' in a closure. - - /** - * Compute and return the score for a match with e errors and x location. - * Accesses loc and pattern through being a closure. - * @param {number} e Number of errors in match. - * @param {number} x Location of match. - * @return {number} Overall score for match (0.0 = good, 1.0 = bad). - * @private - */ - function match_bitapScore(e, x) { - var accuracy = e / pattern.length; - var proximity = Math.abs(loc - x); - if (!dmp.Match_Distance) { - // Dodge divide by zero error. - return proximity ? 1.0 : accuracy; - } - return accuracy + (proximity / dmp.Match_Distance); - } - - // Highest score beyond which we give up. - var score_threshold = this.Match_Threshold; - // Is there a nearby exact match? (speedup) - var best_loc = text.indexOf(pattern, loc); - if (best_loc != -1) { - score_threshold = Math.min(match_bitapScore(0, best_loc), score_threshold); - } - // What about in the other direction? (speedup) - best_loc = text.lastIndexOf(pattern, loc + pattern.length); - if (best_loc != -1) { - score_threshold = Math.min(match_bitapScore(0, best_loc), score_threshold); - } - - // Initialise the bit arrays. - var matchmask = 1 << (pattern.length - 1); - best_loc = -1; - - var bin_min, bin_mid; - var bin_max = pattern.length + text.length; - var last_rd; - for (var d = 0; d < pattern.length; d++) { - // Scan for the best match; each iteration allows for one more error. - // Run a binary search to determine how far from 'loc' we can stray at this - // error level. - bin_min = 0; - bin_mid = bin_max; - while (bin_min < bin_mid) { - if (match_bitapScore(d, loc + bin_mid) <= score_threshold) { - bin_min = bin_mid; - } else { - bin_max = bin_mid; - } - bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min); - } - // Use the result from this iteration as the maximum for the next. - bin_max = bin_mid; - var start = Math.max(1, loc - bin_mid + 1); - var finish = Math.min(loc + bin_mid, text.length) + pattern.length; - - var rd = Array(finish + 2); - rd[finish + 1] = (1 << d) - 1; - for (var j = finish; j >= start; j--) { - // The alphabet (s) is a sparse hash, so the following line generates - // warnings. - var charMatch = s[text.charAt(j - 1)]; - if (d === 0) { // First pass: exact match. - rd[j] = ((rd[j + 1] << 1) | 1) & charMatch; - } else { // Subsequent passes: fuzzy match. - rd[j] = ((rd[j + 1] << 1) | 1) & charMatch | - (((last_rd[j + 1] | last_rd[j]) << 1) | 1) | - last_rd[j + 1]; - } - if (rd[j] & matchmask) { - var score = match_bitapScore(d, j - 1); - // This match will almost certainly be better than any existing match. - // But check anyway. - if (score <= score_threshold) { - // Told you so. - score_threshold = score; - best_loc = j - 1; - if (best_loc > loc) { - // When passing loc, don't exceed our current distance from loc. - start = Math.max(1, 2 * loc - best_loc); - } else { - // Already passed loc, downhill from here on in. - break; - } - } - } - } - // No hope for a (better) match at greater error levels. - if (match_bitapScore(d + 1, loc) > score_threshold) { - break; - } - last_rd = rd; - } - return best_loc; -}; - - -/** - * Initialise the alphabet for the Bitap algorithm. - * @param {string} pattern The text to encode. - * @return {Object} Hash of character locations. - * @private - */ -diff_match_patch.prototype.match_alphabet = function(pattern) { - var s = {}; - for (var i = 0; i < pattern.length; i++) { - s[pattern.charAt(i)] = 0; - } - for (var i = 0; i < pattern.length; i++) { - s[pattern.charAt(i)] |= 1 << (pattern.length - i - 1); - } - return s; -}; - - -// PATCH FUNCTIONS - - -/** - * Increase the context until it is unique, - * but don't let the pattern expand beyond Match_MaxBits. - * @param {patch_obj} patch The patch to grow. - * @param {string} text Source text. - * @private - */ -diff_match_patch.prototype.patch_addContext = function(patch, text) { - var pattern = text.substring(patch.start2, patch.start2 + patch.length1); - var padding = 0; - while (text.indexOf(pattern) != text.lastIndexOf(pattern) && - pattern.length < this.Match_MaxBits - this.Patch_Margin - - this.Patch_Margin) { - padding += this.Patch_Margin; - pattern = text.substring(patch.start2 - padding, - patch.start2 + patch.length1 + padding); - } - // Add one chunk for good luck. - padding += this.Patch_Margin; - // Add the prefix. - var prefix = text.substring(patch.start2 - padding, patch.start2); - if (prefix) { - patch.diffs.unshift([DIFF_EQUAL, prefix]); - } - // Add the suffix. - var suffix = text.substring(patch.start2 + patch.length1, - patch.start2 + patch.length1 + padding); - if (suffix) { - patch.diffs.push([DIFF_EQUAL, suffix]); - } - - // Roll back the start points. - patch.start1 -= prefix.length; - patch.start2 -= prefix.length; - // Extend the lengths. - patch.length1 += prefix.length + suffix.length; - patch.length2 += prefix.length + suffix.length; -}; - - -/** - * Compute a list of patches to turn text1 into text2. - * Use diffs if provided, otherwise compute it ourselves. - * There are four ways to call this function, depending on what data is - * available to the caller: - * Method 1: - * a = text1, b = text2 - * Method 2: - * a = diffs - * Method 3 (optimal): - * a = text1, b = diffs - * Method 4 (deprecated, use method 3): - * a = text1, b = text2, c = diffs - * - * @param {string|Array.>} a text1 (methods 1,3,4) or - * Array of diff tuples for text1 to text2 (method 2). - * @param {string|Array.>} opt_b text2 (methods 1,4) or - * Array of diff tuples for text1 to text2 (method 3) or undefined (method 2). - * @param {string|Array.>} opt_c Array of diff tuples for - * text1 to text2 (method 4) or undefined (methods 1,2,3). - * @return {Array.} Array of patch objects. - */ -diff_match_patch.prototype.patch_make = function(a, opt_b, opt_c) { - var text1, diffs; - if (typeof a == 'string' && typeof opt_b == 'string' && - typeof opt_c == 'undefined') { - // Method 1: text1, text2 - // Compute diffs from text1 and text2. - text1 = a; - diffs = this.diff_main(text1, opt_b, true); - if (diffs.length > 2) { - this.diff_cleanupSemantic(diffs); - this.diff_cleanupEfficiency(diffs); - } - } else if (typeof a == 'object' && typeof opt_b == 'undefined' && - typeof opt_c == 'undefined') { - // Method 2: diffs - // Compute text1 from diffs. - diffs = a; - text1 = this.diff_text1(diffs); - } else if (typeof a == 'string' && typeof opt_b == 'object' && - typeof opt_c == 'undefined') { - // Method 3: text1, diffs - text1 = a; - diffs = opt_b; - } else if (typeof a == 'string' && typeof opt_b == 'string' && - typeof opt_c == 'object') { - // Method 4: text1, text2, diffs - // text2 is not used. - text1 = a; - diffs = opt_c; - } else { - throw new Error('Unknown call format to patch_make.'); - } - - if (diffs.length === 0) { - return []; // Get rid of the null case. - } - var patches = []; - var patch = new patch_obj(); - var patchDiffLength = 0; // Keeping our own length var is faster in JS. - var char_count1 = 0; // Number of characters into the text1 string. - var char_count2 = 0; // Number of characters into the text2 string. - // Start with text1 (prepatch_text) and apply the diffs until we arrive at - // text2 (postpatch_text). We recreate the patches one by one to determine - // context info. - var prepatch_text = text1; - var postpatch_text = text1; - for (var x = 0; x < diffs.length; x++) { - var diff_type = diffs[x][0]; - var diff_text = diffs[x][1]; - - if (!patchDiffLength && diff_type !== DIFF_EQUAL) { - // A new patch starts here. - patch.start1 = char_count1; - patch.start2 = char_count2; - } - - switch (diff_type) { - case DIFF_INSERT: - patch.diffs[patchDiffLength++] = diffs[x]; - patch.length2 += diff_text.length; - postpatch_text = postpatch_text.substring(0, char_count2) + diff_text + - postpatch_text.substring(char_count2); - break; - case DIFF_DELETE: - patch.length1 += diff_text.length; - patch.diffs[patchDiffLength++] = diffs[x]; - postpatch_text = postpatch_text.substring(0, char_count2) + - postpatch_text.substring(char_count2 + - diff_text.length); - break; - case DIFF_EQUAL: - if (diff_text.length <= 2 * this.Patch_Margin && - patchDiffLength && diffs.length != x + 1) { - // Small equality inside a patch. - patch.diffs[patchDiffLength++] = diffs[x]; - patch.length1 += diff_text.length; - patch.length2 += diff_text.length; - } else if (diff_text.length >= 2 * this.Patch_Margin) { - // Time for a new patch. - if (patchDiffLength) { - this.patch_addContext(patch, prepatch_text); - patches.push(patch); - patch = new patch_obj(); - patchDiffLength = 0; - // Unlike Unidiff, our patch lists have a rolling context. - // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff - // Update prepatch text & pos to reflect the application of the - // just completed patch. - prepatch_text = postpatch_text; - char_count1 = char_count2; - } - } - break; - } - - // Update the current character count. - if (diff_type !== DIFF_INSERT) { - char_count1 += diff_text.length; - } - if (diff_type !== DIFF_DELETE) { - char_count2 += diff_text.length; - } - } - // Pick up the leftover patch if not empty. - if (patchDiffLength) { - this.patch_addContext(patch, prepatch_text); - patches.push(patch); - } - - return patches; -}; - - -/** - * Given an array of patches, return another array that is identical. - * @param {Array.} patches Array of patch objects. - * @return {Array.} Array of patch objects. - */ -diff_match_patch.prototype.patch_deepCopy = function(patches) { - // Making deep copies is hard in JavaScript. - var patchesCopy = []; - for (var x = 0; x < patches.length; x++) { - var patch = patches[x]; - var patchCopy = new patch_obj(); - patchCopy.diffs = []; - for (var y = 0; y < patch.diffs.length; y++) { - patchCopy.diffs[y] = patch.diffs[y].slice(); - } - patchCopy.start1 = patch.start1; - patchCopy.start2 = patch.start2; - patchCopy.length1 = patch.length1; - patchCopy.length2 = patch.length2; - patchesCopy[x] = patchCopy; - } - return patchesCopy; -}; - - -/** - * Merge a set of patches onto the text. Return a patched text, as well - * as a list of true/false values indicating which patches were applied. - * @param {Array.} patches Array of patch objects. - * @param {string} text Old text. - * @return {Array.>} Two element Array, containing the - * new text and an array of boolean values. - */ -diff_match_patch.prototype.patch_apply = function(patches, text) { - if (patches.length == 0) { - return [text, []]; - } - - // Deep copy the patches so that no changes are made to originals. - patches = this.patch_deepCopy(patches); - - var nullPadding = this.patch_addPadding(patches); - text = nullPadding + text + nullPadding; - - this.patch_splitMax(patches); - // delta keeps track of the offset between the expected and actual location - // of the previous patch. If there are patches expected at positions 10 and - // 20, but the first patch was found at 12, delta is 2 and the second patch - // has an effective expected position of 22. - var delta = 0; - var results = []; - for (var x = 0; x < patches.length; x++) { - var expected_loc = patches[x].start2 + delta; - var text1 = this.diff_text1(patches[x].diffs); - var start_loc; - var end_loc = -1; - if (text1.length > this.Match_MaxBits) { - // patch_splitMax will only provide an oversized pattern in the case of - // a monster delete. - start_loc = this.match_main(text, text1.substring(0, this.Match_MaxBits), - expected_loc); - if (start_loc != -1) { - end_loc = this.match_main(text, - text1.substring(text1.length - this.Match_MaxBits), - expected_loc + text1.length - this.Match_MaxBits); - if (end_loc == -1 || start_loc >= end_loc) { - // Can't find valid trailing context. Drop this patch. - start_loc = -1; - } - } - } else { - start_loc = this.match_main(text, text1, expected_loc); - } - if (start_loc == -1) { - // No match found. :( - results[x] = false; - // Subtract the delta for this failed patch from subsequent patches. - delta -= patches[x].length2 - patches[x].length1; - } else { - // Found a match. :) - results[x] = true; - delta = start_loc - expected_loc; - var text2; - if (end_loc == -1) { - text2 = text.substring(start_loc, start_loc + text1.length); - } else { - text2 = text.substring(start_loc, end_loc + this.Match_MaxBits); - } - if (text1 == text2) { - // Perfect match, just shove the replacement text in. - text = text.substring(0, start_loc) + - this.diff_text2(patches[x].diffs) + - text.substring(start_loc + text1.length); - } else { - // Imperfect match. Run a diff to get a framework of equivalent - // indices. - var diffs = this.diff_main(text1, text2, false); - if (text1.length > this.Match_MaxBits && - this.diff_levenshtein(diffs) / text1.length > - this.Patch_DeleteThreshold) { - // The end points match, but the content is unacceptably bad. - results[x] = false; - } else { - this.diff_cleanupSemanticLossless(diffs); - var index1 = 0; - var index2; - for (var y = 0; y < patches[x].diffs.length; y++) { - var mod = patches[x].diffs[y]; - if (mod[0] !== DIFF_EQUAL) { - index2 = this.diff_xIndex(diffs, index1); - } - if (mod[0] === DIFF_INSERT) { // Insertion - text = text.substring(0, start_loc + index2) + mod[1] + - text.substring(start_loc + index2); - } else if (mod[0] === DIFF_DELETE) { // Deletion - text = text.substring(0, start_loc + index2) + - text.substring(start_loc + this.diff_xIndex(diffs, - index1 + mod[1].length)); - } - if (mod[0] !== DIFF_DELETE) { - index1 += mod[1].length; - } - } - } - } - } - } - // Strip the padding off. - text = text.substring(nullPadding.length, text.length - nullPadding.length); - return [text, results]; -}; - - -/** - * Add some padding on text start and end so that edges can match something. - * Intended to be called only from within patch_apply. - * @param {Array.} patches Array of patch objects. - * @return {string} The padding string added to each side. - */ -diff_match_patch.prototype.patch_addPadding = function(patches) { - var paddingLength = this.Patch_Margin; - var nullPadding = ''; - for (var x = 1; x <= paddingLength; x++) { - nullPadding += String.fromCharCode(x); - } - - // Bump all the patches forward. - for (var x = 0; x < patches.length; x++) { - patches[x].start1 += paddingLength; - patches[x].start2 += paddingLength; - } - - // Add some padding on start of first diff. - var patch = patches[0]; - var diffs = patch.diffs; - if (diffs.length == 0 || diffs[0][0] != DIFF_EQUAL) { - // Add nullPadding equality. - diffs.unshift([DIFF_EQUAL, nullPadding]); - patch.start1 -= paddingLength; // Should be 0. - patch.start2 -= paddingLength; // Should be 0. - patch.length1 += paddingLength; - patch.length2 += paddingLength; - } else if (paddingLength > diffs[0][1].length) { - // Grow first equality. - var extraLength = paddingLength - diffs[0][1].length; - diffs[0][1] = nullPadding.substring(diffs[0][1].length) + diffs[0][1]; - patch.start1 -= extraLength; - patch.start2 -= extraLength; - patch.length1 += extraLength; - patch.length2 += extraLength; - } - - // Add some padding on end of last diff. - patch = patches[patches.length - 1]; - diffs = patch.diffs; - if (diffs.length == 0 || diffs[diffs.length - 1][0] != DIFF_EQUAL) { - // Add nullPadding equality. - diffs.push([DIFF_EQUAL, nullPadding]); - patch.length1 += paddingLength; - patch.length2 += paddingLength; - } else if (paddingLength > diffs[diffs.length - 1][1].length) { - // Grow last equality. - var extraLength = paddingLength - diffs[diffs.length - 1][1].length; - diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength); - patch.length1 += extraLength; - patch.length2 += extraLength; - } - - return nullPadding; -}; - - -/** - * Look through the patches and break up any which are longer than the maximum - * limit of the match algorithm. - * @param {Array.} patches Array of patch objects. - */ -diff_match_patch.prototype.patch_splitMax = function(patches) { - for (var x = 0; x < patches.length; x++) { - if (patches[x].length1 > this.Match_MaxBits) { - var bigpatch = patches[x]; - // Remove the big old patch. - 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) { - // Create one of several smaller patches. - 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 < patch_size - this.Patch_Margin) { - var diff_type = bigpatch.diffs[0][0]; - var diff_text = bigpatch.diffs[0][1]; - if (diff_type === DIFF_INSERT) { - // Insertions are harmless. - patch.length2 += diff_text.length; - start2 += diff_text.length; - patch.diffs.push(bigpatch.diffs.shift()); - empty = false; - } else if (diff_type === DIFF_DELETE && patch.diffs.length == 1 && - patch.diffs[0][0] == DIFF_EQUAL && - diff_text.length > 2 * patch_size) { - // This is a large deletion. Let it pass in one chunk. - patch.length1 += diff_text.length; - start1 += diff_text.length; - empty = false; - patch.diffs.push([diff_type, diff_text]); - bigpatch.diffs.shift(); - } else { - // Deletion or equality. Only take as much as we can stomach. - diff_text = diff_text.substring(0, patch_size - patch.length1 - - this.Patch_Margin); - patch.length1 += diff_text.length; - start1 += diff_text.length; - if (diff_type === DIFF_EQUAL) { - patch.length2 += diff_text.length; - start2 += diff_text.length; - } else { - empty = false; - } - patch.diffs.push([diff_type, diff_text]); - if (diff_text == bigpatch.diffs[0][1]) { - bigpatch.diffs.shift(); - } else { - bigpatch.diffs[0][1] = - bigpatch.diffs[0][1].substring(diff_text.length); - } - } - } - // Compute the head context for the next patch. - precontext = this.diff_text2(patch.diffs); - precontext = - precontext.substring(precontext.length - this.Patch_Margin); - // Append the end context for this patch. - var postcontext = this.diff_text1(bigpatch.diffs) - .substring(0, this.Patch_Margin); - if (postcontext !== '') { - patch.length1 += postcontext.length; - patch.length2 += postcontext.length; - if (patch.diffs.length !== 0 && - patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL) { - patch.diffs[patch.diffs.length - 1][1] += postcontext; - } else { - patch.diffs.push([DIFF_EQUAL, postcontext]); - } - } - if (!empty) { - patches.splice(++x, 0, patch); - } - } - } - } -}; - - -/** - * Take a list of patches and return a textual representation. - * @param {Array.} patches Array of patch objects. - * @return {string} Text representation of patches. - */ -diff_match_patch.prototype.patch_toText = function(patches) { - var text = []; - for (var x = 0; x < patches.length; x++) { - text[x] = patches[x]; - } - return text.join(''); -}; - - -/** - * Parse a textual representation of patches and return a list of patch objects. - * @param {string} textline Text representation of patches. - * @return {Array.} Array of patch objects. - * @throws {Error} If invalid input. - */ -diff_match_patch.prototype.patch_fromText = function(textline) { - var patches = []; - if (!textline) { - return patches; - } - // Opera doesn't know how to decode char 0. - textline = textline.replace(/%00/g, '\0'); - var text = textline.split('\n'); - var textPointer = 0; - while (textPointer < text.length) { - var m = text[textPointer].match(/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/); - if (!m) { - throw new Error('Invalid patch string: ' + text[textPointer]); - } - var patch = new patch_obj(); - patches.push(patch); - patch.start1 = parseInt(m[1], 10); - if (m[2] === '') { - patch.start1--; - patch.length1 = 1; - } else if (m[2] == '0') { - patch.length1 = 0; - } else { - patch.start1--; - patch.length1 = parseInt(m[2], 10); - } - - patch.start2 = parseInt(m[3], 10); - if (m[4] === '') { - patch.start2--; - patch.length2 = 1; - } else if (m[4] == '0') { - patch.length2 = 0; - } else { - patch.start2--; - patch.length2 = parseInt(m[4], 10); - } - textPointer++; - - while (textPointer < text.length) { - var sign = text[textPointer].charAt(0); - try { - var line = decodeURI(text[textPointer].substring(1)); - } catch (ex) { - // Malformed URI sequence. - throw new Error('Illegal escape in patch_fromText: ' + line); - } - if (sign == '-') { - // Deletion. - patch.diffs.push([DIFF_DELETE, line]); - } else if (sign == '+') { - // Insertion. - patch.diffs.push([DIFF_INSERT, line]); - } else if (sign == ' ') { - // Minor equality. - patch.diffs.push([DIFF_EQUAL, line]); - } else if (sign == '@') { - // Start of next patch. - break; - } else if (sign === '') { - // Blank line? Whatever. - } else { - // WTF? - throw new Error('Invalid patch mode "' + sign + '" in: ' + line); - } - textPointer++; - } - } - return patches; -}; - - -/** - * Class representing one patch operation. - * @constructor - */ -function patch_obj() { - /** @type {Array.>} */ - this.diffs = []; - /** @type {number?} */ - this.start1 = null; - /** @type {number?} */ - this.start2 = null; - /** @type {number} */ - this.length1 = 0; - /** @type {number} */ - this.length2 = 0; -} - - -/** - * Emmulate GNU diff's format. - * Header: @@ -382,8 +481,9 @@ - * Indicies are printed as 1-based, not 0-based. - * @return {string} The GNU diff string. - */ -patch_obj.prototype.toString = function() { - var coords1, coords2; - if (this.length1 === 0) { - coords1 = this.start1 + ',0'; - } else if (this.length1 == 1) { - coords1 = this.start1 + 1; - } else { - coords1 = (this.start1 + 1) + ',' + this.length1; - } - if (this.length2 === 0) { - coords2 = this.start2 + ',0'; - } else if (this.length2 == 1) { - coords2 = this.start2 + 1; - } else { - coords2 = (this.start2 + 1) + ',' + this.length2; - } - var text = ['@@ -' + coords1 + ' +' + coords2 + ' @@\n']; - var op; - // Escape the body of the patch with %xx notation. - for (var x = 0; x < this.diffs.length; x++) { - switch (this.diffs[x][0]) { - case DIFF_INSERT: - op = '+'; - break; - case DIFF_DELETE: - op = '-'; - break; - case DIFF_EQUAL: - op = ' '; - break; - } - text[x + 1] = op + encodeURI(this.diffs[x][1]) + '\n'; - } - // Opera doesn't know how to encode char 0. - return text.join('').replace(/\x00/g, '%00').replace(/%20/g, ' '); -}; - - -// Export these global variables so that they survive Google's JS compiler. -window['diff_match_patch'] = diff_match_patch; -window['patch_obj'] = patch_obj; -window['DIFF_DELETE'] = DIFF_DELETE; -window['DIFF_INSERT'] = DIFF_INSERT; -window['DIFF_EQUAL'] = DIFF_EQUAL; - diff --git a/Specs/SlickSpec/ie.css b/Specs/SlickSpec/ie.css deleted file mode 100644 index 94c336e15..000000000 --- a/Specs/SlickSpec/ie.css +++ /dev/null @@ -1,37 +0,0 @@ -/* -curl -s http://tripledoubleyou.subtlegradient.com/c/blueprint/ie.css #*/ -/* ----------------------------------------------------------------------- - - - Blueprint CSS Framework 0.9 - http://blueprintcss.org - - * Copyright (c) 2007-Present. See LICENSE for more info. - * See README for instructions on how to use Blueprint. - * For credits and origins, see AUTHORS. - * This is a compressed file. See the sources in the 'src' directory. - ------------------------------------------------------------------------ */ - -/* ie.css */ -body {text-align:center;} -.container {text-align:left;} -* html .column, * html div.span-1, * html div.span-2, * html div.span-3, * html div.span-4, * html div.span-5, * html div.span-6, * html div.span-7, * html div.span-8, * html div.span-9, * html div.span-10, * html div.span-11, * html div.span-12, * html div.span-13, * html div.span-14, * html div.span-15, * html div.span-16, * html div.span-17, * html div.span-18, * html div.span-19, * html div.span-20, * html div.span-21, * html div.span-22, * html div.span-23, * html div.span-24 {display:inline;overflow-x:hidden;} -* html legend {margin:0px -8px 16px 0;padding:0;} -sup {vertical-align:text-top;} -sub {vertical-align:text-bottom;} -html>body p code {*white-space:normal;} -hr {margin:-8px auto 11px;} -img {-ms-interpolation-mode:bicubic;} -.clearfix, .container {display:inline-block;} -* html .clearfix, * html .container {height:1%;} -fieldset {padding-top:0;} -textarea {overflow:auto;} -input.text, input.title, textarea {background-color:#fff;border:1px solid #bbb;} -input.text:focus, input.title:focus {border-color:#666;} -input.text, input.title, textarea, select {margin:0.5em 0;} -input.checkbox, input.radio {position:relative;top:.25em;} -form.inline div, form.inline p {vertical-align:middle;} -form.inline label {position:relative;top:-0.25em;} -form.inline input.checkbox, form.inline input.radio, form.inline input.button, form.inline button {margin:0.5em 0;} -button, input.button {position:relative;top:0.25em;} diff --git a/Specs/SlickSpec/moobugger/bookmarklet.html b/Specs/SlickSpec/moobugger/bookmarklet.html deleted file mode 100644 index 06b2aff2c..000000000 --- a/Specs/SlickSpec/moobugger/bookmarklet.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - bugger - - - - - - - - -
-

The MooBugger.

-

moobugger - bookmark it!

-
- - - - \ No newline at end of file diff --git a/Specs/SlickSpec/moobugger/debugger-iframe.js b/Specs/SlickSpec/moobugger/debugger-iframe.js deleted file mode 100644 index a30d1d8f9..000000000 --- a/Specs/SlickSpec/moobugger/debugger-iframe.js +++ /dev/null @@ -1,386 +0,0 @@ -/* -Script: Debugger.js - Creates Firebug style debugger for browsers without Firebug. - -License: - MIT-style license. -*/ - -var FOR_IN_MAX = 20; - -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': - try{ - 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(', ')); - if (x > FOR_IN_MAX){ - holder.adopt(new Element('span').setHTML('and '+ (length - x) +' more properties…')); - break; - } - } - holder.adopt(new Element('span').setHTML('}')); - }catch(e){ - new Element('span').addClass(chunk.type).appendText(chunk.value).inject(holder); - } - 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 el_style = el.style; - if (!el_style) el_style = {}; - - 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/Specs/SlickSpec/moobugger/debugger.css b/Specs/SlickSpec/moobugger/debugger.css deleted file mode 100644 index ecc6991a8..000000000 --- a/Specs/SlickSpec/moobugger/debugger.css +++ /dev/null @@ -1,190 +0,0 @@ -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/Specs/SlickSpec/moobugger/debugger.html b/Specs/SlickSpec/moobugger/debugger.html deleted file mode 100644 index 60dd577a7..000000000 --- a/Specs/SlickSpec/moobugger/debugger.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - debugger - - - - - -

-
- - - - - -
-
-
- -
-
- - \ No newline at end of file diff --git a/Specs/SlickSpec/moobugger/debugger.js b/Specs/SlickSpec/moobugger/debugger.js deleted file mode 100644 index 166b72d11..000000000 --- a/Specs/SlickSpec/moobugger/debugger.js +++ /dev/null @@ -1,284 +0,0 @@ -var Moo = { - - defined: function(obj){ - return (obj != undefined); - }, - - type: function(obj){ - if (obj == null) return false; - 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){ - var i = 0; - for (var property in properties){ - item[property] = properties[property]; - if (i++ > 10) break; - } - } - -}; - -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(){ - - document.documentElement.className = document.documentElement.className + ' moobugger'; - - debug.spacer = document.createElement('div'); - debug.spacer.className = 'debug-spacer'; - 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 = []; - document.documentElement.className = document.documentElement.className.replace(/ ?moobugger ?/,' '); - Moo.Element.remove(debug.iFrame); - Moo.Element.remove(debug.spacer); - Moo.Element.remove(document.getElementById('debug-bookmarklet')); - }, - - evaluate: function(value){ - try { - var evaluation = value; - if (typeof value == 'string') - evaluation = eval(value); - if (evaluation !== debug.frame.debug.$nil){ - if (evaluation == window) evaluation = {'window': '[native code]'}; - if (evaluation.nodeType === 9) 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); -} - -if (!window.onerror) -window.onerror = function(error, url, line){ - console.error({error:error, url:url, line:line}); - return true; -} - diff --git a/Specs/SlickSpec/moobugger/images/close.png b/Specs/SlickSpec/moobugger/images/close.png deleted file mode 100644 index 17fc775e803c88b6131986b1bac4c02e9814a13b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 508 zcmV2|(*&;8E%F1u)e#ssF7JV&46$O|x`;-B?knMO4A8J`OsC%yy;W`)Nyu9lU97kI!_ z4PY!=Vp##p_=>1re=V`FLLCNFUjW{oVN}dTNm!JH;M4|+yZRwKrLYX6lSJ)`qPx85 z4ti57xW5X)QVQ zkEc!!5IfwLQ_2j@cUBQ6fm7vh)`YI8^d?e?_Zd;*tE2h0xmE6RYdN!lzoh70uWr09 y4G$d=J!2MGOFu~HAT$#S@c)Vt&Ix=Xn4C0000M5skAD!Pd7bWugDE?fo|x)DT0K`T;(mex-+1Wb)d zrO=qqB=etn-lx-&y74iGVcxyx+&lLk0h^CN@DTh2uX|?^41!Hy?TPD$6N1;aU}!A0 zXFQ%v4pE*^D-=GxS^AoptYeYlsw=QT6bX^p-CbAqPF+01q!=7WA$bPT@qpz^$WGs$ z9?jJ*Q=ZJpf=ljv-QRUJb^p$U+R8&;n5AOk-;hUue{dK+Er{&-^sUiv@&yXCczfQd zAO??Kns}fG*Py?93BenHRVjmMO^AUA?3E%|Pba#2wvEIWK0kS7;wP8&AK4`xXHo>( z+zW`ID9q9q^xa%U@5v0T)dC6mVdb)L5+RHwA}2V96TPv7w9isj!E}Srg0)tJs;X$J z8m#IHm_h%m>9EZ@Lhq>~5zr-VK-N6-!Fw9>qd?{jSCF!Xcn2H0e|>xd4g z&=?QL*#HkVYsf9J=)+0W-_xh^ujT${a?^cpnEbZ@0|0E3`{(kt{~Q1S002ovPDHLk FV1g+>H|+ob diff --git a/Specs/SlickSpec/moobugger/images/group-close.png b/Specs/SlickSpec/moobugger/images/group-close.png deleted file mode 100644 index c2a8676938c598b1ac53426ca7b7f4fa9e285374..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 304 zcmV-00nh%4P)2He#l-g4l~c8sV<%UUgmfT5GDR zikNdQgh1Z=w{z|Zz#wd`C1VT$0+1kt;ceS`WC1Wj2m`{kQYxFU?|XX20ODsL2+Op1 zf7kth2w?m;j?}hovGF|5G)>b5Knr;Vk{zAqKV10TgbUCPJmsvepv_ zX?3@4WIB!`zC#v(z~0H8A1Pd#ApIP&{O_;v6<`49$5oy&TJhZg0000&AY z;G?eVuQW~XT5F1;h?IKuF*8|fzl|}CMrOcSmQj)<1k*4K4($8h!O(FWcd#%hK!9Pw zy{al_$n)Ht=Xp{bqjO>LMH>JisYcgzIS@$@PdLP_X&RpAnYV3wt7TcZZCea})82)$ zKJ(v@{=+>OFrXiLnkM(wb=@zh^{W8`7e(PrsD>!ZGE|qf1_S%m`E9K08bAbEecl-c xFje)?^U^@RCwBA{Qv(y137>NL@+WkVwLPF zE%gObn_&F1?rugDjkv)7fB)c`-hTLC4Wzh$_#24NgiqtYfB(Sv;j?GjU32GNXv)pi zYA-DOkJrZ5{Cr=KCJ^9cXBPl!(qv|0It>-$!m6<;C&%~i-@kBY^7HTcbm zAL}zSQ8b~0Z{NR%f&&y39k5WXNlirwMY!T0KSKK!FW!bE^b@YJG9dw{rim+7fHeIC zVz^tu8q4G2aB7;edNqb7cy#>v^Ji1n;>9eVzkUq`vO#*Y| z?LR7*2DcHPrn}d!Wv*MW04`SA)dg}HBca@pxpv+>I48cakm2XgpR@l%{5GAa+>usQ z#ULOeGW-4O*Qp&vMPNf&a5?k#)vFA!-0|bvHxN#p*VDs*(~lrcx2{~tTsdc8_vl%q>^&t@q)WpHT0r4YP z(}fF}izZIQ&=i-S&!DKGF&h{QndrG=+V%72GZ*ytV`xeMMuC!+7T5;#+yS!fe^F#4 zI9Xgddlt+FVG#Srj~}yuN|>?v6*+e>Xd4-U*-6F43@X~%*lj`%l*^}2{|Dv{Fb1*l h*@QDO6RQazzyRdMdkwE%pN9Yd002ovPDHLkV1fXqEhhi~ diff --git a/Specs/SlickSpec/moobugger/images/info.png b/Specs/SlickSpec/moobugger/images/info.png deleted file mode 100644 index cd34f124d7597a9a631eae83fc3ef32a7bb65e06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 674 zcmV;T0$u%yP)1=kPP^UX0`=`AI_Y%ph@+NwUim|1Jjz;8cI> z$#b1O;pVzl+XhRnWM}8&AKzelaFXKrVu2FqAywC1i9URA{miXK(F1N+upN>@iyHeedqoQLb@}&nVaj)d4WS_QbNo`T!#I-@4%Ulp8P%Y^Y^dBso?Bqu zF~H|RXKM}ex&_k$6y1av2)0m@f^#DZIg3eo6B;K_v#^}z`2FH2Vv#0#vhJQ~RLsdK zs77g;#?nG+I;)uAmgOe>*w7$J5)^q8D;d56(v_)g6WP`6gfmqKXLmsXc9RMmz^s;)ar#yNwcP(qt{1;0lm8K50QeIJM%|0PkpKVy07*qo IM6N<$f-pTY+yDRo diff --git a/Specs/SlickSpec/moobugger/images/lick.png b/Specs/SlickSpec/moobugger/images/lick.png deleted file mode 100644 index 556e247fa0a42d74c9babd5560d3c6540c3ce513..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 285 zcmV+&0pk9NP)ooZ1~Et# z2LYzP|Ni*_F#{BDN^V^150W5N90V9aL|n~ke_Bm6Qp6d(^OyJn z8Jl2E{`LJ+=P)c!mct+Sh4 zylCDr472-Y=IzXpi389>6n0|_mZKp^Qw@MXCj>y%;c!~3!~WU2Xi!Wjr41-%;s9nO z3shqez|RjC+_b~3orsm9vN}7yF0>PA z@OPrrU(u`N$&*M7uz#H?F78EuNU9aKG|M;q9fCwq3t1`&H+^Drt0?#2jl5DVDXD%* z5-B5pkM4uwud&B;Gv^9t1`i_5v68k_30-5K{jt%QEImidbXsG(6>OrSzeQjkHAkBfnYg_(f~P1nEw z|E2%@`CHA+$)*bAMzH{GNS2cnVvrK!XW(RKWnf}Lvj(Q|-+zWbfB*RcneHq=Cy5I3 zapKhg0w6gS1}07*(~Jq^2Ub>Qyc&=-0s#*T$oY&w80f6eAR@?vRq>nmUl`W!y$I*C zz!+b?d|_Z^`ioW5hYz0^KD>X!ARs7$s%iJhyI_ewzkg%Z$im8sX%h&*Od{wvV8p%t z&+wlp#jGsM-@%%IF+KP9@4w)9AOxgD`LBSy&jd^w^_(1R>w%iS;?l^*%KR0W0M0s^ zs~rV$&oKV~4_3$w#9lyb1jM{JEcy(@=YV({K!5=No<3iWc~NV%00000NkvXXu0mjf DN9efU diff --git a/Specs/SlickSpec/moobugger/images/mootools.png b/Specs/SlickSpec/moobugger/images/mootools.png deleted file mode 100644 index e26a1dca57b83b930f106eb9799a8297bc790339..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3769 zcmV;q4o2~bP)Eu%qO?>jic(ROO2tKKQItwWsjM_?P%4!MrD8EO z5GoBDC@UKX8#Xi$c=my8$j%|(;5g3AIrq+eZ>_l>T=Mhg&7HaTeCO|;J2Pi`dYU{u zW(yuZd}#aC>Y%L-+Gx-Qvkt7St<8O%6@IEbJXDwp+805)7qq>l?#vU@!{cdu60{Ez zh}i?nc{FHW2CdQ))5D`Y=m^?-LF-KTtS9pOn?d{B6Vt<^JP6&?B?+JP1+5tQyE|wn zJuy8zN{a@Q|)tu zHjaLWXeO(7-|)QaaGqx!g`o9gTwS9wGNy~r*8|MuearJ*qM5?ri~QXu~|NhK!`4h<>i4-*M%<*Et|1E1`p~2XIcI zP>BA`7Uj*1<3qx1rkT>EmW*SWoX3K8A>lI~5Uxku3agfcNs#3P&Lv?!uBkgmyukOj zCuld68n+vL&bRE31?qIrjtEx!S0&+}Mf77#ZyS7PMbJLNPaCU!0!ptS9LuEtdyac! za=(OoOfwSmA>(}PAY{2Oe?-7uED&?46 zuqxG#go(+rJEK1yaNb?e?$E-lfwvI{YxG~9gRtT<Fz<^JA`nHW%}Pi`!q?;D#|1T-5}PP9Bw90?5W7#jTnTk5?ymA+?*)k_rX%u zm7qUXGT$V`QjPTdpdEA8m=HsMg;2^Rc)(3(|XKRh8V(#}{GSBe73x(8?<;otV zGVIRIiPzv#--3oJHCQWt2rGK34E^z>FN`EGx)5(^Fh4_S6jNN~xRq%x!##4m`3eO4 zV}Up>FojSd&8@vFShzUW#PSeq(0Txxf>8D$(?R4(>xx5vN&9({#eny7_^C$ z&_%0sIsdRT_P=Y6JU5n^r5tz0iTN#=?JXOK_||!2ydt^HJl+POZl)x0mP063IO=Z_ zlXjMpmq41}w(L^6!Y@(sPKGSE?bnP@fv;qcb$Lt=L#>7hB#BLkUX zMRgT(IuS{-tU_$MO&KC_w)Xv$FhWz3#|rn)^ki0*UDqEJvONTYAoann^(NaG^RuA+ z5$xvnhlD^_10Li}IM?r?(M~uZ$oinIgz%(gR`1}LcQTIAg4fQtPI5n`uS<^N^M#~a z5I1%2nuJNuTJ%4lAX8Y~vJlp8Ace5Yg0_XSv#+EiNvvbD{l~GiYZ4fMVjbT{Ps!#|?*eh7CAtY*s4DYc&hr-)| zu{H5z3b0O++;nDKujC~r%~5N{9AC(|){U_-Ex@BryV5ZvWMq$`J%5-wVdrzB@g&?i{UniM70B*?~t6mq4ZUWh-#Jjb8l zSv(={CdBMl4vds_x~x2pNpbOK!Q2LRqd7tj}2o_tR>P8y6=jp6my31sdkchIac+U~2g=`TqcF0h>MW5Va0SmVN-1GdC;WiiW5%z{G! zT2$sfTXM$h8aFKMJPnTKNu%sE-p`nWm|Z&_qY2m8WJ%008!TNrmsQ@<%5}y6flwok ziRr5FnYHZlGWXdje15-#1efl?RTY-DsN3c4pd|t+3x?My$t-&pnxqw1nQ@g+yDMTA z4cw|Mmw4PjD>fRC#6^8)mw_^HRXo2f(FEfD;=f;<{x zPEvB=wv>?RbVL&E-0*n1*o%2Un46@hQ?xrWCR};+YRY)Wy^*i8Je>+95wz~7WVu|& zmm%Jxe0wC1lG*MLzP_zFV<2fa!+Apjn8vA-!n`iXNlqrm=Z01=?`sCS1PjeBY*OJ$ zn*-U8TI6MlFr=O`UgKBcIKC`bW;f~hPc0{NABb%V-bZNjtRKGCZ-nH_5ScB>v|1)E z?g-~SnIoP)L*_eoc+JoDRRe7GE(yn+O^7e+h4HgVg8d9~O0~Ny(v+WTV!BHF*zDTx z2067ZW(_o!?S4R>&~FXn&G4B@QnF?b=@;c21d?Z!DN1FJta$!r=#B8PU*zy8&RAIL z)o=~7lnA?*#|+(Ajmw{vm)Ssak;c|6V*XawFynX^g1pHo=j|AbJ z4<&F{;qG5?Xe}jW*hBJ?%xcm$cq@ z!9tddT z%xgtk6=cuCMR*XJoh)6H?-3d-q?;gwUn%8jFXej<6|XUF5yA@+T;RMI#(5etlzY*} zmHjQmm@W~0t_!;&gC*{d$M+So+qRZP%twm3W3s$OZt7wsY=;-ZF7#i^&>zp+tCU`; z)ufPF7vs{LLCUEl^1F^P8wCLvcR=t-XuwA$m`Fb7ZhGI4(;#@Lt1?x_nJi)mtkZ$m+hIKIblT+b#b!PhDK zi5Rx-@*&KZWC&amlao+i#$r~E9giYbPDA3(s0zeJjSk#csievzvsH>vBiLTn_T_Q~Ehc_Fw$`MG+rgO(UkO_)W)a?kF!dT(_Rxjk!sB_c zTpH`klg*p5dDr!chu=XytRprUZX3h5+2)Ipb9lq3O9>N06oSep(p0*58 zn2_r+wzmzGTAO0NC1SE+I~Ox1m9U)Ba?g!4IjBNLXh4X8v^P2+44#YgBneAD+@dgb zzZ$=XPbQD<_3I=3V^Xq6_8}TCC9I{#4|bj#(Xl-%Kz0>i1$bYHh(GYz z!$TWx)KF<&P@9%_Xd~q-?3Ca#%ugcmZV!~uf|$qgqCoC@WWHrBjIUEehN{}yS}$hL zC|tZUyhIo+bAMChJ}cf4xtBE&kBZl#uR$3|Ue#Q9L?-L*9MWwe;c++>Ui>{~DMDf% zrzewBY{jleT;?p?L@d3YH6av2Lr@r zl2I~Tv-QOEn62PM6_*$C?vCh^TLV2VJ2Z`<*~0d^xVSmf)6;&6JZ59u-i26_;96cl zT*>coSpci~0$HqCyU5#kVtUM0VlsH|XVP<*3Wyu69_sCam_GUAF`L2lyPP2nGrl9R joQuiLllHCgKLG{+fRlZkYU|z%00000NkvXXu0mjfc;PBv diff --git a/Specs/SlickSpec/moobugger/images/time.png b/Specs/SlickSpec/moobugger/images/time.png deleted file mode 100644 index 4ec395bb357e95049d83b1c45c47b221188143a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 616 zcmV-u0+;=XP)`Btfnm>{IlnXWpBWDRTpSvYCZJvEXA0U8O-0jwzj$5*JO~DZ*O5r%*6;UUpH3%k zFc^HVR;wSI&E{A1@AL;QpaIPqkH<5qRO-3I;Q(2dLDMwgI1Wam5#;mvx5Z-dHQxJ4 zFt5YrSSl|Ygt223UsaJ$_QjYelP`zE zA(YEy*zI-8EEiNqaAA%;L991cIV+wD-PR6rC(7KJWOr&Bl{ zj|}d1yUgeF`JNF&mAmqIJP%i^6)1|rqEWiD*$fJW0^8ecHgLIIU^bhu|5RnK*UL2H znRKqIrmE@?Q+YxFISmE_d!5oFqrJsq0qiNX+wD7qe=rdBEfE%-PUj6ppn{NIJOdm8 z;CY@!$02yvXf!^MI$oEcV$VKfsy5UYJ?kQf(kH#GR_lGOR(plV8*=?Ka@f;H*qU3D z$rPfg+3)ufX7s7k>3l)|_V1DV-;m4t_cG+a1Q-B^`vZz?fXXQV0000t+Ue1gR+{YC8OO*txphWUc9IHDM-goja5BcG+BBke$92q?G z71N^^hoa|}Pf?sIV7UUj$B)*X-gfZP5zU)LG4l{+E)G+T!zg_Q+t7ge=FUh@^()WS zNn@PiO#!-2bYSb=L;cru-*@O=o`A7xSXvs~%0rU9uvb#xem8=_`u0HfV1=hkeoKOwA+Pr;&5unQ-YG}21mToY> z?E(d-V45aMIg4(dCmX%j(qXd|)c8G3f+@G$F*IgdKj7FJl}RQ^fv)LrB$@(~$X+N9 z!m*ZN8(O)W0<@MAsdxV3=623Ba#9hj3Vl28()+~Zf@CAmMfO4wYC0DaT@|GoV=tD5 z%~%q0kQ!mo&8CX;W1ScrjS!^Le;(XNrOwXd`5XI+V9GfsGFaK;eDl;cdLn#1%~;nE zZJb3%YZ|iK1r~C_nNyJ*S-iaeF|HG%%asMNZ_Mz??%bl!=Vm)tErT3TAbXT@QO^4k zlDE|1-S=>uVhf@z|E%0#7;W3Ppx3hwO^m$x1;pOQaeH72ugPEhd*%MO - - - - - - 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/Specs/SlickSpec/screen.css b/Specs/SlickSpec/screen.css deleted file mode 100644 index 8a8ea9158..000000000 --- a/Specs/SlickSpec/screen.css +++ /dev/null @@ -1,259 +0,0 @@ -/* -curl -s http://tripledoubleyou.subtlegradient.com/c/blueprint/screen.css #*/ -/* ----------------------------------------------------------------------- - - - Blueprint CSS Framework 0.9 - http://blueprintcss.org - - * Copyright (c) 2007-Present. See LICENSE for more info. - * See README for instructions on how to use Blueprint. - * For credits and origins, see AUTHORS. - * This is a compressed file. See the sources in the 'src' directory. - ------------------------------------------------------------------------ */ - -/* reset.css */ -html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;} -body {line-height:1.5;} -table {border-collapse:separate;border-spacing:0;} -caption, th, td {text-align:left;font-weight:normal;} -table, td, th {vertical-align:middle;} -blockquote:before, blockquote:after, q:before, q:after {content:"";} -blockquote, q {quotes:"" "";} -a img {border:none;} - -/* typography.css */ -html {font-size:100.01%;} -body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;} -h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;} -h1 {font-size:3em;line-height:1;margin-bottom:0.5em;} -h2 {font-size:2em;margin-bottom:0.75em;} -h3 {font-size:1.5em;line-height:1;margin-bottom:1em;} -h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;} -h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;} -h6 {font-size:1em;font-weight:bold;} -h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;} -p {margin:0 0 1.5em;} -p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;} -p img.right {float:right;margin:1.5em 0 1.5em 1.5em;} -a:focus, a:hover {color:#000;} -a {color:#009;text-decoration:underline;} -blockquote {margin:1.5em;color:#666;font-style:italic;} -strong {font-weight:bold;} -em, dfn {font-style:italic;} -dfn {font-weight:bold;} -sup, sub {line-height:0;} -abbr, acronym {border-bottom:1px dotted #666;} -address {margin:0 0 1.5em;font-style:italic;} -del {color:#666;} -pre {margin:1.5em 0;white-space:pre;} -pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;} -li ul, li ol {margin:0;} -ul, ol {margin:0 1.5em 1.5em 0;padding-left:3.333em;} -ul {list-style-type:disc;} -ol {list-style-type:decimal;} -dl {margin:0 0 1.5em 0;} -dl dt {font-weight:bold;} -dd {margin-left:1.5em;} -table {margin-bottom:1.4em;width:100%;} -th {font-weight:bold;} -thead th {background:#c3d9ff;} -th, td, caption {padding:4px 10px 4px 5px;} -tr.even td {background:#e5ecf9;} -tfoot {font-style:italic;} -caption {background:#eee;} -.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;} -.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;} -.hide {display:none;} -.quiet {color:#666;} -.loud {color:#000;} -.highlight {background:#ff0;} -.added {background:#060;color:#fff;} -.removed {background:#900;color:#fff;} -.first {margin-left:0;padding-left:0;} -.last {margin-right:0;padding-right:0;} -.top {margin-top:0;padding-top:0;} -.bottom {margin-bottom:0;padding-bottom:0;} - -/* forms.css */ -label {font-weight:bold;} -fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;} -legend {font-weight:bold;font-size:1.2em;} -input[type=text], input[type=password], input.text, input.title, textarea, select {background-color:#fff;border:1px solid #bbb;} -input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus, select:focus {border-color:#666;} -input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;} -input.text, input.title {width:300px;padding:5px;} -input.title {font-size:1.5em;} -textarea {width:390px;height:250px;padding:5px;} -input[type=checkbox], input[type=radio], input.checkbox, input.radio {position:relative;top:.25em;} -form.inline {line-height:3;} -form.inline p {margin-bottom:0;} -.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;} -.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;} -.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;} -.success {background:#E6EFC2;color:#264409;border-color:#C6D880;} -.error a {color:#8a1f11;} -.notice a {color:#514721;} -.success a {color:#264409;} - -/* grid.css */ -.container {width:950px;margin:0 auto;} -.showgrid {background:url(src/grid.png);} -.column, div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 {float:left;margin-right:10px;} -.last, div.last {margin-right:0;} -.span-1 {width:30px;} -.span-2 {width:70px;} -.span-3 {width:110px;} -.span-4 {width:150px;} -.span-5 {width:190px;} -.span-6 {width:230px;} -.span-7 {width:270px;} -.span-8 {width:310px;} -.span-9 {width:350px;} -.span-10 {width:390px;} -.span-11 {width:430px;} -.span-12 {width:470px;} -.span-13 {width:510px;} -.span-14 {width:550px;} -.span-15 {width:590px;} -.span-16 {width:630px;} -.span-17 {width:670px;} -.span-18 {width:710px;} -.span-19 {width:750px;} -.span-20 {width:790px;} -.span-21 {width:830px;} -.span-22 {width:870px;} -.span-23 {width:910px;} -.span-24, div.span-24 {width:950px;margin-right:0;} -input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 {border-left-width:1px!important;border-right-width:1px!important;padding-left:5px!important;padding-right:5px!important;} -input.span-1, textarea.span-1 {width:18px!important;} -input.span-2, textarea.span-2 {width:58px!important;} -input.span-3, textarea.span-3 {width:98px!important;} -input.span-4, textarea.span-4 {width:138px!important;} -input.span-5, textarea.span-5 {width:178px!important;} -input.span-6, textarea.span-6 {width:218px!important;} -input.span-7, textarea.span-7 {width:258px!important;} -input.span-8, textarea.span-8 {width:298px!important;} -input.span-9, textarea.span-9 {width:338px!important;} -input.span-10, textarea.span-10 {width:378px!important;} -input.span-11, textarea.span-11 {width:418px!important;} -input.span-12, textarea.span-12 {width:458px!important;} -input.span-13, textarea.span-13 {width:498px!important;} -input.span-14, textarea.span-14 {width:538px!important;} -input.span-15, textarea.span-15 {width:578px!important;} -input.span-16, textarea.span-16 {width:618px!important;} -input.span-17, textarea.span-17 {width:658px!important;} -input.span-18, textarea.span-18 {width:698px!important;} -input.span-19, textarea.span-19 {width:738px!important;} -input.span-20, textarea.span-20 {width:778px!important;} -input.span-21, textarea.span-21 {width:818px!important;} -input.span-22, textarea.span-22 {width:858px!important;} -input.span-23, textarea.span-23 {width:898px!important;} -input.span-24, textarea.span-24 {width:938px!important;} -.append-1 {padding-right:40px;} -.append-2 {padding-right:80px;} -.append-3 {padding-right:120px;} -.append-4 {padding-right:160px;} -.append-5 {padding-right:200px;} -.append-6 {padding-right:240px;} -.append-7 {padding-right:280px;} -.append-8 {padding-right:320px;} -.append-9 {padding-right:360px;} -.append-10 {padding-right:400px;} -.append-11 {padding-right:440px;} -.append-12 {padding-right:480px;} -.append-13 {padding-right:520px;} -.append-14 {padding-right:560px;} -.append-15 {padding-right:600px;} -.append-16 {padding-right:640px;} -.append-17 {padding-right:680px;} -.append-18 {padding-right:720px;} -.append-19 {padding-right:760px;} -.append-20 {padding-right:800px;} -.append-21 {padding-right:840px;} -.append-22 {padding-right:880px;} -.append-23 {padding-right:920px;} -.prepend-1 {padding-left:40px;} -.prepend-2 {padding-left:80px;} -.prepend-3 {padding-left:120px;} -.prepend-4 {padding-left:160px;} -.prepend-5 {padding-left:200px;} -.prepend-6 {padding-left:240px;} -.prepend-7 {padding-left:280px;} -.prepend-8 {padding-left:320px;} -.prepend-9 {padding-left:360px;} -.prepend-10 {padding-left:400px;} -.prepend-11 {padding-left:440px;} -.prepend-12 {padding-left:480px;} -.prepend-13 {padding-left:520px;} -.prepend-14 {padding-left:560px;} -.prepend-15 {padding-left:600px;} -.prepend-16 {padding-left:640px;} -.prepend-17 {padding-left:680px;} -.prepend-18 {padding-left:720px;} -.prepend-19 {padding-left:760px;} -.prepend-20 {padding-left:800px;} -.prepend-21 {padding-left:840px;} -.prepend-22 {padding-left:880px;} -.prepend-23 {padding-left:920px;} -div.border {padding-right:4px;margin-right:5px;border-right:1px solid #eee;} -div.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #eee;} -.pull-1 {margin-left:-40px;} -.pull-2 {margin-left:-80px;} -.pull-3 {margin-left:-120px;} -.pull-4 {margin-left:-160px;} -.pull-5 {margin-left:-200px;} -.pull-6 {margin-left:-240px;} -.pull-7 {margin-left:-280px;} -.pull-8 {margin-left:-320px;} -.pull-9 {margin-left:-360px;} -.pull-10 {margin-left:-400px;} -.pull-11 {margin-left:-440px;} -.pull-12 {margin-left:-480px;} -.pull-13 {margin-left:-520px;} -.pull-14 {margin-left:-560px;} -.pull-15 {margin-left:-600px;} -.pull-16 {margin-left:-640px;} -.pull-17 {margin-left:-680px;} -.pull-18 {margin-left:-720px;} -.pull-19 {margin-left:-760px;} -.pull-20 {margin-left:-800px;} -.pull-21 {margin-left:-840px;} -.pull-22 {margin-left:-880px;} -.pull-23 {margin-left:-920px;} -.pull-24 {margin-left:-960px;} -.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;} -.push-1 {margin:0 -40px 1.5em 40px;} -.push-2 {margin:0 -80px 1.5em 80px;} -.push-3 {margin:0 -120px 1.5em 120px;} -.push-4 {margin:0 -160px 1.5em 160px;} -.push-5 {margin:0 -200px 1.5em 200px;} -.push-6 {margin:0 -240px 1.5em 240px;} -.push-7 {margin:0 -280px 1.5em 280px;} -.push-8 {margin:0 -320px 1.5em 320px;} -.push-9 {margin:0 -360px 1.5em 360px;} -.push-10 {margin:0 -400px 1.5em 400px;} -.push-11 {margin:0 -440px 1.5em 440px;} -.push-12 {margin:0 -480px 1.5em 480px;} -.push-13 {margin:0 -520px 1.5em 520px;} -.push-14 {margin:0 -560px 1.5em 560px;} -.push-15 {margin:0 -600px 1.5em 600px;} -.push-16 {margin:0 -640px 1.5em 640px;} -.push-17 {margin:0 -680px 1.5em 680px;} -.push-18 {margin:0 -720px 1.5em 720px;} -.push-19 {margin:0 -760px 1.5em 760px;} -.push-20 {margin:0 -800px 1.5em 800px;} -.push-21 {margin:0 -840px 1.5em 840px;} -.push-22 {margin:0 -880px 1.5em 880px;} -.push-23 {margin:0 -920px 1.5em 920px;} -.push-24 {margin:0 -960px 1.5em 960px;} -.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:right;position:relative;} -.prepend-top {margin-top:1.5em;} -.append-bottom {margin-bottom:1.5em;} -.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;} -hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;} -hr.space {background:#fff;color:#fff;visibility:hidden;} -.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;} -.clearfix, .container {display:block;} -.clear {clear:both;} diff --git a/Specs/SlickSpec/simple_request.js b/Specs/SlickSpec/simple_request.js deleted file mode 100644 index f6ed56d14..000000000 --- a/Specs/SlickSpec/simple_request.js +++ /dev/null @@ -1,39 +0,0 @@ -var SimpleRequest = (function(){ - - function SimpleRequest(){ - this.initialize(); - }; - SimpleRequest.prototype = { - - initialize: function(){ - this.xhr = this.createXHR(); - }, - - createXHR: function(){ - // return ('XMLHttpRequest' in window)? new XMLHttpRequest(): new ActiveXObject('MSXML2.XMLHTTP'); - return ('XMLHttpRequest' in window)? new XMLHttpRequest(): new ActiveXObject('Microsoft.XMLHTTP'); - }, - - stateChange: function(fn){ - if(this.xhr.readyState == 4 && this.xhr.status == 200){ - fn.apply(this, [this.xhr.responseText, this.getXML()]); - } - }, - - getXML: function(){ - if (this.xhr.responseXML && this.xhr.responseXML.documentElement) - return this.xhr.responseXML; - return parseXML(this.xhr.responseText); - }, - - send: function(url, fn){ - var self = this; - this.xhr.onreadystatechange = function(){ self.stateChange(fn); }; - this.xhr.open('get', url + '?n=' + (new Date()).getTime(), true); - this.xhr.send(null); - } - - }; - - return SimpleRequest; -})(); diff --git a/Specs/SlickSpec/slickspec.css b/Specs/SlickSpec/slickspec.css deleted file mode 100644 index 936076505..000000000 --- a/Specs/SlickSpec/slickspec.css +++ /dev/null @@ -1,366 +0,0 @@ -@CHARSET "UTF-8"; - -/* -------------------- -* @Layout -*/ - - -#slickspec_logo { - position: absolute; - top: 0px; - left: 0px; - z-index: 9999; - padding:0.5em 0.75em; - color: #fff; - - font-size: 20px; - line-height: 20px; - - font-weight: normal; -} -#slickspec_logo a, -#slickspec_logo a:link, -#slickspec_logo a:visited { - color: #fff; - text-decoration: none; -} -#slickspec_logo a:hover { - color: #000; -} - -#jsspec_container{padding-top:3em !important;} -#framework_name { - position: absolute; - top: 42px; - right: 0px; - z-index: 1; - padding:0.5em 0.75em; - color: #000; - - font-size: 20px; - line-height: 20px; - - font-weight: normal; -} -#framework_name a, -#framework_name a:link, -#framework_name a:visited { - color: #fff; - text-decoration: none; -} -#framework_name a:hover { - color: #000; -} - - -#copyright{ - position: fixed; - bottom: 0px; - right: 0px; - z-index: 1000; - font-size: 10px; - padding:0.5em 0.75em; - background-color: #fff; - background-color: rgba(255,255,255,0.9); - - -webkit-border-top-left-radius: 6px; -} -* html #copyright { - position: absolute; - bottom: auto; - top: expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.clientHeight)); -} -html.moobugger #copyright{ - bottom: 180px; -} - - -html { - overflow-x: hidden; - overflow-y: scroll; -} - -iframe {display:none;} -iframe#debugger {display:block !important;} -iframe#debugger{ position: fixed !important; bottom: 0; top: auto; } -* html iframe#debugger{position:absolute !important;bottom:auto;top:expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.clientHeight));} - -.debug-spacer {display:none;} - -/*Make position:fixed work in IE6!*/ - -* html,* html body /* IE6 Fixed Position Jitter Fix */ {background-image:url(about:blank);background-attachment:fixed;} - -#slickspec_logo, -.fixed-top /* position fixed Top */ {position: fixed ; bottom: auto ; top: 0px ; } -* html #slickspec_logo, -* html .fixed-top /* IE6 position fixed Top */ {position: absolute ; bottom: auto ; top: expression(eval(document.documentElement.scrollTop)) ; } -.fixed-bottom /* position fixed Bottom */ {position: fixed ; bottom: 0px ; top: auto ; } -* html .fixed-bottom /* IE6 position fixed Bottom */ {position: absolute ; bottom: auto ; top: expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.clientHeight)) ; } -.fixed-left /* position fixed Left */ {position: fixed ; right: auto ; left: 0px ; } -* html .fixed-left /* IE6 position fixed Left */ {position: absolute ; right: auto ; left: expression(eval(document.documentElement.scrollLeft)) ; } -.fixed-right /* position fixed right */ {position: fixed ; right: 0px ; left: auto ; } -* html .fixed-right /* IE6 position fixed right */ {position: absolute ; right: auto ; left: expression(eval(document.documentElement.scrollWidth-this.clientWidth)) ; } - - - -body, #jsspec_container { - padding: 0; - margin: 0; - background-color: #FFFFFF; -} - -#jsspec_container { - padding-bottom:180px; -} - -#title { - padding: 0 !important; - margin: 0 !important; - height: 40px !important; - overflow: hidden !important; - - position: fixed; - _position: absolute; - top: 0px; - _top: expression(eval(document.documentElement.scrollTop)); - left: 0px; - _left: expression(eval(document.documentElement.scrollLeft)); - width: 100%; - _width: expression(eval(document.documentElement.clientWidth)); - - z-index: 1000; -} - -#title { - border-bottom:2px solid #fff; -} - -#list { - overflow: auto; - - position: fixed; - top: 0px; - left: 0px; - bottom: 0px; - background: #eee; - - margin-top:42px; - - width: 250px; -} -* html #list{ - position: absolute; - bottom: auto; - top: expression(eval(document.documentElement.scrollTop)); - height: expression(eval(document.documentElement.clientHeight - 42)); -} -html.moobugger #list{ - bottom: 180px; -} -* html.moobugger #list{ - bottom: auto; - height: expression(eval(document.documentElement.clientHeight - 42 - 180)); -} - -#log { - position:relative; - overflow: hidden; - - padding: 0; - margin: 0; - margin-top: 42px; - margin-left: 250px; -} - -/*iPhone*/ -@media only screen and (max-device-width: 480px) { - #list { - overflow: visible; - } - - #log { - overflow: visible; - } -} - - -/* -------------------- -* @Decorations and colors -*/ -* { - padding: 0; - margin: 0; - font-family: "Lucida Grande", Helvetica, sans-serif; -} - -li { - list-style: none; -} - -/* hiding subtitles */ -h2 { - display: none; -} - -/* title section */ -div#title { - padding: 0em 0.5em; -} - -div#title h1 { - float: right; - padding: 0.25em 0.75em; - font-size: 16px; -} -div#title h1:before{ - content:"powered by "; - font-size: 9px; - font-style: italic; - color:#fff; -} - -div#title ul { - position: absolute; - top: 0px; - left: 0px; - margin-left:120px; -} -div#title ul li { - font-size: 12px; - float: left; - padding: 0.75em 0em 0.5em 0.75em; - max-width: 14em; -} - -div#title p { - float:right; - padding: 0.5em 0em 0.5em 0.75em; - font-size: 10px; -} - -/* spec container */ -ul.specs { - margin: 0.5em; -} -ul.specs li { - margin-bottom: 0.1em; - position:relative; -} - -/* spec title */ -ul.specs li h3 { - font-weight: bold; - font-size: 11px; - line-height: 13px; - padding: 0.5em 0.75em; - cursor: pointer; - _cursor: hand; -} -ul.specs li h3 a { - text-decoration: none; -} -ul.specs li h3 a:hover { - text-decoration: underline; -} - -/* example container */ -ul.examples li { - background-color: #eee; - color: #999; - - border-style: solid; - border-width: 0px 0px 1px 5px; - margin: 0.2em 0em 0.2em 1em; -} - -/* example title */ -ul.examples li h4 { - font-weight: normal; - font-size: 12px; - margin-left: 1em; -} - -pre.examples-code { - background: #FFFFFF; - border: solid 1px #CCC; - - margin: 0.5em 2em; -} -pre.examples-code code { - display:block; - - padding: 0.5em; - _padding-right: 0; - _padding-left: 0; - - white-space: pre; - _width:100%; - - font-size: 10px; - font-family: "Panic Sans", "Monaco", monospace !important; - overflow-x: auto; - - scrollbar-base-color: #FFF; - scrollbar-arrow-color: #FFF; - scrollbar-track-color: #FFF; - scrollbar-3dlight-color: #eee; - scrollbar-highlight-color: #eee; - scrollbar-face-color: #eee; - scrollbar-shadow-color: #eee; - scrollbar-darkshadow-color: #FFF; -} - -/* example explaination */ -ul.examples li div { - padding: 1em 2em; - font-size: 11px; -} - -/* styles for ongoing, success, failure, error */ -ul.specs li h3, ul.specs li h3 a { color: #666; background-color: #fff; } - -div.success, div.success a { color: #FFFFFF; background-color: #6C6; } -div.exception, div.exception a { color: #FFFFFF; background-color: #C30; } - -ul.specs li.success h3, ul.specs li.success h3 a { color: #FFFFFF; background-color: #6C6; } -ul.examples li.success, ul.examples li.success a { color: #363; background-color: #CFC; border-color: #6C6; } - -ul.specs li.exception h3, ul.specs li.exception h3 a { color: #FFFFFF; background-color: #C30; } -ul.examples li.exception, ul.examples li.exception a { color: #C30; background-color: #FFC; border-color: #C30; } -div.ongoing, div.ongoing a { color: #330; background-color: #FF9; } - -ul.specs li.ongoing h3, ul.specs li.ongoing h3 a { color: #330; background-color: #FF9; } -ul.examples li.ongoing, ul.examples li.ongoing a { color: #330; background-color: #FF9; border-color: #CC0; } - - - -/* -------------------- -* values -*/ -.number_value, .string_value, .regexp_value, .boolean_value, .dom_value { - font-family: monospace; - color: blue; -} -.object_value, .array_value { - line-height: 2em; - padding: 0.1em 0.2em; - margin: 0.1em 0; -} -.date_value { - font-family: monospace; - color: olive; -} -.undefined_value, .null_value { - font-style: italic; - color: blue; -} -.dom_attr_name { -} -.dom_attr_value { - color: red; -} -.dom_path { - font-size: 11px; - color: gray; -} diff --git a/Specs/index.html b/Specs/index.html deleted file mode 100644 index d76bdb418..000000000 --- a/Specs/index.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - SlickSpec for MooTools - - - - - -
- -

SlickSpec alpha for MooTools-Core

- - - -
- - \ No newline at end of file diff --git a/Specs/runner.html b/Specs/runner.html deleted file mode 100644 index 0150db0f1..000000000 --- a/Specs/runner.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -SlickSpec Select -

SlickSpec

- -

- - - From cd1a146dbc6cb2791d9992b63779203a01087b81 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Wed, 2 Dec 2009 20:05:34 +0100 Subject: [PATCH 15/44] * Adding Specs as a submodule --- .gitmodules | 3 +++ Specs | 1 + 2 files changed, 4 insertions(+) create mode 160000 Specs diff --git a/.gitmodules b/.gitmodules index 5c7191ab3..635fb6329 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "Tests/UnitTester"] path = Tests/UnitTester url = git://github.com/anutron/mootools-unittester.git +[submodule "Specs"] + path = Specs + url = git@github.com:mootools/mootools-core-specs.git diff --git a/Specs b/Specs new file mode 160000 index 000000000..3b07dfa06 --- /dev/null +++ b/Specs @@ -0,0 +1 @@ +Subproject commit 3b07dfa0626365631893b5d80046f6ff78694591 From bea5ca756d71835466d7ce93358b6f6a6b356aaa Mon Sep 17 00:00:00 2001 From: Nathan White Date: Sat, 5 Dec 2009 12:01:58 -0800 Subject: [PATCH 16/44] fixed spec submodule --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 635fb6329..2a5011ba6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,4 +6,4 @@ url = git://github.com/anutron/mootools-unittester.git [submodule "Specs"] path = Specs - url = git@github.com:mootools/mootools-core-specs.git + url = git://github.com:mootools/mootools-core-specs.git From a3c6fc35ccfcec8693881ec590f9cca25d413dc5 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Sun, 6 Dec 2009 02:45:08 +0100 Subject: [PATCH 17/44] * Removing old Compatibility Layer --- Compatibility/Class/Class.js | 8 ----- Compatibility/Core/Browser.js | 9 ----- Compatibility/Core/Core.js | 18 ---------- Compatibility/Element/Element.Event.js | 1 - Compatibility/Element/Element.Style.js | 7 ---- Compatibility/Element/Element.js | 47 -------------------------- Compatibility/Fx/Fx.Morph.js | 9 ----- Compatibility/Fx/Fx.Scroll.js | 7 ---- Compatibility/Fx/Fx.Tween.js | 11 ------ Compatibility/Fx/Fx.js | 17 ---------- Compatibility/Native/Array.js | 9 ----- Compatibility/Native/Function.js | 9 ----- Compatibility/Native/Hash.js | 2 -- Compatibility/Request/Request.JSON.js | 24 ------------- Compatibility/Request/Request.js | 37 -------------------- Compatibility/Utilities/Cookie.js | 11 ------ Compatibility/Utilities/JSON.js | 4 --- Compatibility/Utilities/Selectors.js | 39 --------------------- 18 files changed, 269 deletions(-) delete mode 100644 Compatibility/Class/Class.js delete mode 100644 Compatibility/Core/Browser.js delete mode 100644 Compatibility/Core/Core.js delete mode 100644 Compatibility/Element/Element.Event.js delete mode 100644 Compatibility/Element/Element.Style.js delete mode 100644 Compatibility/Element/Element.js delete mode 100644 Compatibility/Fx/Fx.Morph.js delete mode 100755 Compatibility/Fx/Fx.Scroll.js delete mode 100644 Compatibility/Fx/Fx.Tween.js delete mode 100755 Compatibility/Fx/Fx.js delete mode 100644 Compatibility/Native/Array.js delete mode 100644 Compatibility/Native/Function.js delete mode 100644 Compatibility/Native/Hash.js delete mode 100755 Compatibility/Request/Request.JSON.js delete mode 100644 Compatibility/Request/Request.js delete mode 100644 Compatibility/Utilities/Cookie.js delete mode 100644 Compatibility/Utilities/JSON.js delete mode 100644 Compatibility/Utilities/Selectors.js diff --git a/Compatibility/Class/Class.js b/Compatibility/Class/Class.js deleted file mode 100644 index 08a9db8d2..000000000 --- a/Compatibility/Class/Class.js +++ /dev/null @@ -1,8 +0,0 @@ -Class.empty = $empty; - -//legacy .extend support - -Class.prototype.extend = function(properties){ - properties.Extends = this; - return new Class(properties); -}; diff --git a/Compatibility/Core/Browser.js b/Compatibility/Core/Browser.js deleted file mode 100644 index d0656c554..000000000 --- a/Compatibility/Core/Browser.js +++ /dev/null @@ -1,9 +0,0 @@ -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/Compatibility/Core/Core.js b/Compatibility/Core/Core.js deleted file mode 100644 index db540984c..000000000 --- a/Compatibility/Core/Core.js +++ /dev/null @@ -1,18 +0,0 @@ -$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/Compatibility/Element/Element.Event.js b/Compatibility/Element/Element.Event.js deleted file mode 100644 index e240463dc..000000000 --- a/Compatibility/Element/Element.Event.js +++ /dev/null @@ -1 +0,0 @@ -Event.keys = Event.Keys; \ No newline at end of file diff --git a/Compatibility/Element/Element.Style.js b/Compatibility/Element/Element.Style.js deleted file mode 100644 index fdc627776..000000000 --- a/Compatibility/Element/Element.Style.js +++ /dev/null @@ -1,7 +0,0 @@ -Element.implement({ - - setOpacity: function(op){ - return this.set('opacity', op); - } - -}); \ No newline at end of file diff --git a/Compatibility/Element/Element.js b/Compatibility/Element/Element.js deleted file mode 100644 index 668d6f727..000000000 --- a/Compatibility/Element/Element.js +++ /dev/null @@ -1,47 +0,0 @@ -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/Compatibility/Fx/Fx.Morph.js b/Compatibility/Fx/Fx.Morph.js deleted file mode 100644 index 0e8f59f88..000000000 --- a/Compatibility/Fx/Fx.Morph.js +++ /dev/null @@ -1,9 +0,0 @@ -Fx.Styles = Fx.Morph; - -Element.implement({ - - effects: function(options){ - return new Fx.Morph(this, options); - } - -}); \ No newline at end of file diff --git a/Compatibility/Fx/Fx.Scroll.js b/Compatibility/Fx/Fx.Scroll.js deleted file mode 100755 index 8f76d9048..000000000 --- a/Compatibility/Fx/Fx.Scroll.js +++ /dev/null @@ -1,7 +0,0 @@ -Fx.Scroll.implement({ - - scrollTo: function(y, x){ - return this.start(y, x); - } - -}); \ No newline at end of file diff --git a/Compatibility/Fx/Fx.Tween.js b/Compatibility/Fx/Fx.Tween.js deleted file mode 100644 index 1ef9ee122..000000000 --- a/Compatibility/Fx/Fx.Tween.js +++ /dev/null @@ -1,11 +0,0 @@ -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/Compatibility/Fx/Fx.js b/Compatibility/Fx/Fx.js deleted file mode 100755 index 8da142a79..000000000 --- a/Compatibility/Fx/Fx.js +++ /dev/null @@ -1,17 +0,0 @@ -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/Compatibility/Native/Array.js b/Compatibility/Native/Array.js deleted file mode 100644 index bec54f6d8..000000000 --- a/Compatibility/Native/Array.js +++ /dev/null @@ -1,9 +0,0 @@ -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/Compatibility/Native/Function.js b/Compatibility/Native/Function.js deleted file mode 100644 index 4486a35d1..000000000 --- a/Compatibility/Native/Function.js +++ /dev/null @@ -1,9 +0,0 @@ -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/Compatibility/Native/Hash.js b/Compatibility/Native/Hash.js deleted file mode 100644 index 2eeb1570b..000000000 --- a/Compatibility/Native/Hash.js +++ /dev/null @@ -1,2 +0,0 @@ -Hash.alias({getKeys: 'keys', getValues: 'values', has: 'hasKey', combine: 'merge'}); -var Abstract = Hash; \ No newline at end of file diff --git a/Compatibility/Request/Request.JSON.js b/Compatibility/Request/Request.JSON.js deleted file mode 100755 index 0217d2659..000000000 --- a/Compatibility/Request/Request.JSON.js +++ /dev/null @@ -1,24 +0,0 @@ -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/Compatibility/Request/Request.js b/Compatibility/Request/Request.js deleted file mode 100644 index 7f5abfec8..000000000 --- a/Compatibility/Request/Request.js +++ /dev/null @@ -1,37 +0,0 @@ -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/Compatibility/Utilities/Cookie.js b/Compatibility/Utilities/Cookie.js deleted file mode 100644 index a1b1a214a..000000000 --- a/Compatibility/Utilities/Cookie.js +++ /dev/null @@ -1,11 +0,0 @@ -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/Compatibility/Utilities/JSON.js b/Compatibility/Utilities/JSON.js deleted file mode 100644 index 97d1b35d2..000000000 --- a/Compatibility/Utilities/JSON.js +++ /dev/null @@ -1,4 +0,0 @@ -var Json = JSON; - -JSON.toString = JSON.encode; -JSON.evaluate = JSON.decode; \ No newline at end of file diff --git a/Compatibility/Utilities/Selectors.js b/Compatibility/Utilities/Selectors.js deleted file mode 100644 index 0492b82ab..000000000 --- a/Compatibility/Utilities/Selectors.js +++ /dev/null @@ -1,39 +0,0 @@ -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 From 0805d95db3bac8d634403d010f6e2cd23d1cbadc Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Sun, 6 Dec 2009 02:45:20 +0100 Subject: [PATCH 18/44] * Adding new Compatibility Layer by Nathan White --- Compatibility/Class/Class.js | 13 ++ Compatibility/Core/Browser.js | 42 +++++++ Compatibility/Core/Core.js | 47 +++++++ Compatibility/Element/Element.Dimensions.js | 26 ++++ Compatibility/Element/Element.Event.js | 1 + Compatibility/Element/Element.js | 128 ++++++++++++++++++++ Compatibility/Fx/Fx.Morph.js | 8 ++ Compatibility/Fx/Fx.Tween.js | 4 + Compatibility/Fx/Fx.js | 26 ++++ Compatibility/Native/Array.js | 18 +++ Compatibility/Native/Function.js | 14 +++ Compatibility/Native/Hash.js | 39 ++++++ Compatibility/Request/Request.JSON.js | 26 ++++ Compatibility/Request/Request.js | 59 +++++++++ Compatibility/Utilities/Cookie.js | 15 +++ Compatibility/Utilities/JSON.js | 11 ++ Compatibility/Utilities/Selectors.js | 10 ++ 17 files changed, 487 insertions(+) create mode 100644 Compatibility/Class/Class.js create mode 100644 Compatibility/Core/Browser.js create mode 100644 Compatibility/Core/Core.js create mode 100644 Compatibility/Element/Element.Dimensions.js create mode 100644 Compatibility/Element/Element.Event.js create mode 100644 Compatibility/Element/Element.js create mode 100644 Compatibility/Fx/Fx.Morph.js create mode 100644 Compatibility/Fx/Fx.Tween.js create mode 100644 Compatibility/Fx/Fx.js create mode 100644 Compatibility/Native/Array.js create mode 100644 Compatibility/Native/Function.js create mode 100644 Compatibility/Native/Hash.js create mode 100644 Compatibility/Request/Request.JSON.js create mode 100644 Compatibility/Request/Request.js create mode 100644 Compatibility/Utilities/Cookie.js create mode 100644 Compatibility/Utilities/JSON.js create mode 100644 Compatibility/Utilities/Selectors.js diff --git a/Compatibility/Class/Class.js b/Compatibility/Class/Class.js new file mode 100644 index 000000000..1ee556e89 --- /dev/null +++ b/Compatibility/Class/Class.js @@ -0,0 +1,13 @@ +Class.empty = function(){ + console.warn('replace Class.empty with $empty'); + return $empty; +}; + +//legacy .extend support + +Class.prototype.extend = function(properties){ + console.warn('Class.extend is deprecated. See class mutators.'); + properties.Extends = this; + return new Class(properties); +}; + diff --git a/Compatibility/Core/Browser.js b/Compatibility/Core/Browser.js new file mode 100644 index 000000000..3fcbc3014 --- /dev/null +++ b/Compatibility/Core/Browser.js @@ -0,0 +1,42 @@ + +Browser.__defineGetter__('hasGetter',function(){ + return true; +}); + +if(Browser.hasGetter){ // webkit, gecko, opera support + + window.__defineGetter__('ie',function(){ + console.warn('window.ie is deprecated. Use Browser.Engine.trident'); + return (Browser.Engine.name == 'trident') ? true : false; + }); + window.__defineGetter__('ie6',function(){ + console.warn('window.ie6 is deprecated. Use Browser.Engine.trident and Browser.Engine.version'); + return (Browser.Engine.name == 'trident' && Browser.Engine.version == 4) ? true : false; + }); + window.__defineGetter__('ie7',function(){ + console.warn('window.ie7 is deprecated. Use Browser.Engine.trident and Browser.Engine.version'); + return (Browser.Engine.name == 'trident' && Browser.Engine.version == 5) ? true : false; + }); + window.__defineGetter__('gecko',function(){ + console.warn('window.gecko is deprecated. Use Browser.Engine.gecko'); + return (Browser.Engine.name == 'gecko') ? true : false; + }); + window.__defineGetter__('webkit',function(){ + console.warn('window.webkit is deprecated. Use Browser.Engine.webkit'); + return (Browser.Engine.name == 'webkit') ? true : false; + }); + window.__defineGetter__('webkit419',function(){ + console.warn('window.webkit is deprecated. Use Browser.Engine.webkit and Browser.Engine.version'); + return (Browser.Engine.name == 'webkit' && Browser.Engine.version == 419) ? true : false; + }); + window.__defineGetter__('webkit420',function(){ + console.warn('window.webkit is deprecated. Use Browser.Engine.webkit and Browser.Engine.version'); + return (Browser.Engine.name == 'webkit' && Browser.Engine.version == 420) ? true : false; + }); +} else { // no warnings for IE + window[Browser.Engine.name] = window[Browser.Engine.name + Browser.Engine.version] = true; + + window.ie = window.trident; + window.ie6 = window.trident4; + window.ie7 = window.trident5; +} diff --git a/Compatibility/Core/Core.js b/Compatibility/Core/Core.js new file mode 100644 index 000000000..008d95c55 --- /dev/null +++ b/Compatibility/Core/Core.js @@ -0,0 +1,47 @@ +/* +MooTools 1.2 Custom Backwards-Compatibility Library +By David Isaacson +Portions from Mootools 1.2 by the MooTools production team (http://mootools.net/developers/) +Copyright (c) 2006-2007 Valerio Proietti (http://mad4milk.net/) +Copyright (c) 2008 Siafoo.net + +Cleaned up, shortened and logging added by Nathan White (http://www.nwhite.net) +*/ + +if(!window.console) var console = {}; +if(!console.log) console.log = function(){}; + + +// This is the definition from Mootools 1.2, with error handling +// to prevent an issue in IE where calling .item on an XML (non-HTML) +// element raises an error. +// +// We're using the 1.2 version in the first place because the compat version throws *other* weird errors sometimes +// Note that this will prevent you from using the $A(iterable, start, length) syntax allowed but undocumented (?) in Mootools 1.1 +function $A(iterable){ + var item + try{ + item = iterable.item + } + catch(e){ + item = true + } + + if (item){ + var array = []; + for (var i = 0, l = iterable.length; i < l; i++) array[i] = iterable[i]; + return array; + } + return Array.prototype.slice.call(iterable); +} + +function $extend(original, extended){ + if (!extended) {extended=original; original=this; console.warn('$extend requires two parameters'); } + for (var key in (extended || {})) original[key] = extended[key]; + return original; +} + +(function(){ + var natives = [Array, Function, String, RegExp, Number]; + for (var i = 0, l = natives.length; i < l; i++) natives[i].extend = natives[i].implement; // TODO +})(); diff --git a/Compatibility/Element/Element.Dimensions.js b/Compatibility/Element/Element.Dimensions.js new file mode 100644 index 000000000..33dd3e1f3 --- /dev/null +++ b/Compatibility/Element/Element.Dimensions.js @@ -0,0 +1,26 @@ + +(function(){ + + function isBody(element){ + return (/^(?:body|html)$/i).test(element.tagName); + }; + + var oldgetSize = Element.prototype.getSize; + + Element.implement({ + + getSize: function(){ + var size; + if (isBody(this)) size = this.getWindow().getSize(); + else size = oldgetSize(); + return { + x : size.x, + y: size.y, + size: size, + scroll: this.getScroll(), + scrollSize: this.getScrollSize() + }; + } + }); + +})(); \ No newline at end of file diff --git a/Compatibility/Element/Element.Event.js b/Compatibility/Element/Element.Event.js new file mode 100644 index 000000000..a048a8a48 --- /dev/null +++ b/Compatibility/Element/Element.Event.js @@ -0,0 +1 @@ +Event.keys = Event.Keys; // TODO diff --git a/Compatibility/Element/Element.js b/Compatibility/Element/Element.js new file mode 100644 index 000000000..c9bf8054c --- /dev/null +++ b/Compatibility/Element/Element.js @@ -0,0 +1,128 @@ + +Element.extend = function(obj){ + console.warn('Element.extend is deprecated. Use Element.implement'); + Element.implement(obj); +}; + +Elements.extend = function(obj){ + console.warn('Elements.extend is deprecated. Use Elements.implement'); + Elements.implement(obj); +}; + +Element.implement({ + + remove : function(){ + console.warn('el.remove is deprecated. Use el.dispose'); + return this.dispose(); + }, + + getLastChild : function(){ + console.warn('el.getLastChild is deprecated. Use el.getLast'); + return this.getLast(); + }, + + getFormElements: function(){ + console.warn('el.getFormElements is deprecated.'); + return this.getElements('input, textarea, select'); + }, + + replaceWith: function(el){ + console.warn('el.replaceWith is deprecated.'); + el = $(el); + $(this.parentNode).replaceChild(el, this); // wrapped for ie + return el; + }, + + removeElements: function(){ + console.warn('el.removeElements is deprecated. use el.dispose()'); + return this.dispose(); + }, + + getText: function(){ + console.warn('el.getText is deprecated. use el.get("text")'); + return this.get('text'); + }, + + setText: function(text){ + console.warn('el.setText is deprecated. use el.set("text",value)'); + return this.set('text', text); + }, + + setHTML: function(){ + console.warn('el.setHTML is deprecated. use el.set("html",value)'); + return this.set('html', arguments); + }, + + getHTML: function(){ + console.warn('el.getHTML is deprecated. use el.get("html")'); + return this.get('html'); + }, + + getTag: function(){ + console.warn('el.getTag is deprecated. use el.get("tag")'); + return this.get('tag'); + }, + + setOpacity: function(op){ + console.warn('el.setOpacity is deprecated. use el.set("opacity",value)'); + return this.set('opacity', op); + }, + + getValue: function(){ + console.warn('el.getValue is deprecated. use el.get("value")'); + return this.get('value') + }, + + // Very slightly modified from mootools + toQueryString: function(){ + console.warn('warning el.toQueryString is slightly different'); + var queryString = []; + this.getElements('input, select, textarea').each(function(el){ + if (!el.name || el.disabled) return; + var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map(function(opt){ + return opt.value; + }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value; + $splat(value).each(function(val){ + /*if (val)*/ queryString.push(el.name + '=' + encodeURIComponent(val)); + }); + }); + return queryString.join('&'); + }, + + effect: function(property, options){ + console.warn('el.effect is deprecated. use el.tween'); + return new Fx.Tween(this, $extend({property: property}, options)); + }, + + effects: function(options){ + console.warn('el.effects is deprecated. use el.morph'); + return new Fx.Morph(this, options); + }, + + filterByTag: function(tag){ + console.warn('el.filterByTag is deprecated.'); + return this.filter(tag); + }, + + filterByClass: function(className){ + console.warn('el.filterByClass is deprecated.'); + return this.filter('.' + className); + }, + + filterById: function(id){ + console.warn('el.filterById is deprecated.'); + return this.filter('#' + id); + }, + + filterByAttribute: function(name, operator, value){ + console.warn('el.filterByAttribute is deprecated.'); + return this.filter('[' + name + (operator || '') + (value || '') + ']'); + } + +}); + + +window.extend = document.extend = function(properties){ + console.warn('(window||document).extend is deprecated'); + for (var property in properties) this[property] = properties[property]; +}; diff --git a/Compatibility/Fx/Fx.Morph.js b/Compatibility/Fx/Fx.Morph.js new file mode 100644 index 000000000..b867aac0b --- /dev/null +++ b/Compatibility/Fx/Fx.Morph.js @@ -0,0 +1,8 @@ +Fx.Styles = new Class({ + Extends : Fx.Morph, + initialize : function(el,options){ + console.warn('Fx.Styles is deprecated. Use Fx.Morph'); + return this.parent(el,options); + } + }); + \ No newline at end of file diff --git a/Compatibility/Fx/Fx.Tween.js b/Compatibility/Fx/Fx.Tween.js new file mode 100644 index 000000000..e533bb56f --- /dev/null +++ b/Compatibility/Fx/Fx.Tween.js @@ -0,0 +1,4 @@ +Fx.Style = function(element, property, options){ + console.warn('Fx.Style is deprecated. Use Fx.Tween'); + return new Fx.Tween(element, $extend({property: property}, options)); +}; diff --git a/Compatibility/Fx/Fx.js b/Compatibility/Fx/Fx.js new file mode 100644 index 000000000..a47c0de71 --- /dev/null +++ b/Compatibility/Fx/Fx.js @@ -0,0 +1,26 @@ +Fx.implement({ + + custom: function(from, to){ + console.warn('Fx.custom deprecated. Use Fx.start'); + return this.start(from, to); + }, + + clearTimer: function(){ + console.warn('Fx.clearTimer deprecated. Use Fx.cancel'); + return this.cancel(); + }, + + stop: function(){ + console.warn('Fx.stop deprecated. Use Fx.cancel'); + return this.cancel(); + } + +}); + +Fx.Base = new Class({ + Extends : Fx, + initialize : function(options){ + console.warn('Fx.Base is deprecated. Use Fx.'); + return this.parent(options); + } +}); diff --git a/Compatibility/Native/Array.js b/Compatibility/Native/Array.js new file mode 100644 index 000000000..d0a544412 --- /dev/null +++ b/Compatibility/Native/Array.js @@ -0,0 +1,18 @@ +Array.implement({ + + copy: function(start, length){ + console.warn('Array.copy is deprecated. Use Array.splice'); + return $A(this, start, length); + }, + + remove : function(item){ + console.warn('Array.remove is deprecated. Use Array.erase'); + return this.erase(item); + }, + + merge : function(array){ + console.warn('Array.merge is deprecated. Use Array.combine'); + return this.combine(array); + } + +}); diff --git a/Compatibility/Native/Function.js b/Compatibility/Native/Function.js new file mode 100644 index 000000000..06d04910e --- /dev/null +++ b/Compatibility/Native/Function.js @@ -0,0 +1,14 @@ +Function.extend({ + + bindAsEventListener: function(bind, args){ + console.warn('Function.bindAsEventListener is deprecated.'); + return this.create({'bind': bind, 'event': true, 'arguments': args}); + } + +}); + +Function.empty = function(){ + console.warn('replace Function.empty with $empty'); + return $empty(); +}; + diff --git a/Compatibility/Native/Hash.js b/Compatibility/Native/Hash.js new file mode 100644 index 000000000..a3bbc0746 --- /dev/null +++ b/Compatibility/Native/Hash.js @@ -0,0 +1,39 @@ + +Hash.implement({ + + keys : function(){ + console.warn('Hash.keys is deprecated. Use Hash.getKeys'); + return this.getKeys(); + }, + + values : function(){ + console.warn('Hash.values is deprecated. Use Hash.getValues'); + return this.getValues(); + }, + + hasKey : function(item){ + console.warn('Hash.hasKey is deprecated. Use Hash.has'); + return this.has(item); + }, + + merge : function(properties){ + console.warn('Hash.merge is deprecated. Use Hash.combine'); + return this.combine(properties); + }, + + remove: function(key){ + console.warn('Hash.remove is deprecated. use Hash.erase'); + return this.erase(key) + } +}); + +Object.toQueryString = Hash.toQueryString; // TODO + +var Abstract = new Class({ + initialize : function(obj){ + console.warn('Abstract is deprecated. Use Hash'); + return new Hash(obj); + } +}); + + diff --git a/Compatibility/Request/Request.JSON.js b/Compatibility/Request/Request.JSON.js new file mode 100644 index 000000000..eafac003b --- /dev/null +++ b/Compatibility/Request/Request.JSON.js @@ -0,0 +1,26 @@ +JSON.Remote = new Class({ + + options: { + key: 'json' + }, + + Extends: Request.JSON, + + initialize: function(url, options){ + console.warn('JSON.Remote is deprecated. Use Request.JSON'); + this.parent(options); + this.onComplete = $empty; + this.url = url; + }, + + send: function(data){ + if (!this.check(arguments.callee, data)) return this; + return this.parent({url: this.url, data: {json: Json.encode(data)}}); + }, + + failure: function(){ + this.fireEvent('failure', this.xhr); + } + +}); + diff --git a/Compatibility/Request/Request.js b/Compatibility/Request/Request.js new file mode 100644 index 000000000..ab936db4e --- /dev/null +++ b/Compatibility/Request/Request.js @@ -0,0 +1,59 @@ + +var XHR = new Class({ + + Extends: Request, + + options: { + update: false + }, + + initialize: function(options){ + console.warn('XHR is deprecated. Use Request.'); + this.parent(options); + this.transport = this.xhr; + }, + + request: function(data){ + return this.send(this.url, data || this.options.data); + }, + + send: function(url, data){ + if (!this.check(arguments.callee, 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 = new Class({ + Extends: XHR, + + initialize: function(url, options){ + console.warn('Ajax is deprecated. Use Request.'); + this.url = url; + this.parent(options); + }, + + success: function(text, xml){ + // This version processes scripts *after* the update element is updated, like Mootools 1.1's Ajax class + // Partially from Remote.Ajax.success + response = this.response; + response.html = text.stripScripts(function(script){ + response.javascript = script; + }) + if (this.options.update) $(this.options.update).empty().set('html', response.html); + if (this.options.evalScripts) $exec(response.javascript); + this.onSuccess(text, xml); + } +}); + diff --git a/Compatibility/Utilities/Cookie.js b/Compatibility/Utilities/Cookie.js new file mode 100644 index 000000000..8581f6a9e --- /dev/null +++ b/Compatibility/Utilities/Cookie.js @@ -0,0 +1,15 @@ + +Cookie.set = function(key, value, options){ + console.warn('Cookie.set is deprecated. Use Cookie.write'); + return new Cookie(key, options).write(value); +}; + +Cookie.get = function(key){ + console.warn('Cookie.get is deprecated. Use Cookie.read'); + return new Cookie(key).read(); +}; + +Cookie.remove = function(key, options){ + console.warn('Cookie.remove is deprecated. Use Cookie.dispose'); + return new Cookie(key, options).dispose(); +}; diff --git a/Compatibility/Utilities/JSON.js b/Compatibility/Utilities/JSON.js new file mode 100644 index 000000000..20f19cb29 --- /dev/null +++ b/Compatibility/Utilities/JSON.js @@ -0,0 +1,11 @@ + +JSON.toString = function(obj){ + console.warn('JSON.toString is deprecated. Use JSON.encode'); + return JSON.encode(obj); +} +JSON.evaluate = function(str){ + console.warn('JSON.evaluate is deprecated. Use JSON.decode'); + return JSON.decode(str); +} +var Json = JSON; + diff --git a/Compatibility/Utilities/Selectors.js b/Compatibility/Utilities/Selectors.js new file mode 100644 index 000000000..88eba60c5 --- /dev/null +++ b/Compatibility/Utilities/Selectors.js @@ -0,0 +1,10 @@ +var $E = function(selector, filter){ + console.warn('$E is deprecated.'); + return ($(filter) || document).getElement(selector); +}; + +var $ES = function(selector, filter){ + console.warn('$ES is deprecated.'); + return ($(filter) || document).getElements(selector); +}; + From c13e973e679387a34f679a70b6b0841d8aeba48a Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Fri, 18 Dec 2009 22:14:55 +0100 Subject: [PATCH 19/44] * Updating Specs repository --- Specs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs b/Specs index 3b07dfa06..514d39965 160000 --- a/Specs +++ b/Specs @@ -1 +1 @@ -Subproject commit 3b07dfa0626365631893b5d80046f6ff78694591 +Subproject commit 514d39965f377550349426c84c8215adcc10098f From 18b1f8558aeee3fc75380275a83b39b4bdc90c6b Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Fri, 18 Dec 2009 22:39:01 +0100 Subject: [PATCH 20/44] * Updating Specs repository --- Specs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs b/Specs index 514d39965..be21c3b91 160000 --- a/Specs +++ b/Specs @@ -1 +1 @@ -Subproject commit 514d39965f377550349426c84c8215adcc10098f +Subproject commit be21c3b91a6432ffd4df9ac0fd57f84c4f6aacfd From 43dd8a07eda83d9c0d468e2c04b377a0f90be097 Mon Sep 17 00:00:00 2001 From: cpojer Date: Sat, 19 Dec 2009 00:11:32 -0700 Subject: [PATCH 21/44] * Fixing specs repository (not my fault this time!) --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 2a5011ba6..d0d062343 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,4 +6,4 @@ url = git://github.com/anutron/mootools-unittester.git [submodule "Specs"] path = Specs - url = git://github.com:mootools/mootools-core-specs.git + url = git://github.com/mootools/mootools-core-specs.git From e9f0f01570f99d64479f9c5332816cc63f828201 Mon Sep 17 00:00:00 2001 From: Valerio Proietti Date: Sat, 19 Dec 2009 08:11:44 +0100 Subject: [PATCH 22/44] fixed the Specs submodule path again. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 2a5011ba6..d0d062343 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,4 +6,4 @@ url = git://github.com/anutron/mootools-unittester.git [submodule "Specs"] path = Specs - url = git://github.com:mootools/mootools-core-specs.git + url = git://github.com/mootools/mootools-core-specs.git From 357561376a28fff6857ed17cee76053a2cc7b194 Mon Sep 17 00:00:00 2001 From: Valerio Proietti Date: Sat, 19 Dec 2009 08:17:19 +0100 Subject: [PATCH 23/44] added texmate and espresso projects to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index be33fe253..030e23070 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ mootools.js +mootools-core.js +mootools-core.tmproj +mootools-core.esproj \ No newline at end of file From 61d6c7cc9e176350b42dd0c06b7b11e3074a3f1b Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Thu, 11 Feb 2010 08:53:38 -0700 Subject: [PATCH 24/44] FIXED Cloning all elements onunload in IE Changed it to require retain to be === true or else false. That was the smallest change possible to completely fix the issue. clean is being passed to .each() its second argument is a boolean flag "retain" .each() passes (item, key, object) to its callback function .each(clean) is like running clean(element, 1) Thanks Daniel Steigerwald! --- Source/Element/Element.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Element/Element.js b/Source/Element/Element.js index bd63575ca..5c610c753 100644 --- a/Source/Element/Element.js +++ b/Source/Element/Element.js @@ -247,6 +247,7 @@ var get = function(uid){ var clean = function(item, retain){ if (!item) return; var uid = item.uid; + if (retain !== true) retain = false; if (Browser.Engine.trident){ if (item.clearAttributes){ var clone = retain && item.cloneNode(false); From b5a0c82ff39684f4262c2261dd5da693d2648519 Mon Sep 17 00:00:00 2001 From: Darren Waddell Date: Sat, 27 Feb 2010 17:11:48 +0000 Subject: [PATCH 25/44] Documentation fixes. Thank you all contributors and reporters --- Docs/Class/Class.Extras.md | 2 +- Docs/Element/Element.md | 2 +- Docs/Fx/Fx.Transitions.md | 6 +++--- Docs/Native/Array.md | 24 ++++++++++++------------ Docs/Native/Event.md | 2 +- Docs/Native/Function.md | 6 +++--- Docs/Native/Number.md | 2 +- Docs/Native/String.md | 12 ++++++------ Docs/Request/Request.HTML.md | 1 + Docs/Utilities/Cookie.md | 2 +- Docs/Utilities/Selectors.md | 23 ++++++++++++++++++++++- 11 files changed, 52 insertions(+), 30 deletions(-) diff --git a/Docs/Class/Class.Extras.md b/Docs/Class/Class.Extras.md index ba7878abb..f12e7a1f6 100644 --- a/Docs/Class/Class.Extras.md +++ b/Docs/Class/Class.Extras.md @@ -327,7 +327,7 @@ 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). +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). You will need to call this.setOptions() for this to have an effect, however. ### Syntax: diff --git a/Docs/Element/Element.md b/Docs/Element/Element.md index 2134faa97..8aec49131 100644 --- a/Docs/Element/Element.md +++ b/Docs/Element/Element.md @@ -647,7 +647,7 @@ A text node will be created inside this Element, in either the top or bottom pos ### Arguments: 1. text - (*string*) The text to append. -1. where - (*string*, optional: default 'bottom') The position to inject the text to. +1. where - (*string*, optional: default 'bottom') The position to inject the text to. Values accepted are 'top', 'bottom', 'before' and 'after'. ### Returns: diff --git a/Docs/Fx/Fx.Transitions.md b/Docs/Fx/Fx.Transitions.md index dd4756c98..a468d972c 100644 --- a/Docs/Fx/Fx.Transitions.md +++ b/Docs/Fx/Fx.Transitions.md @@ -15,8 +15,8 @@ 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}); + $('myElement').set('tween', {transition: Fx.Transitions.Elastic.easeOut}); + $('myElement').tween('margin-top', 100); ### See also: @@ -144,4 +144,4 @@ Returns an [Fx][] transition function with 'easeIn', 'easeOut', and 'easeInOut' [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 +[Elastic]: ../Docs/assets/images/Elastic.png diff --git a/Docs/Native/Array.md b/Docs/Native/Array.md index 23be3eac9..2559dfd00 100644 --- a/Docs/Native/Array.md +++ b/Docs/Native/Array.md @@ -627,15 +627,15 @@ Creates a copy of an Array. Useful for applying the Array prototypes to iterable [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 +[MDC Array]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array +[MDC Array:every]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/every +[MDC Array:filter]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter +[MDC Array:indexOf]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf +[MDC Array:map]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/map +[MDC Array:some]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/some +[MDC Array:forEach]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/forEach +[Array:every]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/every +[Array:filter]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter +[Array:indexOf]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf +[Array:map]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/map +[Array:some]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/some \ No newline at end of file diff --git a/Docs/Native/Event.md b/Docs/Native/Event.md index b0908a0c0..c0be5c5f7 100644 --- a/Docs/Native/Event.md +++ b/Docs/Native/Event.md @@ -13,7 +13,7 @@ Event Method: constructor {#Event:constructor} ### Arguments: -1. event - (*event*) An HTMLEvent Object. +1. event - (*event*, required) An HTMLEvent Object. 2. win - (*window*, optional: defaults to window) The context of the event. #### Properties: diff --git a/Docs/Native/Function.md b/Docs/Native/Function.md index 498f0f876..1e8d807b2 100644 --- a/Docs/Native/Function.md +++ b/Docs/Native/Function.md @@ -297,6 +297,6 @@ Runs the Function with specified arguments and binding. The same as apply but re [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 +[MDC Function]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function +[MDC setInterval]: https://developer.mozilla.org/en/DOM/window.setInterval +[MDC setTimeout]: https://developer.mozilla.org/en/DOM/window.setTimeout \ No newline at end of file diff --git a/Docs/Native/Number.md b/Docs/Native/Number.md index 619702026..26312b48a 100644 --- a/Docs/Native/Number.md +++ b/Docs/Native/Number.md @@ -132,4 +132,4 @@ Returns this number as another number with the passed in base. Useful because to -[MDC Number]: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Number \ No newline at end of file +[MDC Number]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number \ No newline at end of file diff --git a/Docs/Native/String.md b/Docs/Native/String.md index ed6df8e34..ed899c594 100644 --- a/Docs/Native/String.md +++ b/Docs/Native/String.md @@ -346,11 +346,11 @@ Removes undefined keywords and ignores escaped keywords. -[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 +[MDC String]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String +[MDC Regexp:test]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/RegExp/test +[MDC Regular Expressions]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Regular_Expressions +[MDC parseInt]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/parseInt +[MDC parseFloat]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/parseFloat +[MDC Array]: https://developer.mozilla.org/en/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/Docs/Request/Request.HTML.md b/Docs/Request/Request.HTML.md index 7d48c4297..06dde330c 100755 --- a/Docs/Request/Request.HTML.md +++ b/Docs/Request/Request.HTML.md @@ -21,6 +21,7 @@ Request Specifically made for receiving HTML. * 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. +* append - (*element*: defaults to null) The Element to append the response text of the Request into upon completion of the request. ### Events: diff --git a/Docs/Utilities/Cookie.md b/Docs/Utilities/Cookie.md index 3b8f4768f..248c0ee45 100755 --- a/Docs/Utilities/Cookie.md +++ b/Docs/Utilities/Cookie.md @@ -97,7 +97,7 @@ Remove a Cookie: 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); } + if (Cookie.read('username') == 'Aaron') { myCookie.dispose(); } diff --git a/Docs/Utilities/Selectors.md b/Docs/Utilities/Selectors.md index 43fcebf57..e39c535d3 100644 --- a/Docs/Utilities/Selectors.md +++ b/Docs/Utilities/Selectors.md @@ -91,7 +91,7 @@ Some default Pseudo Selectors for [Selectors][]. - [W3C Pseudo Classes](http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#pseudo-classes) -Selector: enabled {#Selector:checked} +Selector: checked {#Selector:checked} ------------------------------------- Matches all Elements that are checked. @@ -121,6 +121,7 @@ Matches all Elements that are enabled. $$('*:enabled') $('myElement').getElements(':enabled'); + Selector: empty {#Selector:empty} --------------------------------- @@ -135,6 +136,7 @@ Matches all elements which are empty. $$('div:empty'); + Selector: contains {#Selector:contains} --------------------------------------- @@ -153,6 +155,22 @@ Matches all the Elements which contains the text. $$('p:contains("find me")'); +Selector: not {#Selector:not} +------------------------------------- + +Returns all elements that do not match the selector. + +### Usage: + + ':not(selector)' + +### Examples: + + $$('*:not(.foo)') + + $('myElement').getElements(':not(a)'); + + Selector: nth-child {#Selector:nth-child} ----------------------------------------- @@ -203,6 +221,7 @@ Last Child: 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} ------------------------------- @@ -220,6 +239,7 @@ Matches every even child. 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} ----------------------------- @@ -237,6 +257,7 @@ Matches every odd child. 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-child {#Selector:first-child} --------------------------------- From ecf0c245c575903fecf4a1107af2fc372986eef2 Mon Sep 17 00:00:00 2001 From: Jan Kassens Date: Sat, 27 Feb 2010 19:02:12 +0100 Subject: [PATCH 26/44] Minor improvement to the :not selector documentation. --- Docs/Element/Element.Dimensions.md | 2 +- Docs/Element/Element.Event.md | 2 +- Docs/Element/Element.Style.md | 2 +- Docs/Fx/Fx.CSS.md | 2 +- Docs/Native/Array.md | 2 +- Docs/Native/Event.md | 2 +- Docs/Native/Function.md | 2 +- Docs/Native/Number.md | 2 +- Docs/Native/String.md | 2 +- Docs/Utilities/Cookie.md | 2 +- Docs/Utilities/DomReady.md | 2 +- Docs/Utilities/Selectors.md | 10 +++++++--- Docs/Utilities/Swiff.md | 2 +- Docs/license.md | 2 +- 14 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Docs/Element/Element.Dimensions.md b/Docs/Element/Element.Dimensions.md index a25b705eb..8441ac356 100644 --- a/Docs/Element/Element.Dimensions.md +++ b/Docs/Element/Element.Dimensions.md @@ -225,4 +225,4 @@ Returns the parent of the element that is positioned, if there is one. [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 -[Element.measure]: /more/Element/Element.Measure \ No newline at end of file +[Element.measure]: /more/Element/Element.Measure diff --git a/Docs/Element/Element.Event.md b/Docs/Element/Element.Event.md index 9d1708a67..ae287861e 100644 --- a/Docs/Element/Element.Event.md +++ b/Docs/Element/Element.Event.md @@ -322,4 +322,4 @@ This event fires when the mouse wheel is rotated; [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 +[Function:delay]: /core/Native/Function/#Function:delay diff --git a/Docs/Element/Element.Style.md b/Docs/Element/Element.Style.md index c92e986da..097d4efee 100644 --- a/Docs/Element/Element.Style.md +++ b/Docs/Element/Element.Style.md @@ -119,4 +119,4 @@ Returns an object of styles of the Element for each argument passed in. [$]: /core/Element/Element/#dollar [Function]: /core/Native/Function -[Element:getStyle]: #Element:getStyle \ No newline at end of file +[Element:getStyle]: #Element:getStyle diff --git a/Docs/Fx/Fx.CSS.md b/Docs/Fx/Fx.CSS.md index ba451eeb0..89cee6b11 100644 --- a/Docs/Fx/Fx.CSS.md +++ b/Docs/Fx/Fx.CSS.md @@ -9,4 +9,4 @@ 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 +[Fx.Elements]: /more/Fx/Fx.Elements diff --git a/Docs/Native/Array.md b/Docs/Native/Array.md index 2559dfd00..39d07fdac 100644 --- a/Docs/Native/Array.md +++ b/Docs/Native/Array.md @@ -638,4 +638,4 @@ Creates a copy of an Array. Useful for applying the Array prototypes to iterable [Array:filter]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter [Array:indexOf]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf [Array:map]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/map -[Array:some]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/some \ No newline at end of file +[Array:some]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/some diff --git a/Docs/Native/Event.md b/Docs/Native/Event.md index c0be5c5f7..5a93665b0 100644 --- a/Docs/Native/Event.md +++ b/Docs/Native/Event.md @@ -177,4 +177,4 @@ Additional Event key codes can be added by adding properties to the Event.Keys H [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 +[Function:delay]: /core/Native/Function/#Function:delay diff --git a/Docs/Native/Function.md b/Docs/Native/Function.md index 1e8d807b2..6e7c8b315 100644 --- a/Docs/Native/Function.md +++ b/Docs/Native/Function.md @@ -299,4 +299,4 @@ Runs the Function with specified arguments and binding. The same as apply but re [$clear]: /core/Core/Core/#clear [MDC Function]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function [MDC setInterval]: https://developer.mozilla.org/en/DOM/window.setInterval -[MDC setTimeout]: https://developer.mozilla.org/en/DOM/window.setTimeout \ No newline at end of file +[MDC setTimeout]: https://developer.mozilla.org/en/DOM/window.setTimeout diff --git a/Docs/Native/Number.md b/Docs/Native/Number.md index 26312b48a..b8aebd583 100644 --- a/Docs/Native/Number.md +++ b/Docs/Native/Number.md @@ -132,4 +132,4 @@ Returns this number as another number with the passed in base. Useful because to -[MDC Number]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number \ No newline at end of file +[MDC Number]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number diff --git a/Docs/Native/String.md b/Docs/Native/String.md index ed899c594..e2e143534 100644 --- a/Docs/Native/String.md +++ b/Docs/Native/String.md @@ -353,4 +353,4 @@ Removes undefined keywords and ignores escaped keywords. [MDC parseFloat]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/parseFloat [MDC Array]: https://developer.mozilla.org/en/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 +[Array:rgbToHex]: /core/Native/Array/#Array:rgbToHex diff --git a/Docs/Utilities/Cookie.md b/Docs/Utilities/Cookie.md index 248c0ee45..1aecf097a 100755 --- a/Docs/Utilities/Cookie.md +++ b/Docs/Utilities/Cookie.md @@ -104,4 +104,4 @@ Creating a Cookie and Removing it Right Away: [Cookie]: #Cookie [Cookie.options]: #Cookie-options [Cookie.options.domain]: #Cookie-options -[QuirksMode]: http://www.quirksmode.org \ No newline at end of file +[QuirksMode]: http://www.quirksmode.org diff --git a/Docs/Utilities/DomReady.md b/Docs/Utilities/DomReady.md index a7c0864bc..fe7e4a8a3 100644 --- a/Docs/Utilities/DomReady.md +++ b/Docs/Utilities/DomReady.md @@ -14,4 +14,4 @@ This event is only available to the window Element. ### See Also: [Element.Event][] -[Element.Event]: /core/Element/Element.Event \ No newline at end of file +[Element.Event]: /core/Element/Element.Event diff --git a/Docs/Utilities/Selectors.md b/Docs/Utilities/Selectors.md index e39c535d3..90e336a64 100644 --- a/Docs/Utilities/Selectors.md +++ b/Docs/Utilities/Selectors.md @@ -158,7 +158,7 @@ Matches all the Elements which contains the text. Selector: not {#Selector:not} ------------------------------------- -Returns all elements that do not match the selector. +Matches all elements that do not match the single selector. ### Usage: @@ -166,9 +166,13 @@ Returns all elements that do not match the selector. ### Examples: - $$('*:not(.foo)') + $$(':not(div.foo)'); // all elements except divs with class 'foo' - $('myElement').getElements(':not(a)'); + $$('input:not([type="submit"])'); // all inputs except submit buttons + + myElement.getElements(':not(a)'); + + $$(':not(ul li)'); // NOT allowed! Only single selectors might be passed. Selector: nth-child {#Selector:nth-child} diff --git a/Docs/Utilities/Swiff.md b/Docs/Utilities/Swiff.md index ed0f3ade2..4936528f7 100755 --- a/Docs/Utilities/Swiff.md +++ b/Docs/Utilities/Swiff.md @@ -88,4 +88,4 @@ Calls an ActionScript function from JavaScript. 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 +[External Interface]: http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001652.html diff --git a/Docs/license.md b/Docs/license.md index 267c276c3..68f82536e 100644 --- a/Docs/license.md +++ b/Docs/license.md @@ -5,4 +5,4 @@ Attribution-NonCommercial-ShareAlike 3.0 ## See Also - \ No newline at end of file + From 32ed2c74cb7a3e4ac84dc9a25ea68b50a7807f3b Mon Sep 17 00:00:00 2001 From: Valerio Proietti Date: Wed, 17 Mar 2010 21:29:53 +0100 Subject: [PATCH 27/44] - added package.yml and fixed the headers so that they are valid yaml. MooTools Core 1.2.4 can now be built with [packager](http://github.com/kamicane/packager) --- Source/Class/Class.Extras.js | 5 ++-- Source/Class/Class.js | 13 ++------- Source/Core/Browser.js | 6 ++-- Source/Core/Core.js | 6 ++-- Source/Element/Element.Dimensions.js | 11 ++++---- Source/Element/Element.Event.js | 8 ++---- Source/Element/Element.Style.js | 7 ++--- Source/Element/Element.js | 11 ++------ Source/Fx/Fx.CSS.js | 8 ++---- Source/Fx/Fx.Morph.js | 7 ++--- Source/Fx/Fx.Transitions.js | 10 +++---- Source/Fx/Fx.Tween.js | 5 ++-- Source/Fx/Fx.js | 9 ++---- Source/Native/Array.js | 8 ++---- Source/Native/Event.js | 12 ++------ Source/Native/Function.js | 8 ++---- Source/Native/Hash.js | 7 ++--- Source/Native/Number.js | 8 ++---- Source/Native/String.js | 7 ++--- Source/Request/Request.HTML.js | 8 ++---- Source/Request/Request.JSON.js | 7 ++--- Source/Request/Request.js | 11 ++------ Source/Utilities/Cookie.js | 10 +++---- Source/Utilities/DomReady.js | 7 ++--- Source/Utilities/JSON.js | 13 +++------ Source/Utilities/Selectors.js | 7 ++--- Source/Utilities/Swiff.js | 11 +++----- package.yml | 42 ++++++++++++++++++++++++++++ 28 files changed, 125 insertions(+), 147 deletions(-) create mode 100644 package.yml diff --git a/Source/Class/Class.Extras.js b/Source/Class/Class.Extras.js index 3dd17a661..505d0053e 100644 --- a/Source/Class/Class.Extras.js +++ b/Source/Class/Class.Extras.js @@ -1,14 +1,13 @@ /* --- -script: Class.Extras.js +name: Class.Extras description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. license: MIT-style license. -requires: -- /Class +requires: Class provides: [Chain, Events, Options] diff --git a/Source/Class/Class.js b/Source/Class/Class.js index 16693cae9..9d9afccbf 100644 --- a/Source/Class/Class.js +++ b/Source/Class/Class.js @@ -1,22 +1,15 @@ /* --- -script: Class.js +name: Class description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. license: MIT-style license. -requires: -- /$util -- /Native -- /Array -- /String -- /Function -- /Number -- /Hash +requires: [$util, Native, Array, String, Function, Number, Hash] -provides: [Class] +provides: Class ... */ diff --git a/Source/Core/Browser.js b/Source/Core/Browser.js index 2d1f105f0..bfe314bd0 100644 --- a/Source/Core/Browser.js +++ b/Source/Core/Browser.js @@ -1,15 +1,13 @@ /* --- -script: Browser.js +name: Browser description: The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash. license: MIT-style license. -requires: -- /Native -- /$util +requires: [Native, $util] provides: [Browser, Window, Document, $exec] diff --git a/Source/Core/Core.js b/Source/Core/Core.js index 4c68e6005..612fbd02e 100644 --- a/Source/Core/Core.js +++ b/Source/Core/Core.js @@ -1,7 +1,7 @@ /* --- -script: Core.js +name: Core description: The core of MooTools, contains all the base functions and the Native and Hash implementations. Required by all the other scripts. @@ -12,8 +12,8 @@ copyright: Copyright (c) 2006-2008 [Valerio Proietti](http://mad4milk.net/). authors: The MooTools production team (http://mootools.net/developers/) inspiration: -- Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) -- Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) + - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) + - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) provides: [MooTools, Native, Hash.base, Array.each, $util] diff --git a/Source/Element/Element.Dimensions.js b/Source/Element/Element.Dimensions.js index 01d873263..da2a78eb2 100644 --- a/Source/Element/Element.Dimensions.js +++ b/Source/Element/Element.Dimensions.js @@ -1,20 +1,19 @@ /* --- -script: Element.Dimensions.js +name: Element.Dimensions description: Contains methods to work with size, scroll, or positioning of Elements and the window object. license: MIT-style license. credits: -- Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). -- Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). + - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). + - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). -requires: -- /Element +requires: Element -provides: [Element.Dimensions] +provides: Element.Dimensions ... */ diff --git a/Source/Element/Element.Event.js b/Source/Element/Element.Event.js index 31d28caca..81460df9f 100644 --- a/Source/Element/Element.Event.js +++ b/Source/Element/Element.Event.js @@ -1,17 +1,15 @@ /* --- -script: Element.Event.js +name: Element.Event description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events. license: MIT-style license. -requires: -- /Element -- /Event +requires: [Element, Event] -provides: [Element.Event] +provides: Element.Event ... */ diff --git a/Source/Element/Element.Style.js b/Source/Element/Element.Style.js index 2b01ab2ca..0f162e0e3 100644 --- a/Source/Element/Element.Style.js +++ b/Source/Element/Element.Style.js @@ -1,16 +1,15 @@ /* --- -script: Element.Style.js +name: Element.Style description: Contains methods for interacting with the styles of Elements in a fashionable way. license: MIT-style license. -requires: -- /Element +requires: Element -provides: [Element.Style] +provides: Element.Style ... */ diff --git a/Source/Element/Element.js b/Source/Element/Element.js index 5c610c753..5dfb122b7 100644 --- a/Source/Element/Element.js +++ b/Source/Element/Element.js @@ -1,20 +1,13 @@ /* --- -script: Element.js +name: Element description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. license: MIT-style license. -requires: -- /Window -- /Document -- /Array -- /String -- /Function -- /Number -- /Hash +requires: [Window, Document, Array, String, Function, Number, Hash] provides: [Element, Elements, $, $$, Iframe] diff --git a/Source/Fx/Fx.CSS.js b/Source/Fx/Fx.CSS.js index 6ece0e53a..e250e208a 100644 --- a/Source/Fx/Fx.CSS.js +++ b/Source/Fx/Fx.CSS.js @@ -1,17 +1,15 @@ /* --- -script: Fx.CSS.js +name: Fx.CSS description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. license: MIT-style license. -requires: -- /Fx -- /Element.Style +requires: [Fx, Element.Style] -provides: [Fx.CSS] +provides: Fx.CSS ... */ diff --git a/Source/Fx/Fx.Morph.js b/Source/Fx/Fx.Morph.js index 367025354..c59b78d1a 100644 --- a/Source/Fx/Fx.Morph.js +++ b/Source/Fx/Fx.Morph.js @@ -1,16 +1,15 @@ /* --- -script: Fx.Morph.js +name: Fx.Morph description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. license: MIT-style license. -requires: -- /Fx.CSS +requires: Fx.CSS -provides: [Fx.Morph] +provides: Fx.Morph ... */ diff --git a/Source/Fx/Fx.Transitions.js b/Source/Fx/Fx.Transitions.js index 9a8166935..16fb2f110 100644 --- a/Source/Fx/Fx.Transitions.js +++ b/Source/Fx/Fx.Transitions.js @@ -1,19 +1,17 @@ /* --- -script: Fx.Transitions.js +name: Fx.Transitions description: Contains a set of advanced transitions to be used with any of the Fx Classes. license: MIT-style license. -credits: -- Easing Equations by Robert Penner, , modified and optimized to be used with MooTools. +credits: Easing Equations by Robert Penner, , modified and optimized to be used with MooTools. -requires: -- /Fx +requires: Fx -provides: [Fx.Transitions] +provides: Fx.Transitions ... */ diff --git a/Source/Fx/Fx.Tween.js b/Source/Fx/Fx.Tween.js index ddde55be3..46a695604 100644 --- a/Source/Fx/Fx.Tween.js +++ b/Source/Fx/Fx.Tween.js @@ -1,14 +1,13 @@ /* --- -script: Fx.Tween.js +name: Fx.Tween description: Formerly Fx.Style, effect to transition any CSS property for an element. license: MIT-style license. -requires: -- /Fx.CSS +requires: Fx.CSS provides: [Fx.Tween, Element.fade, Element.highlight] diff --git a/Source/Fx/Fx.js b/Source/Fx/Fx.js index 9f062215e..5feeb40aa 100644 --- a/Source/Fx/Fx.js +++ b/Source/Fx/Fx.js @@ -1,18 +1,15 @@ /* --- -script: Fx.js +name: Fx description: Contains the basic animation logic to be extended by all other Fx Classes. license: MIT-style license. -requires: -- /Chain -- /Events -- /Options +requires: [Chain, Events, Options] -provides: [Fx] +provides: Fx ... */ diff --git a/Source/Native/Array.js b/Source/Native/Array.js index c5d12ec85..1d49caa8c 100644 --- a/Source/Native/Array.js +++ b/Source/Native/Array.js @@ -1,17 +1,15 @@ /* --- -script: Array.js +name: Array description: Contains Array Prototypes like each, contains, and erase. license: MIT-style license. -requires: -- /$util -- /Array.each +requires: [$util, Array.each] -provides: [Array] +provides: Array ... */ diff --git a/Source/Native/Event.js b/Source/Native/Event.js index bf35409e0..bfa637e1a 100644 --- a/Source/Native/Event.js +++ b/Source/Native/Event.js @@ -1,21 +1,15 @@ /* --- -script: Event.js +name: Event description: Contains the Event Class, to make the event object cross-browser. license: MIT-style license. -requires: -- /Window -- /Document -- /Hash -- /Array -- /Function -- /String +requires: [Window, Document, Hash, Array, Function, String] -provides: [Event] +provides: Event ... */ diff --git a/Source/Native/Function.js b/Source/Native/Function.js index d92718947..9c119616b 100644 --- a/Source/Native/Function.js +++ b/Source/Native/Function.js @@ -1,17 +1,15 @@ /* --- -script: Function.js +name: Function description: Contains Function Prototypes like create, bind, pass, and delay. license: MIT-style license. -requires: -- /Native -- /$util +requires: [Native, $util] -provides: [Function] +provides: Function ... */ diff --git a/Source/Native/Hash.js b/Source/Native/Hash.js index bcb36a45a..f0a44a2b6 100644 --- a/Source/Native/Hash.js +++ b/Source/Native/Hash.js @@ -1,16 +1,15 @@ /* --- -script: Hash.js +name: Hash description: Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects. license: MIT-style license. -requires: -- /Hash.base +requires: Hash.base -provides: [Hash] +provides: Hash ... */ diff --git a/Source/Native/Number.js b/Source/Native/Number.js index 1364978c2..ac48cd558 100644 --- a/Source/Native/Number.js +++ b/Source/Native/Number.js @@ -1,17 +1,15 @@ /* --- -script: Number.js +name: Number description: Contains Number Prototypes like limit, round, times, and ceil. license: MIT-style license. -requires: -- /Native -- /$util +requires: [Native, $util] -provides: [Number] +provides: Number ... */ diff --git a/Source/Native/String.js b/Source/Native/String.js index e8353f7b7..c6d9bb5f2 100644 --- a/Source/Native/String.js +++ b/Source/Native/String.js @@ -1,16 +1,15 @@ /* --- -script: String.js +name: String description: Contains String Prototypes like camelCase, capitalize, test, and toInt. license: MIT-style license. -requires: -- /Native +requires: Native -provides: [String] +provides: String ... */ diff --git a/Source/Request/Request.HTML.js b/Source/Request/Request.HTML.js index 2d7ee088c..639b3cc99 100644 --- a/Source/Request/Request.HTML.js +++ b/Source/Request/Request.HTML.js @@ -1,17 +1,15 @@ /* --- -script: Request.HTML.js +name: Request.HTML description: Extends the basic Request Class with additional methods for interacting with HTML responses. license: MIT-style license. -requires: -- /Request -- /Element +requires: [Request, Element] -provides: [Request.HTML] +provides: Request.HTML ... */ diff --git a/Source/Request/Request.JSON.js b/Source/Request/Request.JSON.js index 759e1c716..af2e45ac0 100644 --- a/Source/Request/Request.JSON.js +++ b/Source/Request/Request.JSON.js @@ -1,16 +1,15 @@ /* --- -script: Request.JSON.js +name: Request.JSON description: Extends the basic Request Class with additional methods for sending and receiving JSON data. license: MIT-style license. -requires: -- /Request JSON +requires: [Request, JSON] -provides: [Request.HTML] +provides: Request.HTML ... */ diff --git a/Source/Request/Request.js b/Source/Request/Request.js index 9d0d9d019..113423e1b 100644 --- a/Source/Request/Request.js +++ b/Source/Request/Request.js @@ -1,20 +1,15 @@ /* --- -script: Request.js +name: Request description: Powerful all purpose Request Class. Uses XMLHTTPRequest. license: MIT-style license. -requires: -- /Element -- /Chain -- /Events -- /Options -- /Browser +requires: [Element, Chain, Events, Options, Browser] -provides: [Request] +provides: Request ... */ diff --git a/Source/Utilities/Cookie.js b/Source/Utilities/Cookie.js index c331fb92f..fca5d3482 100644 --- a/Source/Utilities/Cookie.js +++ b/Source/Utilities/Cookie.js @@ -1,19 +1,17 @@ /* --- -script: Cookie.js +name: Cookie description: Class for creating, reading, and deleting browser Cookies. license: MIT-style license. -credits: -- Based on the functions by Peter-Paul Koch (http://quirksmode.org). +credits: Based on the functions by Peter-Paul Koch (http://quirksmode.org). -requires: -- /Options +requires: Options -provides: [Cookie] +provides: Cookie ... */ diff --git a/Source/Utilities/DomReady.js b/Source/Utilities/DomReady.js index 88430c6e2..f5407968b 100644 --- a/Source/Utilities/DomReady.js +++ b/Source/Utilities/DomReady.js @@ -1,16 +1,15 @@ /* --- -script: DomReady.js +name: DomReady description: Contains the custom event domready. license: MIT-style license. -requires: -- /Element.Event +requires: Element.Event -provides: [DomReady] +provides: DomReady ... */ diff --git a/Source/Utilities/JSON.js b/Source/Utilities/JSON.js index aaac7eddb..94e1c65f6 100644 --- a/Source/Utilities/JSON.js +++ b/Source/Utilities/JSON.js @@ -1,22 +1,17 @@ /* --- -script: JSON.js +name: JSON description: JSON encoder and decoder. license: MIT-style license. -See Also: +see: -requires: -- /Array -- /String -- /Number -- /Function -- /Hash +requires: [Array, String, Number, Function, Hash] -provides: [JSON] +provides: JSON ... */ diff --git a/Source/Utilities/Selectors.js b/Source/Utilities/Selectors.js index a07ee8204..4d659212f 100644 --- a/Source/Utilities/Selectors.js +++ b/Source/Utilities/Selectors.js @@ -1,16 +1,15 @@ /* --- -script: Selectors.js +name: Selectors description: Adds advanced CSS-style querying capabilities for targeting HTML Elements. Includes pseudo selectors. license: MIT-style license. -requires: -- /Element +requires: Element -provides: [Selectors] +provides: Selectors ... */ diff --git a/Source/Utilities/Swiff.js b/Source/Utilities/Swiff.js index 8f84deed4..adb54da5e 100644 --- a/Source/Utilities/Swiff.js +++ b/Source/Utilities/Swiff.js @@ -1,20 +1,17 @@ /* --- -script: Swiff.js +name: Swiff description: Wrapper for embedding SWF movies. Supports External Interface Communication. license: MIT-style license. -credits: -- Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. +credits: Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. -requires: -- /Options -- /$util +requires: [Options, $util] -provides: [Swiff] +provides: Swiff ... */ diff --git a/package.yml b/package.yml new file mode 100644 index 000000000..3de916950 --- /dev/null +++ b/package.yml @@ -0,0 +1,42 @@ +name: "Core" + +version: 1.2.4 + +web: "[mootools.net](http://mootools.net)" + +description: "MooTools, The JavaScript framework" + +license: "[MIT License](http://mootools.net/license.txt)" + +copyright: "© [MooTools](http://mootools.net)" + +authors: "[The MooTools development team](http://mootools.net/developers)" + +sources: + - "Source/Core/Core.js" + - "Source/Core/Browser.js" + - "Source/Native/Array.js" + - "Source/Native/String.js" + - "Source/Native/Number.js" + - "Source/Native/Function.js" + - "Source/Native/Hash.js" + - "Source/Native/Event.js" + - "Source/Class/Class.js" + - "Source/Class/Class.Extras.js" + - "Source/Element/Element.js" + - "Source/Element/Element.Style.js" + - "Source/Element/Element.Event.js" + - "Source/Element/Element.Dimensions.js" + - "Source/Fx/Fx.js" + - "Source/Fx/Fx.CSS.js" + - "Source/Fx/Fx.Morph.js" + - "Source/Fx/Fx.Tween.js" + - "Source/Fx/Fx.Transitions.js" + - "Source/Request/Request.js" + - "Source/Request/Request.HTML.js" + - "Source/Request/Request.JSON.js" + - "Source/Utilities/Cookie.js" + - "Source/Utilities/JSON.js" + - "Source/Utilities/DomReady.js" + - "Source/Utilities/Swiff.js" + - "Source/Utilities/Selectors.js" From f40511131bc40dc2c5bb481b07fc5020ac7f4faf Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Mon, 5 Apr 2010 21:32:29 +0200 Subject: [PATCH 28/44] Updating Specs submodule --- Specs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs b/Specs index be21c3b91..db2d94ef4 160000 --- a/Specs +++ b/Specs @@ -1 +1 @@ -Subproject commit be21c3b91a6432ffd4df9ac0fd57f84c4f6aacfd +Subproject commit db2d94ef48136553f4536fe5b6d9344b6bd43a31 From f167725345e98638889a49335790690609541d73 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Mon, 5 Apr 2010 21:36:52 +0200 Subject: [PATCH 29/44] Removing old compat files --- Compatibility/Class/Class.js | 26 ----- Compatibility/Core/Browser.js | 44 -------- Compatibility/Core/Core.js | 44 -------- Compatibility/Element/Element.Dimensions.js | 40 -------- Compatibility/Element/Element.Event.js | 1 - Compatibility/Element/Element.Style.js | 22 ---- Compatibility/Element/Element.js | 106 -------------------- Compatibility/Fx/Fx.Morph.js | 16 --- Compatibility/Fx/Fx.Scroll.js | 8 -- Compatibility/Fx/Fx.Tween.js | 25 ----- Compatibility/Fx/Fx.js | 26 ----- Compatibility/Native/Array.js | 18 ---- Compatibility/Native/Function.js | 12 --- Compatibility/Native/Hash.js | 35 ------- Compatibility/Request/Request.JSON.js | 26 ----- Compatibility/Request/Request.js | 69 ------------- Compatibility/Utilities/Cookie.js | 15 --- Compatibility/Utilities/JSON.js | 11 -- Compatibility/Utilities/Selectors.js | 47 --------- 19 files changed, 591 deletions(-) delete mode 100644 Compatibility/Class/Class.js delete mode 100644 Compatibility/Core/Browser.js delete mode 100644 Compatibility/Core/Core.js delete mode 100644 Compatibility/Element/Element.Dimensions.js delete mode 100644 Compatibility/Element/Element.Event.js delete mode 100644 Compatibility/Element/Element.Style.js delete mode 100644 Compatibility/Element/Element.js delete mode 100644 Compatibility/Fx/Fx.Morph.js delete mode 100644 Compatibility/Fx/Fx.Scroll.js delete mode 100644 Compatibility/Fx/Fx.Tween.js delete mode 100644 Compatibility/Fx/Fx.js delete mode 100644 Compatibility/Native/Array.js delete mode 100644 Compatibility/Native/Function.js delete mode 100644 Compatibility/Native/Hash.js delete mode 100644 Compatibility/Request/Request.JSON.js delete mode 100644 Compatibility/Request/Request.js delete mode 100644 Compatibility/Utilities/Cookie.js delete mode 100644 Compatibility/Utilities/JSON.js delete mode 100644 Compatibility/Utilities/Selectors.js diff --git a/Compatibility/Class/Class.js b/Compatibility/Class/Class.js deleted file mode 100644 index 8758b09d9..000000000 --- a/Compatibility/Class/Class.js +++ /dev/null @@ -1,26 +0,0 @@ -Class.empty = function(){ - console.warn('replace Class.empty with $empty'); - return $empty; -}; - -//legacy .extend support - -Class.prototype.extend = function(properties){ - console.warn('1.1 > 1.2: Class.extend is deprecated. See the class Extend mutator.'); - properties.Extends = this; - return new Class(properties); -}; - -(function(){ - var __implement = Class.prototype.implement; - Class.prototype.implement = function(){ - if (arguments.length > 1 && Array.every(arguments, Object.type)){ - console.warn('1.1 > 1.2: Class.implement no longer takes more than one thing at a time, either MyClass.implement(key, value) or MyClass.implement(object) but NOT MyClass.implement(new Foo, new Bar, new Baz). See also: the class Implements mutator.'); - Array.each(arguments, function(argument){ - __implement.call(this, argument); - }); - return this; - } - return __implement.apply(this, arguments); - }; -})(); \ No newline at end of file diff --git a/Compatibility/Core/Browser.js b/Compatibility/Core/Browser.js deleted file mode 100644 index 366800a38..000000000 --- a/Compatibility/Core/Browser.js +++ /dev/null @@ -1,44 +0,0 @@ -window.extend = document.extend = function(properties){ - console.warn('1.1 > 1.2: window no longer has an .extend method; use .implement instead.'); - for (var property in properties) this[property] = properties[property]; -}; - -if (window.__defineGetter__){ - window.__defineGetter__('ie',function(){ - console.warn('1.1 > 1.2: window.ie is deprecated. Use Browser.Engine.trident'); - return (Browser.Engine.name == 'trident') ? true : false; - }); - window.__defineGetter__('ie6',function(){ - console.warn('1.1 > 1.2: window.ie6 is deprecated. Use Browser.Engine.trident and Browser.Engine.version'); - return (Browser.Engine.name == 'trident' && Browser.Engine.version == 4) ? true : false; - }); - window.__defineGetter__('ie7',function(){ - console.warn('1.1 > 1.2: window.ie7 is deprecated. Use Browser.Engine.trident and Browser.Engine.version'); - return (Browser.Engine.name == 'trident' && Browser.Engine.version == 5) ? true : false; - }); - window.__defineGetter__('gecko',function(){ - console.warn('1.1 > 1.2: window.gecko is deprecated. Use Browser.Engine.gecko'); - return (Browser.Engine.name == 'gecko') ? true : false; - }); - window.__defineGetter__('webkit',function(){ - console.warn('1.1 > 1.2: window.webkit is deprecated. Use Browser.Engine.webkit'); - return (Browser.Engine.name == 'webkit') ? true : false; - }); - window.__defineGetter__('webkit419',function(){ - console.warn('1.1 > 1.2: window.webkit is deprecated. Use Browser.Engine.webkit and Browser.Engine.version'); - return (Browser.Engine.name == 'webkit' && Browser.Engine.version == 419) ? true : false; - }); - window.__defineGetter__('webkit420',function(){ - console.warn('1.1 > 1.2: window.webkit is deprecated. Use Browser.Engine.webkit and Browser.Engine.version'); - return (Browser.Engine.name == 'webkit' && Browser.Engine.version == 420) ? true : false; - }); - window.__defineGetter__('opera',function(){ - console.warn('1.1 > 1.2: window.opera is deprecated. Use Browser.Engine.presto'); - return (Browser.Engine.name == 'presto') ? true : false; - }); -} else { - window[Browser.Engine.name] = window[Browser.Engine.name + Browser.Engine.version] = true; - window.ie = window.trident; - window.ie6 = window.trident4; - window.ie7 = window.trident5; -} diff --git a/Compatibility/Core/Core.js b/Compatibility/Core/Core.js deleted file mode 100644 index ffd73b241..000000000 --- a/Compatibility/Core/Core.js +++ /dev/null @@ -1,44 +0,0 @@ -if(!window.console) var console = {}; -if(!console.log) console.warn = function(){}; - -(function(){ - oldA = $A; - window.$A = function(iterable, start, length){ - if (start != undefined && length != undefined) { - console.warn('1.1 > 1.2: $A no longer takes start and length arguments.'); - 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); - } - return oldA(iterable); - }; - - var natives = [Array, Function, String, RegExp, Number]; - for (var i = 0, l = natives.length; i < l; i++) natives[i].extend = natives[i].implement; -})(); - -var $native = function(){ - for (var i = 0, l = arguments.length; i < l; i++){ - arguments[i].extend = function(props){ - console.warn('1.1 > 1.2: native elements no longer have an .extend method; use .implement instead.'); - for (var prop in props){ - if (!this.prototype[prop]) this.prototype[prop] = props[prop]; - if (!this[prop]) this[prop] = $native.generic(prop); - } - }; - } -}; - -$native.generic = function(prop){ - return function(bind){ - return this.prototype[prop].apply(bind, Array.prototype.slice.call(arguments, 1)); - }; -}; \ No newline at end of file diff --git a/Compatibility/Element/Element.Dimensions.js b/Compatibility/Element/Element.Dimensions.js deleted file mode 100644 index 4fe3007cb..000000000 --- a/Compatibility/Element/Element.Dimensions.js +++ /dev/null @@ -1,40 +0,0 @@ -(function(){ - - var getPosition = Element.prototype.getPosition; - var getCoordinates = Element.prototype.getCoordinates; - - function isBody(element){ - return (/^(?:body|html)$/i).test(element.tagName); - }; - - var getSize = Element.prototype.getSize; - - Element.implement({ - - getSize: function(){ - console.warn('1.1 > 1.2: NOTE: getSize is different in 1.2; it no longer returns values for size, scroll, and scrollSize, but instead just returns x/y values for the dimensions of the element.'); - var size = getSize.apply(this, arguments); - return $merge(size, { - size: size, - scroll: this.getScroll(), - scrollSize: this.getScrollSize() - }); - }, - - getPosition: function(relative){ - if (relative && $type(relative) == "array") { - console.warn('1.1 > 1.2: Element.getPosition no longer accepts an array of overflown elements but rather, optionally, a single element to get relative coordinates.'); - } - return getPosition.apply(this, arguments); - }, - - getCoordinates: function(relative){ - if (relative && $type(relative) == "array") { - console.warn('1.1 > 1.2: Element.getCoordinates no longer accepts an array of overflown elements but rather, optionally, a single element to get relative coordinates.'); - } - return getCoordinates.apply(this, arguments); - } - - }); - -})(); \ No newline at end of file diff --git a/Compatibility/Element/Element.Event.js b/Compatibility/Element/Element.Event.js deleted file mode 100644 index a048a8a48..000000000 --- a/Compatibility/Element/Element.Event.js +++ /dev/null @@ -1 +0,0 @@ -Event.keys = Event.Keys; // TODO diff --git a/Compatibility/Element/Element.Style.js b/Compatibility/Element/Element.Style.js deleted file mode 100644 index ffbeb38b8..000000000 --- a/Compatibility/Element/Element.Style.js +++ /dev/null @@ -1,22 +0,0 @@ -Element.implement({ - - setOpacity: function(op){ - console.warn('1.1 > 1.2: Element.setOpacity is deprecated; use Element.setStyle("opacity", value).'); - return this.set('opacity', op); - } - -}); - -Element.Properties.styles = { - - set: function(styles){ - if ($type(styles) == 'string'){ - styles.split(";").each(function(style){ - this.setStyle(style.split(":")[0], style.split(":")[1]); - }, this); - } else { - this.setStyles(styles); - } - } - -}; \ No newline at end of file diff --git a/Compatibility/Element/Element.js b/Compatibility/Element/Element.js deleted file mode 100644 index 90e09dcde..000000000 --- a/Compatibility/Element/Element.js +++ /dev/null @@ -1,106 +0,0 @@ -Element.extend = function(obj){ - console.warn('1.1 > 1.2: Element.extend is deprecated. Use Element.implement'); - Element.implement(obj); -}; - -Elements.extend = function(obj){ - console.warn('1.1 > 1.2: Elements.extend is deprecated. Use Elements.implement'); - Elements.implement(obj); -}; - -(function(){ - - var toQueryString = Element.prototype.toQueryString; - - Element.implement({ - - getFormElements: function(){ - console.warn('1.1 > 1.2: Element.getFormElements is deprecated, use Element.getElements("input, textarea, select");'); - return this.getElements('input, textarea, select'); - }, - - replaceWith: function(el){ - console.warn('1.1 > 1.2: Element.replaceWith is deprecated, use Element.replaces instead.'); - el = $(el); - this.parentNode.replaceChild(el, this); - return el; - }, - - remove: function() { - console.warn('1.1 > 1.2: Element.remove is deprecated - use Element.dispose.'); - return this.dispose.apply(this, arguments); - }, - - getText: function(){ - console.warn('1.1 > 1.2: Element.getText is deprecated - use Element.get("text").'); - return this.get('text'); - }, - - setText: function(text){ - console.warn('1.1 > 1.2: Element.setText is deprecated - use Element.set("text", text).'); - return this.set('text', text); - }, - - setHTML: function(){ - console.warn('1.1 > 1.2: Element.setHTML is deprecated - use Element.set("html", HTML).'); - return this.set('html', arguments); - }, - - getHTML: function(){ - console.warn('1.1 > 1.2: Element.getHTML is deprecated - use Element.get("html").'); - return this.get('html'); - }, - - getTag: function(){ - console.warn('1.1 > 1.2: Element.getTag is deprecated - use Element.get("tag").'); - return this.get('tag'); - }, - - getValue: function(){ - console.warn('1.1 > 1.2: Element.getValue is deprecated - use Element.get("value").'); - switch(this.getTag()){ - case 'select': - var values = []; - $each(this.options, function(option){ - if (option.selected) values.push($pick(option.value, option.text)); - }); - return (this.multiple) ? values : values[0]; - case 'input': if (!(this.checked && ['checkbox', 'radio'].contains(this.type)) && !['hidden', 'text', 'password'].contains(this.type)) break; - case 'textarea': return this.value; - } - return false; - }, - - toQueryString: function(){ - console.warn('1.1 > 1.2: warning Element.toQueryString is slightly different; inputs without names are excluded, inputs with type == submit, reset, and file are excluded, and inputs with undefined values are excluded.'); - return toQueryString.apply(this, arguments); - } - }); -})(); - -window.extend = document.extend = function(properties){ - console.warn('1.1 > 1.2: (window||document).extend is deprecated'); - for (var property in properties) this[property] = properties[property]; -}; - - -Element.Properties.properties = { - - set: function(props){ - console.warn('1.1 > 1.2: Element.set({properties: {}}) is deprecated; instead of properties, just name the values at the root of the object (Element.set({src: url})).'); - $H(props).each(function(value, property){ - this.set(property, value); - }, this); - } - -}; - - -Element.Properties.styles = { - - set: function(styles){ - if ($type(styles) == 'string') this.style.cssText = styles; - else this.setStyles(styles); - } - -}; \ No newline at end of file diff --git a/Compatibility/Fx/Fx.Morph.js b/Compatibility/Fx/Fx.Morph.js deleted file mode 100644 index ba2f86b04..000000000 --- a/Compatibility/Fx/Fx.Morph.js +++ /dev/null @@ -1,16 +0,0 @@ -Fx.Styles = new Class({ - Extends: Fx.Morph, - initialize: function(){ - console.warn('1.1 > 1.2: Fx.Styles is deprecated. use Fx.Morph.'); - this.parent.apply(this, arguments); - } -}); - -Element.implement({ - - effects: function(options){ - console.warn('1.1 > 1.2: Element.effects is deprecated; use Fx.Morph or Element.morph.'); - return new Fx.Morph(this, options); - } - -}); \ No newline at end of file diff --git a/Compatibility/Fx/Fx.Scroll.js b/Compatibility/Fx/Fx.Scroll.js deleted file mode 100644 index 4166153d7..000000000 --- a/Compatibility/Fx/Fx.Scroll.js +++ /dev/null @@ -1,8 +0,0 @@ -Fx.Scroll.implement({ - - scrollTo: function(y, x){ - console.warn('1.1 > 1.2: Fx.Scroll\'s .scrollTo is deprecated; use .start.'); - return this.start(y, x); - } - -}); \ No newline at end of file diff --git a/Compatibility/Fx/Fx.Tween.js b/Compatibility/Fx/Fx.Tween.js deleted file mode 100644 index 3fc4804ad..000000000 --- a/Compatibility/Fx/Fx.Tween.js +++ /dev/null @@ -1,25 +0,0 @@ -Fx.Style = new Class({ - Extends: Fx.Tween, - initialize: function(){ - console.warn('1.1 > 1.2: Fx.Style is deprecated. use Fx.Tween.'); - this.parent.apply(this, arguments); - } -}); - -Element.implement({ - - effect: function(options){ - console.warn('1.1 > 1.2: Element.effect is deprecated; use Fx.Tween or Element.tween.'); - return new Fx.Tween(this, options); - } - -}) - -Fx.Tween.implement({ - - hide: function(){ - console.warn('1.1 > 1.2: Fx.Style .hide() is deprecated; use Fx.Tween .set("opacity", 0) instead'); - return this.set('opacity', 0); - } - -}); \ No newline at end of file diff --git a/Compatibility/Fx/Fx.js b/Compatibility/Fx/Fx.js deleted file mode 100644 index 51e0dfec4..000000000 --- a/Compatibility/Fx/Fx.js +++ /dev/null @@ -1,26 +0,0 @@ -Fx.implement({ - - custom: function(from, to){ - console.warn('1.1 > 1.2: Fx.custom is deprecated. use Fx.start.'); - return this.start(from, to); - }, - - clearTimer: function(){ - console.warn('1.1 > 1.2: Fx.clearTimer is deprecated. use Fx.cancel.'); - return this.cancel(); - }, - - stop: function(){ - console.warn('1.1 > 1.2: Fx.stop is deprecated. use Fx.cancel.'); - return this.cancel(); - } - -}); - -Fx.Base = new Class({ - Extends: Fx, - initialize: function(){ - console.warn('1.1 > 1.2: Fx.Base is deprecated. use Fx.'); - this.parent.apply(this, arguments); - } -}); diff --git a/Compatibility/Native/Array.js b/Compatibility/Native/Array.js deleted file mode 100644 index ce50264eb..000000000 --- a/Compatibility/Native/Array.js +++ /dev/null @@ -1,18 +0,0 @@ -Array.implement({ - - copy: function(start, length){ - console.warn('Array.copy is deprecated. Use Array.slice'); - return $A(this, start, length); - }, - - remove : function(item){ - console.warn('Array.remove is deprecated. Use Array.erase'); - return this.erase(item); - }, - - merge : function(array){ - console.warn('Array.merge is deprecated. Use Array.combine'); - return this.combine(array); - } - -}); diff --git a/Compatibility/Native/Function.js b/Compatibility/Native/Function.js deleted file mode 100644 index b9a001195..000000000 --- a/Compatibility/Native/Function.js +++ /dev/null @@ -1,12 +0,0 @@ -Function.extend({ - - bindAsEventListener: function(bind, args){ - console.warn('Function.bindAsEventListener is deprecated.'); - return this.create({'bind': bind, 'event': true, 'arguments': args}); - } - -}); - -Function.empty = function(){ - console.warn('1.1 > 1.2: Function.empty is now just $empty.'); -}; \ No newline at end of file diff --git a/Compatibility/Native/Hash.js b/Compatibility/Native/Hash.js deleted file mode 100644 index 9997d2384..000000000 --- a/Compatibility/Native/Hash.js +++ /dev/null @@ -1,35 +0,0 @@ -Hash.implement({ - - keys : function(){ - console.warn('1.1 > 1.2: Hash.keys is deprecated. Use Hash.getKeys'); - return this.getKeys(); - }, - - values : function(){ - console.warn('1.1 > 1.2: Hash.values is deprecated. Use Hash.getValues'); - return this.getValues(); - }, - - hasKey : function(item){ - console.warn('1.1 > 1.2: Hash.hasKey is deprecated. Use Hash.has'); - return this.has(item); - }, - - merge : function(properties){ - console.warn('1.1 > 1.2: Hash.merge is deprecated. Use Hash.combine'); - return this.combine(properties); - }, - - remove: function(key){ - console.warn('1.1 > 1.2: Hash.remove is deprecated. use Hash.erase'); - return this.erase(key); - } - -}); - -Object.toQueryString = Hash.toQueryString; // TODO - -var Abstract = function(obj){ - console.warn('1.1 > 1.2: Abstract is deprecated. Use Hash'); - return new Hash(obj); -}; \ No newline at end of file diff --git a/Compatibility/Request/Request.JSON.js b/Compatibility/Request/Request.JSON.js deleted file mode 100644 index eafac003b..000000000 --- a/Compatibility/Request/Request.JSON.js +++ /dev/null @@ -1,26 +0,0 @@ -JSON.Remote = new Class({ - - options: { - key: 'json' - }, - - Extends: Request.JSON, - - initialize: function(url, options){ - console.warn('JSON.Remote is deprecated. Use Request.JSON'); - this.parent(options); - this.onComplete = $empty; - this.url = url; - }, - - send: function(data){ - if (!this.check(arguments.callee, data)) return this; - return this.parent({url: this.url, data: {json: Json.encode(data)}}); - }, - - failure: function(){ - this.fireEvent('failure', this.xhr); - } - -}); - diff --git a/Compatibility/Request/Request.js b/Compatibility/Request/Request.js deleted file mode 100644 index 69dd95d9e..000000000 --- a/Compatibility/Request/Request.js +++ /dev/null @@ -1,69 +0,0 @@ -Object.toQueryString = function(obj){ - $H(obj).each(function(item, key){ - if ($type(item) == 'object' || $type(item) == 'array'){ - obj[key] = item.toString(); - } - }); - return Hash.toQueryString(obj); -}; - -var XHR = new Class({ - - Extends: Request, - - options: { - update: false - }, - - initialize: function(options){ - console.warn('XHR is deprecated. Use Request.'); - this.parent(options); - this.transport = this.xhr; - }, - - request: function(data){ - return this.send(this.url, data || this.options.data); - }, - - send: function(url, data){ - if (!this.check(arguments.callee, 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 = new Class({ - - Extends: XHR, - - initialize: function(url, options){ - console.warn('Ajax is deprecated. Use Request.'); - this.url = url; - this.parent(options); - }, - - success: function(text, xml){ - // This version processes scripts *after* the update element is updated, like Mootools 1.1's Ajax class - // Partially from Remote.Ajax.success - response = this.response; - response.html = text.stripScripts(function(script){ - response.javascript = script; - }); - if (this.options.update) $(this.options.update).empty().set('html', response.html); - if (this.options.evalScripts) $exec(response.javascript); - this.onSuccess(text, xml); - } - -}); - diff --git a/Compatibility/Utilities/Cookie.js b/Compatibility/Utilities/Cookie.js deleted file mode 100644 index 8581f6a9e..000000000 --- a/Compatibility/Utilities/Cookie.js +++ /dev/null @@ -1,15 +0,0 @@ - -Cookie.set = function(key, value, options){ - console.warn('Cookie.set is deprecated. Use Cookie.write'); - return new Cookie(key, options).write(value); -}; - -Cookie.get = function(key){ - console.warn('Cookie.get is deprecated. Use Cookie.read'); - return new Cookie(key).read(); -}; - -Cookie.remove = function(key, options){ - console.warn('Cookie.remove is deprecated. Use Cookie.dispose'); - return new Cookie(key, options).dispose(); -}; diff --git a/Compatibility/Utilities/JSON.js b/Compatibility/Utilities/JSON.js deleted file mode 100644 index 20f19cb29..000000000 --- a/Compatibility/Utilities/JSON.js +++ /dev/null @@ -1,11 +0,0 @@ - -JSON.toString = function(obj){ - console.warn('JSON.toString is deprecated. Use JSON.encode'); - return JSON.encode(obj); -} -JSON.evaluate = function(str){ - console.warn('JSON.evaluate is deprecated. Use JSON.decode'); - return JSON.decode(str); -} -var Json = JSON; - diff --git a/Compatibility/Utilities/Selectors.js b/Compatibility/Utilities/Selectors.js deleted file mode 100644 index 428d611cb..000000000 --- a/Compatibility/Utilities/Selectors.js +++ /dev/null @@ -1,47 +0,0 @@ -Native.implement([Element, Document], { - - getElementsByClassName: function(className){ - console.warn('1.1 > 1.2: Element.getElementsByClassName is deprecated. Use getElements()'); - return this.getElements('.' + className); - }, - - getElementsBySelector: function(selector){ - console.warn('1.1 > 1.2: Element.getElementsBySelector is deprecated. Use getElements()'); - return this.getElements(selector); - } - -}); - -Elements.implement({ - - filterByTag: function(tag){ - console.warn('1.1 > 1.2: Elements.filterByTag is deprecated. Use Elements.filter.'); - return this.filter(tag); - }, - - filterByClass: function(className){ - console.warn('1.1 > 1.2: Elements.filterByClass is deprecated. Use Elements.filter.'); - return this.filter('.' + className); - }, - - filterById: function(id){ - console.warn('1.1 > 1.2: Elements.filterById is deprecated. Use Elements.filter.'); - return this.filter('#' + id); - }, - - filterByAttribute: function(name, operator, value){ - console.warn('1.1 > 1.2: Elements.filterByAttribute is deprecated. Use Elements.filter.'); - return this.filter('[' + name + (operator || '') + (value || '') + ']'); - } - -}); - -var $E = function(selector, filter){ - console.warn('1.1 > 1.2: $E is deprecated, use document.getElement.'); - return ($(filter) || document).getElement(selector); -}; - -var $ES = function(selector, filter){ - console.warn('1.1 > 1.2: $ES is deprecated. Use $$.'); - return ($(filter) || document).getElements(selector); -}; \ No newline at end of file From fe32d7bc66a1259781acf64d2cb2d7fb11664615 Mon Sep 17 00:00:00 2001 From: Aaron Newton Date: Sun, 5 Sep 2010 00:56:10 -0700 Subject: [PATCH 30/44] updating core yaml updating dependencies to resolve conflicts changing file permissions for some docs files --- Docs/Request/Request.HTML.md | 0 Docs/Request/Request.JSON.md | 0 Docs/Request/Request.md | 0 Docs/Utilities/Cookie.md | 0 Docs/Utilities/JSON.md | 0 Docs/Utilities/Swiff.md | 0 Source/Class/Class.Extras.js | 2 +- Source/Request/Request.JSON.js | 2 +- package.yml | 45 +++++++++++++++++----------------- 9 files changed, 24 insertions(+), 25 deletions(-) mode change 100755 => 100644 Docs/Request/Request.HTML.md mode change 100755 => 100644 Docs/Request/Request.JSON.md mode change 100755 => 100644 Docs/Request/Request.md mode change 100755 => 100644 Docs/Utilities/Cookie.md mode change 100755 => 100644 Docs/Utilities/JSON.md mode change 100755 => 100644 Docs/Utilities/Swiff.md diff --git a/Docs/Request/Request.HTML.md b/Docs/Request/Request.HTML.md old mode 100755 new mode 100644 diff --git a/Docs/Request/Request.JSON.md b/Docs/Request/Request.JSON.md old mode 100755 new mode 100644 diff --git a/Docs/Request/Request.md b/Docs/Request/Request.md old mode 100755 new mode 100644 diff --git a/Docs/Utilities/Cookie.md b/Docs/Utilities/Cookie.md old mode 100755 new mode 100644 diff --git a/Docs/Utilities/JSON.md b/Docs/Utilities/JSON.md old mode 100755 new mode 100644 diff --git a/Docs/Utilities/Swiff.md b/Docs/Utilities/Swiff.md old mode 100755 new mode 100644 diff --git a/Source/Class/Class.Extras.js b/Source/Class/Class.Extras.js index 505d0053e..25b3515ba 100644 --- a/Source/Class/Class.Extras.js +++ b/Source/Class/Class.Extras.js @@ -9,7 +9,7 @@ license: MIT-style license. requires: Class -provides: [Chain, Events, Options] +provides: [Chain, Events, Options, Class.Extras] ... */ diff --git a/Source/Request/Request.JSON.js b/Source/Request/Request.JSON.js index af2e45ac0..6a26adb5a 100644 --- a/Source/Request/Request.JSON.js +++ b/Source/Request/Request.JSON.js @@ -9,7 +9,7 @@ license: MIT-style license. requires: [Request, JSON] -provides: Request.HTML +provides: [Request.JSON] ... */ diff --git a/package.yml b/package.yml index 3de916950..fc1849aa5 100644 --- a/package.yml +++ b/package.yml @@ -1,42 +1,41 @@ name: "Core" - -version: 1.2.4 - web: "[mootools.net](http://mootools.net)" - + description: "MooTools, The JavaScript framework" - + license: "[MIT License](http://mootools.net/license.txt)" - + copyright: "© [MooTools](http://mootools.net)" - + authors: "[The MooTools development team](http://mootools.net/developers)" +version: "1.2.5-dev" + sources: - - "Source/Core/Core.js" - - "Source/Core/Browser.js" - - "Source/Native/Array.js" - - "Source/Native/String.js" - - "Source/Native/Number.js" - - "Source/Native/Function.js" - - "Source/Native/Hash.js" - - "Source/Native/Event.js" - - "Source/Class/Class.js" - "Source/Class/Class.Extras.js" + - "Source/Class/Class.js" + - "Source/Core/Browser.js" + - "Source/Core/Core.js" + - "Source/Element/Element.Dimensions.js" + - "Source/Element/Element.Event.js" - "Source/Element/Element.js" - "Source/Element/Element.Style.js" - - "Source/Element/Element.Event.js" - - "Source/Element/Element.Dimensions.js" - - "Source/Fx/Fx.js" - "Source/Fx/Fx.CSS.js" + - "Source/Fx/Fx.js" - "Source/Fx/Fx.Morph.js" - - "Source/Fx/Fx.Tween.js" - "Source/Fx/Fx.Transitions.js" - - "Source/Request/Request.js" + - "Source/Fx/Fx.Tween.js" + - "Source/Native/Array.js" + - "Source/Native/Event.js" + - "Source/Native/Function.js" + - "Source/Native/Hash.js" + - "Source/Native/Number.js" + - "Source/Native/String.js" - "Source/Request/Request.HTML.js" + - "Source/Request/Request.js" - "Source/Request/Request.JSON.js" - "Source/Utilities/Cookie.js" - - "Source/Utilities/JSON.js" - "Source/Utilities/DomReady.js" - - "Source/Utilities/Swiff.js" + - "Source/Utilities/JSON.js" - "Source/Utilities/Selectors.js" + - "Source/Utilities/Swiff.js" From 06f55ae71a27ac1879cff57d8024fd34056ccde2 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Tue, 14 Sep 2010 02:50:09 +0200 Subject: [PATCH 31/44] * Updating Specs --- Specs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs b/Specs index db2d94ef4..d5df302c2 160000 --- a/Specs +++ b/Specs @@ -1 +1 @@ -Subproject commit db2d94ef48136553f4536fe5b6d9344b6bd43a31 +Subproject commit d5df302c248eabf30772441e79bcb9b0d3f2a2a5 From 631d067470dd7e63197770cbfd20d6bd5e19eb77 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Tue, 14 Sep 2010 02:50:24 +0200 Subject: [PATCH 32/44] * Removing undocumented toJSON which clashes with the native JSON.stringify --- Source/Utilities/JSON.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Source/Utilities/JSON.js b/Source/Utilities/JSON.js index 94e1c65f6..8ffbc9346 100644 --- a/Source/Utilities/JSON.js +++ b/Source/Utilities/JSON.js @@ -53,11 +53,3 @@ var JSON = new Hash(this.JSON && { } }); - -Native.implement([Hash, Array, String, Number], { - - toJSON: function(){ - return JSON.encode(this); - } - -}); From 40fb8a4e6f6d497e79658108a25ab9bd6fa8608c Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Tue, 14 Sep 2010 02:50:38 +0200 Subject: [PATCH 33/44] * Put fireEvent on HTMLElement for IE9 --- Source/Element/Element.Event.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/Element/Element.Event.js b/Source/Element/Element.Event.js index 81460df9f..0cd177a6c 100644 --- a/Source/Element/Element.Event.js +++ b/Source/Element/Element.Event.js @@ -116,6 +116,12 @@ Native.implement([Element, Window, Document], { }); +// IE9 +try { + if (typeof HTMLElement != 'undefined') + HTMLElement.prototype.fireEvent = Element.prototype.fireEvent; +} catch(e){} + Element.NativeEvents = { click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons mousewheel: 2, DOMMouseScroll: 2, //mouse wheel From 1ba2093ab2bcd9e29c77c788064e5ed5e9736a44 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Tue, 14 Sep 2010 02:50:57 +0200 Subject: [PATCH 34/44] * Force our bind implementation in 1.2 and overwrite any existing implementation of bind --- Source/Native/Function.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Native/Function.js b/Source/Native/Function.js index 9c119616b..30dbf62a6 100644 --- a/Source/Native/Function.js +++ b/Source/Native/Function.js @@ -14,6 +14,10 @@ provides: Function ... */ +try { + delete Function.prototype.bind; +} catch(e){} + Function.implement({ extend: function(properties){ From 581383ab245fc9f07331cd42d86c315c58f486c5 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Tue, 14 Sep 2010 02:51:15 +0200 Subject: [PATCH 35/44] * Fix createElement for IE --- Source/Element/Element.js | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/Source/Element/Element.js b/Source/Element/Element.js index 5dfb122b7..af6c3cddd 100644 --- a/Source/Element/Element.js +++ b/Source/Element/Element.js @@ -114,18 +114,35 @@ Elements.implement({ }); +(function(){ + +/**/ +var createElementAcceptsHTML; +try { + var x = document.createElement(''); + createElementAcceptsHTML = (x.name == 'x'); +} catch(e){} + +var escapeQuotes = function(html){ + return ('' + html).replace(/&/g,'&').replace(/"/g,'"'); +}; +/**/ + Document.implement({ newElement: function(tag, props){ - if (Browser.Engine.trident && props){ - ['name', 'type', 'checked'].each(function(attribute){ - if (!props[attribute]) return; - tag += ' ' + attribute + '="' + props[attribute] + '"'; - if (attribute != 'checked') delete props[attribute]; - }); - tag = '<' + tag + '>'; + if (props && props.checked != null) props.defaultChecked = props.checked; + /**/// Fix for readonly name and type properties in IE < 8 + if (createElementAcceptsHTML && props){ + tag = '<' + tag; + if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"'; + if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"'; + tag += '>'; + delete props.name; + delete props.type; } - return document.id(this.createElement(tag)).set(props); + /**/ + return this.id(this.createElement(tag)).set(props); }, newTextNode: function(text){ @@ -177,6 +194,8 @@ Document.implement({ }); +})(); + if (window.$ == null) Window.implement({ $: function(el, nc){ return document.id(el, nc, this.document); From 008d8f0f2fcc2044e54fdd3635341aaab274e757 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Tue, 14 Sep 2010 03:00:50 +0200 Subject: [PATCH 36/44] * Updating Specs --- Specs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs b/Specs index d5df302c2..6348e8a5f 160000 --- a/Specs +++ b/Specs @@ -1 +1 @@ -Subproject commit d5df302c248eabf30772441e79bcb9b0d3f2a2a5 +Subproject commit 6348e8a5fc16a7786e7dce1f7919ba86c252bb9d From 3e7459cb4756475a80921bfde5c19a7c7edb64df Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Tue, 14 Sep 2010 03:17:07 +0200 Subject: [PATCH 37/44] * That's 1.2.5 ! --- Source/Core/Core.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core.js b/Source/Core/Core.js index 612fbd02e..c803e3557 100644 --- a/Source/Core/Core.js +++ b/Source/Core/Core.js @@ -21,8 +21,8 @@ provides: [MooTools, Native, Hash.base, Array.each, $util] */ var MooTools = { - 'version': '1.2.5dev', - 'build': '%build%' + 'version': '1.2.5', + 'build': '008d8f0f2fcc2044e54fdd3635341aaab274e757' }; var Native = function(options){ From 0ef30544e3a07f0dbe376f258376517e847cc81b Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Tue, 14 Sep 2010 03:21:01 +0200 Subject: [PATCH 38/44] * Back to dev --- Source/Core/Core.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core.js b/Source/Core/Core.js index c803e3557..910fa265f 100644 --- a/Source/Core/Core.js +++ b/Source/Core/Core.js @@ -21,8 +21,8 @@ provides: [MooTools, Native, Hash.base, Array.each, $util] */ var MooTools = { - 'version': '1.2.5', - 'build': '008d8f0f2fcc2044e54fdd3635341aaab274e757' + 'version': '1.2.6dev', + 'build': '%build%' }; var Native = function(options){ From fc8f77b718f27dde826bce50a746955c1dd333ae Mon Sep 17 00:00:00 2001 From: Thomas Aylott Date: Tue, 21 Sep 2010 10:25:02 -0400 Subject: [PATCH 39/44] FIXED Bug: Cannot set html of TR elements in Firefox; Cleanup/Speedup -- Don't add extra logic for browsers that don't need it. --- Source/Element/Element.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/Element/Element.js b/Source/Element/Element.js index af6c3cddd..00fa7fcad 100644 --- a/Source/Element/Element.js +++ b/Source/Element/Element.js @@ -681,6 +681,16 @@ Element.Properties.tag = { }; Element.Properties.html = (function(){ + var BUGGY_INNERHTML = true; + try { + var tester = document.createElement('tr'); + tester.innerHTML = 'x'; + tester = tester.firstChild; + BUGGY_INNERHTML = !(tester.nodeName == 'TD' && tester.innerHTML == 'x'); + } + catch (e){} + if (!BUGGY_INNERHTML) return null; + var wrapper = document.createElement('div'); var translations = { @@ -694,7 +704,7 @@ Element.Properties.html = (function(){ var html = { set: function(){ var html = Array.flatten(arguments).join(''); - var wrap = Browser.Engine.trident && translations[this.get('tag')]; + var wrap = translations[this.get('tag')]; if (wrap){ var first = wrapper; first.innerHTML = wrap[1] + html + wrap[2]; From eaf9d3f791dcc6a7c38cb1d6462988034965028c Mon Sep 17 00:00:00 2001 From: Arian Stolwijk Date: Tue, 15 Jan 2013 01:21:46 +0100 Subject: [PATCH 40/44] Fix failing spec where .set("html") should accept an array with values. --- Source/Element/Element.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Source/Element/Element.js b/Source/Element/Element.js index 00fa7fcad..bcb0978da 100644 --- a/Source/Element/Element.js +++ b/Source/Element/Element.js @@ -156,16 +156,16 @@ Document.implement({ getWindow: function(){ return this.window; }, - + id: (function(){ - + var types = { string: function(id, nocash, doc){ id = doc.getElementById(id); return (id) ? types.element(id, nocash) : null; }, - + element: function(el, nocash){ $uid(el); if (!nocash && !el.$family && !(/^object|embed$/i).test(el.tagName)){ @@ -174,16 +174,16 @@ Document.implement({ }; return el; }, - + object: function(obj, nocash, doc){ if (obj.toElement) return types.element(obj.toElement(doc), nocash); return null; } - + }; types.textnode = types.whitespace = types.window = types.document = $arguments(0); - + return function(el, nocash, doc){ if (el && el.$family && el.uid) return el; var type = $type(el); @@ -274,7 +274,7 @@ var clean = function(item, retain){ } Element.dispose(item); } - } + } if (!uid) return; collected[uid] = storage[uid] = null; }; @@ -497,7 +497,7 @@ Element.implement({ getParents: function(match, nocash){ return walk(this, 'parentNode', null, match, true, nocash); }, - + getSiblings: function(match, nocash){ return this.getParent().getChildren(match, nocash).erase(this); }, @@ -689,8 +689,12 @@ Element.Properties.html = (function(){ BUGGY_INNERHTML = !(tester.nodeName == 'TD' && tester.innerHTML == 'x'); } catch (e){} - if (!BUGGY_INNERHTML) return null; - + if (!BUGGY_INNERHTML) return { + set: function(){ + this.innerHTML = Array.flatten(arguments).join(''); + } + }; + var wrapper = document.createElement('div'); var translations = { From 7057039591e41ae64791a9458f182af1cf7a34db Mon Sep 17 00:00:00 2001 From: Arian Stolwijk Date: Tue, 15 Jan 2013 01:23:58 +0100 Subject: [PATCH 41/44] Fixes #2402 for 1.2. Overwrite String contains with the MooTools version. Firefox 18 implements .contains, and ES6 might do that as well. That breaks some stuff, so we have to make sure it's overwritten with the 'correct' MooTools version. --- Source/Native/String.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Native/String.js b/Source/Native/String.js index c6d9bb5f2..8e04ff0e1 100644 --- a/Source/Native/String.js +++ b/Source/Native/String.js @@ -14,6 +14,10 @@ provides: String ... */ +try { + delete String.prototype.contains; +} catch(e){} + String.implement({ test: function(regex, params){ From af297bbcc8e16170c97c7dbd19fb1eb5ae13706e Mon Sep 17 00:00:00 2001 From: Arian Stolwijk Date: Tue, 15 Jan 2013 01:41:05 +0100 Subject: [PATCH 42/44] Update specs --- Specs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs b/Specs index 6348e8a5f..3bc3b1567 160000 --- a/Specs +++ b/Specs @@ -1 +1 @@ -Subproject commit 6348e8a5fc16a7786e7dce1f7919ba86c252bb9d +Subproject commit 3bc3b1567e9a6b0850987733ad19467709f19116 From fa66fa2a0ccc91d9c41641934a9435ab24949aab Mon Sep 17 00:00:00 2001 From: Arian Stolwijk Date: Fri, 15 Feb 2013 21:52:30 +0100 Subject: [PATCH 43/44] 1.2.6 --- Source/Core/Core.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core.js b/Source/Core/Core.js index 910fa265f..34d6b6fa6 100644 --- a/Source/Core/Core.js +++ b/Source/Core/Core.js @@ -21,8 +21,8 @@ provides: [MooTools, Native, Hash.base, Array.each, $util] */ var MooTools = { - 'version': '1.2.6dev', - 'build': '%build%' + 'version': '1.2.6', + 'build': 'a3be7a0ef5205eb655c4ee11e8cbedcb3f2ffa95' }; var Native = function(options){ From 3da348962eea593e0279f062d5e643bfd26597cc Mon Sep 17 00:00:00 2001 From: Arian Stolwijk Date: Fri, 15 Feb 2013 21:58:21 +0100 Subject: [PATCH 44/44] Back to dev --- Source/Core/Core.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core.js b/Source/Core/Core.js index 34d6b6fa6..93a3a57d0 100644 --- a/Source/Core/Core.js +++ b/Source/Core/Core.js @@ -21,8 +21,8 @@ provides: [MooTools, Native, Hash.base, Array.each, $util] */ var MooTools = { - 'version': '1.2.6', - 'build': 'a3be7a0ef5205eb655c4ee11e8cbedcb3f2ffa95' + 'version': '1.2.7dev', + 'build': '%build%' }; var Native = function(options){