<\/div>awright/i);
56 | },
57 |
58 | "test should set style properties": function () {
59 | var el = div({ style: { position: "relative" } });
60 |
61 | assert.equals(el.style.position, "relative");
62 | },
63 |
64 | "test should create element event handler": function () {
65 | var spy = this.spy();
66 | var el = div({ events: { click: spy } });
67 | document.body.appendChild(el);
68 |
69 | $(el).trigger("click");
70 |
71 | assert.calledOnce(spy);
72 | },
73 |
74 | "test should create element with customly handled atrribute": function () {
75 | elementBuilder.attrHandlers["for"] = function (el, attr) {
76 | el.htmlFor = attr;
77 | };
78 |
79 | var el = div({ "for": "somebody" });
80 |
81 | assert.equals(el.htmlFor, "somebody");
82 | },
83 |
84 | "test should create div element directly": function () {
85 | var div = FINN.elementBuilder.build("div", { className: "Yay" });
86 | assert.tagName(div, "div");
87 | assert.className(div, "Yay");
88 | },
89 |
90 | "test should create group of elements as fragment": function () {
91 | var group = FINN.fragment(div({ id: "d1" }), div({ id: "d2" }));
92 | var myDiv = div(group);
93 |
94 | assert.equals(myDiv.childNodes.length, 2);
95 | assert.equals(myDiv.firstChild.id, "d1");
96 | },
97 |
98 | "test should create array of elements as fragment": function () {
99 | var group = FINN.fragment([div({ id: "d1" }), div({ id: "d2" })]);
100 | var myDiv = div(group);
101 |
102 | assert.equals(myDiv.childNodes.length, 2);
103 | assert.equals(myDiv.firstChild.id, "d1");
104 | }
105 | }));
106 |
107 | testCase("ElementBuilderModuleTest", sinon.testCase({
108 | "test should create .mod div": function () {
109 | var mod = elementBuilder.mod();
110 |
111 | assert.tagName(mod, "div");
112 | assert.className(mod, "mod");
113 | },
114 |
115 | "test should add module type": function () {
116 | var mod = elementBuilder.mod("2nd");
117 |
118 | assert.className(mod, "mod_2nd");
119 | },
120 |
121 | "test should add body-div": function () {
122 | var mod = elementBuilder.mod();
123 |
124 | assert.equals(mod.childNodes.length, 1);
125 | assert.tagName(mod.firstChild, "div");
126 | assert.className(mod.firstChild, "bd");
127 | },
128 |
129 | "test should add more elements": function () {
130 | var mod = elementBuilder.mod("1st", div(), p());
131 | var bd = mod.firstChild;
132 |
133 | assert.equals(bd.childNodes.length, 2);
134 | assert.tagName(bd.firstChild, "div");
135 | assert.tagName(bd.lastChild, "p");
136 | }
137 | }));
138 |
139 | }(FINN.elementBuilder));
140 |
--------------------------------------------------------------------------------
/test/lib/buster/buster-format.js:
--------------------------------------------------------------------------------
1 | var buster = this.buster || {};
2 |
3 | if (typeof require != "undefined") {
4 | buster = require("buster-core");
5 | }
6 |
7 | buster.format = buster.format || {};
8 | buster.format.excludeConstructors = ["Object", /^.$/];
9 | buster.format.quoteStrings = true;
10 |
11 | buster.format.ascii = (function () {
12 | function keys(object) {
13 | var k = Object.keys && Object.keys(object) || [];
14 |
15 | if (k.length == 0) {
16 | for (var prop in object) {
17 | if (object.hasOwnProperty(prop)) {
18 | k.push(prop);
19 | }
20 | }
21 | }
22 |
23 | return k.sort();
24 | }
25 |
26 | function isCircular(object, objects) {
27 | if (typeof object != "object") {
28 | return false;
29 | }
30 |
31 | for (var i = 0, l = objects.length; i < l; ++i) {
32 | if (objects[i] === object) {
33 | return true;
34 | }
35 | }
36 |
37 | return false;
38 | }
39 |
40 | function ascii(object, processed, indent) {
41 | if (typeof object == "string") {
42 | var quote = typeof this.quoteStrings != "boolean" || this.quoteStrings;
43 | return processed || quote ? '"' + object + '"' : object;
44 | }
45 |
46 | if (typeof object == "function" && !(object instanceof RegExp)) {
47 | return ascii.func(object);
48 | }
49 |
50 | processed = processed || [];
51 |
52 | if (isCircular(object, processed)) {
53 | return "[Circular]";
54 | }
55 |
56 | if (Object.prototype.toString.call(object) == "[object Array]") {
57 | return ascii.array(object);
58 | }
59 |
60 | if (!object) {
61 | return "" + object;
62 | }
63 |
64 | if (buster.isElement(object)) {
65 | return ascii.element(object);
66 | }
67 |
68 | if (object.toString !== Object.prototype.toString) {
69 | return object.toString();
70 | }
71 |
72 | return ascii.object.call(this, object, processed, indent);
73 | }
74 |
75 | ascii.func = function (func) {
76 | return "function " + buster.functionName(func) + "() {}";
77 | };
78 |
79 | ascii.array = function (array, processed) {
80 | processed = processed || [];
81 | processed.push(array);
82 | var pieces = [];
83 |
84 | for (var i = 0, l = array.length; i < l; ++i) {
85 | pieces.push(ascii(array[i], processed));
86 | }
87 |
88 | return "[" + pieces.join(", ") + "]";
89 | };
90 |
91 | ascii.object = function (object, processed, indent) {
92 | processed = processed || [];
93 | processed.push(object);
94 | indent = indent || 0;
95 | var pieces = [], properties = keys(object), prop, str, obj;
96 | var is = "";
97 | var length = 3;
98 |
99 | for (var i = 0, l = indent; i < l; ++i) {
100 | is += " ";
101 | }
102 |
103 | for (i = 0, l = properties.length; i < l; ++i) {
104 | prop = properties[i];
105 | obj = object[prop];
106 |
107 | if (isCircular(obj, processed)) {
108 | str = "[Circular]";
109 | } else {
110 | str = ascii.call(this, obj, processed, indent + 2);
111 | }
112 |
113 | str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
114 | length += str.length;
115 | pieces.push(str);
116 | }
117 |
118 | var cons = ascii.constructorName.call(this, object);
119 | var prefix = cons ? "[" + cons + "] " : ""
120 |
121 | return (length + indent) > 80 ?
122 | prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" + is + "}" :
123 | prefix + "{ " + pieces.join(", ") + " }";
124 | };
125 |
126 | ascii.element = function (element) {
127 | var tagName = element.tagName.toLowerCase();
128 | var attrs = element.attributes, attribute, pairs = [], attrName;
129 |
130 | for (var i = 0, l = attrs.length; i < l; ++i) {
131 | attribute = attrs.item(i);
132 | attrName = attribute.nodeName.toLowerCase().replace("html:", "");
133 |
134 | if (attrName == "contenteditable" && attribute.nodeValue == "inherit") {
135 | continue;
136 | }
137 |
138 | if (!!attribute.nodeValue) {
139 | pairs.push(attrName + "=\"" + attribute.nodeValue + "\"");
140 | }
141 | }
142 |
143 | var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
144 | var content = element.innerHTML;
145 |
146 | if (content.length > 20) {
147 | content = content.substr(0, 20) + "[...]";
148 | }
149 |
150 | var res = formatted + pairs.join(" ") + ">" + content + "" + tagName + ">";
151 |
152 | return res.replace(/ contentEditable="inherit"/, "");
153 | };
154 |
155 | ascii.constructorName = function (object) {
156 | var name = buster.functionName(object && object.constructor);
157 | var excludes = this.excludeConstructors || buster.format.excludeConstructors || [];
158 |
159 | for (var i = 0, l = excludes.length; i < l; ++i) {
160 | if (typeof excludes[i] == "string" && excludes[i] == name) {
161 | return "";
162 | } else if (excludes[i].test && excludes[i].test(name)) {
163 | return "";
164 | }
165 | }
166 |
167 | return name;
168 | };
169 |
170 | return ascii;
171 | }());
172 |
173 | if (typeof module != "undefined") {
174 | module.exports = buster.format;
175 | }
176 |
--------------------------------------------------------------------------------
/src/lib/bane/bane.js:
--------------------------------------------------------------------------------
1 | ((typeof define === "function" && define.amd && function (m) { define("bane", m); }) ||
2 | (typeof module === "object" && function (m) { module.exports = m(); }) ||
3 | function (m) { this.bane = m(); }
4 | )(function () {
5 | "use strict";
6 | var slice = Array.prototype.slice;
7 |
8 | function handleError(event, error, errbacks) {
9 | var i, l = errbacks.length;
10 | if (l > 0) {
11 | for (i = 0; i < l; ++i) { errbacks[i](event, error); }
12 | return;
13 | }
14 | setTimeout(function () {
15 | error.message = event + " listener threw error: " + error.message;
16 | throw error;
17 | }, 0);
18 | }
19 |
20 | function assertFunction(fn) {
21 | if (typeof fn !== "function") {
22 | throw new TypeError("Listener is not function");
23 | }
24 | return fn;
25 | }
26 |
27 | function supervisors(object) {
28 | if (!object.supervisors) { object.supervisors = []; }
29 | return object.supervisors;
30 | }
31 |
32 | function listeners(object, event) {
33 | if (!object.listeners) { object.listeners = {}; }
34 | if (event && !object.listeners[event]) { object.listeners[event] = []; }
35 | return event ? object.listeners[event] : object.listeners;
36 | }
37 |
38 | function errbacks(object) {
39 | if (!object.errbacks) { object.errbacks = []; }
40 | return object.errbacks;
41 | }
42 |
43 | /**
44 | * @signature var emitter = bane.createEmitter([object]);
45 | *
46 | * Create a new event emitter. If an object is passed, it will be modified
47 | * by adding the event emitter methods (see below).
48 | */
49 | function createEventEmitter(object) {
50 | object = object || {};
51 |
52 | function notifyListener(event, listener, args) {
53 | try {
54 | listener.listener.apply(listener.thisp || object, args);
55 | } catch (e) {
56 | handleError(event, e, errbacks(object));
57 | }
58 | }
59 |
60 | object.on = function (event, listener, thisp) {
61 | if (typeof event === "function") {
62 | return supervisors(this).push({
63 | listener: event,
64 | thisp: listener
65 | });
66 | }
67 | listeners(this, event).push({
68 | listener: assertFunction(listener),
69 | thisp: thisp
70 | });
71 | };
72 |
73 | object.off = function (event, listener) {
74 | var fns, events, i, l;
75 | if (!event) {
76 | fns = supervisors(this);
77 | fns.splice(0, fns.length);
78 |
79 | events = listeners(this);
80 | for (i in events) {
81 | if (events.hasOwnProperty(i)) {
82 | fns = listeners(this, i);
83 | fns.splice(0, fns.length);
84 | }
85 | }
86 |
87 | fns = errbacks(this);
88 | fns.splice(0, fns.length);
89 |
90 | return;
91 | }
92 | if (typeof event === "function") {
93 | fns = supervisors(this);
94 | listener = event;
95 | } else {
96 | fns = listeners(this, event);
97 | }
98 | if (!listener) {
99 | fns.splice(0, fns.length);
100 | return;
101 | }
102 | for (i = 0, l = fns.length; i < l; ++i) {
103 | if (fns[i].listener === listener) {
104 | fns.splice(i, 1);
105 | return;
106 | }
107 | }
108 | };
109 |
110 | object.once = function (event, listener, thisp) {
111 | var wrapper = function () {
112 | object.off(event, wrapper);
113 | listener.apply(this, arguments);
114 | };
115 |
116 | object.on(event, wrapper, thisp);
117 | };
118 |
119 | object.bind = function (object, events) {
120 | var prop, i, l;
121 | if (!events) {
122 | for (prop in object) {
123 | if (typeof object[prop] === "function") {
124 | this.on(prop, object[prop], object);
125 | }
126 | }
127 | } else {
128 | for (i = 0, l = events.length; i < l; ++i) {
129 | if (typeof object[events[i]] === "function") {
130 | this.on(events[i], object[events[i]], object);
131 | } else {
132 | throw new Error("No such method " + events[i]);
133 | }
134 | }
135 | }
136 | return object;
137 | };
138 |
139 | object.emit = function (event) {
140 | var toNotify = supervisors(this);
141 | var args = slice.call(arguments), i, l;
142 |
143 | for (i = 0, l = toNotify.length; i < l; ++i) {
144 | notifyListener(event, toNotify[i], args);
145 | }
146 |
147 | toNotify = listeners(this, event).slice();
148 | args = slice.call(arguments, 1);
149 | for (i = 0, l = toNotify.length; i < l; ++i) {
150 | notifyListener(event, toNotify[i], args);
151 | }
152 | };
153 |
154 | object.errback = function (listener) {
155 | if (!this.errbacks) { this.errbacks = []; }
156 | this.errbacks.push(assertFunction(listener));
157 | };
158 |
159 | return object;
160 | }
161 |
162 | return { createEventEmitter: createEventEmitter };
163 | });
164 |
--------------------------------------------------------------------------------
/src/finn/carousel/horizontalSlider.js:
--------------------------------------------------------------------------------
1 | /*! carousel-js - 2013-06-14. Copyright (c) 2013 FINN.no AS - http://finn.no/; Licensed MIT */
2 | FINN.carousel = FINN.carousel || {};
3 |
4 | (function (C, $) {
5 | "use strict";
6 |
7 | var div = FINN.elementBuilder("div");
8 | var transition;
9 |
10 | var LEFT = -1, RIGHT = 1;
11 | var TRANSITION_TYPES = {
12 | "WebkitTransition": { endEvent: "webkitTransitionEnd", cssStyle: "-webkit-transition" },
13 | "MozTransition": { endEvent: "transitionend", cssStyle: "-moz-transition" },
14 | "OTransition": { endEvent: "oTransitionEnd", cssStyle: "-o-transition" },
15 | "msTransition": { endEvent: "MSTransitionEnd", cssStyle: "-ms-transition" }, // correct endEvent?
16 | "transition": { endEvent: "transitionend", cssStyle: "transition" }
17 | };
18 |
19 | function countSteps(skipSteps, direction, newDirection) {
20 | if (direction !== newDirection) {
21 | return 1;
22 | } else {
23 | return skipSteps + 1;
24 | }
25 | }
26 |
27 | function animate(pos, callback) {
28 | $(this.element).css("left", pos.from + "px");
29 | this.startPos = pos.from;
30 |
31 | if (supportsCssTransitions()) {
32 | return slideWithCss.call(this, pos, callback);
33 | }
34 |
35 | return slideWithJquery.call(this, pos, callback);
36 | }
37 |
38 | function slideWithJquery(pos, callback) {
39 | var opt = $.extend({}, this.animOpt, {
40 | complete: this.animationCallback(callback)
41 | });
42 | var props = { left: pos.to + "px" };
43 |
44 | this.animation = $(this.element).animate(props, opt);
45 | return this.animation;
46 | }
47 |
48 | function slideWithCss(pos, callback) {
49 | var duration = (this.animOpt.duration / 1000) + "s";
50 |
51 | $(this.element).css('left'); // causes necessary reflow
52 |
53 | $(this.element).one(transition.endEvent, this.animationCallback(callback))
54 | .css(transition.cssStyle, "left " + duration)
55 | .css("left", pos.to + "px");
56 |
57 | this.animation = $(this.element);
58 | return this.animation;
59 | }
60 |
61 | function resolveSupportedTransition() {
62 | for (var transitionType in TRANSITION_TYPES) {
63 | if (!TRANSITION_TYPES.hasOwnProperty(transitionType)) {
64 | continue;
65 | }
66 |
67 | if (document.body && typeof document.body.style[transitionType] !== 'undefined') {
68 | transition = TRANSITION_TYPES[transitionType];
69 | break;
70 | }
71 | }
72 | }
73 |
74 | function supportsCssTransitions() {
75 | return (typeof transition !== "undefined");
76 | }
77 |
78 | C.horizontalSlider = FINN.compose(C.animator, {
79 | create: function (element, animOpt) {
80 | var frame = FINN.compose(this, {
81 | width: $(element).width(),
82 | direction: LEFT,
83 | animOpt: animOpt,
84 | element: div({ className: "frame" })
85 | });
86 | $(frame.element).css({ position: "relative", top: 0 });
87 | frame.append(element);
88 | frame.skipSteps = 0;
89 | resolveSupportedTransition();
90 | return frame;
91 | },
92 |
93 | destination: function (forcedTo) {
94 | var offset = this.width * this.skipSteps;
95 | var pos = { from: 0, to: -offset, backwards: false };
96 | if (this.headedLeft()) {
97 | pos = { from: -offset, to: 0 };
98 | }
99 | if (this.animation) {
100 | pos.from = parseInt(this.animation.css("left"), 10);
101 | }
102 | if (typeof forcedTo === "number") { pos.to = forcedTo; }
103 | if (pos.from < pos.to) { pos.backwards = true; }
104 | return pos;
105 | },
106 |
107 | registerElement: function (element) {
108 | element.style.width = this.width + "px";
109 | element.style.cssFloat = "left";
110 | var newWidth = $(this.element).width() + this.width;
111 | this.element.style.width = newWidth + "px";
112 | this.previousContent = this.contentElement;
113 | this.contentElement = element;
114 | },
115 |
116 | append: function (element) {
117 | this.element.appendChild(element);
118 | this.registerElement(element);
119 | this.skipSteps = countSteps(this.skipSteps, this.direction, RIGHT);
120 | this.direction = RIGHT;
121 | },
122 |
123 | prepend: function (element) {
124 | this.element.insertBefore(element, this.element.firstChild);
125 | this.registerElement(element);
126 | var leftPos = parseInt($(this.element).css("left") || 0, 10);
127 | $(this.element).css("left", (leftPos - this.width));
128 | this.skipSteps = countSteps(this.skipSteps, this.direction, LEFT);
129 | this.direction = LEFT;
130 | },
131 |
132 | animate: function (callback) {
133 | this.stopAnimation();
134 | return animate.call(this, this.destination(), callback);
135 | },
136 |
137 | animationCallback: function (callback) {
138 | var self = this;
139 | return function () {
140 | callback(self.contentElement);
141 | delete self.startPos;
142 | };
143 | },
144 |
145 | revertAnimation: function (cb) {
146 | this.stopAnimation();
147 | this.contentElement = this.previousContent;
148 | return animate.call(this, this.destination(this.startPos), cb);
149 | },
150 |
151 | headedLeft: function () {
152 | return this.direction === LEFT;
153 | }
154 | });
155 | }(FINN.carousel, jQuery));
--------------------------------------------------------------------------------
/test/lib/sinon/sinon-buster.js:
--------------------------------------------------------------------------------
1 | /*jslint onevar: false, eqeqeq: false*/
2 | /*global require*/
3 | if (typeof require != "undefined") {
4 | var sinon = require("sinon");
5 |
6 | var buster = {
7 | assertions: require("buster-assertions"),
8 | format: require("buster-format"),
9 | testRunner: require("buster-test").testRunner,
10 | stackFilter: require("buster-test").stackFilter
11 | };
12 | }
13 |
14 | if (buster.stackFilter && buster.stackFilter.filters) {
15 | buster.stackFilter.filters.push("lib/sinon");
16 | }
17 |
18 | (function (ba) {
19 | if (buster.testRunner) {
20 | buster.testRunner.onCreate(function (runner) {
21 | runner.on("test:setUp", function (test) {
22 | var config = sinon.getConfig(sinon.config);
23 | config.useFakeServer = false;
24 | var sandbox = sinon.sandbox.create();
25 | sandbox.inject(test.testCase);
26 |
27 | test.testCase.useFakeTimers = function () {
28 | return sandbox.useFakeTimers.apply(sandbox, arguments);
29 | };
30 |
31 | test.testCase.sandbox = sandbox;
32 | var testFunc = test.func;
33 | });
34 |
35 | runner.on("test:tearDown", function (test) {
36 | try {
37 | test.testCase.sandbox.verifyAndRestore();
38 | } catch (e) {
39 | runner.error(e, test);
40 | }
41 | });
42 | });
43 | }
44 |
45 | if (buster.format) {
46 | var formatter = buster.create(buster.format);
47 | formatter.quoteStrings = false;
48 | sinon.format = function format() {
49 | return formatter.ascii.apply(formatter, arguments);
50 | };
51 | }
52 |
53 | if (!ba) { return; }
54 |
55 | // Sinon assertions for buster
56 | function verifyFakes() {
57 | var method, isNot;
58 |
59 | for (var i = 0, l = arguments.length; i < l; ++i) {
60 | method = arguments[i];
61 | isNot = (method || "fake") + " is not ";
62 |
63 | if (!method) this.fail(isNot + "a spy");
64 | if (typeof method != "function") this.fail(isNot + "a function");
65 | if (typeof method.getCall != "function") this.fail(isNot + "stubbed");
66 | }
67 |
68 | return true;
69 | }
70 |
71 | var sf = sinon.spy.formatters;
72 | var spyValues = function (spy) { return [spy, sf.c(spy), sf.C(spy)]; };
73 |
74 | ba.add("called", {
75 | assert: function (spy) {
76 | verifyFakes.call(this, spy);
77 | return spy.called;
78 | },
79 | assertMessage: "Expected ${0} to be called at least once but was never called",
80 | refuteMessage: "Expected ${0} to not be called but was called ${1}${2}",
81 | expectation: "toBeCalled",
82 | values: spyValues
83 | });
84 |
85 | function slice(arr, from, to) {
86 | return [].slice.call(arr, from, to);
87 | }
88 |
89 | ba.add("callOrder", {
90 | assert: function (spy) {
91 | verifyFakes.apply(this, arguments);
92 | if (sinon.calledInOrder(arguments)) return true;
93 |
94 | this.expected = [].join.call(arguments, ", ");
95 | this.actual = sinon.orderByFirstCall(slice(arguments)).join(", ");
96 | },
97 |
98 | assertMessage: "Expected ${expected} to be called in order but were called as ${actual}",
99 | refuteMessage: "Expected ${expected} not to be called in order"
100 | });
101 |
102 | function addCallCountAssertion(count) {
103 | var c = count.toLowerCase();
104 |
105 | ba.add("called" + count, {
106 | assert: function (spy) {
107 | verifyFakes.call(this, spy);
108 | return spy["called" + count];
109 | },
110 | assertMessage: "Expected ${0} to be called " + c + " but was called ${1}${2}",
111 | refuteMessage: "Expected ${0} to not be called exactly " + c + "${2}",
112 | expectation: "toBeCalled" + count,
113 | values: spyValues
114 | });
115 | }
116 |
117 | addCallCountAssertion("Once");
118 | addCallCountAssertion("Twice");
119 | addCallCountAssertion("Thrice");
120 |
121 | function valuesWithThis(spy, thisObj) {
122 | return [spy, thisObj, spy.printf && spy.printf("%t") || ""];
123 | }
124 |
125 | ba.add("calledOn", {
126 | assert: function (spy, thisObj) {
127 | verifyFakes.call(this, spy);
128 | return spy.calledOn(thisObj);
129 | },
130 | assertMessage: "Expected ${0} to be called with ${1} as this but was called on ${2}",
131 | refuteMessage: "Expected ${0} not to be called with ${1} as this",
132 | expectation: "toBeCalledOn",
133 | values: valuesWithThis
134 | });
135 |
136 | ba.add("alwaysCalledOn", {
137 | assert: function (spy, thisObj) {
138 | verifyFakes.call(this, spy);
139 | return spy.alwaysCalledOn(thisObj);
140 | },
141 | assertMessage: "Expected ${0} to always be called with ${1} as this but was called on ${2}",
142 | refuteMessage: "Expected ${0} not to always be called with ${1} as this",
143 | expectation: "toAlwaysBeCalledOn",
144 | values: valuesWithThis
145 | });
146 |
147 | function formattedArgs(args, i) {
148 | for (var l = args.length, result = []; i < l; ++i) {
149 | result.push(sinon.format(args[i]));
150 | }
151 |
152 | return result.join(", ");
153 | }
154 |
155 | function spyAndCalls(spy) {
156 | return [spy, formattedArgs(arguments, 1), spy.printf && spy.printf("%C")];
157 | }
158 |
159 | ba.add("calledWith", {
160 | assert: function (spy) {
161 | verifyFakes.call(this, spy);
162 | return spy.calledWith.apply(spy, slice(arguments, 1));
163 | },
164 | assertMessage: "Expected ${0} to be called with arguments ${1}${2}",
165 | refuteMessage: "Expected ${0} not to be called with arguments ${1}${2}",
166 | expectation: "toBeCalledWith",
167 | values: spyAndCalls
168 | });
169 |
170 | ba.add("alwaysCalledWith", {
171 | assert: function (spy) {
172 | verifyFakes.call(this, spy);
173 | return spy.alwaysCalledWith.apply(spy, slice(arguments, 1));
174 | },
175 | assertMessage: "Expected ${0} to always be called with arguments ${1}${2}",
176 | refuteMessage: "Expected ${0} not to always be called with arguments${1}${2}",
177 | expectation: "toAlwaysBeCalledWith",
178 | values: spyAndCalls
179 | });
180 |
181 | ba.add("calledOnceWith", {
182 | assert: function (spy) {
183 | verifyFakes.call(this, spy);
184 | return spy.calledOnce && spy.calledWith.apply(spy, slice(arguments, 1));
185 | },
186 | assertMessage: "Expected ${0} to be called once with arguments ${1}${2}",
187 | refuteMessage: "Expected ${0} not to be called once with arguments ${1}${2}",
188 | expectation: "toBeCalledWith",
189 | values: spyAndCalls
190 | });
191 |
192 | ba.add("calledWithExactly", {
193 | assert: function (spy) {
194 | verifyFakes.call(this, spy);
195 | return spy.calledWithExactly.apply(spy, slice(arguments, 1));
196 | },
197 | assertMessage: "Expected ${0} to be called with exact arguments ${1}${2}",
198 | refuteMessage: "Expected ${0} not to be called with exact arguments${1}${2}",
199 | expectation: "toBeCalledWithExactly",
200 | values: spyAndCalls
201 | });
202 |
203 | ba.add("alwaysCalledWithExactly", {
204 | assert: function (spy) {
205 | verifyFakes.call(this, spy);
206 | return spy.alwaysCalledWithExactly.apply(spy, slice(arguments, 1));
207 | },
208 | assertMessage: "Expected ${0} to always be called with exact arguments ${1}${2}",
209 | refuteMessage: "Expected ${0} not to always be called with exact arguments${1}${2}",
210 | expectation: "toAlwaysBeCalledWithExactly",
211 | values: spyAndCalls
212 | });
213 |
214 | function spyAndException(spy, exception) {
215 | return [spy, spy.printf && spy.printf("%C")];
216 | }
217 |
218 | ba.add("threw", {
219 | assert: function (spy) {
220 | verifyFakes.call(this, spy);
221 | return spy.threw(arguments[1]);
222 | },
223 | assertMessage: "Expected ${0} to throw an exception${1}",
224 | refuteMessage: "Expected ${0} not to throw an exception${1}",
225 | expectation: "toHaveThrown",
226 | values: spyAndException
227 | });
228 |
229 | ba.add("alwaysThrew", {
230 | assert: function (spy) {
231 | verifyFakes.call(this, spy);
232 | return spy.alwaysThrew(arguments[1]);
233 | },
234 | assertMessage: "Expected ${0} to always throw an exception${1}",
235 | refuteMessage: "Expected ${0} not to always throw an exception${1}",
236 | expectation: "toAlwaysHaveThrown",
237 | values: spyAndException
238 | });
239 | }(buster.assertions));
240 |
--------------------------------------------------------------------------------
/dist/carousel-1.0.0.min.js:
--------------------------------------------------------------------------------
1 | /*! carousel - v1.0.0 - 2013-06-14. Copyright (c) 2013 FINN.no AS - http://finn.no/; Licensed MIT */
2 | var FINN=FINN||{};!function(a){"use strict";"function"!=typeof Object.create&&(Object.create=function(a){function b(){}return b.prototype=a,new b}),a.create=function(a){return Object.create(a)},a.compose=function(){if(0===arguments.length||!arguments[0])throw new TypeError("compose expects at least one object argument");var a,b,c,d=FINN.create(arguments[0]);for(a=1,b=arguments.length;b>a;++a){if(!arguments[a])throw new TypeError("Tried to compose null or undefined");for(c in arguments[a])d[c]=arguments[a][c]}return d}}(FINN),function(a,b){"use strict";a.fragment=function(){for(var a=document.createDocumentFragment(),c=b.isArray(arguments[0])?arguments[0]:arguments,d=0,e=c.length;e>d;++d)c[d]&&a.appendChild(c[d]);return a};var c=11,d=a.elementBuilder=function(a){return function(b){var e=1,f=b;return(!b||b.tagName||b.nodeType===c||"string"==typeof b)&&(e=0,f={}),d.addContent(d.attr(document.createElement(a),f),[].slice.call(arguments,e))}};a.elementBuilder.build=function(b){return a.elementBuilder(b).apply(null,[].slice.call(arguments,1))},d.attr=function(a,b){var c,e;for(c in b)b.hasOwnProperty(c)&&(e=d.attrHandlers[c],e?e(a,b[c]):a[c]=b[c]);return a},d.addContent=function(a,b){for(var c=0,d=b.length;d>c;++c)"string"==typeof b[c]?a.appendChild(document.createTextNode(b[c])):a.appendChild(b[c]);return a},d.attrHandlers={events:function(a,c){var d=b(a);for(var e in c)c.hasOwnProperty(e)&&d.bind(e,c[e])},style:function(a,c){b(a).css(c)}};var e=d("div");d.mod=function(a){return e({className:"mod mod_"+a},d.addContent(e({className:"bd"}),[].slice.call(arguments,1)))}}(FINN,jQuery),FINN.carousel=FINN.carousel||{},function(a,b){"use strict";var c=FINN.elementBuilder("div");a.animatedProjector={create:function(b,c,d){var e=FINN.compose(this,{data:c,options:d||{},animator:d.animator||a.horizontalSlider,currentId:0,queue:[]});return b.on("show",function(){return e.show.apply(e,arguments)}),e},buildCarousel:function(a){var b=this.carousel=c({className:"carousel"}),d=this;return this.data.get(0,function(e){d.mainFrame=c({className:"frame"}),d.mainFrame.appendChild(e),d.viewport=c({className:"viewport"},d.mainFrame),d.viewport.style.position="relative",d.viewport.style.overflow="hidden",b.appendChild(d.viewport),"function"==typeof a&&a(b)}),b},show:function(a){if(this.isAnimating()||a!==this.currentId){var b=this,c=function(){return b.animationComplete.apply(b,[a].concat([].slice.call(arguments)))};return this.currTarget=a,a===this.currentId?this.animationFrame().revertAnimation(c):(this.data.get(a,function(d){b.addElementToFrame(d,a),b.animationFrame().animate(c)}),void 0)}},isAnimating:function(){return"number"==typeof this.currTarget},animationComplete:function(a,b){this.currentId=a,delete this.currTarget,this.display(b.innerHTML),this.finishAnimation()},animationFrame:function(){if(!this._animFrame){var a=this.mainFrame.firstChild.cloneNode(!0);a.style.width=b(this.mainFrame).css("width"),this._animFrame=this.animator.create(a,this.options),this.viewport.appendChild(this._animFrame.element),this.mainFrame.firstChild.innerHTML=""}return this._animFrame},finishAnimation:function(){this._animFrame&&(this._animFrame.detach(),delete this._animFrame),delete this.animation},isAnimatingBackwards:function(a){var b=this.data.size()-1,c=0===this.currentId&&a===b||this.currentId===b&&0===a;return c&&b>1?a>0:a
this.currentId?!1:a=c.size()-1)};b.on("show",g),g(b.currentId)}}(jQuery,FINN.carousel),FINN.carousel=FINN.carousel||{},function(a){"use strict";function b(a){var b=$(a.target).data("gallery-url");b&&(document.location=b)}a.setupClickToGallery=function(a){$(a).on("click",b)}}(FINN.carousel),function(a){"use strict";a.setupClickableElementNavigation=function(a,b,c,d,e){var f=d||"selectedElement",g=function(a){return $(a).index()};e&&(g=e),$(b).delegate(c,"click",function(){a.show(g(this))}),$(b).find(c).css("cursor","pointer"),a.on("show",function(a){$(b).children().removeClass(f).eq(a).addClass(f)})}}(FINN.carousel),FINN.carousel=FINN.carousel||{},function(a){"use strict";a.controller=bane.createEventEmitter({create:function(a){return FINN.compose(this,{seq:a,currentId:0})},start:function(a){this.currentId=-1,this.show(+a||0)},show:function(a){0>a||!this.seq.contains(a)||this.currentId===a||(this.currentId=a,this.emit("show",a))},peek:function(){return this.currentId},setCurrentId:function(a){this.currentId=a},next:function(){this.show(this.currentId+1)},prev:function(){var a="number"==typeof this.currentId?this.currentId-1:0;this.show(a)}})}(FINN.carousel),function(a){"use strict";a.setupDottedIndexDisplayer=function(a){function b(){for(var a="",b=0;b'}c.innerHTML=a}if(!a)throw new TypeError("Params must be given");var c=a.root,d=a.list,e=a.controller;b(),e.on("show",b)}}(FINN.carousel),FINN.carousel=FINN.carousel||{},function(a,b){"use strict";function c(a,c){return c>=0?b(a).children().get(c):!1}a.elementList={isBounded:!0,create:function(a){return FINN.compose(this,{element:a})},size:function(){return b(this.element).children().length},contains:function(a){return!!c(this.element,a)},get:function(a,d){var e=c(this.element,a);d(b(e).clone().get(0))}}}(FINN.carousel,jQuery),FINN.carousel=FINN.carousel||{},function(a){"use strict";a.emptyList={isBounded:!1,create:function(a){a=a||{};var b=FINN.compose(this,a);return a.get&&(b.get=function(b,c){var d=a.get.call(this,b,c);"undefined"!=typeof d&&c(d)}),b},size:function(){return 0},contains:function(){return!1},get:function(){}}}(FINN.carousel,_),FINN.carousel=FINN.carousel||{},function(a,b){"use strict";var c=FINN.elementBuilder("div");a.fader=FINN.compose(a.animator,{create:function(a,d){return FINN.compose(this,{animOpt:b.extend({duration:150},d),element:c({className:"frame",style:{position:"relative",display:"none"}},a)})},append:function(a){b(a).css({position:"absolute",left:0,top:0,display:"none"});for(var c=this.element.firstChild.nextSibling;c;)c.parentNode.removeChild(c),c=c.nextSibling;this.element.appendChild(a)},animate:function(a){this.stopAnimation(),b(this.element).css("display","block");var c=this.animOpt.duration;this.animation=b(this.element.lastChild).fadeIn(c,function(){a(this.element.lastChild)}.bind(this))},revertAnimation:function(a){this.stopAnimation();var c=this.animOpt.duration;this.animation=b(this.element.lastChild).fadeOut(c,function(){a(this.element.firstChild)}.bind(this))}})}(FINN.carousel,jQuery),FINN.carousel=FINN.carousel||{},function(a,b){"use strict";function c(){var a=document.documentElement;a.requestFullscreen?a.requestFullscreen():a.mozRequestFullScreen?a.mozRequestFullScreen():a.webkitRequestFullScreen&&a.webkitRequestFullScreen()}a.hasFullscreenSupport=function(){var a=document.documentElement;return a.requestFullscreen?!0:a.mozRequestFullScreen?!0:a.webkitRequestFullScreen?!0:!1},a.setupFullscreenSupport=function(a){var d=document.getElementById(a);d&&d.addEventListener("click",function(){b("#"+a).hide(),c()},!1),document.addEventListener("fullscreenchange",function(){document.fullscreen||b("#"+a).show()},!1),document.addEventListener("mozfullscreenchange",function(){document.mozFullScreen||b("#"+a).show()},!1),document.addEventListener("webkitfullscreenchange",function(){document.webkitIsFullScreen||b("#"+a).show()},!1)},a.setupKeyboardShortcut=function(){b(document).bind("keyup",function(a){a&&(console.log(a.which),70===a.which&&c())})}}(FINN.carousel,jQuery),FINN.carousel=FINN.carousel||{},function(a,b){"use strict";function c(a,b,c){return b!==c?1:a+1}function d(a,c){return b(this.element).css("left",a.from+"px"),this.startPos=a.from,h()?f.call(this,a,c):e.call(this,a,c)}function e(a,c){var d=b.extend({},this.animOpt,{complete:this.animationCallback(c)}),e={left:a.to+"px"};return this.animation=b(this.element).animate(e,d),this.animation}function f(a,c){var d=this.animOpt.duration/1e3+"s";return b(this.element).css("left"),b(this.element).one(i.endEvent,this.animationCallback(c)).css(i.cssStyle,"left "+d).css("left",a.to+"px"),this.animation=b(this.element),this.animation}function g(){for(var a in m)if(m.hasOwnProperty(a)&&document.body&&"undefined"!=typeof document.body.style[a]){i=m[a];break}}function h(){return"undefined"!=typeof i}var i,j=FINN.elementBuilder("div"),k=-1,l=1,m={WebkitTransition:{endEvent:"webkitTransitionEnd",cssStyle:"-webkit-transition"},MozTransition:{endEvent:"transitionend",cssStyle:"-moz-transition"},OTransition:{endEvent:"oTransitionEnd",cssStyle:"-o-transition"},msTransition:{endEvent:"MSTransitionEnd",cssStyle:"-ms-transition"},transition:{endEvent:"transitionend",cssStyle:"transition"}};a.horizontalSlider=FINN.compose(a.animator,{create:function(a,c){var d=FINN.compose(this,{width:b(a).width(),direction:k,animOpt:c,element:j({className:"frame"})});return b(d.element).css({position:"relative",top:0}),d.append(a),d.skipSteps=0,g(),d},destination:function(a){var b=this.width*this.skipSteps,c={from:0,to:-b,backwards:!1};return this.headedLeft()&&(c={from:-b,to:0}),this.animation&&(c.from=parseInt(this.animation.css("left"),10)),"number"==typeof a&&(c.to=a),c.froma?a=this.seq.size()-1:0!==a&&this.seq.contains(a)&&this.currentId!==a||(a=0),this.currentId=a,this.emit("show",a)},prev:function(){var a="number"==typeof this.currentId?this.currentId-1:-1;this.show(a)}})}(FINN.carousel),function(a){"use strict";a.overlayProjector={create:function(a,b,c){return FINN.compose(this,{controller:a,data:b,view:c})},buildCarousel:function(){var a=this;return this.controller.on("show",function(){return a.show.apply(a,arguments)}),this.show(0),this.view},show:function(a){var b=this;this.data.get(a,function(a){b.view.innerHTML="",b.view.appendChild(a)})}}}(FINN.carousel),FINN.carousel=FINN.carousel||{},function(a,b){"use strict";function c(){return"-webkit-transform"in document.body.style}function d(a,c,d){for(var e=b(c).find(d),f=Math.ceil(e.length-6)/2,g=e[a],i=e.length,j=0,k=0;i>k;k++)k<=Math.ceil(f+1)||(b(g).before(b(e[k]).clone()),b(e[k]).remove(),j=++j);return console.log("newViewIndex",j),h=j+1,j}function e(a,c,d,e){var f=b(d).find(e),i=b(f[0]),j=f.length-1,k=f[j];b(d).find(".thumbwrap").removeClass("selectedThumb"),g(a,c)||0===c&&a===j?b(d).append(i):b(k).insertBefore(i),b(b(d).find(".thumbwrap")[h]).addClass("selectedThumb")}function f(a,d,e,f,g,h){f+=1;var i=b(d).find(e),j=b(i[f]),k=j.position(),l=b(d.parentNode.parentNode).parent().width(),m=j.outerWidth(!0),n=70,o=l/2-(m-j.width()),p=0;null!=k&&(p=k.left+n);var q={left:-1*p+o};b(d).find(".thumbwrap").removeClass("selected"),g===i.length-1&&0===f||0===g&&f===i.length-1?c()&&b("#thumbnails").css({"-webkit-transition":"all 0.0s ease-in-out","-webkit-transform":"translate3d("+q.left+"px,0,0)"}):c()?b("#thumbnails").css({"-webkit-transition":"all 0.4s","-webkit-transform":"translate3d("+q.left+"px,0,0)"}):b("#thumbnails").animate(q,376,"swing",function(){j.addClass("selected"),console.log("Added selected")}),h&&h.apply(null,this)}function g(a,b){return b>a}var h=0;a.setupScrollingThumbnailStrip=function(a,b,c){var g=!1,h=0,i=d(0,b,c,a);f(a,b,c,i,h),a.on("show",function(a){console.log("pushAndPop",h,a),e(h,a,b,c),h=a,g=!0})}}(FINN.carousel,jQuery),FINN.carousel=FINN.carousel||{},function(a){"use strict";a.setupSlideshow=function(a,b){var c;a.on("show",function(){clearTimeout(c),c=setTimeout(a.next.bind(a),b)})}}(FINN.carousel),function(a,b){"use strict";a.setupSplitProjectorNavigation=function(a,c){b(c).on("click",function(c){var d=b(this).offset().left,e=c.pageX,f=e-d,g=b(this).width()/2;g>=f?a.prev():a.next()})}}(FINN.carousel,jQuery),function(a,b){"use strict";a.setupThumbnailNavigation=function(c,d,e){a.setupClickableElementNavigation(c,d,"img","selectedThumb",e),a.setupClickNavigation(c,d,b(".thumbnails"))}}(FINN.carousel,jQuery),function(a){"use strict";function b(a){return{x:a.targetTouches[0].pageX,y:a.targetTouches[0].pageY}}a.setupTouchNavigation=function(a,c){var d;c.addEventListener("touchstart",function(a){a.touches.length>1||(d=b(a))},!1),c.addEventListener("touchmove",function(c){if(!d||c.touches.length>1)return d=null,void 0;var e=b(c),f=d.x-e.x,g=d.y-e.y;Math.abs(g)>Math.abs(f)||(c.preventDefault(),f>=30&&a.next(),-30>=f&&a.prev())},!1)}}(FINN.carousel);
--------------------------------------------------------------------------------
/test/lib/jquery-ui-1.8.13.custom.min.js:
--------------------------------------------------------------------------------
1 | // Core, Widget, Position, Autocomplete
2 | /*!
3 | * jQuery UI 1.8.13
4 | *
5 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6 | * Dual licensed under the MIT or GPL Version 2 licenses.
7 | * http://jquery.org/license
8 | *
9 | * http://docs.jquery.com/UI
10 | */
11 | (function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.13",
12 | keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();
13 | b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,
14 | "overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",
15 | function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,
16 | outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a,"tabindex"),d=isNaN(b);
17 | return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=
18 | 0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+=
48 | a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b),
49 | g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery);
50 | ;/*
51 | * jQuery UI Autocomplete 1.8.13
52 | *
53 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
54 | * Dual licensed under the MIT or GPL Version 2 licenses.
55 | * http://jquery.org/license
56 | *
57 | * http://docs.jquery.com/UI/Autocomplete
58 | *
59 | * Depends:
60 | * jquery.ui.core.js
61 | * jquery.ui.widget.js
62 | * jquery.ui.position.js
63 | */
64 | (function(d){var e=0;d.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var a=this,b=this.element[0].ownerDocument,g;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.attr("readonly"))){g=
65 | false;var f=d.ui.keyCode;switch(c.keyCode){case f.PAGE_UP:a._move("previousPage",c);break;case f.PAGE_DOWN:a._move("nextPage",c);break;case f.UP:a._move("previous",c);c.preventDefault();break;case f.DOWN:a._move("next",c);c.preventDefault();break;case f.ENTER:case f.NUMPAD_ENTER:if(a.menu.active){g=true;c.preventDefault()}case f.TAB:if(!a.menu.active)return;a.menu.select(c);break;case f.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!=
66 | a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);break}}}).bind("keypress.autocomplete",function(c){if(g){g=false;c.preventDefault()}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)};
67 | this.menu=d("").addClass("ui-autocomplete").appendTo(d(this.options.appendTo||"body",b)[0]).mousedown(function(c){var f=a.menu.element[0];d(c.target).closest(".ui-menu-item").length||setTimeout(function(){d(document).one("mousedown",function(h){h.target!==a.element[0]&&h.target!==f&&!d.ui.contains(f,h.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,f){f=f.item.data("item.autocomplete");false!==a._trigger("focus",c,{item:f})&&/^key/.test(c.originalEvent.type)&&
68 | a.element.val(f.value)},selected:function(c,f){var h=f.item.data("item.autocomplete"),i=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=i;setTimeout(function(){a.previous=i;a.selectedItem=h},1)}false!==a._trigger("select",c,{item:h})&&a.element.val(h.value);a.term=a.element.val();a.close(c);a.selectedItem=h},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");
69 | d.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();d.Widget.prototype.destroy.call(this)},_setOption:function(a,b){d.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(d(b||"body",this.element[0].ownerDocument)[0]);a==="disabled"&&
70 | b&&this.xhr&&this.xhr.abort()},_initSource:function(){var a=this,b,g;if(d.isArray(this.options.source)){b=this.options.source;this.source=function(c,f){f(d.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source==="string"){g=this.options.source;this.source=function(c,f){a.xhr&&a.xhr.abort();a.xhr=d.ajax({url:g,data:c,dataType:"json",autocompleteRequest:++e,success:function(h){this.autocompleteRequest===e&&f(h)},error:function(){this.autocompleteRequest===e&&f([])}})}}else this.source=
71 | this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length").data("item.autocomplete",b).append(d("").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});d.extend(d.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,
75 | "\\$&")},filter:function(a,b){var g=new RegExp(d.ui.autocomplete.escapeRegex(b),"i");return d.grep(a,function(c){return g.test(c.label||c.value||c)})}})})(jQuery);
76 | (function(d){d.widget("ui.menu",{_create:function(){var e=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(a){if(d(a.target).closest(".ui-menu-item a").length){a.preventDefault();e.select(a)}});this.refresh()},refresh:function(){var e=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex",
77 | -1).mouseenter(function(a){e.activate(a,d(this).parent())}).mouseleave(function(){e.deactivate()})},activate:function(e,a){this.deactivate();if(this.hasScroll()){var b=a.offset().top-this.element.offset().top,g=this.element.scrollTop(),c=this.element.height();if(b<0)this.element.scrollTop(g+b);else b>=c&&this.element.scrollTop(g+b-c+a.height())}this.active=a.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",e,{item:a})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id");
78 | this._trigger("blur");this.active=null}},next:function(e){this.move("next",".ui-menu-item:first",e)},previous:function(e){this.move("prev",".ui-menu-item:last",e)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(e,a,b){if(this.active){e=this.active[e+"All"](".ui-menu-item").eq(0);e.length?this.activate(b,e):this.activate(b,this.element.children(a))}else this.activate(b,
79 | this.element.children(a))},nextPage:function(e){if(this.hasScroll())if(!this.active||this.last())this.activate(e,this.element.children(".ui-menu-item:first"));else{var a=this.active.offset().top,b=this.element.height(),g=this.element.children(".ui-menu-item").filter(function(){var c=d(this).offset().top-a-b+d(this).height();return c<10&&c>-10});g.length||(g=this.element.children(".ui-menu-item:last"));this.activate(e,g)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active||
80 | this.last()?":first":":last"))},previousPage:function(e){if(this.hasScroll())if(!this.active||this.first())this.activate(e,this.element.children(".ui-menu-item:last"));else{var a=this.active.offset().top,b=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var g=d(this).offset().top-a+b-d(this).height();return g<10&&g>-10});result.length||(result=this.element.children(".ui-menu-item:first"));this.activate(e,result)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active||
81 | this.first()?":last":":first"))},hasScroll:function(){return this.element.height() 1 ? "s" : ""));
28 | return false;
29 | }
30 |
31 | return true;
32 | }
33 |
34 | function defineAssertion(type, name, func, fl, messageValues) {
35 | ba[type][name] = function () {
36 | var fullName = type + "." + name;
37 | countAssertion();
38 | if (!assertEnoughArguments(fullName, arguments, fl || func.length)) return;
39 |
40 | var failed = false;
41 |
42 | var ctx = {
43 | fail: function () {
44 | failed = true;
45 | var failArgs = [type, name].concat(slice.call(arguments));
46 | fail.apply(this, failArgs);
47 | return true;
48 | }
49 | };
50 |
51 | var args = slice.call(arguments, 0);
52 |
53 | if (typeof messageValues == "function") {
54 | args = messageValues.apply(this, args);
55 | }
56 |
57 | if (!func.apply(ctx, arguments)) {
58 | return fail.apply(ctx, [type, name, "message"].concat(args));
59 | }
60 |
61 | if (!failed) {
62 | ba.emit.apply(ba, ["pass", fullName].concat(args));
63 | }
64 | };
65 | }
66 |
67 | ba.add = function (name, options) {
68 | var refuteArgs;
69 |
70 | if (options.refute) {
71 | refuteArgs = options.refute.length;
72 | } else {
73 | refuteArgs = options.assert.length;
74 | options.refute = function () {
75 | return !options.assert.apply(this, arguments);
76 | };
77 | }
78 |
79 | var values = options && options.values; // TODO: Remove
80 | defineAssertion("assert", name, options.assert, options.assert.length, values);
81 | defineAssertion("refute", name, options.refute, refuteArgs, values);
82 |
83 | assert[name].message = options.assertMessage;
84 | refute[name].message = options.refuteMessage;
85 |
86 | if (options.expectation) {
87 | if (ba.expect && ba.expect.wrapAssertion) {
88 | ba.expect.wrapAssertion(name, options.expectation);
89 | } else {
90 | assert[name].expectationName = options.expectation;
91 | refute[name].expectationName = options.expectation;
92 | }
93 | }
94 | };
95 |
96 | function interpolate(string, property, value) {
97 | return string.replace(new RegExp("\\$\\{" + property + "\\}", "g"), value);
98 | }
99 |
100 | function interpolatePosArg(message, values) {
101 | var value;
102 | values = values || [];
103 |
104 | for (var i = 0, l = values.length; i < l; i++) {
105 | message = interpolate(message, i, ba.format(values[i]));
106 | }
107 |
108 | return message;
109 | }
110 |
111 | function interpolateProperties(msg, properties) {
112 | for (var prop in properties) {
113 | msg = interpolate(msg, prop, ba.format(properties[prop]));
114 | }
115 |
116 | return msg || "";
117 | }
118 |
119 | function fail(type, assertion, msg) {
120 | delete this.fail;
121 | var message = interpolateProperties(
122 | interpolatePosArg(ba[type][assertion][msg] || msg,
123 | [].slice.call(arguments, 3)), this);
124 | ba.fail("[" + type + "." + assertion + "] " + message);
125 | }
126 |
127 | function isDate(value) {
128 | // Duck typed dates, allows objects to take on the role of dates
129 | // without actually being dates
130 | return typeof value.getTime == "function" &&
131 | value.getTime() == value.valueOf();
132 | }
133 |
134 | ba.isDate = isDate;
135 |
136 | function areEqual(expected, actual) {
137 | if (expected === actual) {
138 | return true;
139 | }
140 |
141 | // Elements are only equal if expected === actual
142 | if (buster.isElement(expected) || buster.isElement(actual)) {
143 | return false;
144 | }
145 |
146 | // null and undefined only pass for null === null and
147 | // undefined === undefined
148 | /*jsl: ignore*/
149 | if (expected == null || actual == null) {
150 | return actual === expected;
151 | }
152 | /*jsl: end*/
153 |
154 | if (isDate(expected) || isDate(actual)) {
155 | return isDate(expected) && isDate(actual) &&
156 | expected.getTime() == actual.getTime();
157 | }
158 |
159 | var useCoercingEquality = typeof expected != "object" || typeof actual != "object";
160 |
161 | if (expected instanceof RegExp && actual instanceof RegExp) {
162 | if (expected.toString() != actual.toString()) {
163 | return false;
164 | }
165 |
166 | useCoercingEquality = false;
167 | }
168 |
169 | // Arrays can only be equal to arrays
170 | var expectedStr = toString.call(expected);
171 | var actualStr = toString.call(actual);
172 |
173 | // Coerce and compare when primitives are involved
174 | if (useCoercingEquality) {
175 | return expectedStr != "[object Array]" && actualStr != "[object Array]" &&
176 | expected == actual;
177 | }
178 |
179 | var expectedKeys = ba.keys(expected);
180 | var actualKeys = ba.keys(actual);
181 |
182 | if (isArguments(expected) || isArguments(actual)) {
183 | if (expected.length != actual.length) {
184 | return false;
185 | }
186 | } else {
187 | if (typeof expected != typeof actual || expectedStr != actualStr ||
188 | expectedKeys.length != actualKeys.length) {
189 | return false;
190 | }
191 | }
192 |
193 | var key;
194 |
195 | for (var i = 0, l = expectedKeys.length; i < l; i++) {
196 | key = expectedKeys[i];
197 |
198 | if (!Object.prototype.hasOwnProperty.call(actual, key) ||
199 | !areEqual(expected[key], actual[key])) {
200 | return false;
201 | }
202 | }
203 |
204 | return true;
205 | }
206 |
207 | ba.deepEqual = areEqual;
208 |
209 | assert = ba.assert = function assert(actual, message) {
210 | countAssertion();
211 | if (!assertEnoughArguments("assert", arguments, 1)) return;
212 |
213 | if (!actual) {
214 | var val = ba.format(actual)
215 | ba.fail(message || "[assert] Expected " + val + " to be truthy");
216 | } else {
217 | ba.emit("pass", "assert", message || "", actual);
218 | }
219 | };
220 |
221 | assert.toString = function () {
222 | return "buster.assert";
223 | };
224 |
225 | refute = ba.refute = function (actual, message) {
226 | countAssertion();
227 | if (!assertEnoughArguments("refute", arguments, 1)) return;
228 |
229 | if (actual) {
230 | var val = ba.format(actual)
231 | ba.fail(message || "[refute] Expected " + val + " to be falsy");
232 | } else {
233 | ba.emit("pass", "refute", message || "", actual);
234 | }
235 | };
236 |
237 | assert.message = "[assert] Expected ${0} to be thruthy";
238 | ba.count = 0;
239 |
240 | ba.fail = function (message) {
241 | var exception = new Error(message);
242 | exception.name = "AssertionError";
243 |
244 | try {
245 | throw exception;
246 | } catch (e) {
247 | ba.emit("failure", e);
248 | }
249 |
250 | if (typeof ba.throwOnFailure != "boolean" || ba.throwOnFailure) {
251 | throw exception;
252 | }
253 | };
254 |
255 | ba.format = function (object) {
256 | return "" + object;
257 | };
258 |
259 | function msg(message) {
260 | if (!message) { return ""; }
261 | return message + (/[.:!?]$/.test(message) ? " " : ": ");
262 | }
263 |
264 | function actualAndExpectedMessageValues(actual, expected, message) {
265 | return [actual, expected, msg(message)]
266 | }
267 |
268 | function actualMessageValues(actual) {
269 | return [actual, msg(arguments[1])];
270 | }
271 |
272 | function actualAndTypeOfMessageValues(actual) {
273 | return [actual, typeof actual, msg(arguments[1])];
274 | }
275 |
276 | ba.add("same", {
277 | assert: function (actual, expected) {
278 | return actual === expected;
279 | },
280 | refute: function (actual, expected) {
281 | return actual !== expected;
282 | },
283 | assertMessage: "${2}${0} expected to be the same object as ${1}",
284 | refuteMessage: "${2}${0} expected not to be the same object as ${1}",
285 | expectation: "toBeSameAs",
286 | values: actualAndExpectedMessageValues
287 | });
288 |
289 | function multiLineStringDiff(actual, expected, message) {
290 | if (actual == expected) return true;
291 |
292 | var message = interpolatePosArg(assert.equals.multiLineStringHeading, [message]),
293 | actualLines = actual.split("\n"),
294 | expectedLines = expected.split("\n"),
295 | lineCount = Math.max(expectedLines.length, actualLines.length),
296 | lines = [];
297 |
298 | for (var i = 0; i < lineCount; ++i) {
299 | if (expectedLines[i] != actualLines[i]) {
300 | lines.push("line " + (i + 1) + ": " + (expectedLines[i] || "") +
301 | "\nwas: " + (actualLines[i] || ""));
302 | }
303 | }
304 |
305 | ba.fail("[assert.equals] " + message + lines.join("\n\n"));
306 | return false;
307 | }
308 |
309 | ba.add("equals", {
310 | assert: function (actual, expected) {
311 | if (typeof actual == "string" && typeof expected == "string" &&
312 | (actual.indexOf("\n") >= 0 || expected.indexOf("\n") >= 0)) {
313 | var message = msg(arguments[2]);
314 | return multiLineStringDiff.call(this, actual, expected, message);
315 | }
316 |
317 | return areEqual(actual, expected);
318 | },
319 |
320 | refute: function (actual, expected) {
321 | return !areEqual(actual, expected);
322 | },
323 |
324 | assertMessage: "${2}${0} expected to be equal to ${1}",
325 | refuteMessage: "${2}${0} expected not to be equal to ${1}",
326 | expectation: "toEqual",
327 | values: actualAndExpectedMessageValues
328 | });
329 |
330 | assert.equals.multiLineStringHeading = "${0}Expected multi-line strings to be equal:\n";
331 |
332 | ba.add("typeOf", {
333 | assert: function (actual, expected) {
334 | return typeof actual == expected;
335 | },
336 | assertMessage: "${3}typeof ${0} (${2}) expected to be ${1}",
337 | refuteMessage: "${3}typeof ${0} expected not to be ${1}",
338 | expectation: "toBeType",
339 |
340 | values: function (actual, expected) {
341 | return [actual, expected, typeof actual, msg(arguments[2])];
342 | }
343 | });
344 |
345 | ba.add("defined", {
346 | assert: function (actual) {
347 | return typeof actual != "undefined";
348 | },
349 | assertMessage: "${2}Expected to be defined",
350 | refuteMessage: "${2}Expected ${0} (${1}) not to be defined",
351 | expectation: "toBeDefined",
352 | values: actualAndTypeOfMessageValues
353 | });
354 |
355 | ba.add("isNull", {
356 | assert: function (actual) {
357 | return actual === null;
358 | },
359 | assertMessage: "${1}Expected ${0} to be null",
360 | refuteMessage: "${1}Expected not to be null",
361 | expectation: "toBeNull",
362 | values: actualMessageValues
363 | });
364 |
365 | function match(object, matcher) {
366 | if (object === matcher) {
367 | return true;
368 | }
369 |
370 | if (matcher && typeof matcher.test == "function") {
371 | return matcher.test(object);
372 | }
373 |
374 | if (typeof matcher == "function") {
375 | return matcher(object) === true;
376 | }
377 |
378 | if (typeof matcher == "string") {
379 | matcher = matcher.toLowerCase();
380 | return !!object && ("" + object).toLowerCase().indexOf(matcher) >= 0;
381 | }
382 |
383 | if (typeof matcher == "number") {
384 | return matcher == object;
385 | }
386 |
387 | if (typeof matcher == "boolean") {
388 | return matcher === object;
389 | }
390 |
391 | if (matcher && typeof matcher == "object") {
392 | for (var prop in matcher) {
393 | if (!match(object[prop], matcher[prop])) {
394 | return false;
395 | }
396 | }
397 |
398 | return true;
399 | }
400 |
401 | throw new Error("Matcher (" + ba.format(matcher) + ") was not a " +
402 | "string, a number, a function, a boolean or an object");
403 | }
404 |
405 | ba.match = match;
406 |
407 | ba.add("match", {
408 | assert: function (actual, matcher) {
409 | var passed;
410 |
411 | try {
412 | passed = match(actual, matcher);
413 | } catch (e) {
414 | return this.fail("exceptionMessage", e.message, msg(arguments[2]));
415 | }
416 |
417 | return passed;
418 | },
419 |
420 | refute: function (actual, matcher) {
421 | var passed;
422 |
423 | try {
424 | passed = match(actual, matcher);
425 | } catch (e) {
426 | return this.fail("exceptionMessage", e.message);
427 | }
428 |
429 | return !passed;
430 | },
431 |
432 | assertMessage: "${2}${0} expected to match ${1}",
433 | refuteMessage: "${2}${0} expected not to match ${1}",
434 | expectation: "toMatch",
435 | values: actualAndExpectedMessageValues
436 | });
437 |
438 | assert.match.exceptionMessage = "${1}${0}";
439 | refute.match.exceptionMessage = "${1}${0}";
440 |
441 | ba.add("isObject", {
442 | assert: function (actual) {
443 | return typeof actual == "object" && !!actual;
444 | },
445 | assertMessage: "${2}${0} (${1}) expected to be object and not null",
446 | refuteMessage: "${2}${0} expected to be null or not an object",
447 | expectation: "toBeObject",
448 | values: actualAndTypeOfMessageValues
449 | });
450 |
451 | ba.add("isFunction", {
452 | assert: function (actual) {
453 | return typeof actual == "function";
454 | },
455 | assertMessage: "${2}${0} (${1}) expected to be function",
456 | refuteMessage: "${2}${0} expected not to be function",
457 | expectation: "toBeFunction",
458 | values: function (actual) {
459 | return [("" + actual).replace("\n", ""), typeof actual, msg(arguments[1])];
460 | }
461 | });
462 |
463 | ba.add("isTrue", {
464 | assert: function (actual) {
465 | return actual === true;
466 | },
467 | assertMessage: "${1}Expected ${0} to be true",
468 | refuteMessage: "${1}Expected ${0} to not be true",
469 | expectation: "toBeTrue",
470 | values: actualMessageValues
471 | });
472 |
473 | ba.add("isFalse", {
474 | assert: function (actual) {
475 | return actual === false;
476 | },
477 | assertMessage: "${1}Expected ${0} to be false",
478 | refuteMessage: "${1}Expected ${0} to not be false",
479 | expectation: "toBeFalse",
480 | values: actualMessageValues
481 | });
482 |
483 | ba.add("isString", {
484 | assert: function (actual) {
485 | return typeof actual == "string";
486 | },
487 | assertMessage: "${2}Expected ${0} (${1}) to be string",
488 | refuteMessage: "${2}Expected ${0} not to be string",
489 | expectation: "toBeString",
490 | values: actualAndTypeOfMessageValues
491 | });
492 |
493 | ba.add("isBoolean", {
494 | assert: function (actual) {
495 | return typeof actual == "boolean";
496 | },
497 | assertMessage: "${2}Expected ${0} (${1}) to be boolean",
498 | refuteMessage: "${2}Expected ${0} not to be boolean",
499 | expectation: "toBeBoolean",
500 | values: actualAndTypeOfMessageValues
501 | });
502 |
503 | ba.add("isNumber", {
504 | assert: function (actual) {
505 | return typeof actual == "number" && !isNaN(actual);
506 | },
507 | assertMessage: "${2}Expected ${0} (${1}) to be a non-NaN number",
508 | refuteMessage: "${2}Expected ${0} to be NaN or another non-number value",
509 | expectation: "toBeNumber",
510 | values: actualAndTypeOfMessageValues
511 | });
512 |
513 | ba.add("isNaN", {
514 | assert: function (actual) {
515 | return typeof actual == "number" && isNaN(actual);
516 | },
517 | assertMessage: "${2}Expected ${0} to be NaN",
518 | refuteMessage: "${2}Expected not to be NaN",
519 | expectation: "toBeNaN",
520 | values: actualAndTypeOfMessageValues
521 | });
522 |
523 | ba.add("isArray", {
524 | assert: function (actual) {
525 | return toString.call(actual) == "[object Array]";
526 | },
527 | assertMessage: "${2}Expected ${0} to be array",
528 | refuteMessage: "${2}Expected ${0} not to be array",
529 | expectation: "toBeArray",
530 | values: actualAndTypeOfMessageValues
531 | });
532 |
533 | function isArrayLike(object) {
534 | return toString.call(object) == "[object Array]" ||
535 | (!!object && typeof object.length == "number" &&
536 | typeof object.splice == "function") ||
537 | ba.isArguments(object);
538 | }
539 |
540 | ba.isArrayLike = isArrayLike;
541 |
542 | ba.add("isArrayLike", {
543 | assert: function (actual) {
544 | return isArrayLike(actual);
545 | },
546 | assertMessage: "${2}Expected ${0} to be array like",
547 | refuteMessage: "${2}Expected ${0} not to be array like",
548 | expectation: "toBeArrayLike",
549 | values: actualAndTypeOfMessageValues
550 | });
551 |
552 | function captureException(callback) {
553 | try {
554 | callback();
555 | } catch (e) {
556 | return e;
557 | }
558 |
559 | return null;
560 | }
561 |
562 | ba.captureException = captureException;
563 |
564 | assert.exception = function (callback, exception, message) {
565 | countAssertion();
566 | if (!assertEnoughArguments("assert.exception", arguments, 1)) return
567 |
568 | if (!callback) {
569 | return;
570 | }
571 |
572 | var err = captureException(callback);
573 | message = msg(message);
574 |
575 | if (!err) {
576 | if (exception) {
577 | return fail.call({}, "assert", "exception", "typeNoExceptionMessage",
578 | message, exception);
579 | } else {
580 | return fail.call({}, "assert", "exception", "message",
581 | message, exception);
582 | }
583 | }
584 |
585 | if (exception && err.name != exception) {
586 | if (typeof window != "undefined" && typeof console != "undefined") {
587 | console.log(err);
588 | }
589 |
590 | return fail.call({}, "assert", "exception", "typeFailMessage",
591 | message, exception, err.name, err.message);
592 | }
593 |
594 | ba.emit("pass", "assert.exception", message, callback, exception);
595 | };
596 |
597 | assert.exception.typeNoExceptionMessage = "${0}Expected ${1} but no exception was thrown";
598 | assert.exception.message = "${0}Expected exception";
599 | assert.exception.typeFailMessage = "${0}Expected ${1} but threw ${2} (${3})";
600 | assert.exception.expectationName = "toThrow";
601 |
602 | refute.exception = function (callback) {
603 | countAssertion();
604 | if (!assertEnoughArguments("refute.exception", arguments, 1)) return;
605 |
606 | var err = captureException(callback);
607 |
608 | if (err) {
609 | fail("refute", "exception", "message",
610 | msg(arguments[1]), err.name, err.message, callback);
611 | } else {
612 | ba.emit("pass", "refute.exception", callback);
613 | }
614 | };
615 |
616 | refute.exception.message = "${0}Expected not to throw but threw ${1} (${2})";
617 | refute.exception.expectationName = "toThrow";
618 |
619 | ba.add("inDelta", {
620 | assert: function (actual, expected, delta) {
621 | return Math.abs(actual - expected) <= delta;
622 | },
623 | assertMessage: "${3}Expected ${0} to be equal to ${1} +/- ${2}",
624 | refuteMessage: "${3}Expected ${0} not to be equal to ${1} +/- ${2}",
625 | expectation: "toBeInDelta",
626 | values: function (actual, expected, delta, message) {
627 | return [actual, expected, delta, msg(message)];
628 | }
629 | });
630 |
631 | ba.add("hasPrototype", {
632 | assert: function (actual, protoObj) {
633 | return protoObj.isPrototypeOf(actual);
634 | },
635 | assertMessage: "${2}Expected ${0} to have ${1} on its prototype chain",
636 | refuteMessage: "${2}Expected ${0} not to have ${1} on its prototype chain",
637 | expectation: "toHavePrototype",
638 | values: actualAndExpectedMessageValues
639 | });
640 |
641 | ba.add("tagName", {
642 | assert: function (element, tagName) {
643 | if (!element.tagName) {
644 | return this.fail("noTagNameMessage", tagName, element, msg(arguments[2]));
645 | }
646 |
647 | return tagName.toLowerCase &&
648 | tagName.toLowerCase() == element.tagName.toLowerCase();
649 | },
650 | assertMessage: "${2}Expected tagName to be ${0} but was ${1}",
651 | refuteMessage: "${2}Expected tagName not to be ${0}",
652 | expectation: "toHaveTagName",
653 | values: function (element, tagName, message) {
654 | return [tagName, element.tagName, msg(message)];
655 | }
656 | });
657 |
658 | assert.tagName.noTagNameMessage = "${2}Expected ${1} to have tagName property";
659 | refute.tagName.noTagNameMessage = "${2}Expected ${1} to have tagName property";
660 |
661 | function indexOf(arr, item) {
662 | for (var i = 0, l = arr.length; i < l; i++) {
663 | if (arr[i] == item) {
664 | return i;
665 | }
666 | }
667 |
668 | return -1;
669 | }
670 |
671 | ba.add("className", {
672 | assert: function (element, className) {
673 | if (typeof element.className == "undefined") {
674 | return this.fail("noClassNameMessage", className, element, msg(arguments[2]));
675 | }
676 |
677 | var expected = typeof className == "string" ? className.split(" ") : className;
678 | var actual = element.className.split(" ");
679 |
680 | for (var i = 0, l = expected.length; i < l; i++) {
681 | if (indexOf(actual, expected[i]) < 0) {
682 | return false;
683 | }
684 | }
685 |
686 | return true;
687 | },
688 | assertMessage: "${2}Expected object's className to include ${0} but was ${1}",
689 | refuteMessage: "${2}Expected object's className not to include ${0}",
690 | expectation: "toHaveClassName",
691 | values: function (element, className, message) {
692 | return [className, element.className, msg(message)];
693 | }
694 | });
695 |
696 | assert.className.noClassNameMessage = "${2}Expected object to have className property";
697 | refute.className.noClassNameMessage = "${2}Expected object to have className property";
698 |
699 | if (typeof module != "undefined") {
700 | ba.expect = function () {
701 | ba.expect = require("./buster-assertions/expect");
702 | return ba.expect.apply(exports, arguments);
703 | };
704 | }
705 |
706 | function isArguments(obj) {
707 | if (typeof obj != "object" || typeof obj.length != "number" ||
708 | toString.call(obj) == "[object Array]") {
709 | return false;
710 | }
711 |
712 | if (typeof obj.callee == "function") {
713 | return true;
714 | }
715 |
716 | try {
717 | obj[obj.length] = 6;
718 | delete obj[obj.length];
719 | } catch (e) {
720 | return true;
721 | }
722 |
723 | return false;
724 | }
725 |
726 | ba.isArguments = isArguments;
727 |
728 | if (Object.keys) {
729 | ba.keys = function (obj) {
730 | return Object.keys(obj)
731 | };
732 | } else {
733 | ba.keys = function (object) {
734 | var keys = [];
735 |
736 | for (var prop in object) {
737 | if (Object.prototype.hasOwnProperty.call(object, prop)) {
738 | keys.push(prop);
739 | }
740 | }
741 |
742 | return keys;
743 | }
744 | }
745 | }());
746 |
--------------------------------------------------------------------------------
/src/lib/underscore/underscore.js:
--------------------------------------------------------------------------------
1 | // Underscore.js 1.1.5
2 | // (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
3 | // Underscore is freely distributable under the MIT license.
4 | // Portions of Underscore are inspired or borrowed from Prototype,
5 | // Oliver Steele's Functional, and John Resig's Micro-Templating.
6 | // For all details and documentation:
7 | // http://documentcloud.github.com/underscore
8 |
9 | (function() {
10 |
11 | // Baseline setup
12 | // --------------
13 |
14 | // Establish the root object, `window` in the browser, or `global` on the server.
15 | var root = this;
16 |
17 | // Save the previous value of the `_` variable.
18 | var previousUnderscore = root._;
19 |
20 | // Establish the object that gets returned to break out of a loop iteration.
21 | var breaker = {};
22 |
23 | // Save bytes in the minified (but not gzipped) version:
24 | var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
25 |
26 | // Create quick reference variables for speed access to core prototypes.
27 | var slice = ArrayProto.slice,
28 | unshift = ArrayProto.unshift,
29 | toString = ObjProto.toString,
30 | hasOwnProperty = ObjProto.hasOwnProperty;
31 |
32 | // All **ECMAScript 5** native function implementations that we hope to use
33 | // are declared here.
34 | var
35 | nativeForEach = ArrayProto.forEach,
36 | nativeMap = ArrayProto.map,
37 | nativeReduce = ArrayProto.reduce,
38 | nativeReduceRight = ArrayProto.reduceRight,
39 | nativeFilter = ArrayProto.filter,
40 | nativeEvery = ArrayProto.every,
41 | nativeSome = ArrayProto.some,
42 | nativeIndexOf = ArrayProto.indexOf,
43 | nativeLastIndexOf = ArrayProto.lastIndexOf,
44 | nativeIsArray = Array.isArray,
45 | nativeKeys = Object.keys,
46 | nativeBind = FuncProto.bind;
47 |
48 | // Create a safe reference to the Underscore object for use below.
49 | var _ = function(obj) { return new wrapper(obj); };
50 |
51 | // Export the Underscore object for **CommonJS**, with backwards-compatibility
52 | // for the old `require()` API. If we're not in CommonJS, add `_` to the
53 | // global object.
54 | if (typeof module !== 'undefined' && module.exports) {
55 | module.exports = _;
56 | _._ = _;
57 | } else {
58 | root._ = _;
59 | }
60 |
61 | // Current version.
62 | _.VERSION = '1.1.5';
63 |
64 | // Collection Functions
65 | // --------------------
66 |
67 | // The cornerstone, an `each` implementation, aka `forEach`.
68 | // Handles objects implementing `forEach`, arrays, and raw objects.
69 | // Delegates to **ECMAScript 5**'s native `forEach` if available.
70 | var each = _.each = _.forEach = function(obj, iterator, context) {
71 | if (obj == null) return;
72 | if (nativeForEach && obj.forEach === nativeForEach) {
73 | obj.forEach(iterator, context);
74 | } else if (_.isNumber(obj.length)) {
75 | for (var i = 0, l = obj.length; i < l; i++) {
76 | if (iterator.call(context, obj[i], i, obj) === breaker) return;
77 | }
78 | } else {
79 | for (var key in obj) {
80 | if (hasOwnProperty.call(obj, key)) {
81 | if (iterator.call(context, obj[key], key, obj) === breaker) return;
82 | }
83 | }
84 | }
85 | };
86 |
87 | // Return the results of applying the iterator to each element.
88 | // Delegates to **ECMAScript 5**'s native `map` if available.
89 | _.map = function(obj, iterator, context) {
90 | var results = [];
91 | if (obj == null) return results;
92 | if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
93 | each(obj, function(value, index, list) {
94 | results[results.length] = iterator.call(context, value, index, list);
95 | });
96 | return results;
97 | };
98 |
99 | // **Reduce** builds up a single result from a list of values, aka `inject`,
100 | // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
101 | _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
102 | var initial = memo !== void 0;
103 | if (obj == null) obj = [];
104 | if (nativeReduce && obj.reduce === nativeReduce) {
105 | if (context) iterator = _.bind(iterator, context);
106 | return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
107 | }
108 | each(obj, function(value, index, list) {
109 | if (!initial && index === 0) {
110 | memo = value;
111 | initial = true;
112 | } else {
113 | memo = iterator.call(context, memo, value, index, list);
114 | }
115 | });
116 | if (!initial) throw new TypeError("Reduce of empty array with no initial value");
117 | return memo;
118 | };
119 |
120 | // The right-associative version of reduce, also known as `foldr`.
121 | // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
122 | _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
123 | if (obj == null) obj = [];
124 | if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
125 | if (context) iterator = _.bind(iterator, context);
126 | return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
127 | }
128 | var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
129 | return _.reduce(reversed, iterator, memo, context);
130 | };
131 |
132 | // Return the first value which passes a truth test. Aliased as `detect`.
133 | _.find = _.detect = function(obj, iterator, context) {
134 | var result;
135 | any(obj, function(value, index, list) {
136 | if (iterator.call(context, value, index, list)) {
137 | result = value;
138 | return true;
139 | }
140 | });
141 | return result;
142 | };
143 |
144 | // Return all the elements that pass a truth test.
145 | // Delegates to **ECMAScript 5**'s native `filter` if available.
146 | // Aliased as `select`.
147 | _.filter = _.select = function(obj, iterator, context) {
148 | var results = [];
149 | if (obj == null) return results;
150 | if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
151 | each(obj, function(value, index, list) {
152 | if (iterator.call(context, value, index, list)) results[results.length] = value;
153 | });
154 | return results;
155 | };
156 |
157 | // Return all the elements for which a truth test fails.
158 | _.reject = function(obj, iterator, context) {
159 | var results = [];
160 | if (obj == null) return results;
161 | each(obj, function(value, index, list) {
162 | if (!iterator.call(context, value, index, list)) results[results.length] = value;
163 | });
164 | return results;
165 | };
166 |
167 | // Determine whether all of the elements match a truth test.
168 | // Delegates to **ECMAScript 5**'s native `every` if available.
169 | // Aliased as `all`.
170 | _.every = _.all = function(obj, iterator, context) {
171 | iterator = iterator || _.identity;
172 | var result = true;
173 | if (obj == null) return result;
174 | if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
175 | each(obj, function(value, index, list) {
176 | if (!(result = result && iterator.call(context, value, index, list))) return breaker;
177 | });
178 | return result;
179 | };
180 |
181 | // Determine if at least one element in the object matches a truth test.
182 | // Delegates to **ECMAScript 5**'s native `some` if available.
183 | // Aliased as `any`.
184 | var any = _.some = _.any = function(obj, iterator, context) {
185 | iterator = iterator || _.identity;
186 | var result = false;
187 | if (obj == null) return result;
188 | if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
189 | each(obj, function(value, index, list) {
190 | if (result = iterator.call(context, value, index, list)) return breaker;
191 | });
192 | return result;
193 | };
194 |
195 | // Determine if a given value is included in the array or object using `===`.
196 | // Aliased as `contains`.
197 | _.include = _.contains = function(obj, target) {
198 | var found = false;
199 | if (obj == null) return found;
200 | if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
201 | any(obj, function(value) {
202 | if (found = value === target) return true;
203 | });
204 | return found;
205 | };
206 |
207 | // Invoke a method (with arguments) on every item in a collection.
208 | _.invoke = function(obj, method) {
209 | var args = slice.call(arguments, 2);
210 | return _.map(obj, function(value) {
211 | return (method ? value[method] : value).apply(value, args);
212 | });
213 | };
214 |
215 | // Convenience version of a common use case of `map`: fetching a property.
216 | _.pluck = function(obj, key) {
217 | return _.map(obj, function(value){ return value[key]; });
218 | };
219 |
220 | // Return the maximum element or (element-based computation).
221 | _.max = function(obj, iterator, context) {
222 | if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
223 | var result = {computed : -Infinity};
224 | each(obj, function(value, index, list) {
225 | var computed = iterator ? iterator.call(context, value, index, list) : value;
226 | computed >= result.computed && (result = {value : value, computed : computed});
227 | });
228 | return result.value;
229 | };
230 |
231 | // Return the minimum element (or element-based computation).
232 | _.min = function(obj, iterator, context) {
233 | if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
234 | var result = {computed : Infinity};
235 | each(obj, function(value, index, list) {
236 | var computed = iterator ? iterator.call(context, value, index, list) : value;
237 | computed < result.computed && (result = {value : value, computed : computed});
238 | });
239 | return result.value;
240 | };
241 |
242 | // Sort the object's values by a criterion produced by an iterator.
243 | _.sortBy = function(obj, iterator, context) {
244 | return _.pluck(_.map(obj, function(value, index, list) {
245 | return {
246 | value : value,
247 | criteria : iterator.call(context, value, index, list)
248 | };
249 | }).sort(function(left, right) {
250 | var a = left.criteria, b = right.criteria;
251 | return a < b ? -1 : a > b ? 1 : 0;
252 | }), 'value');
253 | };
254 |
255 | // Use a comparator function to figure out at what index an object should
256 | // be inserted so as to maintain order. Uses binary search.
257 | _.sortedIndex = function(array, obj, iterator) {
258 | iterator = iterator || _.identity;
259 | var low = 0, high = array.length;
260 | while (low < high) {
261 | var mid = (low + high) >> 1;
262 | iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
263 | }
264 | return low;
265 | };
266 |
267 | // Safely convert anything iterable into a real, live array.
268 | _.toArray = function(iterable) {
269 | if (!iterable) return [];
270 | if (iterable.toArray) return iterable.toArray();
271 | if (_.isArray(iterable)) return iterable;
272 | if (_.isArguments(iterable)) return slice.call(iterable);
273 | return _.values(iterable);
274 | };
275 |
276 | // Return the number of elements in an object.
277 | _.size = function(obj) {
278 | return _.toArray(obj).length;
279 | };
280 |
281 | // Array Functions
282 | // ---------------
283 |
284 | // Get the first element of an array. Passing **n** will return the first N
285 | // values in the array. Aliased as `head`. The **guard** check allows it to work
286 | // with `_.map`.
287 | _.first = _.head = function(array, n, guard) {
288 | return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
289 | };
290 |
291 | // Returns everything but the first entry of the array. Aliased as `tail`.
292 | // Especially useful on the arguments object. Passing an **index** will return
293 | // the rest of the values in the array from that index onward. The **guard**
294 | // check allows it to work with `_.map`.
295 | _.rest = _.tail = function(array, index, guard) {
296 | return slice.call(array, (index == null) || guard ? 1 : index);
297 | };
298 |
299 | // Get the last element of an array.
300 | _.last = function(array) {
301 | return array[array.length - 1];
302 | };
303 |
304 | // Trim out all falsy values from an array.
305 | _.compact = function(array) {
306 | return _.filter(array, function(value){ return !!value; });
307 | };
308 |
309 | // Return a completely flattened version of an array.
310 | _.flatten = function(array) {
311 | return _.reduce(array, function(memo, value) {
312 | if (_.isArray(value)) return memo.concat(_.flatten(value));
313 | memo[memo.length] = value;
314 | return memo;
315 | }, []);
316 | };
317 |
318 | // Return a version of the array that does not contain the specified value(s).
319 | _.without = function(array) {
320 | var values = slice.call(arguments, 1);
321 | return _.filter(array, function(value){ return !_.include(values, value); });
322 | };
323 |
324 | // Produce a duplicate-free version of the array. If the array has already
325 | // been sorted, you have the option of using a faster algorithm.
326 | // Aliased as `unique`.
327 | _.uniq = _.unique = function(array, isSorted) {
328 | return _.reduce(array, function(memo, el, i) {
329 | if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
330 | return memo;
331 | }, []);
332 | };
333 |
334 | // Produce an array that contains every item shared between all the
335 | // passed-in arrays.
336 | _.intersect = function(array) {
337 | var rest = slice.call(arguments, 1);
338 | return _.filter(_.uniq(array), function(item) {
339 | return _.every(rest, function(other) {
340 | return _.indexOf(other, item) >= 0;
341 | });
342 | });
343 | };
344 |
345 | // Zip together multiple lists into a single array -- elements that share
346 | // an index go together.
347 | _.zip = function() {
348 | var args = slice.call(arguments);
349 | var length = _.max(_.pluck(args, 'length'));
350 | var results = new Array(length);
351 | for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
352 | return results;
353 | };
354 |
355 | // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
356 | // we need this function. Return the position of the first occurrence of an
357 | // item in an array, or -1 if the item is not included in the array.
358 | // Delegates to **ECMAScript 5**'s native `indexOf` if available.
359 | // If the array is large and already in sort order, pass `true`
360 | // for **isSorted** to use binary search.
361 | _.indexOf = function(array, item, isSorted) {
362 | if (array == null) return -1;
363 | var i, l;
364 | if (isSorted) {
365 | i = _.sortedIndex(array, item);
366 | return array[i] === item ? i : -1;
367 | }
368 | if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
369 | for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
370 | return -1;
371 | };
372 |
373 |
374 | // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
375 | _.lastIndexOf = function(array, item) {
376 | if (array == null) return -1;
377 | if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
378 | var i = array.length;
379 | while (i--) if (array[i] === item) return i;
380 | return -1;
381 | };
382 |
383 | // Generate an integer Array containing an arithmetic progression. A port of
384 | // the native Python `range()` function. See
385 | // [the Python documentation](http://docs.python.org/library/functions.html#range).
386 | _.range = function(start, stop, step) {
387 | if (arguments.length <= 1) {
388 | stop = start || 0;
389 | start = 0;
390 | }
391 | step = arguments[2] || 1;
392 |
393 | var len = Math.max(Math.ceil((stop - start) / step), 0);
394 | var idx = 0;
395 | var range = new Array(len);
396 |
397 | while(idx < len) {
398 | range[idx++] = start;
399 | start += step;
400 | }
401 |
402 | return range;
403 | };
404 |
405 | // Function (ahem) Functions
406 | // ------------------
407 |
408 | // Create a function bound to a given object (assigning `this`, and arguments,
409 | // optionally). Binding with arguments is also known as `curry`.
410 | // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
411 | _.bind = function(func, obj) {
412 | if (nativeBind && func.bind === nativeBind) return func.bind.apply(func, slice.call(arguments, 1));
413 | var args = slice.call(arguments, 2);
414 | return function() {
415 | return func.apply(obj, args.concat(slice.call(arguments)));
416 | };
417 | };
418 |
419 | // Bind all of an object's methods to that object. Useful for ensuring that
420 | // all callbacks defined on an object belong to it.
421 | _.bindAll = function(obj) {
422 | var funcs = slice.call(arguments, 1);
423 | if (funcs.length == 0) funcs = _.functions(obj);
424 | each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
425 | return obj;
426 | };
427 |
428 | // Memoize an expensive function by storing its results.
429 | _.memoize = function(func, hasher) {
430 | var memo = {};
431 | hasher = hasher || _.identity;
432 | return function() {
433 | var key = hasher.apply(this, arguments);
434 | return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
435 | };
436 | };
437 |
438 | // Delays a function for the given number of milliseconds, and then calls
439 | // it with the arguments supplied.
440 | _.delay = function(func, wait) {
441 | var args = slice.call(arguments, 2);
442 | return setTimeout(function(){ return func.apply(func, args); }, wait);
443 | };
444 |
445 | // Defers a function, scheduling it to run after the current call stack has
446 | // cleared.
447 | _.defer = function(func) {
448 | return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
449 | };
450 |
451 | // Internal function used to implement `_.throttle` and `_.debounce`.
452 | var limit = function(func, wait, debounce) {
453 | var timeout;
454 | return function() {
455 | var context = this, args = arguments;
456 | var throttler = function() {
457 | timeout = null;
458 | func.apply(context, args);
459 | };
460 | if (debounce) clearTimeout(timeout);
461 | if (debounce || !timeout) timeout = setTimeout(throttler, wait);
462 | };
463 | };
464 |
465 | // Returns a function, that, when invoked, will only be triggered at most once
466 | // during a given window of time.
467 | _.throttle = function(func, wait) {
468 | return limit(func, wait, false);
469 | };
470 |
471 | // Returns a function, that, as long as it continues to be invoked, will not
472 | // be triggered. The function will be called after it stops being called for
473 | // N milliseconds.
474 | _.debounce = function(func, wait) {
475 | return limit(func, wait, true);
476 | };
477 |
478 | // Returns a function that will be executed at most one time, no matter how
479 | // often you call it. Useful for lazy initialization.
480 | _.once = function(func) {
481 | var ran = false, memo;
482 | return function() {
483 | if (ran) return memo;
484 | ran = true;
485 | return memo = func.apply(this, arguments);
486 | };
487 | };
488 |
489 | // Returns the first function passed as an argument to the second,
490 | // allowing you to adjust arguments, run code before and after, and
491 | // conditionally execute the original function.
492 | _.wrap = function(func, wrapper) {
493 | return function() {
494 | var args = [func].concat(slice.call(arguments));
495 | return wrapper.apply(this, args);
496 | };
497 | };
498 |
499 | // Returns a function that is the composition of a list of functions, each
500 | // consuming the return value of the function that follows.
501 | _.compose = function() {
502 | var funcs = slice.call(arguments);
503 | return function() {
504 | var args = slice.call(arguments);
505 | for (var i=funcs.length-1; i >= 0; i--) {
506 | args = [funcs[i].apply(this, args)];
507 | }
508 | return args[0];
509 | };
510 | };
511 |
512 | // Object Functions
513 | // ----------------
514 |
515 | // Retrieve the names of an object's properties.
516 | // Delegates to **ECMAScript 5**'s native `Object.keys`
517 | _.keys = nativeKeys || function(obj) {
518 | if (obj !== Object(obj)) throw new TypeError('Invalid object');
519 | var keys = [];
520 | for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
521 | return keys;
522 | };
523 |
524 | // Retrieve the values of an object's properties.
525 | _.values = function(obj) {
526 | return _.map(obj, _.identity);
527 | };
528 |
529 | // Return a sorted list of the function names available on the object.
530 | // Aliased as `methods`
531 | _.functions = _.methods = function(obj) {
532 | return _.filter(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
533 | };
534 |
535 | // Extend a given object with all the properties in passed-in object(s).
536 | _.extend = function(obj) {
537 | each(slice.call(arguments, 1), function(source) {
538 | for (var prop in source) obj[prop] = source[prop];
539 | });
540 | return obj;
541 | };
542 |
543 | // Fill in a given object with default properties.
544 | _.defaults = function(obj) {
545 | each(slice.call(arguments, 1), function(source) {
546 | for (var prop in source) if (obj[prop] == null) obj[prop] = source[prop];
547 | });
548 | return obj;
549 | };
550 |
551 | // Create a (shallow-cloned) duplicate of an object.
552 | _.clone = function(obj) {
553 | return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
554 | };
555 |
556 | // Invokes interceptor with the obj, and then returns obj.
557 | // The primary purpose of this method is to "tap into" a method chain, in
558 | // order to perform operations on intermediate results within the chain.
559 | _.tap = function(obj, interceptor) {
560 | interceptor(obj);
561 | return obj;
562 | };
563 |
564 | // Perform a deep comparison to check if two objects are equal.
565 | _.isEqual = function(a, b) {
566 | // Check object identity.
567 | if (a === b) return true;
568 | // Different types?
569 | var atype = typeof(a), btype = typeof(b);
570 | if (atype != btype) return false;
571 | // Basic equality test (watch out for coercions).
572 | if (a == b) return true;
573 | // One is falsy and the other truthy.
574 | if ((!a && b) || (a && !b)) return false;
575 | // Unwrap any wrapped objects.
576 | if (a._chain) a = a._wrapped;
577 | if (b._chain) b = b._wrapped;
578 | // One of them implements an isEqual()?
579 | if (a.isEqual) return a.isEqual(b);
580 | // Check dates' integer values.
581 | if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
582 | // Both are NaN?
583 | if (_.isNaN(a) && _.isNaN(b)) return false;
584 | // Compare regular expressions.
585 | if (_.isRegExp(a) && _.isRegExp(b))
586 | return a.source === b.source &&
587 | a.global === b.global &&
588 | a.ignoreCase === b.ignoreCase &&
589 | a.multiline === b.multiline;
590 | // If a is not an object by this point, we can't handle it.
591 | if (atype !== 'object') return false;
592 | // Check for different array lengths before comparing contents.
593 | if (a.length && (a.length !== b.length)) return false;
594 | // Nothing else worked, deep compare the contents.
595 | var aKeys = _.keys(a), bKeys = _.keys(b);
596 | // Different object sizes?
597 | if (aKeys.length != bKeys.length) return false;
598 | // Recursive comparison of contents.
599 | for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
600 | return true;
601 | };
602 |
603 | // Is a given array or object empty?
604 | _.isEmpty = function(obj) {
605 | if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
606 | for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
607 | return true;
608 | };
609 |
610 | // Is a given value a DOM element?
611 | _.isElement = function(obj) {
612 | return !!(obj && obj.nodeType == 1);
613 | };
614 |
615 | // Is a given value an array?
616 | // Delegates to ECMA5's native Array.isArray
617 | _.isArray = nativeIsArray || function(obj) {
618 | return toString.call(obj) === '[object Array]';
619 | };
620 |
621 | // Is a given variable an arguments object?
622 | _.isArguments = function(obj) {
623 | return !!(obj && hasOwnProperty.call(obj, 'callee'));
624 | };
625 |
626 | // Is a given value a function?
627 | _.isFunction = function(obj) {
628 | return !!(obj && obj.constructor && obj.call && obj.apply);
629 | };
630 |
631 | // Is a given value a string?
632 | _.isString = function(obj) {
633 | return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
634 | };
635 |
636 | // Is a given value a number?
637 | _.isNumber = function(obj) {
638 | return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
639 | };
640 |
641 | // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
642 | // that does not equal itself.
643 | _.isNaN = function(obj) {
644 | return obj !== obj;
645 | };
646 |
647 | // Is a given value a boolean?
648 | _.isBoolean = function(obj) {
649 | return obj === true || obj === false;
650 | };
651 |
652 | // Is a given value a date?
653 | _.isDate = function(obj) {
654 | return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
655 | };
656 |
657 | // Is the given value a regular expression?
658 | _.isRegExp = function(obj) {
659 | return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
660 | };
661 |
662 | // Is a given value equal to null?
663 | _.isNull = function(obj) {
664 | return obj === null;
665 | };
666 |
667 | // Is a given variable undefined?
668 | _.isUndefined = function(obj) {
669 | return obj === void 0;
670 | };
671 |
672 | // Utility Functions
673 | // -----------------
674 |
675 | // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
676 | // previous owner. Returns a reference to the Underscore object.
677 | _.noConflict = function() {
678 | root._ = previousUnderscore;
679 | return this;
680 | };
681 |
682 | // Keep the identity function around for default iterators.
683 | _.identity = function(value) {
684 | return value;
685 | };
686 |
687 | // Run a function **n** times.
688 | _.times = function (n, iterator, context) {
689 | for (var i = 0; i < n; i++) iterator.call(context, i);
690 | };
691 |
692 | // Add your own custom functions to the Underscore object, ensuring that
693 | // they're correctly added to the OOP wrapper as well.
694 | _.mixin = function(obj) {
695 | each(_.functions(obj), function(name){
696 | addToWrapper(name, _[name] = obj[name]);
697 | });
698 | };
699 |
700 | // Generate a unique integer id (unique within the entire client session).
701 | // Useful for temporary DOM ids.
702 | var idCounter = 0;
703 | _.uniqueId = function(prefix) {
704 | var id = idCounter++;
705 | return prefix ? prefix + id : id;
706 | };
707 |
708 | // By default, Underscore uses ERB-style template delimiters, change the
709 | // following template settings to use alternative delimiters.
710 | _.templateSettings = {
711 | evaluate : /<%([\s\S]+?)%>/g,
712 | interpolate : /<%=([\s\S]+?)%>/g
713 | };
714 |
715 | // JavaScript micro-templating, similar to John Resig's implementation.
716 | // Underscore templating handles arbitrary delimiters, preserves whitespace,
717 | // and correctly escapes quotes within interpolated code.
718 | _.template = function(str, data) {
719 | var c = _.templateSettings;
720 | var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
721 | 'with(obj||{}){__p.push(\'' +
722 | str.replace(/\\/g, '\\\\')
723 | .replace(/'/g, "\\'")
724 | .replace(c.interpolate, function(match, code) {
725 | return "'," + code.replace(/\\'/g, "'") + ",'";
726 | })
727 | .replace(c.evaluate || null, function(match, code) {
728 | return "');" + code.replace(/\\'/g, "'")
729 | .replace(/[\r\n\t]/g, ' ') + "__p.push('";
730 | })
731 | .replace(/\r/g, '\\r')
732 | .replace(/\n/g, '\\n')
733 | .replace(/\t/g, '\\t')
734 | + "');}return __p.join('');";
735 | var func = new Function('obj', tmpl);
736 | return data ? func(data) : func;
737 | };
738 |
739 | // The OOP Wrapper
740 | // ---------------
741 |
742 | // If Underscore is called as a function, it returns a wrapped object that
743 | // can be used OO-style. This wrapper holds altered versions of all the
744 | // underscore functions. Wrapped objects may be chained.
745 | var wrapper = function(obj) { this._wrapped = obj; };
746 |
747 | // Expose `wrapper.prototype` as `_.prototype`
748 | _.prototype = wrapper.prototype;
749 |
750 | // Helper function to continue chaining intermediate results.
751 | var result = function(obj, chain) {
752 | return chain ? _(obj).chain() : obj;
753 | };
754 |
755 | // A method to easily add functions to the OOP wrapper.
756 | var addToWrapper = function(name, func) {
757 | wrapper.prototype[name] = function() {
758 | var args = slice.call(arguments);
759 | unshift.call(args, this._wrapped);
760 | return result(func.apply(_, args), this._chain);
761 | };
762 | };
763 |
764 | // Add all of the Underscore functions to the wrapper object.
765 | _.mixin(_);
766 |
767 | // Add all mutator Array functions to the wrapper.
768 | each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
769 | var method = ArrayProto[name];
770 | wrapper.prototype[name] = function() {
771 | method.apply(this._wrapped, arguments);
772 | return result(this._wrapped, this._chain);
773 | };
774 | });
775 |
776 | // Add all accessor Array functions to the wrapper.
777 | each(['concat', 'join', 'slice'], function(name) {
778 | var method = ArrayProto[name];
779 | wrapper.prototype[name] = function() {
780 | return result(method.apply(this._wrapped, arguments), this._chain);
781 | };
782 | });
783 |
784 | // Start chaining a wrapped Underscore object.
785 | wrapper.prototype.chain = function() {
786 | this._chain = true;
787 | return this;
788 | };
789 |
790 | // Extracts the result from a wrapped and chained object.
791 | wrapper.prototype.value = function() {
792 | return this._wrapped;
793 | };
794 |
795 | })();
--------------------------------------------------------------------------------