@angular-wave/angular.ts 0.0.43 → 0.0.45
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/README.md +1 -1
- package/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -2
- package/package.json +1 -1
- package/src/animations/module.js +1 -1
- package/src/exts/aria/aria.js +2 -130
- package/src/exts/aria/aria.md +145 -0
- package/src/exts/messages/messages.js +1 -1
- package/src/filters/filter.js +14 -2
- package/src/filters/filters.js +2 -2
- package/src/filters/limit-to.js +11 -4
- package/src/filters/order-by.js +0 -5
- package/src/index.js +2 -1
- package/src/injector.js +1 -1
- package/src/loader.js +60 -60
- package/src/public.js +1 -1
- package/src/router/directives/directives.test.js +1 -1
- package/src/router/index.js +1 -1
- package/src/router/params/param-type.js +3 -3
- package/src/router/services.spec.js +3 -3
- package/src/router/state/state-service.js +0 -8
- package/src/shared/jqlite/jqlite.js +751 -699
- package/src/shared/jqlite/jqlite.spec.js +0 -8
- package/src/shared/utils.js +3 -3
- package/src/src.test.js +1 -1
- package/src/types.js +6 -6
- package/tsconfig.json +1 -1
- package/types/filters/filter.d.ts +2 -2
- package/types/filters/filters.d.ts +4 -4
- package/types/filters/limit-to.d.ts +2 -2
- package/types/filters/order-by.d.ts +1 -6
- package/types/public.d.ts +2 -2
- package/types/router/params/param-type.d.ts +3 -3
- package/types/router/state/state-service.d.ts +9 -15
- package/types/shared/jqlite/jqlite.d.ts +46 -19
- package/types/shared/utils.d.ts +1 -1
- package/types/types.d.ts +5 -5
- package/types-back/index.d.ts +0 -24
|
@@ -86,48 +86,17 @@ import { CACHE, EXPANDO } from "../../core/cache/cache";
|
|
|
86
86
|
* https://github.com/angular/angular.js/issues/14251 for more information.
|
|
87
87
|
*
|
|
88
88
|
* @param {string|Element} element HTML string or Element to be wrapped into jQuery.
|
|
89
|
-
* @returns {
|
|
89
|
+
* @returns {JQLite} jQuery object.
|
|
90
90
|
*/
|
|
91
91
|
|
|
92
92
|
/** @type {number} */
|
|
93
93
|
let jqId = 1;
|
|
94
94
|
|
|
95
|
-
function jqNextId() {
|
|
96
|
-
return ++jqId;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
95
|
const DASH_LOWERCASE_REGEXP = /-([a-z])/g;
|
|
100
96
|
const UNDERSCORE_LOWERCASE_REGEXP = /_([a-z])/g;
|
|
101
97
|
const MOUSE_EVENT_MAP = { mouseleave: "mouseout", mouseenter: "mouseover" };
|
|
102
98
|
const JQLiteMinErr = minErr("jqLite");
|
|
103
99
|
|
|
104
|
-
/**
|
|
105
|
-
* @param {string} _all
|
|
106
|
-
* @param {string} letter
|
|
107
|
-
* @returns {string}
|
|
108
|
-
*/
|
|
109
|
-
function fnCamelCaseReplace(_all, letter) {
|
|
110
|
-
return letter.toUpperCase();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Converts kebab-case to camelCase.
|
|
115
|
-
* @param {string} name Name to normalize
|
|
116
|
-
* @returns {string}
|
|
117
|
-
*/
|
|
118
|
-
export function kebabToCamel(name) {
|
|
119
|
-
return name.replace(DASH_LOWERCASE_REGEXP, fnCamelCaseReplace);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Converts sname to camelCase.
|
|
124
|
-
* @param {string} name
|
|
125
|
-
* @returns {string}
|
|
126
|
-
*/
|
|
127
|
-
export function snakeToCamel(name) {
|
|
128
|
-
return name.replace(UNDERSCORE_LOWERCASE_REGEXP, fnCamelCaseReplace);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
100
|
const SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/;
|
|
132
101
|
const TAG_NAME_REGEXP = /<([\w:-]+)/;
|
|
133
102
|
|
|
@@ -172,7 +141,7 @@ const BOOLEAN_ELEMENTS = {};
|
|
|
172
141
|
*/
|
|
173
142
|
export function JQLite(element) {
|
|
174
143
|
if (element instanceof JQLite) {
|
|
175
|
-
return element;
|
|
144
|
+
return /** @type {JQLite} */ (element);
|
|
176
145
|
}
|
|
177
146
|
|
|
178
147
|
let argIsString = false;
|
|
@@ -202,787 +171,846 @@ export function JQLite(element) {
|
|
|
202
171
|
}
|
|
203
172
|
}
|
|
204
173
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
174
|
+
/// ///////////////////////////////////////
|
|
175
|
+
// Functions which are declared directly.
|
|
176
|
+
/// ///////////////////////////////////////
|
|
177
|
+
JQLite.prototype = {
|
|
178
|
+
toString() {
|
|
179
|
+
const value = [];
|
|
180
|
+
forEach(this, (e) => {
|
|
181
|
+
value.push(`${e}`);
|
|
182
|
+
});
|
|
183
|
+
return `[${value.join(", ")}]`;
|
|
184
|
+
},
|
|
211
185
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
186
|
+
eq(index) {
|
|
187
|
+
return index >= 0 ? JQLite(this[index]) : JQLite(this[this.length + index]);
|
|
188
|
+
},
|
|
215
189
|
|
|
216
|
-
|
|
190
|
+
length: 0,
|
|
191
|
+
};
|
|
217
192
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
193
|
+
/**
|
|
194
|
+
* Remove all child nodes of the set of matched elements from the DOM and clears CACHE data, associated with the node.
|
|
195
|
+
* @returns {JQLite} The current instance of JQLite.
|
|
196
|
+
*/
|
|
197
|
+
JQLite.prototype.empty = function () {
|
|
198
|
+
for (let i = 0; i < this.length; i++) {
|
|
199
|
+
const element = this[i];
|
|
200
|
+
dealoc(element, true);
|
|
201
|
+
// we may run into situation where we empty a transcluded node
|
|
202
|
+
if (
|
|
203
|
+
[
|
|
204
|
+
Node.ELEMENT_NODE,
|
|
205
|
+
Node.DOCUMENT_NODE,
|
|
206
|
+
Node.DOCUMENT_FRAGMENT_NODE,
|
|
207
|
+
].includes(element.nodeType)
|
|
208
|
+
) {
|
|
209
|
+
element.replaceChildren();
|
|
224
210
|
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
211
|
+
}
|
|
212
|
+
return this;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Returns the `$scope` of the element.
|
|
217
|
+
* @returns {import("../../core/scope/scope").Scope}
|
|
218
|
+
*/
|
|
219
|
+
JQLite.prototype.scope = function () {
|
|
220
|
+
// Can't use JQLiteData here directly so we stay compatible with jQuery!
|
|
221
|
+
return (
|
|
222
|
+
getOrSetCacheData(this[0], "$scope") ||
|
|
223
|
+
getInheritedData(this[0].parentNode || this[0], ["$isolateScope", "$scope"])
|
|
224
|
+
);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Returns the isolate `$scope` of the element.
|
|
229
|
+
* @returns {import("../../core/scope/scope").Scope}
|
|
230
|
+
*/
|
|
231
|
+
JQLite.prototype.isolateScope = function () {
|
|
232
|
+
return (
|
|
233
|
+
getOrSetCacheData(this[0], "$isolateScope") ||
|
|
234
|
+
getOrSetCacheData(this[0], "$isolateScopeNoTemplate")
|
|
235
|
+
);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Return instance of controller attached to element
|
|
240
|
+
* @param {string} [name] - Controller name
|
|
241
|
+
* @returns {any}
|
|
242
|
+
*/
|
|
243
|
+
JQLite.prototype.controller = function (name) {
|
|
244
|
+
return getController(this[0], name);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Return instance of injector attached to element
|
|
249
|
+
* @returns {import('../../types').InjectorService}
|
|
250
|
+
*/
|
|
251
|
+
JQLite.prototype.injector = function () {
|
|
252
|
+
return getInheritedData(this[0], "$injector");
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Adds an event listener to each element in the JQLite collection.
|
|
257
|
+
*
|
|
258
|
+
* @param {string} type - The event type(s) to listen for. Multiple event types can be specified, separated by a space.
|
|
259
|
+
* @param {Function} fn - The function to execute when the event is triggered.
|
|
260
|
+
* @returns {JQLite} The JQLite collection for chaining.
|
|
261
|
+
*/
|
|
262
|
+
JQLite.prototype.on = function (type, fn) {
|
|
263
|
+
// Do not add event handlers to non-elements because they will not be cleaned up.
|
|
264
|
+
for (let i = 0, ii = this.length; i < ii; i++) {
|
|
265
|
+
const element = this[i];
|
|
266
|
+
if (!elementAcceptsData(element)) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const expandoStore = getExpando(element, true);
|
|
271
|
+
|
|
272
|
+
if (!expandoStore.handle) {
|
|
273
|
+
expandoStore.handle = createEventHandler(element, expandoStore.events);
|
|
274
|
+
}
|
|
275
|
+
// http://jsperf.com/string-indexof-vs-split
|
|
276
|
+
const types = type.indexOf(" ") >= 0 ? type.split(" ") : [type];
|
|
277
|
+
let j = types.length;
|
|
278
|
+
|
|
279
|
+
const addHandler = function (type, specialHandlerWrapper, noEventListener) {
|
|
280
|
+
let eventFns = expandoStore.events[type];
|
|
281
|
+
|
|
282
|
+
if (!eventFns) {
|
|
283
|
+
eventFns = expandoStore.events[type] = [];
|
|
284
|
+
eventFns.specialHandlerWrapper = specialHandlerWrapper;
|
|
285
|
+
if (type !== "$destroy" && !noEventListener) {
|
|
286
|
+
element.addEventListener(type, expandoStore.handle);
|
|
287
|
+
}
|
|
234
288
|
}
|
|
289
|
+
|
|
290
|
+
eventFns.push(fn);
|
|
235
291
|
};
|
|
236
292
|
|
|
237
|
-
|
|
238
|
-
|
|
293
|
+
while (j--) {
|
|
294
|
+
type = types[j];
|
|
239
295
|
if (MOUSE_EVENT_MAP[type]) {
|
|
240
|
-
|
|
296
|
+
addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);
|
|
297
|
+
addHandler(type, undefined, true);
|
|
298
|
+
} else {
|
|
299
|
+
addHandler(type);
|
|
241
300
|
}
|
|
242
|
-
}
|
|
301
|
+
}
|
|
243
302
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
303
|
+
return this;
|
|
304
|
+
};
|
|
247
305
|
|
|
248
306
|
/**
|
|
249
|
-
* Removes
|
|
250
|
-
*
|
|
251
|
-
* from
|
|
252
|
-
* @param {
|
|
253
|
-
* @
|
|
307
|
+
* Removes an event listener to each element in JQLite collection.
|
|
308
|
+
*
|
|
309
|
+
* @param {string} type - The event type(s) to remove listener from
|
|
310
|
+
* @param {Function} fn - The function to remove from event type.
|
|
311
|
+
* @returns {JQLite}
|
|
254
312
|
*/
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
313
|
+
JQLite.prototype.off = function (type, fn) {
|
|
314
|
+
for (let i = 0, ii = this.length; i < ii; i++) {
|
|
315
|
+
const element = this[i];
|
|
316
|
+
const expandoStore = getExpando(element);
|
|
317
|
+
const events = expandoStore && expandoStore.events;
|
|
318
|
+
const handle = expandoStore && expandoStore.handle;
|
|
258
319
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
320
|
+
if (!handle) return; // no listeners registered
|
|
321
|
+
|
|
322
|
+
if (!type) {
|
|
323
|
+
for (type in events) {
|
|
324
|
+
if (type !== "$destroy") {
|
|
325
|
+
element.removeEventListener(type, handle);
|
|
326
|
+
}
|
|
327
|
+
delete events[type];
|
|
328
|
+
}
|
|
262
329
|
} else {
|
|
263
|
-
|
|
330
|
+
const removeHandler = function (type) {
|
|
331
|
+
const listenerFns = events[type];
|
|
332
|
+
if (isDefined(fn) && Array.isArray(listenerFns)) {
|
|
333
|
+
arrayRemove(listenerFns, fn);
|
|
334
|
+
}
|
|
335
|
+
if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) {
|
|
336
|
+
element.removeEventListener(type, handle);
|
|
337
|
+
delete events[type];
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
forEach(type.split(" "), (type) => {
|
|
342
|
+
removeHandler(type);
|
|
343
|
+
if (MOUSE_EVENT_MAP[type]) {
|
|
344
|
+
removeHandler(MOUSE_EVENT_MAP[type]);
|
|
345
|
+
}
|
|
346
|
+
});
|
|
264
347
|
}
|
|
265
348
|
|
|
266
349
|
removeIfEmptyData(element);
|
|
267
350
|
}
|
|
268
|
-
|
|
351
|
+
return this;
|
|
352
|
+
};
|
|
269
353
|
|
|
270
354
|
/**
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
* @
|
|
274
|
-
*
|
|
275
|
-
* @param {Element} element
|
|
276
|
-
* @param {boolean} [createIfNecessary=false]
|
|
277
|
-
* @returns {import("../../core/cache/cache").ExpandoStore}
|
|
355
|
+
* Remove data by name from cache associated with each element in JQLite collection.
|
|
356
|
+
* @param {string} name - The key of the data associated with element
|
|
357
|
+
* @returns {JQLite}
|
|
278
358
|
*/
|
|
279
|
-
function
|
|
280
|
-
let
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (createIfNecessary && !expandoStore) {
|
|
284
|
-
element[EXPANDO] = expandoId = jqNextId();
|
|
285
|
-
expandoStore = {
|
|
286
|
-
events: {},
|
|
287
|
-
data: {},
|
|
288
|
-
handle: null,
|
|
289
|
-
};
|
|
290
|
-
CACHE.set(expandoId, expandoStore);
|
|
359
|
+
JQLite.prototype.removeData = function (name) {
|
|
360
|
+
for (let i = 0, ii = this.length; i < ii; i++) {
|
|
361
|
+
const element = this[i];
|
|
362
|
+
removeElementData(element, name);
|
|
291
363
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
|
|
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
|
-
}
|
|
364
|
+
return this;
|
|
365
|
+
};
|
|
304
366
|
|
|
305
367
|
/**
|
|
306
|
-
*
|
|
307
|
-
* @param {
|
|
308
|
-
* @
|
|
368
|
+
* Gets or sets data on a parent element
|
|
369
|
+
* @param {string} name
|
|
370
|
+
* @param {any} value
|
|
371
|
+
* @returns {JQLite|any}
|
|
309
372
|
*/
|
|
310
|
-
function
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
return
|
|
318
|
-
|
|
319
|
-
return false;
|
|
373
|
+
JQLite.prototype.inheritedData = function (name, value) {
|
|
374
|
+
for (let i = 0, ii = this.length; i < ii; i++) {
|
|
375
|
+
const element = this[0];
|
|
376
|
+
let res = getInheritedData(element, name, value);
|
|
377
|
+
if (value) {
|
|
378
|
+
return this;
|
|
379
|
+
} else {
|
|
380
|
+
return res;
|
|
381
|
+
}
|
|
320
382
|
}
|
|
321
|
-
}
|
|
383
|
+
};
|
|
322
384
|
|
|
323
385
|
/**
|
|
324
|
-
*
|
|
325
|
-
* @
|
|
386
|
+
* Gets or sets innerHTML on the first element in JQLite collection
|
|
387
|
+
* @param {string} value
|
|
388
|
+
* @returns {JQLite|any|undefined}
|
|
326
389
|
*/
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
390
|
+
JQLite.prototype.html = function (value) {
|
|
391
|
+
const element = this[0];
|
|
392
|
+
if (!element) return undefined;
|
|
393
|
+
if (isUndefined(value)) {
|
|
394
|
+
return element.innerHTML;
|
|
395
|
+
}
|
|
396
|
+
dealoc(element, true);
|
|
397
|
+
element.innerHTML = value;
|
|
398
|
+
return this;
|
|
399
|
+
};
|
|
334
400
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
401
|
+
/// ///////////////////////////////////////
|
|
402
|
+
// Functions iterating getter/setters.
|
|
403
|
+
// these functions return self on setter and
|
|
404
|
+
// value on get.
|
|
405
|
+
/// ///////////////////////////////////////
|
|
406
|
+
forEach(
|
|
407
|
+
{
|
|
408
|
+
data: getOrSetCacheData,
|
|
409
|
+
attr(element, name, value) {
|
|
410
|
+
let ret;
|
|
411
|
+
const { nodeType } = element;
|
|
412
|
+
if (
|
|
413
|
+
nodeType === Node.TEXT_NODE ||
|
|
414
|
+
nodeType === Node.ATTRIBUTE_NODE ||
|
|
415
|
+
nodeType === Node.COMMENT_NODE ||
|
|
416
|
+
!element.getAttribute
|
|
417
|
+
) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
342
420
|
|
|
343
|
-
|
|
421
|
+
const lowercasedName = lowercase(name);
|
|
422
|
+
const isBooleanAttr = BOOLEAN_ATTR[lowercasedName];
|
|
344
423
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
while (--i > -1) {
|
|
348
|
-
tmp.appendChild(window.document.createElement(wrap[i]));
|
|
349
|
-
tmp = tmp.firstChild;
|
|
350
|
-
}
|
|
351
|
-
tmp.innerHTML = html;
|
|
424
|
+
if (isDefined(value)) {
|
|
425
|
+
// setter
|
|
352
426
|
|
|
353
|
-
|
|
427
|
+
if (value === null || (value === false && isBooleanAttr)) {
|
|
428
|
+
element.removeAttribute(name);
|
|
429
|
+
} else {
|
|
430
|
+
element.setAttribute(name, isBooleanAttr ? lowercasedName : value);
|
|
431
|
+
}
|
|
432
|
+
} else {
|
|
433
|
+
// getter
|
|
354
434
|
|
|
355
|
-
|
|
356
|
-
tmp.textContent = "";
|
|
357
|
-
}
|
|
435
|
+
ret = element.getAttribute(name);
|
|
358
436
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
437
|
+
if (isBooleanAttr && ret !== null) {
|
|
438
|
+
ret = lowercasedName;
|
|
439
|
+
}
|
|
440
|
+
// Normalize non-existing attributes to undefined (as jQuery).
|
|
441
|
+
return ret === null ? undefined : ret;
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
text: (function () {
|
|
445
|
+
getText.$dv = "";
|
|
446
|
+
return getText;
|
|
363
447
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
448
|
+
function getText(element, value) {
|
|
449
|
+
if (isUndefined(value)) {
|
|
450
|
+
const { nodeType } = element;
|
|
451
|
+
return nodeType === Node.ELEMENT_NODE || nodeType === Node.TEXT_NODE
|
|
452
|
+
? element.textContent
|
|
453
|
+
: "";
|
|
454
|
+
}
|
|
455
|
+
element.textContent = value;
|
|
456
|
+
}
|
|
457
|
+
})(),
|
|
458
|
+
val(element, value) {
|
|
459
|
+
if (isUndefined(value)) {
|
|
460
|
+
if (element.multiple && nodeName_(element) === "select") {
|
|
461
|
+
const result = [];
|
|
462
|
+
forEach(element.options, (option) => {
|
|
463
|
+
if (option.selected) {
|
|
464
|
+
result.push(option.value || option.text);
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
return result;
|
|
468
|
+
}
|
|
469
|
+
return element.value;
|
|
470
|
+
}
|
|
471
|
+
element.value = value;
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
(fn, name) => {
|
|
475
|
+
/**
|
|
476
|
+
* Properties: writes return selection, reads return first value
|
|
477
|
+
*/
|
|
478
|
+
JQLite.prototype[name] = function (arg1, arg2) {
|
|
479
|
+
let i;
|
|
480
|
+
let key;
|
|
481
|
+
const nodeCount = this.length;
|
|
377
482
|
|
|
378
|
-
|
|
379
|
-
|
|
483
|
+
// JQLiteEmpty takes no arguments but is a setter.
|
|
484
|
+
if (isUndefined(fn.length === 2 && fn !== getController ? arg1 : arg2)) {
|
|
485
|
+
if (isObject(arg1)) {
|
|
486
|
+
// we are a write, but the object properties are the key/values
|
|
487
|
+
for (i = 0; i < nodeCount; i++) {
|
|
488
|
+
if (fn === getOrSetCacheData) {
|
|
489
|
+
fn(this[i], arg1);
|
|
490
|
+
} else {
|
|
491
|
+
for (key in arg1) {
|
|
492
|
+
fn(this[i], key, arg1[key]);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
// return self for chaining
|
|
497
|
+
return this;
|
|
498
|
+
}
|
|
499
|
+
// we are a read, so read the first child.
|
|
500
|
+
// TODO: do we still need this?
|
|
501
|
+
let value = fn.$dv;
|
|
502
|
+
// Only if we have $dv do we iterate over all, otherwise it is just the first element.
|
|
503
|
+
const jj = isUndefined(value) ? Math.min(nodeCount, 1) : nodeCount;
|
|
504
|
+
for (let j = 0; j < jj; j++) {
|
|
505
|
+
const nodeValue = fn(this[j], arg1, arg2);
|
|
506
|
+
value = value ? value + nodeValue : nodeValue;
|
|
507
|
+
}
|
|
508
|
+
return value;
|
|
509
|
+
}
|
|
510
|
+
// we are a write, so apply to all children
|
|
511
|
+
for (i = 0; i < nodeCount; i++) {
|
|
512
|
+
fn(this[i], arg1, arg2);
|
|
513
|
+
}
|
|
514
|
+
// return self for chaining
|
|
515
|
+
return this;
|
|
516
|
+
};
|
|
517
|
+
},
|
|
518
|
+
);
|
|
380
519
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
520
|
+
/// ///////////////////////////////////////
|
|
521
|
+
// Functions iterating traversal.
|
|
522
|
+
// These functions chain results into a single
|
|
523
|
+
// selector.
|
|
524
|
+
/// ///////////////////////////////////////
|
|
525
|
+
forEach(
|
|
526
|
+
{
|
|
527
|
+
replaceWith(element, replaceNode) {
|
|
528
|
+
let index;
|
|
529
|
+
const parent = element.parentNode;
|
|
530
|
+
dealoc(element);
|
|
531
|
+
forEach(new JQLite(replaceNode), (node) => {
|
|
532
|
+
if (index) {
|
|
533
|
+
parent.insertBefore(node, index.nextSibling);
|
|
534
|
+
} else {
|
|
535
|
+
parent.replaceChild(node, element);
|
|
536
|
+
}
|
|
537
|
+
index = node;
|
|
538
|
+
});
|
|
539
|
+
},
|
|
540
|
+
children(element) {
|
|
541
|
+
return Array.from(element.childNodes).filter(
|
|
542
|
+
(child) => child.nodeType === Node.ELEMENT_NODE,
|
|
543
|
+
);
|
|
544
|
+
},
|
|
545
|
+
append(element, node) {
|
|
546
|
+
const { nodeType } = element;
|
|
547
|
+
if (
|
|
548
|
+
nodeType !== Node.ELEMENT_NODE &&
|
|
549
|
+
nodeType !== Node.DOCUMENT_FRAGMENT_NODE
|
|
550
|
+
)
|
|
551
|
+
return;
|
|
390
552
|
|
|
391
|
-
|
|
392
|
-
cleanElementData(element.querySelectorAll("*"));
|
|
393
|
-
}
|
|
394
|
-
}
|
|
553
|
+
node = new JQLite(node);
|
|
395
554
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
*/
|
|
402
|
-
function removeIfEmptyData(element) {
|
|
403
|
-
const expandoId = element[EXPANDO];
|
|
404
|
-
const { events, data } = CACHE.get(expandoId);
|
|
555
|
+
for (let i = 0, ii = node.length; i < ii; i++) {
|
|
556
|
+
const child = node[i];
|
|
557
|
+
element.appendChild(child);
|
|
558
|
+
}
|
|
559
|
+
},
|
|
405
560
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
561
|
+
prepend(element, node) {
|
|
562
|
+
if (element.nodeType === Node.ELEMENT_NODE) {
|
|
563
|
+
const index = element.firstChild;
|
|
564
|
+
forEach(new JQLite(node), (child) => {
|
|
565
|
+
element.insertBefore(child, index);
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
},
|
|
414
569
|
|
|
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) {
|
|
424
|
-
if (elementAcceptsData(element)) {
|
|
425
|
-
let prop;
|
|
570
|
+
remove: removeElement,
|
|
426
571
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
const expandoStore = getExpando(element, !isSimpleGetter);
|
|
431
|
-
const data = expandoStore && expandoStore.data;
|
|
572
|
+
detach(element) {
|
|
573
|
+
removeElement(element, true);
|
|
574
|
+
},
|
|
432
575
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
576
|
+
after(element, newElement) {
|
|
577
|
+
let index = element;
|
|
578
|
+
const parent = element.parentNode;
|
|
579
|
+
|
|
580
|
+
if (parent) {
|
|
581
|
+
newElement = new JQLite(newElement);
|
|
582
|
+
|
|
583
|
+
for (let i = 0, ii = newElement.length; i < ii; i++) {
|
|
584
|
+
const node = newElement[i];
|
|
585
|
+
parent.insertBefore(node, index.nextSibling);
|
|
586
|
+
index = node;
|
|
587
|
+
}
|
|
442
588
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
589
|
+
},
|
|
590
|
+
|
|
591
|
+
parent(element) {
|
|
592
|
+
const parent = element.parentNode;
|
|
593
|
+
return parent && parent.nodeType !== Node.DOCUMENT_FRAGMENT_NODE
|
|
594
|
+
? parent
|
|
595
|
+
: null;
|
|
596
|
+
},
|
|
597
|
+
|
|
598
|
+
// TODO: remove after migrating tests away from JQLite
|
|
599
|
+
find(element, selector) {
|
|
600
|
+
if (element.getElementsByTagName) {
|
|
601
|
+
return element.getElementsByTagName(selector);
|
|
446
602
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
// TODO: check should occur perhaps prior at compilation level that this is a valid element
|
|
450
|
-
}
|
|
451
|
-
}
|
|
603
|
+
return [];
|
|
604
|
+
},
|
|
452
605
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
606
|
+
triggerHandler(element, event, extraParameters) {
|
|
607
|
+
let dummyEvent;
|
|
608
|
+
let eventFnsCopy;
|
|
609
|
+
let handlerArgs;
|
|
610
|
+
const eventName = event.type || event;
|
|
611
|
+
const expandoStore = getExpando(element);
|
|
612
|
+
const events = expandoStore && expandoStore.events;
|
|
613
|
+
const eventFns = events && events[eventName];
|
|
461
614
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
615
|
+
if (eventFns) {
|
|
616
|
+
// Create a dummy event to pass to the handlers
|
|
617
|
+
dummyEvent = {
|
|
618
|
+
preventDefault() {
|
|
619
|
+
this.defaultPrevented = true;
|
|
620
|
+
},
|
|
621
|
+
isDefaultPrevented() {
|
|
622
|
+
return this.defaultPrevented === true;
|
|
623
|
+
},
|
|
624
|
+
stopImmediatePropagation() {
|
|
625
|
+
this.immediatePropagationStopped = true;
|
|
626
|
+
},
|
|
627
|
+
isImmediatePropagationStopped() {
|
|
628
|
+
return this.immediatePropagationStopped === true;
|
|
629
|
+
},
|
|
630
|
+
stopPropagation: () => {},
|
|
631
|
+
type: eventName,
|
|
632
|
+
target: element,
|
|
633
|
+
};
|
|
468
634
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
for (let i = 0; i < length; i++) {
|
|
473
|
-
root[root.length++] = elements[i];
|
|
474
|
-
}
|
|
635
|
+
// If a custom event was provided then extend our dummy event with it
|
|
636
|
+
if (event.type) {
|
|
637
|
+
dummyEvent = extend(dummyEvent, event);
|
|
475
638
|
}
|
|
476
|
-
} else {
|
|
477
|
-
root[root.length++] = elements;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
639
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
640
|
+
// Copy event handlers in case event handlers array is modified during execution.
|
|
641
|
+
eventFnsCopy = shallowCopy(eventFns);
|
|
642
|
+
handlerArgs = extraParameters
|
|
643
|
+
? [dummyEvent].concat(extraParameters)
|
|
644
|
+
: [dummyEvent];
|
|
486
645
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
646
|
+
forEach(eventFnsCopy, (fn) => {
|
|
647
|
+
if (!dummyEvent.isImmediatePropagationStopped()) {
|
|
648
|
+
fn.apply(element, handlerArgs);
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
},
|
|
654
|
+
(fn, name) => {
|
|
655
|
+
/**
|
|
656
|
+
* chaining functions
|
|
657
|
+
*/
|
|
658
|
+
JQLite.prototype[name] = function (arg1, arg2, arg3) {
|
|
659
|
+
let value;
|
|
494
660
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
661
|
+
for (let i = 0, ii = this.length; i < ii; i++) {
|
|
662
|
+
if (isUndefined(value)) {
|
|
663
|
+
value = fn(this[i], arg1, arg2, arg3);
|
|
664
|
+
if (isDefined(value)) {
|
|
665
|
+
// any function which returns a value needs to be wrapped
|
|
666
|
+
value = JQLite(value);
|
|
667
|
+
}
|
|
668
|
+
} else {
|
|
669
|
+
addNodes(value, fn(this[i], arg1, arg2, arg3));
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return isDefined(value) ? value : this;
|
|
673
|
+
};
|
|
674
|
+
},
|
|
675
|
+
);
|
|
500
676
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
element =
|
|
505
|
-
element.parentNode ||
|
|
506
|
-
(element.nodeType === Node.DOCUMENT_FRAGMENT_NODE && element.host);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
677
|
+
///////////////////////////////////////////////////////////////////
|
|
678
|
+
//////////// HELPER FUNCTIONS /////////////////////////
|
|
679
|
+
///////////////////////////////////////////////////////////////////
|
|
509
680
|
|
|
510
681
|
/**
|
|
511
682
|
*
|
|
512
|
-
* @
|
|
513
|
-
* @param {boolean} keepData
|
|
683
|
+
* @returns {number} Next unique JQInstance id
|
|
514
684
|
*/
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
const parent = element.parentNode;
|
|
518
|
-
if (parent) parent.removeChild(element);
|
|
685
|
+
function jqNextId() {
|
|
686
|
+
return ++jqId;
|
|
519
687
|
}
|
|
520
688
|
|
|
521
689
|
/**
|
|
522
|
-
*
|
|
523
|
-
* @param {
|
|
690
|
+
* @param {string} _all
|
|
691
|
+
* @param {string} letter
|
|
692
|
+
* @returns {string}
|
|
524
693
|
*/
|
|
525
|
-
function
|
|
526
|
-
|
|
527
|
-
window.document.removeEventListener("DOMContentLoaded", trigger);
|
|
528
|
-
fn();
|
|
529
|
-
}
|
|
530
|
-
// check if document is already loaded
|
|
531
|
-
if (window.document.readyState === "complete") {
|
|
532
|
-
window.setTimeout(fn);
|
|
533
|
-
} else {
|
|
534
|
-
// We can not use JQLite since we are not done loading.
|
|
535
|
-
window.document.addEventListener("DOMContentLoaded", trigger);
|
|
536
|
-
}
|
|
694
|
+
function fnCamelCaseReplace(_all, letter) {
|
|
695
|
+
return letter.toUpperCase();
|
|
537
696
|
}
|
|
538
697
|
|
|
539
|
-
/// ///////////////////////////////////////
|
|
540
|
-
// Functions which are declared directly.
|
|
541
|
-
/// ///////////////////////////////////////
|
|
542
|
-
JQLite.prototype = {
|
|
543
|
-
toString() {
|
|
544
|
-
const value = [];
|
|
545
|
-
forEach(this, (e) => {
|
|
546
|
-
value.push(`${e}`);
|
|
547
|
-
});
|
|
548
|
-
return `[${value.join(", ")}]`;
|
|
549
|
-
},
|
|
550
|
-
|
|
551
|
-
eq(index) {
|
|
552
|
-
return index >= 0 ? JQLite(this[index]) : JQLite(this[this.length + index]);
|
|
553
|
-
},
|
|
554
|
-
|
|
555
|
-
length: 0,
|
|
556
|
-
};
|
|
557
|
-
|
|
558
698
|
/**
|
|
559
|
-
*
|
|
560
|
-
* @
|
|
699
|
+
* Converts kebab-case to camelCase.
|
|
700
|
+
* @param {string} name Name to normalize
|
|
701
|
+
* @returns {string}
|
|
561
702
|
*/
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
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
|
-
};
|
|
703
|
+
export function kebabToCamel(name) {
|
|
704
|
+
return name.replace(DASH_LOWERCASE_REGEXP, fnCamelCaseReplace);
|
|
705
|
+
}
|
|
579
706
|
|
|
580
707
|
/**
|
|
581
|
-
*
|
|
582
|
-
* @
|
|
708
|
+
* Converts sname to camelCase.
|
|
709
|
+
* @param {string} name
|
|
710
|
+
* @returns {string}
|
|
583
711
|
*/
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
getOrSetCacheData(this[0], "$scope") ||
|
|
588
|
-
JQLiteInheritedData(this[0].parentNode || this[0], [
|
|
589
|
-
"$isolateScope",
|
|
590
|
-
"$scope",
|
|
591
|
-
])
|
|
592
|
-
);
|
|
593
|
-
};
|
|
712
|
+
export function snakeToCamel(name) {
|
|
713
|
+
return name.replace(UNDERSCORE_LOWERCASE_REGEXP, fnCamelCaseReplace);
|
|
714
|
+
}
|
|
594
715
|
|
|
595
716
|
/**
|
|
596
|
-
*
|
|
597
|
-
*
|
|
717
|
+
* Removes expando data from this element. If key is provided, only
|
|
718
|
+
* its field is removed. If data is empty, also removes `ExpandoStore`
|
|
719
|
+
* from cache.
|
|
720
|
+
* @param {Element} element
|
|
721
|
+
* @param {string} [name] - key of field to remove
|
|
598
722
|
*/
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
getOrSetCacheData(this[0], "$isolateScopeNoTemplate")
|
|
603
|
-
);
|
|
604
|
-
};
|
|
723
|
+
export function removeElementData(element, name) {
|
|
724
|
+
const expandoId = element[EXPANDO];
|
|
725
|
+
const expandoStore = expandoId && CACHE.get(expandoId);
|
|
605
726
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
return JQLiteController(this[0], name);
|
|
613
|
-
};
|
|
727
|
+
if (expandoStore) {
|
|
728
|
+
if (name) {
|
|
729
|
+
delete expandoStore.data[name];
|
|
730
|
+
} else {
|
|
731
|
+
expandoStore.data = {};
|
|
732
|
+
}
|
|
614
733
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
*/
|
|
619
|
-
JQLite.prototype.injector = function () {
|
|
620
|
-
return JQLiteInheritedData(this[0], "$injector");
|
|
621
|
-
};
|
|
734
|
+
removeIfEmptyData(element);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
622
737
|
|
|
623
738
|
/**
|
|
624
|
-
*
|
|
739
|
+
* Stores data associated with an element inside the expando property of the DOM element.
|
|
625
740
|
*
|
|
626
|
-
* @
|
|
627
|
-
*
|
|
628
|
-
* @
|
|
741
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Glossary/Expando MDN Glossary: Expando}
|
|
742
|
+
*
|
|
743
|
+
* @param {Element} element
|
|
744
|
+
* @param {boolean} [createIfNecessary=false]
|
|
745
|
+
* @returns {import("../../core/cache/cache").ExpandoStore}
|
|
629
746
|
*/
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
const element = this[i];
|
|
634
|
-
if (!elementAcceptsData(element)) {
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
const expandoStore = getExpando(element, true);
|
|
639
|
-
|
|
640
|
-
if (!expandoStore.handle) {
|
|
641
|
-
expandoStore.handle = createEventHandler(element, expandoStore.events);
|
|
642
|
-
}
|
|
643
|
-
// http://jsperf.com/string-indexof-vs-split
|
|
644
|
-
const types = type.indexOf(" ") >= 0 ? type.split(" ") : [type];
|
|
645
|
-
let j = types.length;
|
|
646
|
-
|
|
647
|
-
const addHandler = function (type, specialHandlerWrapper, noEventListener) {
|
|
648
|
-
let eventFns = expandoStore.events[type];
|
|
649
|
-
|
|
650
|
-
if (!eventFns) {
|
|
651
|
-
eventFns = expandoStore.events[type] = [];
|
|
652
|
-
eventFns.specialHandlerWrapper = specialHandlerWrapper;
|
|
653
|
-
if (type !== "$destroy" && !noEventListener) {
|
|
654
|
-
element.addEventListener(type, expandoStore.handle);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
747
|
+
function getExpando(element, createIfNecessary = false) {
|
|
748
|
+
let expandoId = element[EXPANDO];
|
|
749
|
+
let expandoStore = expandoId && CACHE.get(expandoId);
|
|
657
750
|
|
|
658
|
-
|
|
751
|
+
if (createIfNecessary && !expandoStore) {
|
|
752
|
+
element[EXPANDO] = expandoId = jqNextId();
|
|
753
|
+
expandoStore = {
|
|
754
|
+
events: {},
|
|
755
|
+
data: {},
|
|
756
|
+
handle: null,
|
|
659
757
|
};
|
|
660
|
-
|
|
661
|
-
while (j--) {
|
|
662
|
-
type = types[j];
|
|
663
|
-
if (MOUSE_EVENT_MAP[type]) {
|
|
664
|
-
addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);
|
|
665
|
-
addHandler(type, undefined, true);
|
|
666
|
-
} else {
|
|
667
|
-
addHandler(type);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
758
|
+
CACHE.set(expandoId, expandoStore);
|
|
670
759
|
}
|
|
671
|
-
return this;
|
|
672
|
-
};
|
|
673
760
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
const booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
|
|
761
|
+
return expandoStore;
|
|
762
|
+
}
|
|
677
763
|
|
|
678
|
-
|
|
679
|
-
|
|
764
|
+
/**
|
|
765
|
+
* Checks if the string contains HTML tags or entities.
|
|
766
|
+
* @param {string} html
|
|
767
|
+
* @returns {boolean} True if the string is plain text, false if it contains HTML tags or entities.
|
|
768
|
+
*/
|
|
769
|
+
export function isTextNode(html) {
|
|
770
|
+
return !/<|&#?\w+;/.test(html);
|
|
680
771
|
}
|
|
681
772
|
|
|
682
773
|
/**
|
|
683
|
-
*
|
|
684
|
-
*
|
|
685
|
-
* @
|
|
774
|
+
* Check if element can accept expando data
|
|
775
|
+
* @param {Element} node
|
|
776
|
+
* @returns {boolean}
|
|
686
777
|
*/
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
778
|
+
function elementAcceptsData(node) {
|
|
779
|
+
// The window object can accept data but has no nodeType
|
|
780
|
+
// Otherwise we are only interested in elements (1) and documents (9)
|
|
781
|
+
switch (node.nodeType) {
|
|
782
|
+
case Node.ELEMENT_NODE:
|
|
783
|
+
case Node.DOCUMENT_NODE:
|
|
784
|
+
case undefined: // window.object
|
|
785
|
+
return true;
|
|
786
|
+
default:
|
|
787
|
+
return false;
|
|
695
788
|
}
|
|
696
789
|
}
|
|
697
790
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
const { nodeType } = element;
|
|
710
|
-
if (
|
|
711
|
-
nodeType === Node.TEXT_NODE ||
|
|
712
|
-
nodeType === Node.ATTRIBUTE_NODE ||
|
|
713
|
-
nodeType === Node.COMMENT_NODE ||
|
|
714
|
-
!element.getAttribute
|
|
715
|
-
) {
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
const lowercasedName = lowercase(name);
|
|
720
|
-
const isBooleanAttr = BOOLEAN_ATTR[lowercasedName];
|
|
721
|
-
|
|
722
|
-
if (isDefined(value)) {
|
|
723
|
-
// setter
|
|
724
|
-
|
|
725
|
-
if (value === null || (value === false && isBooleanAttr)) {
|
|
726
|
-
element.removeAttribute(name);
|
|
727
|
-
} else {
|
|
728
|
-
element.setAttribute(name, isBooleanAttr ? lowercasedName : value);
|
|
729
|
-
}
|
|
730
|
-
} else {
|
|
731
|
-
// getter
|
|
791
|
+
/**
|
|
792
|
+
* @param {string} html
|
|
793
|
+
* @returns {DocumentFragment}
|
|
794
|
+
*/
|
|
795
|
+
export function buildFragment(html) {
|
|
796
|
+
let tmp;
|
|
797
|
+
let tag;
|
|
798
|
+
let wrap;
|
|
799
|
+
let tempFragment = document.createDocumentFragment();
|
|
800
|
+
let nodes = [];
|
|
801
|
+
let i;
|
|
732
802
|
|
|
733
|
-
|
|
803
|
+
if (isTextNode(html)) {
|
|
804
|
+
// Convert non-html into a text node
|
|
805
|
+
nodes.push(document.createTextNode(html));
|
|
806
|
+
} else {
|
|
807
|
+
// Convert html into DOM nodes
|
|
808
|
+
tmp = tempFragment.appendChild(document.createElement("div"));
|
|
809
|
+
tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
|
|
734
810
|
|
|
735
|
-
|
|
736
|
-
ret = lowercasedName;
|
|
737
|
-
}
|
|
738
|
-
// Normalize non-existing attributes to undefined (as jQuery).
|
|
739
|
-
return ret === null ? undefined : ret;
|
|
740
|
-
}
|
|
741
|
-
},
|
|
742
|
-
text: (function () {
|
|
743
|
-
getText.$dv = "";
|
|
744
|
-
return getText;
|
|
811
|
+
wrap = wrapMap[tag] || [];
|
|
745
812
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
element.textContent = value;
|
|
754
|
-
}
|
|
755
|
-
})(),
|
|
756
|
-
val(element, value) {
|
|
757
|
-
if (isUndefined(value)) {
|
|
758
|
-
if (element.multiple && nodeName_(element) === "select") {
|
|
759
|
-
const result = [];
|
|
760
|
-
forEach(element.options, (option) => {
|
|
761
|
-
if (option.selected) {
|
|
762
|
-
result.push(option.value || option.text);
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
return result;
|
|
766
|
-
}
|
|
767
|
-
return element.value;
|
|
768
|
-
}
|
|
769
|
-
element.value = value;
|
|
770
|
-
},
|
|
771
|
-
html(element, value) {
|
|
772
|
-
if (isUndefined(value)) {
|
|
773
|
-
return element.innerHTML;
|
|
774
|
-
}
|
|
775
|
-
dealoc(element, true);
|
|
776
|
-
element.innerHTML = value;
|
|
777
|
-
},
|
|
778
|
-
},
|
|
779
|
-
(fn, name) => {
|
|
780
|
-
/**
|
|
781
|
-
* Properties: writes return selection, reads return first value
|
|
782
|
-
*/
|
|
783
|
-
JQLite.prototype[name] = function (arg1, arg2) {
|
|
784
|
-
let i;
|
|
785
|
-
let key;
|
|
786
|
-
const nodeCount = this.length;
|
|
813
|
+
// Create wrappers & descend into them
|
|
814
|
+
i = wrap.length;
|
|
815
|
+
while (--i > -1) {
|
|
816
|
+
tmp.appendChild(window.document.createElement(wrap[i]));
|
|
817
|
+
tmp = tmp.firstChild;
|
|
818
|
+
}
|
|
819
|
+
tmp.innerHTML = html;
|
|
787
820
|
|
|
788
|
-
|
|
789
|
-
if (
|
|
790
|
-
isUndefined(fn.length === 2 && fn !== JQLiteController ? arg1 : arg2)
|
|
791
|
-
) {
|
|
792
|
-
if (isObject(arg1)) {
|
|
793
|
-
// we are a write, but the object properties are the key/values
|
|
794
|
-
for (i = 0; i < nodeCount; i++) {
|
|
795
|
-
if (fn === getOrSetCacheData) {
|
|
796
|
-
fn(this[i], arg1);
|
|
797
|
-
} else {
|
|
798
|
-
for (key in arg1) {
|
|
799
|
-
fn(this[i], key, arg1[key]);
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
// return self for chaining
|
|
804
|
-
return this;
|
|
805
|
-
}
|
|
806
|
-
// we are a read, so read the first child.
|
|
807
|
-
// TODO: do we still need this?
|
|
808
|
-
let value = fn.$dv;
|
|
809
|
-
// Only if we have $dv do we iterate over all, otherwise it is just the first element.
|
|
810
|
-
const jj = isUndefined(value) ? Math.min(nodeCount, 1) : nodeCount;
|
|
811
|
-
for (let j = 0; j < jj; j++) {
|
|
812
|
-
const nodeValue = fn(this[j], arg1, arg2);
|
|
813
|
-
value = value ? value + nodeValue : nodeValue;
|
|
814
|
-
}
|
|
815
|
-
return value;
|
|
816
|
-
}
|
|
817
|
-
// we are a write, so apply to all children
|
|
818
|
-
for (i = 0; i < nodeCount; i++) {
|
|
819
|
-
fn(this[i], arg1, arg2);
|
|
820
|
-
}
|
|
821
|
-
// return self for chaining
|
|
822
|
-
return this;
|
|
823
|
-
};
|
|
824
|
-
},
|
|
825
|
-
);
|
|
821
|
+
nodes = concat(nodes, tmp.childNodes);
|
|
826
822
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
// selector.
|
|
831
|
-
/// ///////////////////////////////////////
|
|
832
|
-
forEach(
|
|
833
|
-
{
|
|
834
|
-
removeData: removeElementData,
|
|
823
|
+
tmp = tempFragment.firstChild;
|
|
824
|
+
tmp.textContent = "";
|
|
825
|
+
}
|
|
835
826
|
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
dealoc(element);
|
|
841
|
-
forEach(new JQLite(replaceNode), (node) => {
|
|
842
|
-
if (index) {
|
|
843
|
-
parent.insertBefore(node, index.nextSibling);
|
|
844
|
-
} else {
|
|
845
|
-
parent.replaceChild(node, element);
|
|
846
|
-
}
|
|
847
|
-
index = node;
|
|
848
|
-
});
|
|
849
|
-
},
|
|
850
|
-
children(element) {
|
|
851
|
-
return Array.from(element.childNodes).filter(
|
|
852
|
-
(child) => child.nodeType === Node.ELEMENT_NODE,
|
|
853
|
-
);
|
|
854
|
-
},
|
|
855
|
-
append(element, node) {
|
|
856
|
-
const { nodeType } = element;
|
|
857
|
-
if (
|
|
858
|
-
nodeType !== Node.ELEMENT_NODE &&
|
|
859
|
-
nodeType !== Node.DOCUMENT_FRAGMENT_NODE
|
|
860
|
-
)
|
|
861
|
-
return;
|
|
827
|
+
let fragment = document.createDocumentFragment();
|
|
828
|
+
fragment.append(...nodes);
|
|
829
|
+
return fragment;
|
|
830
|
+
}
|
|
862
831
|
|
|
863
|
-
|
|
832
|
+
/**
|
|
833
|
+
* @param {string} html
|
|
834
|
+
* @returns {NodeListOf<ChildNode> | HTMLElement[]}
|
|
835
|
+
*/
|
|
836
|
+
function parseHtml(html) {
|
|
837
|
+
let regEx = SINGLE_TAG_REGEXP.exec(html);
|
|
838
|
+
if (regEx) {
|
|
839
|
+
return [document.createElement(regEx[1])];
|
|
840
|
+
}
|
|
841
|
+
let fragment = buildFragment(html);
|
|
842
|
+
if (fragment) {
|
|
843
|
+
return fragment.childNodes;
|
|
844
|
+
}
|
|
864
845
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
element.appendChild(child);
|
|
868
|
-
}
|
|
869
|
-
},
|
|
846
|
+
return [];
|
|
847
|
+
}
|
|
870
848
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
849
|
+
/**
|
|
850
|
+
* @param {Element} element
|
|
851
|
+
* @param {boolean} [onlyDescendants]
|
|
852
|
+
* @returns {void}
|
|
853
|
+
*/
|
|
854
|
+
export function dealoc(element, onlyDescendants) {
|
|
855
|
+
if (!element) return;
|
|
856
|
+
if (!onlyDescendants && elementAcceptsData(element))
|
|
857
|
+
cleanElementData([element]);
|
|
879
858
|
|
|
880
|
-
|
|
859
|
+
if (element.querySelectorAll) {
|
|
860
|
+
cleanElementData(element.querySelectorAll("*"));
|
|
861
|
+
}
|
|
862
|
+
}
|
|
881
863
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
864
|
+
/**
|
|
865
|
+
* If `ExpandoStore.data` and `ExpandoStore.events` are empty,
|
|
866
|
+
* then delete element's `ExpandoStore` and set its `ExpandoId`
|
|
867
|
+
* to undefined.
|
|
868
|
+
* @param {Element} element
|
|
869
|
+
*/
|
|
870
|
+
function removeIfEmptyData(element) {
|
|
871
|
+
const expandoId = element[EXPANDO];
|
|
872
|
+
const { events, data } = CACHE.get(expandoId);
|
|
885
873
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
874
|
+
if (
|
|
875
|
+
(!data || !Object.keys(data).length) &&
|
|
876
|
+
(!events || !Object.keys(events).length)
|
|
877
|
+
) {
|
|
878
|
+
CACHE.delete(expandoId);
|
|
879
|
+
element[EXPANDO] = undefined; // don't delete DOM expandos. Chrome don't like it
|
|
880
|
+
}
|
|
881
|
+
}
|
|
889
882
|
|
|
890
|
-
|
|
891
|
-
|
|
883
|
+
/**
|
|
884
|
+
* Gets or sets cache data for a given element.
|
|
885
|
+
*
|
|
886
|
+
* @param {Element} element - The DOM element to get or set data on.
|
|
887
|
+
* @param {string|Object} key - The key (as a string) to get/set or an object for mass-setting.
|
|
888
|
+
* @param {*} [value] - The value to set. If not provided, the function acts as a getter.
|
|
889
|
+
* @returns {*} - The retrieved data if acting as a getter. Otherwise, returns undefined.
|
|
890
|
+
*/
|
|
891
|
+
export function getOrSetCacheData(element, key, value) {
|
|
892
|
+
if (elementAcceptsData(element)) {
|
|
893
|
+
let prop;
|
|
892
894
|
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
895
|
+
const isSimpleSetter = isDefined(value);
|
|
896
|
+
const isSimpleGetter = !isSimpleSetter && key && !isObject(key);
|
|
897
|
+
const massGetter = !key;
|
|
898
|
+
const expandoStore = getExpando(element, !isSimpleGetter);
|
|
899
|
+
const data = expandoStore && expandoStore.data;
|
|
900
|
+
|
|
901
|
+
if (isSimpleSetter) {
|
|
902
|
+
data[kebabToCamel(key)] = value;
|
|
903
|
+
} else {
|
|
904
|
+
if (massGetter) {
|
|
905
|
+
return data;
|
|
898
906
|
}
|
|
899
|
-
|
|
907
|
+
if (isSimpleGetter) {
|
|
908
|
+
// don't force creation of expandoStore if it doesn't exist yet
|
|
909
|
+
return data && data[kebabToCamel(key)];
|
|
910
|
+
}
|
|
911
|
+
// mass-setter: data({key1: val1, key2: val2})
|
|
912
|
+
for (prop in key) {
|
|
913
|
+
data[kebabToCamel(prop)] = key[prop];
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
} else {
|
|
917
|
+
// TODO: check should occur perhaps prior at compilation level that this is a valid element
|
|
918
|
+
}
|
|
919
|
+
}
|
|
900
920
|
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
921
|
+
/**
|
|
922
|
+
* Adds nodes or elements to the root array-like object.
|
|
923
|
+
*
|
|
924
|
+
* @param {Array} root - The array-like object to which elements will be added.
|
|
925
|
+
* @param {(Node|Array|NodeList|Object)} elements - The elements to add to the root. This can be a single DOM node, an array-like object (such as an Array or NodeList), or any other object.
|
|
926
|
+
*/
|
|
927
|
+
function addNodes(root, elements) {
|
|
928
|
+
// THIS CODE IS VERY HOT. Don't make changes without benchmarking.
|
|
907
929
|
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
930
|
+
if (elements) {
|
|
931
|
+
// if a Node (the most common case)
|
|
932
|
+
if (elements.nodeType) {
|
|
933
|
+
root[root.length++] = elements;
|
|
934
|
+
} else {
|
|
935
|
+
const { length } = elements;
|
|
936
|
+
|
|
937
|
+
// if an Array or NodeList and not a Window
|
|
938
|
+
if (typeof length === "number" && elements.window !== elements) {
|
|
939
|
+
if (length) {
|
|
940
|
+
for (let i = 0; i < length; i++) {
|
|
941
|
+
root[root.length++] = elements[i];
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
} else {
|
|
945
|
+
root[root.length++] = elements;
|
|
912
946
|
}
|
|
913
|
-
|
|
914
|
-
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
915
950
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
let handlerArgs;
|
|
920
|
-
const eventName = event.type || event;
|
|
921
|
-
const expandoStore = getExpando(element);
|
|
922
|
-
const events = expandoStore && expandoStore.events;
|
|
923
|
-
const eventFns = events && events[eventName];
|
|
951
|
+
function getController(element, name) {
|
|
952
|
+
return getInheritedData(element, `$${name || "ngController"}Controller`);
|
|
953
|
+
}
|
|
924
954
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
stopPropagation: () => {},
|
|
941
|
-
type: eventName,
|
|
942
|
-
target: element,
|
|
943
|
-
};
|
|
955
|
+
/**
|
|
956
|
+
*
|
|
957
|
+
* @param {Element} element
|
|
958
|
+
* @param {string} name
|
|
959
|
+
* @param {any} [value]
|
|
960
|
+
* @returns
|
|
961
|
+
*/
|
|
962
|
+
function getInheritedData(element, name, value) {
|
|
963
|
+
// if element is the document object work with the html element instead
|
|
964
|
+
// this makes $(document).scope() possible
|
|
965
|
+
if (element.nodeType === Node.DOCUMENT_NODE) {
|
|
966
|
+
// TODO Fix types
|
|
967
|
+
element = element.documentElement;
|
|
968
|
+
}
|
|
969
|
+
const names = Array.isArray(name) ? name : [name];
|
|
944
970
|
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
971
|
+
while (element) {
|
|
972
|
+
for (let i = 0, ii = names.length; i < ii; i++) {
|
|
973
|
+
if (isDefined((value = getOrSetCacheData(element, names[i]))))
|
|
974
|
+
return value;
|
|
975
|
+
}
|
|
949
976
|
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
977
|
+
// If dealing with a document fragment node with a host element, and no parent, use the host
|
|
978
|
+
// element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
|
|
979
|
+
// to lookup parent controllers.
|
|
980
|
+
element =
|
|
981
|
+
element.parentNode ||
|
|
982
|
+
(element.nodeType === Node.DOCUMENT_FRAGMENT_NODE && element.host);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
955
985
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
(
|
|
965
|
-
|
|
966
|
-
* chaining functions
|
|
967
|
-
*/
|
|
968
|
-
JQLite.prototype[name] = function (arg1, arg2, arg3) {
|
|
969
|
-
let value;
|
|
986
|
+
/**
|
|
987
|
+
*
|
|
988
|
+
* @param {Element} element
|
|
989
|
+
* @param {boolean} keepData
|
|
990
|
+
*/
|
|
991
|
+
export function removeElement(element, keepData = false) {
|
|
992
|
+
if (!keepData) dealoc(element);
|
|
993
|
+
const parent = element.parentNode;
|
|
994
|
+
if (parent) parent.removeChild(element);
|
|
995
|
+
}
|
|
970
996
|
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
);
|
|
997
|
+
/**
|
|
998
|
+
* Executea a function on `DOMContentLoaded`
|
|
999
|
+
* @param {Function} fn
|
|
1000
|
+
*/
|
|
1001
|
+
function onReady(fn) {
|
|
1002
|
+
function trigger() {
|
|
1003
|
+
window.document.removeEventListener("DOMContentLoaded", trigger);
|
|
1004
|
+
fn();
|
|
1005
|
+
}
|
|
1006
|
+
// check if document is already loaded
|
|
1007
|
+
if (window.document.readyState === "complete") {
|
|
1008
|
+
window.setTimeout(fn);
|
|
1009
|
+
} else {
|
|
1010
|
+
// We can not use JQLite since we are not done loading.
|
|
1011
|
+
window.document.addEventListener("DOMContentLoaded", trigger);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
986
1014
|
|
|
987
1015
|
function createEventHandler(element, events) {
|
|
988
1016
|
const eventHandler = function (event, type) {
|
|
@@ -1102,3 +1130,27 @@ export function getBlockNodes(nodes) {
|
|
|
1102
1130
|
|
|
1103
1131
|
return JQLite(blockNodes || nodes);
|
|
1104
1132
|
}
|
|
1133
|
+
|
|
1134
|
+
export function getBooleanAttrName(element, name) {
|
|
1135
|
+
// check dom last since we will most likely fail on name
|
|
1136
|
+
const booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
|
|
1137
|
+
|
|
1138
|
+
// booleanAttr is here twice to minimize DOM access
|
|
1139
|
+
return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* Takes an array of elements, calls any `$destroy` event handlers, removes any data in cache, and finally removes any
|
|
1144
|
+
* listeners.
|
|
1145
|
+
* @param {NodeListOf<Element>} nodes
|
|
1146
|
+
*/
|
|
1147
|
+
export function cleanElementData(nodes) {
|
|
1148
|
+
for (let i = 0, ii = nodes.length; i < ii; i++) {
|
|
1149
|
+
var events = (CACHE.get(nodes[i][EXPANDO]) || {}).events;
|
|
1150
|
+
if (events && events.$destroy) {
|
|
1151
|
+
JQLite(nodes[i]).triggerHandler("$destroy");
|
|
1152
|
+
}
|
|
1153
|
+
removeElementData(nodes[i]);
|
|
1154
|
+
JQLite.prototype.off.call(JQLite(nodes[i]));
|
|
1155
|
+
}
|
|
1156
|
+
}
|