diff options
author | Jose Antonio Marquez | 2012-05-16 15:42:37 -0700 |
---|---|---|
committer | Jose Antonio Marquez | 2012-05-16 15:42:37 -0700 |
commit | 857aafee732b6a85fa155ff4a05d1b8fde48f09d (patch) | |
tree | e06d330caee280aa05aec46391979e9abdcf974c /node_modules/montage/core/extras/array.js | |
parent | 5cc5d29736d8bf253e3a168cdd6443e839ffb23c (diff) | |
parent | fd54dabad7cbc27a0efb0957155c00d578912909 (diff) | |
download | ninja-857aafee732b6a85fa155ff4a05d1b8fde48f09d.tar.gz |
Merge branch 'refs/heads/Ninja-DOM-Architecture' into Document
Diffstat (limited to 'node_modules/montage/core/extras/array.js')
-rwxr-xr-x | node_modules/montage/core/extras/array.js | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/node_modules/montage/core/extras/array.js b/node_modules/montage/core/extras/array.js new file mode 100755 index 00000000..73e1bd87 --- /dev/null +++ b/node_modules/montage/core/extras/array.js | |||
@@ -0,0 +1,292 @@ | |||
1 | /* <copyright> | ||
2 | This file contains proprietary software owned by Motorola Mobility, Inc.<br/> | ||
3 | No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> | ||
4 | (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. | ||
5 | </copyright> */ | ||
6 | /** | ||
7 | Defines extensions to native Array object. | ||
8 | @see [Array class]{@link external:Array} | ||
9 | @module montage/core/shim/array | ||
10 | */ | ||
11 | /** | ||
12 | @external Array | ||
13 | */ | ||
14 | |||
15 | /** | ||
16 | @function external:Array#equals | ||
17 | @param {object} right The object to compare. | ||
18 | @returns {Boolean} true or false | ||
19 | */ | ||
20 | if (!Array.prototype.equals) { | ||
21 | Object.defineProperty(Array.prototype, "equals", { | ||
22 | value: function (right) { | ||
23 | var i = 0, | ||
24 | length = this.length, | ||
25 | lhs, | ||
26 | rhs; | ||
27 | |||
28 | if (this === right) { | ||
29 | return true; | ||
30 | } | ||
31 | |||
32 | if (!right || !Array.isArray(right)) { | ||
33 | return false; | ||
34 | } | ||
35 | |||
36 | if (length !== right.length) { | ||
37 | return false; | ||
38 | } else { | ||
39 | for (; i < length; ++i) { | ||
40 | if (i in this) { | ||
41 | lhs = this[i], | ||
42 | rhs = right[i]; | ||
43 | |||
44 | if (lhs !== rhs && (lhs && rhs && !lhs.equals(rhs))) { | ||
45 | return false; | ||
46 | } | ||
47 | } else { | ||
48 | if (i in right) { | ||
49 | return false; | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | return true; | ||
55 | } | ||
56 | }); | ||
57 | } | ||
58 | Object.defineProperty(Array, "isCanvasPixelArray", { | ||
59 | value: function(obj) { | ||
60 | return Object.prototype.toString.call(obj) === "[object CanvasPixelArray]"; | ||
61 | } | ||
62 | }); | ||
63 | |||
64 | /** | ||
65 | Description | ||
66 | @member external:Array#getProperty | ||
67 | @function | ||
68 | @param {Object} aPropertyPath | ||
69 | @param {Property} unique | ||
70 | @param {Property} preserve | ||
71 | @param {Function} visitedComponentCallback | ||
72 | @param {Array} currentIndex | ||
73 | */ | ||
74 | var _index_array_regexp = /^[0-9]+$/; | ||
75 | Object.defineProperty(Array.prototype, "getProperty", { | ||
76 | value: function(aPropertyPath, unique, preserve, visitedComponentCallback, currentIndex) { | ||
77 | |||
78 | if (aPropertyPath == null) { | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | currentIndex = currentIndex || 0; | ||
83 | |||
84 | var result, | ||
85 | propertyIsNumber = _index_array_regexp.test(aPropertyPath),//!isNaN(aPropertyPath), | ||
86 | parenthesisStartIndex = propertyIsNumber ? -1 : aPropertyPath.indexOf("(", currentIndex), | ||
87 | parenthesisEndIndex = propertyIsNumber ? -1 : aPropertyPath.lastIndexOf(")"), | ||
88 | currentPathComponentEndIndex = propertyIsNumber ? -1 : aPropertyPath.indexOf(".", currentIndex), | ||
89 | nextDelimiterIndex = -1, | ||
90 | itemResult, | ||
91 | index, | ||
92 | currentPathComponent, | ||
93 | functionName, | ||
94 | functionArgPropertyPath, | ||
95 | tmpResult, | ||
96 | uniques; | ||
97 | |||
98 | // PARSE: Determine the indices of the currentPathComponent we're concerned with | ||
99 | |||
100 | if (currentPathComponentEndIndex > -1 && parenthesisStartIndex > -1) { | ||
101 | // We have both a dot and an open parenthesis somewhere in the path, figure out the next path component | ||
102 | if (currentPathComponentEndIndex > parenthesisStartIndex) { | ||
103 | // The next dot was actually inside the function call; use the entire function call: foo.bar(a.b.c) -> bar(a.b.c) | ||
104 | nextDelimiterIndex = parenthesisEndIndex + 1; | ||
105 | functionName = aPropertyPath.substring(currentIndex, parenthesisStartIndex); | ||
106 | } else { | ||
107 | // The next dot comes before the start of the function parenthesis; use the dot: foo.bar(a.b.c) -> foo | ||
108 | nextDelimiterIndex = currentPathComponentEndIndex; | ||
109 | } | ||
110 | } else { | ||
111 | // We have either a dot, parenthesis, or neither | ||
112 | if (parenthesisStartIndex > -1) { | ||
113 | // we had a starting parenthesis; use the END parenthesis to include the entire function call | ||
114 | nextDelimiterIndex = parenthesisEndIndex + 1; | ||
115 | functionName = aPropertyPath.substring(currentIndex, parenthesisStartIndex); | ||
116 | } else { | ||
117 | nextDelimiterIndex = currentPathComponentEndIndex; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | // Find the component of the propertyPath we want to deal with during this particular invocation of this function | ||
122 | currentPathComponent = propertyIsNumber ? aPropertyPath : aPropertyPath.substring(currentIndex, (nextDelimiterIndex === -1 ? aPropertyPath.length : nextDelimiterIndex)); | ||
123 | |||
124 | // EVALUATE: Determine the value of the currentPathComponent | ||
125 | |||
126 | if (functionName) { | ||
127 | // We have a function to execute as part of this propertyPath; execute it assuming that it will know | ||
128 | // how to handle the property path being passed along | ||
129 | |||
130 | // TODO do we call this before or after finding the result (probably before to maintain the chain | ||
131 | // of one invocation's discovered value being the context of the next invocation | ||
132 | if (visitedComponentCallback) { | ||
133 | visitedComponentCallback(this, functionName + "()", null, null, null); | ||
134 | } | ||
135 | |||
136 | functionArgPropertyPath = aPropertyPath.substring(parenthesisStartIndex + 1, parenthesisEndIndex); | ||
137 | result = this[functionName](functionArgPropertyPath, visitedComponentCallback); | ||
138 | |||
139 | |||
140 | } else { | ||
141 | |||
142 | // TODO we don't provide any way to access properties that are actually accessible on the array itself | ||
143 | // we assume that by default, any property in a propertyPath after an array refers to a property | ||
144 | // you are interested in getting on each member of the array | ||
145 | |||
146 | if (isNaN(currentPathComponent)) { | ||
147 | |||
148 | if (visitedComponentCallback) { | ||
149 | //console.log("....", currentPathComponent, aPropertyPath , currentPathComponentEndIndex != -1 ? aPropertyPath.slice(currentPathComponentEndIndex + 1) : null); | ||
150 | //console.log(aPropertyPath.slice(currentIndex)); | ||
151 | visitedComponentCallback(this, null, undefined, null, aPropertyPath.slice(currentIndex)); | ||
152 | } | ||
153 | |||
154 | result = []; | ||
155 | index = 0; | ||
156 | |||
157 | // The currentPathComponent is some property not directly on this array, and not an index in the array | ||
158 | // so we'll be getting an array of resolving this currentPathComponent on each member in the array | ||
159 | if (preserve) { | ||
160 | |||
161 | while((itemResult = this[index]) != null) { | ||
162 | result[index] = itemResult.getProperty(aPropertyPath, unique, preserve, visitedComponentCallback, currentIndex); | ||
163 | index++; | ||
164 | } | ||
165 | |||
166 | } else { | ||
167 | |||
168 | // TODO in either case, why do we stop if we encounter null|undefined? there could be useful | ||
169 | // values after that in the collection. I already had to fix an issue here where a zero | ||
170 | // would short-circuit the loop | ||
171 | while((itemResult = this[index]) != null) { | ||
172 | tmpResult = itemResult.getProperty(aPropertyPath, unique, preserve, visitedComponentCallback, currentIndex); | ||
173 | |||
174 | if (Array.isArray(tmpResult)) { | ||
175 | result = result.concat(tmpResult); | ||
176 | } else { | ||
177 | result[index] = tmpResult; | ||
178 | } | ||
179 | index++; | ||
180 | } | ||
181 | |||
182 | if (unique) { | ||
183 | var uniques = {}; // TODO reuse this object if possible | ||
184 | // TODO don't recreate this filter function each time | ||
185 | result = result.filter(function(element) { | ||
186 | return uniques[element] ? false : (uniques[element] = true); | ||
187 | }); | ||
188 | } | ||
189 | |||
190 | } | ||
191 | |||
192 | } else { | ||
193 | |||
194 | // The currentPathComponent is an index into this array | ||
195 | result = this[currentPathComponent]; | ||
196 | |||
197 | |||
198 | if (visitedComponentCallback) { | ||
199 | visitedComponentCallback(this, currentPathComponent, result, null, currentPathComponentEndIndex != -1 ? aPropertyPath.slice(currentPathComponentEndIndex + 1) : null); | ||
200 | } | ||
201 | |||
202 | if (currentPathComponentEndIndex > 0) { | ||
203 | result = result ? result.getProperty(aPropertyPath, unique, preserve, visitedComponentCallback, currentPathComponentEndIndex + 1) : undefined; | ||
204 | } else if (visitedComponentCallback && currentPathComponentEndIndex === -1 && result) { | ||
205 | // If we're at the end of the path, but have a result, visit it | ||
206 | //visitedComponentCallback(result, null, null, null, null); | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | |||
211 | return result; | ||
212 | }, | ||
213 | enumerable: false | ||
214 | }); | ||
215 |