DYEBench should use TodoMVC to test FlightJS for consistency
[WebKit-https.git] / PerformanceTests / DoYouEvenBench / resources / todomvc / dependency-examples / flight / bower_components / flight / lib / utils.js
1 // ==========================================
2 // Copyright 2013 Twitter, Inc
3 // Licensed under The MIT License
4 // http://opensource.org/licenses/MIT
5 // ==========================================
6
7 define(
8
9   [],
10
11   function() {
12     'use strict';
13
14     var arry = [];
15     var DEFAULT_INTERVAL = 100;
16
17     var utils = {
18
19       isDomObj: function(obj) {
20         return !!(obj.nodeType || (obj === window));
21       },
22
23       toArray: function(obj, from) {
24         return arry.slice.call(obj, from);
25       },
26
27       // returns new object representing multiple objects merged together
28       // optional final argument is boolean which specifies if merge is recursive
29       // original objects are unmodified
30       //
31       // usage:
32       //   var base = {a:2, b:6};
33       //   var extra = {b:3, c:4};
34       //   merge(base, extra); //{a:2, b:3, c:4}
35       //   base; //{a:2, b:6}
36       //
37       //   var base = {a:2, b:6};
38       //   var extra = {b:3, c:4};
39       //   var extraExtra = {a:4, d:9};
40       //   merge(base, extra, extraExtra); //{a:4, b:3, c:4. d: 9}
41       //   base; //{a:2, b:6}
42       //
43       //   var base = {a:2, b:{bb:4, cc:5}};
44       //   var extra = {a:4, b:{cc:7, dd:1}};
45       //   merge(base, extra, true); //{a:4, b:{bb:4, cc:7, dd:1}}
46       //   base; //{a:2, b:6}
47
48       merge: function(/*obj1, obj2,....deepCopy*/) {
49         // unpacking arguments by hand benchmarked faster
50         var l = arguments.length,
51             i = 0,
52             args = new Array(l + 1);
53         for (; i < l; i++) args[i + 1] = arguments[i];
54
55         if (l === 0) {
56           return {};
57         }
58
59         //start with empty object so a copy is created
60         args[0] = {};
61
62         if (args[args.length - 1] === true) {
63           //jquery extend requires deep copy as first arg
64           args.pop();
65           args.unshift(true);
66         }
67
68         return $.extend.apply(undefined, args);
69       },
70
71       // updates base in place by copying properties of extra to it
72       // optionally clobber protected
73       // usage:
74       //   var base = {a:2, b:6};
75       //   var extra = {c:4};
76       //   push(base, extra); //{a:2, b:6, c:4}
77       //   base; //{a:2, b:6, c:4}
78       //
79       //   var base = {a:2, b:6};
80       //   var extra = {b: 4 c:4};
81       //   push(base, extra, true); //Error ("utils.push attempted to overwrite 'b' while running in protected mode")
82       //   base; //{a:2, b:6}
83       //
84       // objects with the same key will merge recursively when protect is false
85       // eg:
86       // var base = {a:16, b:{bb:4, cc:10}};
87       // var extra = {b:{cc:25, dd:19}, c:5};
88       // push(base, extra); //{a:16, {bb:4, cc:25, dd:19}, c:5}
89       //
90       push: function(base, extra, protect) {
91         if (base) {
92           Object.keys(extra || {}).forEach(function(key) {
93             if (base[key] && protect) {
94               throw new Error('utils.push attempted to overwrite "' + key + '" while running in protected mode');
95             }
96
97             if (typeof base[key] == 'object' && typeof extra[key] == 'object') {
98               // recurse
99               this.push(base[key], extra[key]);
100             } else {
101               // no protect, so extra wins
102               base[key] = extra[key];
103             }
104           }, this);
105         }
106
107         return base;
108       },
109
110       isEnumerable: function(obj, property) {
111         return Object.keys(obj).indexOf(property) > -1;
112       },
113
114       // build a function from other function(s)
115       // utils.compose(a,b,c) -> a(b(c()));
116       // implementation lifted from underscore.js (c) 2009-2012 Jeremy Ashkenas
117       compose: function() {
118         var funcs = arguments;
119
120         return function() {
121           var args = arguments;
122
123           for (var i = funcs.length-1; i >= 0; i--) {
124             args = [funcs[i].apply(this, args)];
125           }
126
127           return args[0];
128         };
129       },
130
131       // Can only unique arrays of homogeneous primitives, e.g. an array of only strings, an array of only booleans, or an array of only numerics
132       uniqueArray: function(array) {
133         var u = {}, a = [];
134
135         for (var i = 0, l = array.length; i < l; ++i) {
136           if (u.hasOwnProperty(array[i])) {
137             continue;
138           }
139
140           a.push(array[i]);
141           u[array[i]] = 1;
142         }
143
144         return a;
145       },
146
147       debounce: function(func, wait, immediate) {
148         if (typeof wait != 'number') {
149           wait = DEFAULT_INTERVAL;
150         }
151
152         var timeout, result;
153
154         return function() {
155           var context = this, args = arguments;
156           var later = function() {
157             timeout = null;
158             if (!immediate) {
159               result = func.apply(context, args);
160             }
161           };
162           var callNow = immediate && !timeout;
163
164           clearTimeout(timeout);
165           timeout = setTimeout(later, wait);
166
167           if (callNow) {
168             result = func.apply(context, args);
169           }
170
171           return result;
172         };
173       },
174
175       throttle: function(func, wait) {
176         if (typeof wait != 'number') {
177           wait = DEFAULT_INTERVAL;
178         }
179
180         var context, args, timeout, throttling, more, result;
181         var whenDone = this.debounce(function(){
182           more = throttling = false;
183         }, wait);
184
185         return function() {
186           context = this; args = arguments;
187           var later = function() {
188             timeout = null;
189             if (more) {
190               result = func.apply(context, args);
191             }
192             whenDone();
193           };
194
195           if (!timeout) {
196             timeout = setTimeout(later, wait);
197           }
198
199           if (throttling) {
200             more = true;
201           } else {
202             throttling = true;
203             result = func.apply(context, args);
204           }
205
206           whenDone();
207           return result;
208         };
209       },
210
211       countThen: function(num, base) {
212         return function() {
213           if (!--num) { return base.apply(this, arguments); }
214         };
215       },
216
217       delegate: function(rules) {
218         return function(e, data) {
219           var target = $(e.target), parent;
220
221           Object.keys(rules).forEach(function(selector) {
222             if ((parent = target.closest(selector)).length) {
223               data = data || {};
224               data.el = parent[0];
225               return rules[selector].apply(this, [e, data]);
226             }
227           }, this);
228         };
229       }
230
231     };
232
233     return utils;
234   }
235 );