@angular-wave/angular.ts 0.0.39 → 0.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Makefile +2 -0
- package/README.md +2 -1
- package/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -1
- package/package.json +1 -1
- package/rollup.config.js +10 -5
- package/src/angular.spec.js +25 -26
- package/src/animations/animate-css-driver.js +3 -3
- package/src/animations/animate-queue.js +10 -7
- package/src/animations/animation.js +2 -2
- package/src/animations/shared.js +6 -6
- package/src/binding.spec.js +7 -7
- package/src/core/animate/animate.js +5 -5
- package/src/core/animate/animate.spec.js +31 -31
- package/src/core/cache/cache-factory.html +18 -0
- package/src/core/cache/{cache-factor.test.js → cache-factory.test.js} +1 -1
- package/src/core/compile/compile.js +33 -25
- package/src/core/compile/compile.md +2 -2
- package/src/core/compile/compile.spec.js +2 -43
- package/src/core/cookie-reader.spec.js +2 -2
- package/src/core/core.html +22 -0
- package/src/core/core.test.js +12 -0
- package/src/core/document.spec.js +4 -4
- package/src/core/exception-handler.js +30 -23
- package/src/core/interpolate/interpolate.js +7 -0
- package/src/core/{cache/cache-factor.html → location/location.html} +1 -1
- package/src/core/location/location.js +2 -2
- package/src/core/location/location.spec.js +17 -17
- package/src/core/location/location.test.js +12 -0
- package/src/core/on.spec.js +3 -3
- package/src/core/parser/parse.html +18 -0
- package/src/core/parser/parse.spec.js +1 -1
- package/src/core/parser/parse.test.js +12 -0
- package/src/core/prop.spec.js +3 -4
- package/src/core/pubsub/pubsub.html +18 -0
- package/src/core/pubsub/pubsub.spec.js +1 -1
- package/src/core/pubsub/pubsub.test.js +12 -0
- package/src/core/q/q.html +18 -0
- package/src/core/q/q.js +33 -0
- package/src/core/q/q.test.js +0 -0
- package/src/core/root-element.spec.js +4 -4
- package/src/core/sanitize/sanitize-uri.spec.js +1 -1
- package/src/core/sanitize/sanitize-uri.test.js +12 -0
- package/src/core/sanitize/sanitize.html +21 -0
- package/src/core/sce/sce.html +18 -0
- package/src/core/sce/sce.spec.js +2 -1
- package/src/core/sce/sce.test.js +12 -0
- package/src/core/scope/scope.html +18 -0
- package/src/core/scope/scope.js +1 -1
- package/src/core/scope/scope.spec.js +1 -1
- package/src/core/scope/scope.test.js +12 -0
- package/src/core/task-tracker-factory.js +9 -11
- package/src/core/timeout/timeout.html +18 -0
- package/src/core/timeout/timeout.js +9 -0
- package/src/core/timeout/timeout.spec.js +2 -2
- package/src/core/timeout/timout.test.js +12 -0
- package/src/core/url-utils/url-utils.html +18 -0
- package/src/core/url-utils/url-utils.spec.js +4 -2
- package/src/core/url-utils/url-utils.test.js +12 -0
- package/src/directive/attrs/attrs.spec.js +1 -2
- package/src/directive/attrs/boolean.spec.js +1 -2
- package/src/directive/attrs/element-style.spec.js +6 -7
- package/src/directive/attrs/src.spec.js +1 -2
- package/src/directive/bind/bind.spec.js +1 -2
- package/src/directive/class/class.spec.js +15 -16
- package/src/directive/cloak/cloak.spec.js +3 -4
- package/src/directive/controller/controller.spec.js +4 -5
- package/src/directive/events/click.spec.js +1 -2
- package/src/directive/events/event.spec.js +1 -1
- package/src/directive/events/events.js +7 -0
- package/src/directive/form/form.spec.js +17 -17
- package/src/directive/if/if.spec.js +2 -2
- package/src/directive/include/include.js +5 -7
- package/src/directive/include/include.spec.js +32 -32
- package/src/directive/init/init.spec.js +2 -3
- package/src/directive/input/input.spec.js +3 -3
- package/src/directive/list/list.spec.js +1 -2
- package/src/directive/model/model.js +13 -0
- package/src/directive/model/model.spec.js +4 -5
- package/src/directive/model-options/model-options.spec.js +3 -3
- package/src/directive/non-bindable/non-bindable.spec.js +1 -2
- package/src/directive/options/options.js +5 -5
- package/src/directive/options/options.spec.js +13 -13
- package/src/directive/ref/href.spec.js +1 -2
- package/src/directive/repeat/repeat.spec.js +12 -12
- package/src/directive/script/script.spec.js +2 -3
- package/src/directive/select/select.js +6 -6
- package/src/directive/select/select.spec.js +5 -5
- package/src/directive/show-hide/show-hide.spec.js +12 -13
- package/src/directive/style/style.spec.js +3 -4
- package/src/directive/switch/switch.spec.js +2 -3
- package/src/directive/validators/validators.spec.js +1 -1
- package/src/exts/aria/aria.spec.js +1 -2
- package/src/exts/messages/messages.spec.js +5 -5
- package/src/filters/filter.spec.js +5 -5
- package/src/filters/filters.html +21 -0
- package/src/filters/filters.spec.js +3 -3
- package/src/filters/filters.test.js +12 -0
- package/src/filters/limit-to.md +1 -1
- package/src/filters/limit-to.spec.js +4 -4
- package/src/filters/order-by.spec.js +2 -2
- package/src/index.js +186 -31
- package/src/loader.js +49 -11
- package/src/public.js +2 -3
- package/src/router/directives/state-directives.spec.js +90 -90
- package/src/router/directives/view-directive.js +2 -2
- package/src/router/directives/view-directive.spec.js +9 -9
- package/src/router/state/state.spec.js +2 -4
- package/src/router/template-factory.spec.js +2 -2
- package/src/router/transition/hook-registry.js +2 -2
- package/src/router/view/view.spec.js +1 -1
- package/src/services/browser.js +56 -39
- package/src/services/document.js +16 -13
- package/src/services/http/http.js +11 -7
- package/src/services/log.js +39 -43
- package/src/services/template-request.js +9 -0
- package/src/shared/common.js +0 -3
- package/src/shared/jqlite/jqlite.js +370 -355
- package/src/shared/jqlite/jqlite.spec.js +260 -272
- package/src/shared/strings.js +2 -2
- package/src/shared/test-utils.js +2 -2
- package/src/shared/utils.js +8 -11
- package/src/types.js +13 -0
- package/types/animations/shared.d.ts +7 -2
- package/types/core/compile/compile.d.ts +2 -1
- package/types/core/exception-handler.d.ts +9 -42
- package/types/core/interpolate/interpolate.d.ts +1 -1
- package/types/core/q/q.d.ts +35 -1
- package/types/core/task-tracker-factory.d.ts +18 -11
- package/types/core/timeout/timeout.d.ts +10 -1
- package/types/directive/include/include.d.ts +2 -2
- package/types/directive/model/model.d.ts +28 -4
- package/types/index.d.ts +664 -79
- package/types/services/browser.d.ts +50 -20
- package/types/services/document.d.ts +14 -9
- package/types/services/log.d.ts +37 -34
- package/types/services/template-request.d.ts +1 -1
- package/types/shared/common.d.ts +0 -1
- package/types/shared/jqlite/jqlite.d.ts +83 -22
- package/types/shared/utils.d.ts +22 -22
- package/types/types.d.ts +34 -0
- package/types-back/index.d.ts +0 -130
- package/types-back/jqlite.d.ts +1 -40
- /package/src/core/cache/{cache-factor.spec.js → cache-factory.spec.js} +0 -0
|
@@ -12,12 +12,10 @@ import {
|
|
|
12
12
|
lowercase,
|
|
13
13
|
nodeName_,
|
|
14
14
|
shallowCopy,
|
|
15
|
-
trim,
|
|
16
15
|
} from "../../shared/utils";
|
|
17
16
|
import { CACHE, EXPANDO } from "../../core/cache/cache";
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
|
-
* @ngdoc function
|
|
21
19
|
* @name angular.element
|
|
22
20
|
* @module ng
|
|
23
21
|
* @kind function
|
|
@@ -26,24 +24,23 @@ import { CACHE, EXPANDO } from "../../core/cache/cache";
|
|
|
26
24
|
* Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. Regardless of the presence of jQuery, `angular.element`
|
|
27
25
|
* delegates to AngularJS's built-in subset of jQuery, called "jQuery lite" or **jqLite**.
|
|
28
26
|
*
|
|
29
|
-
*
|
|
30
|
-
* AngularJS to manipulate the DOM in a cross-browser compatible way.
|
|
27
|
+
* JQLite is a tiny, API-compatible subset of jQuery that allows
|
|
28
|
+
* AngularJS to manipulate the DOM in a cross-browser compatible way. JQLite implements only the most
|
|
31
29
|
* commonly needed functionality with the goal of having a very small footprint.
|
|
32
30
|
*
|
|
33
|
-
*
|
|
34
31
|
* <div class="alert alert-info">**Note:** All element references in AngularJS are always wrapped with
|
|
35
|
-
*
|
|
32
|
+
* JQLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.</div>
|
|
36
33
|
*
|
|
37
34
|
* <div class="alert alert-warning">**Note:** Keep in mind that this function will not find elements
|
|
38
35
|
* by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)`
|
|
39
36
|
* or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.</div>
|
|
40
37
|
*
|
|
41
|
-
* ## AngularJS's
|
|
42
|
-
*
|
|
38
|
+
* ## AngularJS's JQLite
|
|
39
|
+
* JQLite provides only the following jQuery methods:
|
|
43
40
|
*
|
|
44
41
|
* - [`after()`](http://api.jquery.com/after/)
|
|
45
42
|
* - [`append()`](http://api.jquery.com/append/) - Contrary to jQuery, this doesn't clone elements
|
|
46
|
-
* so will not work correctly when invoked on a
|
|
43
|
+
* so will not work correctly when invoked on a JQLite object containing more than one DOM node
|
|
47
44
|
* - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
|
|
48
45
|
* - [`children()`](http://api.jquery.com/children/) - Does not support selectors
|
|
49
46
|
* - [`data()`](http://api.jquery.com/data/)
|
|
@@ -52,7 +49,6 @@ import { CACHE, EXPANDO } from "../../core/cache/cache";
|
|
|
52
49
|
* - [`html()`](http://api.jquery.com/html/)
|
|
53
50
|
* - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
|
|
54
51
|
* - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter
|
|
55
|
-
* - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
|
|
56
52
|
* - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
|
|
57
53
|
* - [`prepend()`](http://api.jquery.com/prepend/)
|
|
58
54
|
* - [`remove()`](http://api.jquery.com/remove/)
|
|
@@ -63,10 +59,10 @@ import { CACHE, EXPANDO } from "../../core/cache/cache";
|
|
|
63
59
|
* - [`val()`](http://api.jquery.com/val/)
|
|
64
60
|
*
|
|
65
61
|
* ## jQuery/jqLite Extras
|
|
66
|
-
* AngularJS also provides the following additional methods and events to both jQuery and
|
|
62
|
+
* AngularJS also provides the following additional methods and events to both jQuery and JQLite:
|
|
67
63
|
*
|
|
68
64
|
* ### Events
|
|
69
|
-
* - `$destroy` - AngularJS intercepts all
|
|
65
|
+
* - `$destroy` - AngularJS intercepts all JQLite/jQuery's DOM destruction apis and fires this event
|
|
70
66
|
* on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM
|
|
71
67
|
* element before it is removed.
|
|
72
68
|
*
|
|
@@ -93,6 +89,7 @@ import { CACHE, EXPANDO } from "../../core/cache/cache";
|
|
|
93
89
|
* @returns {Object} jQuery object.
|
|
94
90
|
*/
|
|
95
91
|
|
|
92
|
+
/** @type {number} */
|
|
96
93
|
let jqId = 1;
|
|
97
94
|
|
|
98
95
|
function jqNextId() {
|
|
@@ -102,7 +99,7 @@ function jqNextId() {
|
|
|
102
99
|
const DASH_LOWERCASE_REGEXP = /-([a-z])/g;
|
|
103
100
|
const UNDERSCORE_LOWERCASE_REGEXP = /_([a-z])/g;
|
|
104
101
|
const MOUSE_EVENT_MAP = { mouseleave: "mouseout", mouseenter: "mouseover" };
|
|
105
|
-
const
|
|
102
|
+
const JQLiteMinErr = minErr("jqLite");
|
|
106
103
|
|
|
107
104
|
/**
|
|
108
105
|
* @param {string} _all
|
|
@@ -153,177 +150,66 @@ wrapMap.tbody =
|
|
|
153
150
|
wrapMap.thead;
|
|
154
151
|
wrapMap.th = wrapMap.td;
|
|
155
152
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
153
|
+
export const BOOLEAN_ATTR = {};
|
|
154
|
+
"multiple,selected,checked,disabled,readOnly,required,open"
|
|
155
|
+
.split(",")
|
|
156
|
+
.forEach((value) => {
|
|
157
|
+
BOOLEAN_ATTR[lowercase(value)] = value;
|
|
158
|
+
});
|
|
159
|
+
const BOOLEAN_ELEMENTS = {};
|
|
160
|
+
"input,select,option,textarea,button,form,details"
|
|
161
|
+
.split(",")
|
|
162
|
+
.forEach((value) => {
|
|
163
|
+
BOOLEAN_ELEMENTS[value] = true;
|
|
164
|
+
});
|
|
164
165
|
|
|
165
166
|
/**
|
|
167
|
+
* JQLite both a function and an array-like data structure for manipulation of DOM, linking elements to expando cache,
|
|
168
|
+
* and execution of chain functions.
|
|
166
169
|
*
|
|
167
|
-
* @param {Element}
|
|
168
|
-
* @returns {
|
|
170
|
+
* @param {string|Element|Document|Window|JQLite|ArrayLike<Element>|(() => void)} element
|
|
171
|
+
* @returns {JQLite}
|
|
169
172
|
*/
|
|
170
|
-
function elementAcceptsData(node) {
|
|
171
|
-
// The window object can accept data but has no nodeType
|
|
172
|
-
// Otherwise we are only interested in elements (1) and documents (9)
|
|
173
|
-
switch (node.nodeType) {
|
|
174
|
-
case Node.ELEMENT_NODE:
|
|
175
|
-
case Node.DOCUMENT_NODE:
|
|
176
|
-
case undefined:
|
|
177
|
-
return true;
|
|
178
|
-
default:
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export function jqLiteBuildFragment(html, context) {
|
|
184
|
-
let tmp;
|
|
185
|
-
let tag;
|
|
186
|
-
let wrap;
|
|
187
|
-
let finalHtml;
|
|
188
|
-
const fragment = context.createDocumentFragment();
|
|
189
|
-
let nodes = [];
|
|
190
|
-
let i;
|
|
191
|
-
|
|
192
|
-
if (isTextNode(html)) {
|
|
193
|
-
// Convert non-html into a text node
|
|
194
|
-
nodes.push(context.createTextNode(html));
|
|
195
|
-
} else {
|
|
196
|
-
// Convert html into DOM nodes
|
|
197
|
-
tmp = fragment.appendChild(context.createElement("div"));
|
|
198
|
-
tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
|
|
199
|
-
finalHtml = html;
|
|
200
|
-
|
|
201
|
-
wrap = wrapMap[tag] || [];
|
|
202
|
-
|
|
203
|
-
// Create wrappers & descend into them
|
|
204
|
-
i = wrap.length;
|
|
205
|
-
while (--i > -1) {
|
|
206
|
-
tmp.appendChild(window.document.createElement(wrap[i]));
|
|
207
|
-
tmp = tmp.firstChild;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
tmp.innerHTML = finalHtml;
|
|
211
|
-
|
|
212
|
-
nodes = concat(nodes, tmp.childNodes);
|
|
213
|
-
|
|
214
|
-
tmp = fragment.firstChild;
|
|
215
|
-
tmp.textContent = "";
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Remove wrapper from fragment
|
|
219
|
-
fragment.textContent = "";
|
|
220
|
-
fragment.innerHTML = ""; // Clear inner HTML
|
|
221
|
-
forEach(nodes, (node) => {
|
|
222
|
-
fragment.appendChild(node);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
return fragment;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function jqLiteParseHTML(html, context) {
|
|
229
|
-
context = context || window.document;
|
|
230
|
-
let parsed;
|
|
231
|
-
|
|
232
|
-
if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
|
|
233
|
-
return [context.createElement(parsed[1])];
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if ((parsed = jqLiteBuildFragment(html, context))) {
|
|
237
|
-
return parsed.childNodes;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return [];
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
|
|
244
|
-
const jqLiteContains =
|
|
245
|
-
window.Node.prototype.contains ||
|
|
246
|
-
function (arg) {
|
|
247
|
-
return !!(this.compareDocumentPosition(arg) & 16);
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
/// //////////////////////////////////////////
|
|
251
173
|
export function JQLite(element) {
|
|
252
174
|
if (element instanceof JQLite) {
|
|
253
175
|
return element;
|
|
254
176
|
}
|
|
255
177
|
|
|
256
|
-
let argIsString;
|
|
178
|
+
let argIsString = false;
|
|
257
179
|
|
|
258
180
|
if (isString(element)) {
|
|
259
|
-
element =
|
|
181
|
+
element = /** @type {string} */ (element).trim();
|
|
260
182
|
argIsString = true;
|
|
261
183
|
}
|
|
184
|
+
|
|
262
185
|
if (!(this instanceof JQLite)) {
|
|
263
|
-
if (argIsString && element.charAt(0) !== "<") {
|
|
264
|
-
throw
|
|
186
|
+
if (argIsString && /** @type {string} */ (element).charAt(0) !== "<") {
|
|
187
|
+
throw JQLiteMinErr(
|
|
265
188
|
"nosel",
|
|
266
|
-
"Looking up elements via selectors is not supported by
|
|
189
|
+
"Looking up elements via selectors is not supported by JQLite! See: http://docs.angularjs.org/api/angular.element",
|
|
267
190
|
);
|
|
268
191
|
}
|
|
269
192
|
return new JQLite(element);
|
|
270
193
|
}
|
|
271
194
|
|
|
272
195
|
if (argIsString) {
|
|
273
|
-
const parsed =
|
|
196
|
+
const parsed = parseHtml(/** @type {string} */ (element));
|
|
274
197
|
addNodes(this, parsed);
|
|
275
198
|
} else if (isFunction(element)) {
|
|
276
|
-
|
|
199
|
+
onReady(/** @type {Function} */ (element));
|
|
277
200
|
} else {
|
|
278
201
|
addNodes(this, element);
|
|
279
202
|
}
|
|
280
203
|
}
|
|
281
|
-
export var jqLite = JQLite;
|
|
282
|
-
|
|
283
|
-
jqLite.CACHE = CACHE;
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* @param {Element} element
|
|
287
|
-
* @param {boolean} [onlyDescendants]
|
|
288
|
-
* @returns {void}
|
|
289
|
-
*/
|
|
290
|
-
export function dealoc(element, onlyDescendants) {
|
|
291
|
-
if (!element) return;
|
|
292
|
-
if (!onlyDescendants && elementAcceptsData(element))
|
|
293
|
-
jqLiteCleanData([element]);
|
|
294
|
-
|
|
295
|
-
if (element.querySelectorAll) {
|
|
296
|
-
jqLiteCleanData(element.querySelectorAll("*"));
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* If `ExpandoStore.data` and `ExpandoStore.events` are empty,
|
|
302
|
-
* then delete element's `ExpandoStore` and set its `ExpandoId`
|
|
303
|
-
* to undefined.
|
|
304
|
-
* @param {Element} element
|
|
305
|
-
*/
|
|
306
|
-
function removeIfEmptyData(element) {
|
|
307
|
-
const expandoId = element[EXPANDO];
|
|
308
|
-
const { events, data } = CACHE.get(expandoId);
|
|
309
|
-
|
|
310
|
-
if (
|
|
311
|
-
(!data || !Object.keys(data).length) &&
|
|
312
|
-
(!events || !Object.keys(events).length)
|
|
313
|
-
) {
|
|
314
|
-
CACHE.delete(expandoId);
|
|
315
|
-
element[EXPANDO] = undefined; // don't delete DOM expandos. Chrome don't like it
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
204
|
|
|
319
|
-
function
|
|
205
|
+
function JQLiteOff(element, type, fn, unsupported) {
|
|
320
206
|
if (isDefined(unsupported))
|
|
321
|
-
throw
|
|
207
|
+
throw JQLiteMinErr(
|
|
322
208
|
"offargs",
|
|
323
209
|
"jqLite#off() does not support the `selector` argument",
|
|
324
210
|
);
|
|
325
211
|
|
|
326
|
-
const expandoStore =
|
|
212
|
+
const expandoStore = getExpando(element);
|
|
327
213
|
const events = expandoStore && expandoStore.events;
|
|
328
214
|
const handle = expandoStore && expandoStore.handle;
|
|
329
215
|
|
|
@@ -366,7 +252,7 @@ function jqLiteOff(element, type, fn, unsupported) {
|
|
|
366
252
|
* @param {Element} element
|
|
367
253
|
* @param {string} [name] - key of field to remove
|
|
368
254
|
*/
|
|
369
|
-
function
|
|
255
|
+
export function removeElementData(element, name) {
|
|
370
256
|
const expandoId = element[EXPANDO];
|
|
371
257
|
const expandoStore = expandoId && CACHE.get(expandoId);
|
|
372
258
|
|
|
@@ -382,12 +268,15 @@ function jqLiteRemoveData(element, name) {
|
|
|
382
268
|
}
|
|
383
269
|
|
|
384
270
|
/**
|
|
271
|
+
* Stores data associated with an element inside the expando property of the DOM element.
|
|
272
|
+
*
|
|
273
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Glossary/Expando MDN Glossary: Expando}
|
|
385
274
|
*
|
|
386
275
|
* @param {Element} element
|
|
387
|
-
* @param {boolean} createIfNecessary
|
|
388
|
-
* @returns {import("
|
|
276
|
+
* @param {boolean} [createIfNecessary=false]
|
|
277
|
+
* @returns {import("../../core/cache/cache").ExpandoStore}
|
|
389
278
|
*/
|
|
390
|
-
function
|
|
279
|
+
function getExpando(element, createIfNecessary = false) {
|
|
391
280
|
let expandoId = element[EXPANDO];
|
|
392
281
|
let expandoStore = expandoId && CACHE.get(expandoId);
|
|
393
282
|
|
|
@@ -404,14 +293,141 @@ function jqLiteExpandoStore(element, createIfNecessary = false) {
|
|
|
404
293
|
return expandoStore;
|
|
405
294
|
}
|
|
406
295
|
|
|
407
|
-
|
|
296
|
+
/**
|
|
297
|
+
* Checks if the string contains HTML tags or entities.
|
|
298
|
+
* @param {string} html
|
|
299
|
+
* @returns {boolean} True if the string is plain text, false if it contains HTML tags or entities.
|
|
300
|
+
*/
|
|
301
|
+
export function isTextNode(html) {
|
|
302
|
+
return !/<|&#?\w+;/.test(html);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Check if element can accept expando data
|
|
307
|
+
* @param {Element} node
|
|
308
|
+
* @returns {boolean}
|
|
309
|
+
*/
|
|
310
|
+
function elementAcceptsData(node) {
|
|
311
|
+
// The window object can accept data but has no nodeType
|
|
312
|
+
// Otherwise we are only interested in elements (1) and documents (9)
|
|
313
|
+
switch (node.nodeType) {
|
|
314
|
+
case Node.ELEMENT_NODE:
|
|
315
|
+
case Node.DOCUMENT_NODE:
|
|
316
|
+
case undefined: // window.object
|
|
317
|
+
return true;
|
|
318
|
+
default:
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* @param {string} html
|
|
325
|
+
* @returns {DocumentFragment}
|
|
326
|
+
*/
|
|
327
|
+
export function buildFragment(html) {
|
|
328
|
+
let tmp;
|
|
329
|
+
let tag;
|
|
330
|
+
let wrap;
|
|
331
|
+
let tempFragment = document.createDocumentFragment();
|
|
332
|
+
let nodes = [];
|
|
333
|
+
let i;
|
|
334
|
+
|
|
335
|
+
if (isTextNode(html)) {
|
|
336
|
+
// Convert non-html into a text node
|
|
337
|
+
nodes.push(document.createTextNode(html));
|
|
338
|
+
} else {
|
|
339
|
+
// Convert html into DOM nodes
|
|
340
|
+
tmp = tempFragment.appendChild(document.createElement("div"));
|
|
341
|
+
tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
|
|
342
|
+
|
|
343
|
+
wrap = wrapMap[tag] || [];
|
|
344
|
+
|
|
345
|
+
// Create wrappers & descend into them
|
|
346
|
+
i = wrap.length;
|
|
347
|
+
while (--i > -1) {
|
|
348
|
+
tmp.appendChild(window.document.createElement(wrap[i]));
|
|
349
|
+
tmp = tmp.firstChild;
|
|
350
|
+
}
|
|
351
|
+
tmp.innerHTML = html;
|
|
352
|
+
|
|
353
|
+
nodes = concat(nodes, tmp.childNodes);
|
|
354
|
+
|
|
355
|
+
tmp = tempFragment.firstChild;
|
|
356
|
+
tmp.textContent = "";
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
let fragment = document.createDocumentFragment();
|
|
360
|
+
fragment.append(...nodes);
|
|
361
|
+
return fragment;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* @param {string} html
|
|
366
|
+
* @returns {NodeListOf<ChildNode> | HTMLElement[]}
|
|
367
|
+
*/
|
|
368
|
+
function parseHtml(html) {
|
|
369
|
+
let regEx = SINGLE_TAG_REGEXP.exec(html);
|
|
370
|
+
if (regEx) {
|
|
371
|
+
return [document.createElement(regEx[1])];
|
|
372
|
+
}
|
|
373
|
+
let fragment = buildFragment(html);
|
|
374
|
+
if (fragment) {
|
|
375
|
+
return fragment.childNodes;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return [];
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @param {Element} element
|
|
383
|
+
* @param {boolean} [onlyDescendants]
|
|
384
|
+
* @returns {void}
|
|
385
|
+
*/
|
|
386
|
+
export function dealoc(element, onlyDescendants) {
|
|
387
|
+
if (!element) return;
|
|
388
|
+
if (!onlyDescendants && elementAcceptsData(element))
|
|
389
|
+
cleanElementData([element]);
|
|
390
|
+
|
|
391
|
+
if (element.querySelectorAll) {
|
|
392
|
+
cleanElementData(element.querySelectorAll("*"));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* If `ExpandoStore.data` and `ExpandoStore.events` are empty,
|
|
398
|
+
* then delete element's `ExpandoStore` and set its `ExpandoId`
|
|
399
|
+
* to undefined.
|
|
400
|
+
* @param {Element} element
|
|
401
|
+
*/
|
|
402
|
+
function removeIfEmptyData(element) {
|
|
403
|
+
const expandoId = element[EXPANDO];
|
|
404
|
+
const { events, data } = CACHE.get(expandoId);
|
|
405
|
+
|
|
406
|
+
if (
|
|
407
|
+
(!data || !Object.keys(data).length) &&
|
|
408
|
+
(!events || !Object.keys(events).length)
|
|
409
|
+
) {
|
|
410
|
+
CACHE.delete(expandoId);
|
|
411
|
+
element[EXPANDO] = undefined; // don't delete DOM expandos. Chrome don't like it
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Gets or sets cache data for a given element.
|
|
417
|
+
*
|
|
418
|
+
* @param {Element} element - The DOM element to get or set data on.
|
|
419
|
+
* @param {string|Object} key - The key (as a string) to get/set or an object for mass-setting.
|
|
420
|
+
* @param {*} [value] - The value to set. If not provided, the function acts as a getter.
|
|
421
|
+
* @returns {*} - The retrieved data if acting as a getter. Otherwise, returns undefined.
|
|
422
|
+
*/
|
|
423
|
+
export function getOrSetCacheData(element, key, value) {
|
|
408
424
|
if (elementAcceptsData(element)) {
|
|
409
425
|
let prop;
|
|
410
426
|
|
|
411
427
|
const isSimpleSetter = isDefined(value);
|
|
412
428
|
const isSimpleGetter = !isSimpleSetter && key && !isObject(key);
|
|
413
429
|
const massGetter = !key;
|
|
414
|
-
const expandoStore =
|
|
430
|
+
const expandoStore = getExpando(element, !isSimpleGetter);
|
|
415
431
|
const data = expandoStore && expandoStore.data;
|
|
416
432
|
|
|
417
433
|
if (isSimpleSetter) {
|
|
@@ -429,6 +445,8 @@ function jqLiteData(element, key, value) {
|
|
|
429
445
|
data[kebabToCamel(prop)] = key[prop];
|
|
430
446
|
}
|
|
431
447
|
}
|
|
448
|
+
} else {
|
|
449
|
+
// TODO: check should occur perhaps prior at compilation level that this is a valid element
|
|
432
450
|
}
|
|
433
451
|
}
|
|
434
452
|
|
|
@@ -462,11 +480,11 @@ function addNodes(root, elements) {
|
|
|
462
480
|
}
|
|
463
481
|
}
|
|
464
482
|
|
|
465
|
-
function
|
|
466
|
-
return
|
|
483
|
+
function JQLiteController(element, name) {
|
|
484
|
+
return JQLiteInheritedData(element, `$${name || "ngController"}Controller`);
|
|
467
485
|
}
|
|
468
486
|
|
|
469
|
-
function
|
|
487
|
+
function JQLiteInheritedData(element, name, value) {
|
|
470
488
|
// if element is the document object work with the html element instead
|
|
471
489
|
// this makes $(document).scope() possible
|
|
472
490
|
if (element.nodeType === Node.DOCUMENT_NODE) {
|
|
@@ -476,7 +494,8 @@ function jqLiteInheritedData(element, name, value) {
|
|
|
476
494
|
|
|
477
495
|
while (element) {
|
|
478
496
|
for (let i = 0, ii = names.length; i < ii; i++) {
|
|
479
|
-
if (isDefined((value =
|
|
497
|
+
if (isDefined((value = getOrSetCacheData(element, names[i]))))
|
|
498
|
+
return value;
|
|
480
499
|
}
|
|
481
500
|
|
|
482
501
|
// If dealing with a document fragment node with a host element, and no parent, use the host
|
|
@@ -488,37 +507,32 @@ function jqLiteInheritedData(element, name, value) {
|
|
|
488
507
|
}
|
|
489
508
|
}
|
|
490
509
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
export function jqLiteRemove(element, keepData) {
|
|
510
|
+
/**
|
|
511
|
+
*
|
|
512
|
+
* @param {Element} element
|
|
513
|
+
* @param {boolean} keepData
|
|
514
|
+
*/
|
|
515
|
+
export function removeElement(element, keepData = false) {
|
|
499
516
|
if (!keepData) dealoc(element);
|
|
500
517
|
const parent = element.parentNode;
|
|
501
518
|
if (parent) parent.removeChild(element);
|
|
502
519
|
}
|
|
503
520
|
|
|
504
|
-
|
|
521
|
+
/**
|
|
522
|
+
* Executea a function on `DOMContentLoaded`
|
|
523
|
+
* @param {Function} fn
|
|
524
|
+
*/
|
|
525
|
+
function onReady(fn) {
|
|
505
526
|
function trigger() {
|
|
506
527
|
window.document.removeEventListener("DOMContentLoaded", trigger);
|
|
507
|
-
window.removeEventListener("load", trigger);
|
|
508
528
|
fn();
|
|
509
529
|
}
|
|
510
|
-
|
|
511
530
|
// check if document is already loaded
|
|
512
531
|
if (window.document.readyState === "complete") {
|
|
513
532
|
window.setTimeout(fn);
|
|
514
533
|
} else {
|
|
515
|
-
// We can not use
|
|
516
|
-
|
|
517
|
-
// Works for modern browsers and IE9
|
|
534
|
+
// We can not use JQLite since we are not done loading.
|
|
518
535
|
window.document.addEventListener("DOMContentLoaded", trigger);
|
|
519
|
-
|
|
520
|
-
// Fallback to window.onload for others
|
|
521
|
-
window.addEventListener("load", trigger);
|
|
522
536
|
}
|
|
523
537
|
}
|
|
524
538
|
|
|
@@ -526,7 +540,6 @@ function jqLiteReady(fn) {
|
|
|
526
540
|
// Functions which are declared directly.
|
|
527
541
|
/// ///////////////////////////////////////
|
|
528
542
|
JQLite.prototype = {
|
|
529
|
-
ready: jqLiteReady,
|
|
530
543
|
toString() {
|
|
531
544
|
const value = [];
|
|
532
545
|
forEach(this, (e) => {
|
|
@@ -536,32 +549,76 @@ JQLite.prototype = {
|
|
|
536
549
|
},
|
|
537
550
|
|
|
538
551
|
eq(index) {
|
|
539
|
-
return index >= 0 ?
|
|
552
|
+
return index >= 0 ? JQLite(this[index]) : JQLite(this[this.length + index]);
|
|
540
553
|
},
|
|
541
554
|
|
|
542
555
|
length: 0,
|
|
543
|
-
push: [].push,
|
|
544
|
-
sort: [].sort,
|
|
545
|
-
splice: [].splice,
|
|
546
556
|
};
|
|
547
557
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
558
|
+
/**
|
|
559
|
+
* Remove all child nodes of the set of matched elements from the DOM and clears CACHE data, associated with the node.
|
|
560
|
+
* @returns {JQLite} The current instance of JQLite.
|
|
561
|
+
*/
|
|
562
|
+
JQLite.prototype.empty = function () {
|
|
563
|
+
for (let i = 0; i < this.length; i++) {
|
|
564
|
+
const element = this[i];
|
|
565
|
+
dealoc(element, true);
|
|
566
|
+
// we may run into situation where we empty a transcluded node
|
|
567
|
+
if (
|
|
568
|
+
[
|
|
569
|
+
Node.ELEMENT_NODE,
|
|
570
|
+
Node.DOCUMENT_NODE,
|
|
571
|
+
Node.DOCUMENT_FRAGMENT_NODE,
|
|
572
|
+
].includes(element.nodeType)
|
|
573
|
+
) {
|
|
574
|
+
element.replaceChildren();
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return this;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Returns the `$scope` of the element.
|
|
582
|
+
* @returns {import("../../core/scope/scope").Scope}
|
|
583
|
+
*/
|
|
584
|
+
JQLite.prototype.scope = function () {
|
|
585
|
+
// Can't use JQLiteData here directly so we stay compatible with jQuery!
|
|
586
|
+
return (
|
|
587
|
+
getOrSetCacheData(this[0], "$scope") ||
|
|
588
|
+
JQLiteInheritedData(this[0].parentNode || this[0], [
|
|
589
|
+
"$isolateScope",
|
|
590
|
+
"$scope",
|
|
591
|
+
])
|
|
592
|
+
);
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Returns the isolate `$scope` of the element.
|
|
597
|
+
* @returns {import("../../core/scope/scope").Scope}
|
|
598
|
+
*/
|
|
599
|
+
JQLite.prototype.isolateScope = function () {
|
|
600
|
+
return (
|
|
601
|
+
getOrSetCacheData(this[0], "$isolateScope") ||
|
|
602
|
+
getOrSetCacheData(this[0], "$isolateScopeNoTemplate")
|
|
603
|
+
);
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Return instance of controller attached to element
|
|
608
|
+
* @param {string} [name] - Controller name
|
|
609
|
+
* @returns {any}
|
|
610
|
+
*/
|
|
611
|
+
JQLite.prototype.controller = function (name) {
|
|
612
|
+
return JQLiteController(this[0], name);
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Return instance of injector attached to element
|
|
617
|
+
* @returns {import('../../types').angular.InjectorService}
|
|
618
|
+
*/
|
|
619
|
+
JQLite.prototype.injector = function () {
|
|
620
|
+
return JQLiteInheritedData(this[0], "$injector");
|
|
621
|
+
};
|
|
565
622
|
|
|
566
623
|
export function getBooleanAttrName(element, name) {
|
|
567
624
|
// check dom last since we will most likely fail on name
|
|
@@ -571,58 +628,31 @@ export function getBooleanAttrName(element, name) {
|
|
|
571
628
|
return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
|
|
572
629
|
}
|
|
573
630
|
|
|
574
|
-
|
|
631
|
+
/**
|
|
632
|
+
* Takes an array of elements, calls any `$destroy` event handlers, removes any data in cache, and finally removes any
|
|
633
|
+
* listeners.
|
|
634
|
+
* @param {NodeListOf<Element>} nodes
|
|
635
|
+
*/
|
|
636
|
+
export function cleanElementData(nodes) {
|
|
575
637
|
for (let i = 0, ii = nodes.length; i < ii; i++) {
|
|
576
638
|
var events = (CACHE.get(nodes[i][EXPANDO]) || {}).events;
|
|
577
639
|
if (events && events.$destroy) {
|
|
578
|
-
|
|
640
|
+
JQLite(nodes[i]).triggerHandler("$destroy");
|
|
579
641
|
}
|
|
580
|
-
|
|
581
|
-
|
|
642
|
+
removeElementData(nodes[i]);
|
|
643
|
+
JQLiteOff(nodes[i]);
|
|
582
644
|
}
|
|
583
645
|
}
|
|
584
646
|
|
|
647
|
+
/// ///////////////////////////////////////
|
|
648
|
+
// Functions iterating getter/setters.
|
|
649
|
+
// these functions return self on setter and
|
|
650
|
+
// value on get.
|
|
651
|
+
/// ///////////////////////////////////////
|
|
585
652
|
forEach(
|
|
586
653
|
{
|
|
587
|
-
data:
|
|
588
|
-
|
|
589
|
-
cleanData: jqLiteCleanData,
|
|
590
|
-
},
|
|
591
|
-
(fn, name) => {
|
|
592
|
-
JQLite[name] = fn;
|
|
593
|
-
},
|
|
594
|
-
);
|
|
595
|
-
|
|
596
|
-
forEach(
|
|
597
|
-
{
|
|
598
|
-
data: jqLiteData,
|
|
599
|
-
inheritedData: jqLiteInheritedData,
|
|
600
|
-
|
|
601
|
-
scope(element) {
|
|
602
|
-
// Can't use jqLiteData here directly so we stay compatible with jQuery!
|
|
603
|
-
return (
|
|
604
|
-
jqLiteData(element, "$scope") ||
|
|
605
|
-
jqLiteInheritedData(element.parentNode || element, [
|
|
606
|
-
"$isolateScope",
|
|
607
|
-
"$scope",
|
|
608
|
-
])
|
|
609
|
-
);
|
|
610
|
-
},
|
|
611
|
-
|
|
612
|
-
isolateScope(element) {
|
|
613
|
-
// Can't use jqLiteData here directly so we stay compatible with jQuery!
|
|
614
|
-
return (
|
|
615
|
-
jqLiteData(element, "$isolateScope") ||
|
|
616
|
-
jqLiteData(element, "$isolateScopeNoTemplate")
|
|
617
|
-
);
|
|
618
|
-
},
|
|
619
|
-
|
|
620
|
-
controller: jqLiteController,
|
|
621
|
-
|
|
622
|
-
injector(element) {
|
|
623
|
-
return jqLiteInheritedData(element, "$injector");
|
|
624
|
-
},
|
|
625
|
-
|
|
654
|
+
data: getOrSetCacheData,
|
|
655
|
+
inheritedData: JQLiteInheritedData,
|
|
626
656
|
attr(element, name, value) {
|
|
627
657
|
let ret;
|
|
628
658
|
const { nodeType } = element;
|
|
@@ -672,7 +702,6 @@ forEach(
|
|
|
672
702
|
element.textContent = value;
|
|
673
703
|
}
|
|
674
704
|
})(),
|
|
675
|
-
|
|
676
705
|
val(element, value) {
|
|
677
706
|
if (isUndefined(value)) {
|
|
678
707
|
if (element.multiple && nodeName_(element) === "select") {
|
|
@@ -688,7 +717,6 @@ forEach(
|
|
|
688
717
|
}
|
|
689
718
|
element.value = value;
|
|
690
719
|
},
|
|
691
|
-
|
|
692
720
|
html(element, value) {
|
|
693
721
|
if (isUndefined(value)) {
|
|
694
722
|
return element.innerHTML;
|
|
@@ -696,8 +724,6 @@ forEach(
|
|
|
696
724
|
dealoc(element, true);
|
|
697
725
|
element.innerHTML = value;
|
|
698
726
|
},
|
|
699
|
-
|
|
700
|
-
empty: jqLiteEmpty,
|
|
701
727
|
},
|
|
702
728
|
(fn, name) => {
|
|
703
729
|
/**
|
|
@@ -708,15 +734,14 @@ forEach(
|
|
|
708
734
|
let key;
|
|
709
735
|
const nodeCount = this.length;
|
|
710
736
|
|
|
711
|
-
//
|
|
737
|
+
// JQLiteEmpty takes no arguments but is a setter.
|
|
712
738
|
if (
|
|
713
|
-
fn !==
|
|
714
|
-
isUndefined(fn.length === 2 && fn !== jqLiteController ? arg1 : arg2)
|
|
739
|
+
isUndefined(fn.length === 2 && fn !== JQLiteController ? arg1 : arg2)
|
|
715
740
|
) {
|
|
716
741
|
if (isObject(arg1)) {
|
|
717
742
|
// we are a write, but the object properties are the key/values
|
|
718
743
|
for (i = 0; i < nodeCount; i++) {
|
|
719
|
-
if (fn ===
|
|
744
|
+
if (fn === getOrSetCacheData) {
|
|
720
745
|
fn(this[i], arg1);
|
|
721
746
|
} else {
|
|
722
747
|
for (key in arg1) {
|
|
@@ -748,78 +773,6 @@ forEach(
|
|
|
748
773
|
},
|
|
749
774
|
);
|
|
750
775
|
|
|
751
|
-
function createEventHandler(element, events) {
|
|
752
|
-
const eventHandler = function (event, type) {
|
|
753
|
-
// jQuery specific api
|
|
754
|
-
event.isDefaultPrevented = function () {
|
|
755
|
-
return event.defaultPrevented;
|
|
756
|
-
};
|
|
757
|
-
|
|
758
|
-
let eventFns = events[type || event.type];
|
|
759
|
-
const eventFnsLength = eventFns ? eventFns.length : 0;
|
|
760
|
-
|
|
761
|
-
if (!eventFnsLength) return;
|
|
762
|
-
|
|
763
|
-
if (isUndefined(event.immediatePropagationStopped)) {
|
|
764
|
-
const originalStopImmediatePropagation = event.stopImmediatePropagation;
|
|
765
|
-
event.stopImmediatePropagation = function () {
|
|
766
|
-
event.immediatePropagationStopped = true;
|
|
767
|
-
|
|
768
|
-
if (event.stopPropagation) {
|
|
769
|
-
event.stopPropagation();
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
if (originalStopImmediatePropagation) {
|
|
773
|
-
originalStopImmediatePropagation.call(event);
|
|
774
|
-
}
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
event.isImmediatePropagationStopped = function () {
|
|
779
|
-
return event.immediatePropagationStopped === true;
|
|
780
|
-
};
|
|
781
|
-
|
|
782
|
-
// Some events have special handlers that wrap the real handler
|
|
783
|
-
const handlerWrapper =
|
|
784
|
-
eventFns.specialHandlerWrapper || defaultHandlerWrapper;
|
|
785
|
-
|
|
786
|
-
// Copy event handlers in case event handlers array is modified during execution.
|
|
787
|
-
if (eventFnsLength > 1) {
|
|
788
|
-
eventFns = shallowCopy(eventFns);
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
for (let i = 0; i < eventFnsLength; i++) {
|
|
792
|
-
if (!event.isImmediatePropagationStopped()) {
|
|
793
|
-
handlerWrapper(element, event, eventFns[i]);
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
};
|
|
797
|
-
|
|
798
|
-
// TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all
|
|
799
|
-
// events on `element`
|
|
800
|
-
eventHandler.elem = element;
|
|
801
|
-
return eventHandler;
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
function defaultHandlerWrapper(element, event, handler) {
|
|
805
|
-
handler.call(element, event);
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
function specialMouseHandlerWrapper(target, event, handler) {
|
|
809
|
-
// Refer to jQuery's implementation of mouseenter & mouseleave
|
|
810
|
-
// Read about mouseenter and mouseleave:
|
|
811
|
-
// http://www.quirksmode.org/js/events_mouse.html#link8
|
|
812
|
-
const related = event.relatedTarget;
|
|
813
|
-
// For mousenter/leave call the handler if related is outside the target.
|
|
814
|
-
// NB: No relatedTarget if the mouse left/entered the browser window
|
|
815
|
-
if (
|
|
816
|
-
!related ||
|
|
817
|
-
(related !== target && !jqLiteContains.call(target, related))
|
|
818
|
-
) {
|
|
819
|
-
handler.call(target, event);
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
|
|
823
776
|
/// ///////////////////////////////////////
|
|
824
777
|
// Functions iterating traversal.
|
|
825
778
|
// These functions chain results into a single
|
|
@@ -827,25 +780,17 @@ function specialMouseHandlerWrapper(target, event, handler) {
|
|
|
827
780
|
/// ///////////////////////////////////////
|
|
828
781
|
forEach(
|
|
829
782
|
{
|
|
830
|
-
removeData:
|
|
831
|
-
on: (element, type, fn
|
|
832
|
-
if (isDefined(unsupported))
|
|
833
|
-
throw jqLiteMinErr(
|
|
834
|
-
"onargs",
|
|
835
|
-
"jqLite#on() does not support the `selector` or `eventData` parameters",
|
|
836
|
-
);
|
|
837
|
-
|
|
783
|
+
removeData: removeElementData,
|
|
784
|
+
on: (element, type, fn) => {
|
|
838
785
|
// Do not add event handlers to non-elements because they will not be cleaned up.
|
|
839
786
|
if (!elementAcceptsData(element)) {
|
|
840
787
|
return;
|
|
841
788
|
}
|
|
842
789
|
|
|
843
|
-
const expandoStore =
|
|
844
|
-
const { events } = expandoStore;
|
|
845
|
-
let { handle } = expandoStore;
|
|
790
|
+
const expandoStore = getExpando(element, true);
|
|
846
791
|
|
|
847
|
-
if (!handle) {
|
|
848
|
-
|
|
792
|
+
if (!expandoStore.handle) {
|
|
793
|
+
expandoStore.handle = createEventHandler(element, expandoStore.events);
|
|
849
794
|
}
|
|
850
795
|
|
|
851
796
|
// http://jsperf.com/string-indexof-vs-split
|
|
@@ -857,13 +802,13 @@ forEach(
|
|
|
857
802
|
specialHandlerWrapper,
|
|
858
803
|
noEventListener,
|
|
859
804
|
) {
|
|
860
|
-
let eventFns = events[type];
|
|
805
|
+
let eventFns = expandoStore.events[type];
|
|
861
806
|
|
|
862
807
|
if (!eventFns) {
|
|
863
|
-
eventFns = events[type] = [];
|
|
808
|
+
eventFns = expandoStore.events[type] = [];
|
|
864
809
|
eventFns.specialHandlerWrapper = specialHandlerWrapper;
|
|
865
810
|
if (type !== "$destroy" && !noEventListener) {
|
|
866
|
-
element.addEventListener(type, handle);
|
|
811
|
+
element.addEventListener(type, expandoStore.handle);
|
|
867
812
|
}
|
|
868
813
|
}
|
|
869
814
|
|
|
@@ -880,9 +825,7 @@ forEach(
|
|
|
880
825
|
}
|
|
881
826
|
}
|
|
882
827
|
},
|
|
883
|
-
|
|
884
|
-
off: jqLiteOff,
|
|
885
|
-
|
|
828
|
+
off: JQLiteOff,
|
|
886
829
|
replaceWith(element, replaceNode) {
|
|
887
830
|
let index;
|
|
888
831
|
const parent = element.parentNode;
|
|
@@ -896,13 +839,11 @@ forEach(
|
|
|
896
839
|
index = node;
|
|
897
840
|
});
|
|
898
841
|
},
|
|
899
|
-
|
|
900
842
|
children(element) {
|
|
901
843
|
return Array.from(element.childNodes).filter(
|
|
902
844
|
(child) => child.nodeType === Node.ELEMENT_NODE,
|
|
903
845
|
);
|
|
904
846
|
},
|
|
905
|
-
|
|
906
847
|
append(element, node) {
|
|
907
848
|
const { nodeType } = element;
|
|
908
849
|
if (
|
|
@@ -928,10 +869,10 @@ forEach(
|
|
|
928
869
|
}
|
|
929
870
|
},
|
|
930
871
|
|
|
931
|
-
remove:
|
|
872
|
+
remove: removeElement,
|
|
932
873
|
|
|
933
874
|
detach(element) {
|
|
934
|
-
|
|
875
|
+
removeElement(element, true);
|
|
935
876
|
},
|
|
936
877
|
|
|
937
878
|
after(element, newElement) {
|
|
@@ -956,7 +897,7 @@ forEach(
|
|
|
956
897
|
: null;
|
|
957
898
|
},
|
|
958
899
|
|
|
959
|
-
// TODO: remove after migrating tests away from
|
|
900
|
+
// TODO: remove after migrating tests away from JQLite
|
|
960
901
|
find(element, selector) {
|
|
961
902
|
if (element.getElementsByTagName) {
|
|
962
903
|
return element.getElementsByTagName(selector);
|
|
@@ -969,7 +910,7 @@ forEach(
|
|
|
969
910
|
let eventFnsCopy;
|
|
970
911
|
let handlerArgs;
|
|
971
912
|
const eventName = event.type || event;
|
|
972
|
-
const expandoStore =
|
|
913
|
+
const expandoStore = getExpando(element);
|
|
973
914
|
const events = expandoStore && expandoStore.events;
|
|
974
915
|
const eventFns = events && events[eventName];
|
|
975
916
|
|
|
@@ -1024,7 +965,7 @@ forEach(
|
|
|
1024
965
|
value = fn(this[i], arg1, arg2, arg3);
|
|
1025
966
|
if (isDefined(value)) {
|
|
1026
967
|
// any function which returns a value needs to be wrapped
|
|
1027
|
-
value =
|
|
968
|
+
value = JQLite(value);
|
|
1028
969
|
}
|
|
1029
970
|
} else {
|
|
1030
971
|
addNodes(value, fn(this[i], arg1, arg2, arg3));
|
|
@@ -1035,14 +976,88 @@ forEach(
|
|
|
1035
976
|
},
|
|
1036
977
|
);
|
|
1037
978
|
|
|
979
|
+
function createEventHandler(element, events) {
|
|
980
|
+
const eventHandler = function (event, type) {
|
|
981
|
+
// jQuery specific api
|
|
982
|
+
event.isDefaultPrevented = function () {
|
|
983
|
+
return event.defaultPrevented;
|
|
984
|
+
};
|
|
985
|
+
|
|
986
|
+
let eventFns = events[type || event.type];
|
|
987
|
+
const eventFnsLength = eventFns ? eventFns.length : 0;
|
|
988
|
+
|
|
989
|
+
if (!eventFnsLength) return;
|
|
990
|
+
|
|
991
|
+
if (isUndefined(event.immediatePropagationStopped)) {
|
|
992
|
+
const originalStopImmediatePropagation = event.stopImmediatePropagation;
|
|
993
|
+
event.stopImmediatePropagation = function () {
|
|
994
|
+
event.immediatePropagationStopped = true;
|
|
995
|
+
|
|
996
|
+
if (event.stopPropagation) {
|
|
997
|
+
event.stopPropagation();
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
if (originalStopImmediatePropagation) {
|
|
1001
|
+
originalStopImmediatePropagation.call(event);
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
event.isImmediatePropagationStopped = function () {
|
|
1007
|
+
return event.immediatePropagationStopped === true;
|
|
1008
|
+
};
|
|
1009
|
+
|
|
1010
|
+
// Some events have special handlers that wrap the real handler
|
|
1011
|
+
const handlerWrapper =
|
|
1012
|
+
eventFns.specialHandlerWrapper || defaultHandlerWrapper;
|
|
1013
|
+
|
|
1014
|
+
// Copy event handlers in case event handlers array is modified during execution.
|
|
1015
|
+
if (eventFnsLength > 1) {
|
|
1016
|
+
eventFns = shallowCopy(eventFns);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
for (let i = 0; i < eventFnsLength; i++) {
|
|
1020
|
+
if (!event.isImmediatePropagationStopped()) {
|
|
1021
|
+
handlerWrapper(element, event, eventFns[i]);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
// TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all
|
|
1027
|
+
// events on `element`
|
|
1028
|
+
eventHandler.elem = element;
|
|
1029
|
+
return eventHandler;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
function defaultHandlerWrapper(element, event, handler) {
|
|
1033
|
+
handler.call(element, event);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* @param {Node} target
|
|
1038
|
+
* @param {*} event
|
|
1039
|
+
* @param {*} handler
|
|
1040
|
+
*/
|
|
1041
|
+
function specialMouseHandlerWrapper(target, event, handler) {
|
|
1042
|
+
// Refer to jQuery's implementation of mouseenter & mouseleave
|
|
1043
|
+
// Read about mouseenter and mouseleave:
|
|
1044
|
+
// http://www.quirksmode.org/js/events_mouse.html#link8
|
|
1045
|
+
const related = event.relatedTarget;
|
|
1046
|
+
// For mousenter/leave call the handler if related is outside the target.
|
|
1047
|
+
// NB: No relatedTarget if the mouse left/entered the browser window
|
|
1048
|
+
if (!related || (related !== target && !target.contains(related))) {
|
|
1049
|
+
handler.call(target, event);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1038
1053
|
/**
|
|
1039
1054
|
* @param {string} elementStr
|
|
1040
1055
|
* @returns {string} Returns the string representation of the element.
|
|
1041
1056
|
*/
|
|
1042
1057
|
export function startingTag(elementStr) {
|
|
1043
|
-
const clone =
|
|
1044
|
-
const element =
|
|
1045
|
-
var elemHtml =
|
|
1058
|
+
const clone = JQLite(elementStr)[0].cloneNode(true);
|
|
1059
|
+
const element = JQLite(clone).empty();
|
|
1060
|
+
var elemHtml = JQLite("<div></div>").append(element).html();
|
|
1046
1061
|
try {
|
|
1047
1062
|
return element[0].nodeType === Node.TEXT_NODE
|
|
1048
1063
|
? lowercase(elemHtml)
|
|
@@ -1059,7 +1074,7 @@ export function startingTag(elementStr) {
|
|
|
1059
1074
|
/**
|
|
1060
1075
|
* Return the DOM siblings between the first and last node in the given array.
|
|
1061
1076
|
* @param {Array} nodes An array-like object
|
|
1062
|
-
* @returns {
|
|
1077
|
+
* @returns {JQLite} the inputted object or a JQLite collection containing the nodes
|
|
1063
1078
|
*/
|
|
1064
1079
|
export function getBlockNodes(nodes) {
|
|
1065
1080
|
// TODO(perf): update `nodes` instead of creating a new object?
|
|
@@ -1071,11 +1086,11 @@ export function getBlockNodes(nodes) {
|
|
|
1071
1086
|
if (blockNodes || nodes[i] !== node) {
|
|
1072
1087
|
if (!blockNodes) {
|
|
1073
1088
|
// use element to avoid circular dependency
|
|
1074
|
-
blockNodes =
|
|
1089
|
+
blockNodes = Array.prototype.slice.call(nodes, 0, i);
|
|
1075
1090
|
}
|
|
1076
1091
|
blockNodes.push(node);
|
|
1077
1092
|
}
|
|
1078
1093
|
}
|
|
1079
1094
|
|
|
1080
|
-
return blockNodes || nodes;
|
|
1095
|
+
return JQLite(blockNodes || nodes);
|
|
1081
1096
|
}
|