UNPKG

66.6 kBJavaScriptView Raw
1import { Container, inject, Optional } from 'aurelia-dependency-injection';
2import { DOM, FEATURE } from 'aurelia-pal';
3import { TaskQueue } from 'aurelia-task-queue';
4import { bindable, noView, customElement, CompositionEngine, ViewSlot, ViewResources, customAttribute, templateController, BoundViewFactory, TargetInstruction, Animator, resource, useView, useShadowDOM, ViewEngine } from 'aurelia-templating';
5import { createOverrideContext, bindingMode, BindingBehavior, sourceContext, ValueConverter, mergeSplice, ObserverLocator, valueConverter, bindingBehavior, DataAttributeObserver, targetContext, EventSubscriber } from 'aurelia-binding';
6import { Loader } from 'aurelia-loader';
7import { relativeToFile } from 'aurelia-path';
8import { mixin } from 'aurelia-metadata';
9import { getLogger } from 'aurelia-logging';
10
11/*! *****************************************************************************
12Copyright (c) Microsoft Corporation.
13
14Permission to use, copy, modify, and/or distribute this software for any
15purpose with or without fee is hereby granted.
16
17THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
18REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23PERFORMANCE OF THIS SOFTWARE.
24***************************************************************************** */
25
26function __decorate(decorators, target, key, desc) {
27 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
28 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
29 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
30 return c > 3 && r && Object.defineProperty(target, key, r), r;
31}
32
33var ActivationStrategy;
34(function (ActivationStrategy) {
35 ActivationStrategy["InvokeLifecycle"] = "invoke-lifecycle";
36 ActivationStrategy["Replace"] = "replace";
37})(ActivationStrategy || (ActivationStrategy = {}));
38let Compose = class Compose {
39 constructor(element, container, compositionEngine, viewSlot, viewResources, taskQueue) {
40 this.activationStrategy = ActivationStrategy.InvokeLifecycle;
41 this.element = element;
42 this.container = container;
43 this.compositionEngine = compositionEngine;
44 this.viewSlot = viewSlot;
45 this.viewResources = viewResources;
46 this.taskQueue = taskQueue;
47 this.currentController = null;
48 this.currentViewModel = null;
49 this.changes = Object.create(null);
50 }
51 static inject() {
52 return [DOM.Element, Container, CompositionEngine, ViewSlot, ViewResources, TaskQueue];
53 }
54 created(owningView) {
55 this.owningView = owningView;
56 }
57 bind(bindingContext, overrideContext) {
58 this.bindingContext = bindingContext;
59 this.overrideContext = overrideContext;
60 let changes = this.changes;
61 changes.view = this.view;
62 changes.viewModel = this.viewModel;
63 changes.model = this.model;
64 if (!this.pendingTask) {
65 processChanges(this);
66 }
67 }
68 unbind() {
69 this.changes = Object.create(null);
70 this.bindingContext = null;
71 this.overrideContext = null;
72 let returnToCache = true;
73 let skipAnimation = true;
74 this.viewSlot.removeAll(returnToCache, skipAnimation);
75 }
76 modelChanged(newValue, oldValue) {
77 this.changes.model = newValue;
78 requestUpdate(this);
79 }
80 viewChanged(newValue, oldValue) {
81 this.changes.view = newValue;
82 requestUpdate(this);
83 }
84 viewModelChanged(newValue, oldValue) {
85 this.changes.viewModel = newValue;
86 requestUpdate(this);
87 }
88};
89__decorate([
90 bindable
91], Compose.prototype, "model", void 0);
92__decorate([
93 bindable
94], Compose.prototype, "view", void 0);
95__decorate([
96 bindable
97], Compose.prototype, "viewModel", void 0);
98__decorate([
99 bindable
100], Compose.prototype, "activationStrategy", void 0);
101__decorate([
102 bindable
103], Compose.prototype, "swapOrder", void 0);
104Compose = __decorate([
105 noView,
106 customElement('compose')
107], Compose);
108function isEmpty(obj) {
109 for (const _ in obj) {
110 return false;
111 }
112 return true;
113}
114function tryActivateViewModel(vm, model) {
115 if (vm && typeof vm.activate === 'function') {
116 return Promise.resolve(vm.activate(model));
117 }
118}
119function createInstruction(composer, instruction) {
120 return Object.assign(instruction, {
121 bindingContext: composer.bindingContext,
122 overrideContext: composer.overrideContext,
123 owningView: composer.owningView,
124 container: composer.container,
125 viewSlot: composer.viewSlot,
126 viewResources: composer.viewResources,
127 currentController: composer.currentController,
128 host: composer.element,
129 swapOrder: composer.swapOrder
130 });
131}
132function processChanges(composer) {
133 const changes = composer.changes;
134 composer.changes = Object.create(null);
135 if (needsReInitialization(composer, changes)) {
136 let instruction = {
137 view: composer.view,
138 viewModel: composer.currentViewModel || composer.viewModel,
139 model: composer.model
140 };
141 instruction = Object.assign(instruction, changes);
142 instruction = createInstruction(composer, instruction);
143 composer.pendingTask = composer.compositionEngine.compose(instruction).then(controller => {
144 composer.currentController = controller;
145 composer.currentViewModel = controller ? controller.viewModel : null;
146 });
147 }
148 else {
149 composer.pendingTask = tryActivateViewModel(composer.currentViewModel, changes.model);
150 if (!composer.pendingTask) {
151 return;
152 }
153 }
154 composer.pendingTask = composer.pendingTask
155 .then(() => {
156 completeCompositionTask(composer);
157 }, reason => {
158 completeCompositionTask(composer);
159 throw reason;
160 });
161}
162function completeCompositionTask(composer) {
163 composer.pendingTask = null;
164 if (!isEmpty(composer.changes)) {
165 processChanges(composer);
166 }
167}
168function requestUpdate(composer) {
169 if (composer.pendingTask || composer.updateRequested) {
170 return;
171 }
172 composer.updateRequested = true;
173 composer.taskQueue.queueMicroTask(() => {
174 composer.updateRequested = false;
175 processChanges(composer);
176 });
177}
178function needsReInitialization(composer, changes) {
179 let activationStrategy = composer.activationStrategy;
180 const vm = composer.currentViewModel;
181 if (vm && typeof vm.determineActivationStrategy === 'function') {
182 activationStrategy = vm.determineActivationStrategy();
183 }
184 return 'view' in changes
185 || 'viewModel' in changes
186 || activationStrategy === ActivationStrategy.Replace;
187}
188
189class IfCore {
190 constructor(viewFactory, viewSlot) {
191 this.viewFactory = viewFactory;
192 this.viewSlot = viewSlot;
193 this.view = null;
194 this.bindingContext = null;
195 this.overrideContext = null;
196 this.showing = false;
197 this.cache = true;
198 }
199 bind(bindingContext, overrideContext) {
200 this.bindingContext = bindingContext;
201 this.overrideContext = overrideContext;
202 }
203 unbind() {
204 if (this.view === null) {
205 return;
206 }
207 this.view.unbind();
208 if (!this.viewFactory.isCaching) {
209 return;
210 }
211 if (this.showing) {
212 this.showing = false;
213 this.viewSlot.remove(this.view, true, true);
214 }
215 else {
216 this.view.returnToCache();
217 }
218 this.view = null;
219 }
220 _show() {
221 if (this.showing) {
222 if (!this.view.isBound) {
223 this.view.bind(this.bindingContext, this.overrideContext);
224 }
225 return;
226 }
227 if (this.view === null) {
228 this.view = this.viewFactory.create();
229 }
230 if (!this.view.isBound) {
231 this.view.bind(this.bindingContext, this.overrideContext);
232 }
233 this.showing = true;
234 return this.viewSlot.add(this.view);
235 }
236 _hide() {
237 if (!this.showing) {
238 return;
239 }
240 this.showing = false;
241 let removed = this.viewSlot.remove(this.view);
242 if (removed instanceof Promise) {
243 return removed.then(() => {
244 this._unbindView();
245 });
246 }
247 this._unbindView();
248 }
249 _unbindView() {
250 const cache = this.cache === 'false' ? false : !!this.cache;
251 this.view.unbind();
252 if (!cache) {
253 this.view = null;
254 }
255 }
256}
257
258let If = class If extends IfCore {
259 constructor() {
260 super(...arguments);
261 this.cache = true;
262 }
263 bind(bindingContext, overrideContext) {
264 super.bind(bindingContext, overrideContext);
265 if (this.condition) {
266 this._show();
267 }
268 else {
269 this._hide();
270 }
271 }
272 conditionChanged(newValue) {
273 this._update(newValue);
274 }
275 _update(show) {
276 if (this.animating) {
277 return;
278 }
279 let promise;
280 if (this.elseVm) {
281 promise = show ? this._swap(this.elseVm, this) : this._swap(this, this.elseVm);
282 }
283 else {
284 promise = show ? this._show() : this._hide();
285 }
286 if (promise) {
287 this.animating = true;
288 promise.then(() => {
289 this.animating = false;
290 if (this.condition !== this.showing) {
291 this._update(this.condition);
292 }
293 });
294 }
295 }
296 _swap(remove, add) {
297 switch (this.swapOrder) {
298 case 'before':
299 return Promise.resolve(add._show()).then(() => remove._hide());
300 case 'with':
301 return Promise.all([remove._hide(), add._show()]);
302 default:
303 let promise = remove._hide();
304 return promise ? promise.then(() => add._show()) : add._show();
305 }
306 }
307};
308__decorate([
309 bindable({ primaryProperty: true })
310], If.prototype, "condition", void 0);
311__decorate([
312 bindable
313], If.prototype, "swapOrder", void 0);
314__decorate([
315 bindable
316], If.prototype, "cache", void 0);
317If = __decorate([
318 customAttribute('if'),
319 templateController,
320 inject(BoundViewFactory, ViewSlot)
321], If);
322
323let Else = class Else extends IfCore {
324 constructor(viewFactory, viewSlot) {
325 super(viewFactory, viewSlot);
326 this._registerInIf();
327 }
328 bind(bindingContext, overrideContext) {
329 super.bind(bindingContext, overrideContext);
330 if (this.ifVm.condition) {
331 this._hide();
332 }
333 else {
334 this._show();
335 }
336 }
337 _registerInIf() {
338 let previous = this.viewSlot.anchor.previousSibling;
339 while (previous && !previous.au) {
340 previous = previous.previousSibling;
341 }
342 if (!previous || !previous.au.if) {
343 throw new Error("Can't find matching If for Else custom attribute.");
344 }
345 this.ifVm = previous.au.if.viewModel;
346 this.ifVm.elseVm = this;
347 }
348};
349Else = __decorate([
350 customAttribute('else'),
351 templateController,
352 inject(BoundViewFactory, ViewSlot)
353], Else);
354
355let With = class With {
356 constructor(viewFactory, viewSlot) {
357 this.viewFactory = viewFactory;
358 this.viewSlot = viewSlot;
359 this.parentOverrideContext = null;
360 this.view = null;
361 }
362 bind(bindingContext, overrideContext) {
363 this.parentOverrideContext = overrideContext;
364 this.valueChanged(this.value);
365 }
366 valueChanged(newValue) {
367 let overrideContext = createOverrideContext(newValue, this.parentOverrideContext);
368 let view = this.view;
369 if (!view) {
370 view = this.view = this.viewFactory.create();
371 view.bind(newValue, overrideContext);
372 this.viewSlot.add(view);
373 }
374 else {
375 view.bind(newValue, overrideContext);
376 }
377 }
378 unbind() {
379 let view = this.view;
380 this.parentOverrideContext = null;
381 if (view) {
382 view.unbind();
383 }
384 }
385};
386With = __decorate([
387 customAttribute('with'),
388 templateController,
389 inject(BoundViewFactory, ViewSlot)
390], With);
391
392const oneTime = bindingMode.oneTime;
393function updateOverrideContexts(views, startIndex) {
394 let length = views.length;
395 if (startIndex > 0) {
396 startIndex = startIndex - 1;
397 }
398 for (; startIndex < length; ++startIndex) {
399 updateOverrideContext(views[startIndex].overrideContext, startIndex, length);
400 }
401}
402function createFullOverrideContext(repeat, data, index, length, key) {
403 let bindingContext = {};
404 let overrideContext = createOverrideContext(bindingContext, repeat.scope.overrideContext);
405 if (typeof key !== 'undefined') {
406 bindingContext[repeat.key] = key;
407 bindingContext[repeat.value] = data;
408 }
409 else {
410 bindingContext[repeat.local] = data;
411 }
412 updateOverrideContext(overrideContext, index, length);
413 return overrideContext;
414}
415function updateOverrideContext(overrideContext, index, length) {
416 let first = (index === 0);
417 let last = (index === length - 1);
418 let even = index % 2 === 0;
419 overrideContext.$index = index;
420 overrideContext.$first = first;
421 overrideContext.$last = last;
422 overrideContext.$middle = !(first || last);
423 overrideContext.$odd = !even;
424 overrideContext.$even = even;
425}
426function getItemsSourceExpression(instruction, attrName) {
427 return instruction.behaviorInstructions
428 .filter(bi => bi.originalAttrName === attrName)[0]
429 .attributes
430 .items
431 .sourceExpression;
432}
433function unwrapExpression(expression) {
434 let unwrapped = false;
435 while (expression instanceof BindingBehavior) {
436 expression = expression.expression;
437 }
438 while (expression instanceof ValueConverter) {
439 expression = expression.expression;
440 unwrapped = true;
441 }
442 return unwrapped ? expression : null;
443}
444function isOneTime(expression) {
445 while (expression instanceof BindingBehavior) {
446 if (expression.name === 'oneTime') {
447 return true;
448 }
449 expression = expression.expression;
450 }
451 return false;
452}
453function updateOneTimeBinding(binding) {
454 if (binding.call && binding.mode === oneTime) {
455 binding.call(sourceContext);
456 }
457 else if (binding.updateOneTimeBindings) {
458 binding.updateOneTimeBindings();
459 }
460}
461function indexOf(array, item, matcher, startIndex) {
462 if (!matcher) {
463 return array.indexOf(item);
464 }
465 const length = array.length;
466 for (let index = startIndex || 0; index < length; index++) {
467 if (matcher(array[index], item)) {
468 return index;
469 }
470 }
471 return -1;
472}
473
474class ArrayRepeatStrategy {
475 getCollectionObserver(observerLocator, items) {
476 return observerLocator.getArrayObserver(items);
477 }
478 instanceChanged(repeat, items) {
479 const $repeat = repeat;
480 const itemsLength = items.length;
481 if (!items || itemsLength === 0) {
482 $repeat.removeAllViews(true, !$repeat.viewsRequireLifecycle);
483 return;
484 }
485 const children = $repeat.views();
486 const viewsLength = children.length;
487 if (viewsLength === 0) {
488 this._standardProcessInstanceChanged($repeat, items);
489 return;
490 }
491 if ($repeat.viewsRequireLifecycle) {
492 const childrenSnapshot = children.slice(0);
493 const itemNameInBindingContext = $repeat.local;
494 const matcher = $repeat.matcher();
495 let itemsPreviouslyInViews = [];
496 const viewsToRemove = [];
497 for (let index = 0; index < viewsLength; index++) {
498 const view = childrenSnapshot[index];
499 const oldItem = view.bindingContext[itemNameInBindingContext];
500 if (indexOf(items, oldItem, matcher) === -1) {
501 viewsToRemove.push(view);
502 }
503 else {
504 itemsPreviouslyInViews.push(oldItem);
505 }
506 }
507 let updateViews;
508 let removePromise;
509 if (itemsPreviouslyInViews.length > 0) {
510 removePromise = $repeat.removeViews(viewsToRemove, true, !$repeat.viewsRequireLifecycle);
511 updateViews = () => {
512 for (let index = 0; index < itemsLength; index++) {
513 const item = items[index];
514 const indexOfView = indexOf(itemsPreviouslyInViews, item, matcher, index);
515 let view;
516 if (indexOfView === -1) {
517 const overrideContext = createFullOverrideContext($repeat, items[index], index, itemsLength);
518 $repeat.insertView(index, overrideContext.bindingContext, overrideContext);
519 itemsPreviouslyInViews.splice(index, 0, undefined);
520 }
521 else if (indexOfView === index) {
522 view = children[indexOfView];
523 itemsPreviouslyInViews[indexOfView] = undefined;
524 }
525 else {
526 view = children[indexOfView];
527 $repeat.moveView(indexOfView, index);
528 itemsPreviouslyInViews.splice(indexOfView, 1);
529 itemsPreviouslyInViews.splice(index, 0, undefined);
530 }
531 if (view) {
532 updateOverrideContext(view.overrideContext, index, itemsLength);
533 }
534 }
535 this._inPlaceProcessItems($repeat, items);
536 };
537 }
538 else {
539 removePromise = $repeat.removeAllViews(true, !$repeat.viewsRequireLifecycle);
540 updateViews = () => this._standardProcessInstanceChanged($repeat, items);
541 }
542 if (removePromise instanceof Promise) {
543 removePromise.then(updateViews);
544 }
545 else {
546 updateViews();
547 }
548 }
549 else {
550 this._inPlaceProcessItems($repeat, items);
551 }
552 }
553 _standardProcessInstanceChanged(repeat, items) {
554 for (let i = 0, ii = items.length; i < ii; i++) {
555 let overrideContext = createFullOverrideContext(repeat, items[i], i, ii);
556 repeat.addView(overrideContext.bindingContext, overrideContext);
557 }
558 }
559 _inPlaceProcessItems(repeat, items) {
560 let itemsLength = items.length;
561 let viewsLength = repeat.viewCount();
562 while (viewsLength > itemsLength) {
563 viewsLength--;
564 repeat.removeView(viewsLength, true, !repeat.viewsRequireLifecycle);
565 }
566 let local = repeat.local;
567 for (let i = 0; i < viewsLength; i++) {
568 let view = repeat.view(i);
569 let last = i === itemsLength - 1;
570 let middle = i !== 0 && !last;
571 let bindingContext = view.bindingContext;
572 let overrideContext = view.overrideContext;
573 if (bindingContext[local] === items[i]
574 && overrideContext.$middle === middle
575 && overrideContext.$last === last) {
576 continue;
577 }
578 bindingContext[local] = items[i];
579 overrideContext.$middle = middle;
580 overrideContext.$last = last;
581 repeat.updateBindings(view);
582 }
583 for (let i = viewsLength; i < itemsLength; i++) {
584 let overrideContext = createFullOverrideContext(repeat, items[i], i, itemsLength);
585 repeat.addView(overrideContext.bindingContext, overrideContext);
586 }
587 }
588 instanceMutated(repeat, array, splices) {
589 if (repeat.__queuedSplices) {
590 for (let i = 0, ii = splices.length; i < ii; ++i) {
591 let { index, removed, addedCount } = splices[i];
592 mergeSplice(repeat.__queuedSplices, index, removed, addedCount);
593 }
594 repeat.__array = array.slice(0);
595 return;
596 }
597 let maybePromise = this._runSplices(repeat, array.slice(0), splices);
598 if (maybePromise instanceof Promise) {
599 let queuedSplices = repeat.__queuedSplices = [];
600 let runQueuedSplices = () => {
601 if (!queuedSplices.length) {
602 repeat.__queuedSplices = undefined;
603 repeat.__array = undefined;
604 return;
605 }
606 let nextPromise = this._runSplices(repeat, repeat.__array, queuedSplices) || Promise.resolve();
607 queuedSplices = repeat.__queuedSplices = [];
608 nextPromise.then(runQueuedSplices);
609 };
610 maybePromise.then(runQueuedSplices);
611 }
612 }
613 _runSplices(repeat, array, splices) {
614 let removeDelta = 0;
615 let rmPromises = [];
616 for (let i = 0, ii = splices.length; i < ii; ++i) {
617 let splice = splices[i];
618 let removed = splice.removed;
619 for (let j = 0, jj = removed.length; j < jj; ++j) {
620 let viewOrPromise = repeat.removeView(splice.index + removeDelta + rmPromises.length, true);
621 if (viewOrPromise instanceof Promise) {
622 rmPromises.push(viewOrPromise);
623 }
624 }
625 removeDelta -= splice.addedCount;
626 }
627 if (rmPromises.length > 0) {
628 return Promise.all(rmPromises).then(() => {
629 let spliceIndexLow = this._handleAddedSplices(repeat, array, splices);
630 updateOverrideContexts(repeat.views(), spliceIndexLow);
631 });
632 }
633 let spliceIndexLow = this._handleAddedSplices(repeat, array, splices);
634 updateOverrideContexts(repeat.views(), spliceIndexLow);
635 return undefined;
636 }
637 _handleAddedSplices(repeat, array, splices) {
638 let spliceIndex;
639 let spliceIndexLow;
640 let arrayLength = array.length;
641 for (let i = 0, ii = splices.length; i < ii; ++i) {
642 let splice = splices[i];
643 let addIndex = spliceIndex = splice.index;
644 let end = splice.index + splice.addedCount;
645 if (typeof spliceIndexLow === 'undefined' || spliceIndexLow === null || spliceIndexLow > splice.index) {
646 spliceIndexLow = spliceIndex;
647 }
648 for (; addIndex < end; ++addIndex) {
649 let overrideContext = createFullOverrideContext(repeat, array[addIndex], addIndex, arrayLength);
650 repeat.insertView(addIndex, overrideContext.bindingContext, overrideContext);
651 }
652 }
653 return spliceIndexLow;
654 }
655}
656
657class MapRepeatStrategy {
658 getCollectionObserver(observerLocator, items) {
659 return observerLocator.getMapObserver(items);
660 }
661 instanceChanged(repeat, items) {
662 let removePromise = repeat.removeAllViews(true, !repeat.viewsRequireLifecycle);
663 if (removePromise instanceof Promise) {
664 removePromise.then(() => this._standardProcessItems(repeat, items));
665 return;
666 }
667 this._standardProcessItems(repeat, items);
668 }
669 _standardProcessItems(repeat, items) {
670 let index = 0;
671 let overrideContext;
672 items.forEach((value, key) => {
673 overrideContext = createFullOverrideContext(repeat, value, index, items.size, key);
674 repeat.addView(overrideContext.bindingContext, overrideContext);
675 ++index;
676 });
677 }
678 instanceMutated(repeat, map, records) {
679 let key;
680 let i;
681 let ii;
682 let overrideContext;
683 let removeIndex;
684 let addIndex;
685 let record;
686 let rmPromises = [];
687 let viewOrPromise;
688 for (i = 0, ii = records.length; i < ii; ++i) {
689 record = records[i];
690 key = record.key;
691 switch (record.type) {
692 case 'update':
693 removeIndex = this._getViewIndexByKey(repeat, key);
694 viewOrPromise = repeat.removeView(removeIndex, true, !repeat.viewsRequireLifecycle);
695 if (viewOrPromise instanceof Promise) {
696 rmPromises.push(viewOrPromise);
697 }
698 overrideContext = createFullOverrideContext(repeat, map.get(key), removeIndex, map.size, key);
699 repeat.insertView(removeIndex, overrideContext.bindingContext, overrideContext);
700 break;
701 case 'add':
702 addIndex = repeat.viewCount() <= map.size - 1 ? repeat.viewCount() : map.size - 1;
703 overrideContext = createFullOverrideContext(repeat, map.get(key), addIndex, map.size, key);
704 repeat.insertView(map.size - 1, overrideContext.bindingContext, overrideContext);
705 break;
706 case 'delete':
707 if (record.oldValue === undefined) {
708 return;
709 }
710 removeIndex = this._getViewIndexByKey(repeat, key);
711 viewOrPromise = repeat.removeView(removeIndex, true, !repeat.viewsRequireLifecycle);
712 if (viewOrPromise instanceof Promise) {
713 rmPromises.push(viewOrPromise);
714 }
715 break;
716 case 'clear':
717 repeat.removeAllViews(true, !repeat.viewsRequireLifecycle);
718 break;
719 default:
720 continue;
721 }
722 }
723 if (rmPromises.length > 0) {
724 Promise.all(rmPromises).then(() => {
725 updateOverrideContexts(repeat.views(), 0);
726 });
727 }
728 else {
729 updateOverrideContexts(repeat.views(), 0);
730 }
731 }
732 _getViewIndexByKey(repeat, key) {
733 let i;
734 let ii;
735 let child;
736 for (i = 0, ii = repeat.viewCount(); i < ii; ++i) {
737 child = repeat.view(i);
738 if (child.bindingContext[repeat.key] === key) {
739 return i;
740 }
741 }
742 return undefined;
743 }
744}
745
746class NullRepeatStrategy {
747 instanceChanged(repeat, items) {
748 repeat.removeAllViews(true);
749 }
750 getCollectionObserver(observerLocator, items) {
751 }
752}
753
754class NumberRepeatStrategy {
755 getCollectionObserver() {
756 return null;
757 }
758 instanceChanged(repeat, value) {
759 let removePromise = repeat.removeAllViews(true, !repeat.viewsRequireLifecycle);
760 if (removePromise instanceof Promise) {
761 removePromise.then(() => this._standardProcessItems(repeat, value));
762 return;
763 }
764 this._standardProcessItems(repeat, value);
765 }
766 _standardProcessItems(repeat, value) {
767 let childrenLength = repeat.viewCount();
768 let i;
769 let ii;
770 let overrideContext;
771 let viewsToRemove;
772 value = Math.floor(value);
773 viewsToRemove = childrenLength - value;
774 if (viewsToRemove > 0) {
775 if (viewsToRemove > childrenLength) {
776 viewsToRemove = childrenLength;
777 }
778 for (i = 0, ii = viewsToRemove; i < ii; ++i) {
779 repeat.removeView(childrenLength - (i + 1), true, !repeat.viewsRequireLifecycle);
780 }
781 return;
782 }
783 for (i = childrenLength, ii = value; i < ii; ++i) {
784 overrideContext = createFullOverrideContext(repeat, i, i, ii);
785 repeat.addView(overrideContext.bindingContext, overrideContext);
786 }
787 updateOverrideContexts(repeat.views(), 0);
788 }
789}
790
791class SetRepeatStrategy {
792 getCollectionObserver(observerLocator, items) {
793 return observerLocator.getSetObserver(items);
794 }
795 instanceChanged(repeat, items) {
796 let removePromise = repeat.removeAllViews(true, !repeat.viewsRequireLifecycle);
797 if (removePromise instanceof Promise) {
798 removePromise.then(() => this._standardProcessItems(repeat, items));
799 return;
800 }
801 this._standardProcessItems(repeat, items);
802 }
803 _standardProcessItems(repeat, items) {
804 let index = 0;
805 let overrideContext;
806 items.forEach(value => {
807 overrideContext = createFullOverrideContext(repeat, value, index, items.size);
808 repeat.addView(overrideContext.bindingContext, overrideContext);
809 ++index;
810 });
811 }
812 instanceMutated(repeat, set, records) {
813 let value;
814 let i;
815 let ii;
816 let overrideContext;
817 let removeIndex;
818 let record;
819 let rmPromises = [];
820 let viewOrPromise;
821 for (i = 0, ii = records.length; i < ii; ++i) {
822 record = records[i];
823 value = record.value;
824 switch (record.type) {
825 case 'add':
826 let size = Math.max(set.size - 1, 0);
827 overrideContext = createFullOverrideContext(repeat, value, size, set.size);
828 repeat.insertView(size, overrideContext.bindingContext, overrideContext);
829 break;
830 case 'delete':
831 removeIndex = this._getViewIndexByValue(repeat, value);
832 viewOrPromise = repeat.removeView(removeIndex, true, !repeat.viewsRequireLifecycle);
833 if (viewOrPromise instanceof Promise) {
834 rmPromises.push(viewOrPromise);
835 }
836 break;
837 case 'clear':
838 repeat.removeAllViews(true, !repeat.viewsRequireLifecycle);
839 break;
840 default:
841 continue;
842 }
843 }
844 if (rmPromises.length > 0) {
845 Promise.all(rmPromises).then(() => {
846 updateOverrideContexts(repeat.views(), 0);
847 });
848 }
849 else {
850 updateOverrideContexts(repeat.views(), 0);
851 }
852 }
853 _getViewIndexByValue(repeat, value) {
854 let i;
855 let ii;
856 let child;
857 for (i = 0, ii = repeat.viewCount(); i < ii; ++i) {
858 child = repeat.view(i);
859 if (child.bindingContext[repeat.local] === value) {
860 return i;
861 }
862 }
863 return undefined;
864 }
865}
866
867class RepeatStrategyLocator {
868 constructor() {
869 this.matchers = [];
870 this.strategies = [];
871 this.addStrategy(items => items === null || items === undefined, new NullRepeatStrategy());
872 this.addStrategy(items => items instanceof Array, new ArrayRepeatStrategy());
873 this.addStrategy(items => items instanceof Map, new MapRepeatStrategy());
874 this.addStrategy(items => items instanceof Set, new SetRepeatStrategy());
875 this.addStrategy(items => typeof items === 'number', new NumberRepeatStrategy());
876 }
877 addStrategy(matcher, strategy) {
878 this.matchers.push(matcher);
879 this.strategies.push(strategy);
880 }
881 getStrategy(items) {
882 let matchers = this.matchers;
883 for (let i = 0, ii = matchers.length; i < ii; ++i) {
884 if (matchers[i](items)) {
885 return this.strategies[i];
886 }
887 }
888 return null;
889 }
890}
891
892const lifecycleOptionalBehaviors = ['focus', 'if', 'else', 'repeat', 'show', 'hide', 'with'];
893function behaviorRequiresLifecycle(instruction) {
894 let t = instruction.type;
895 let name = t.elementName !== null ? t.elementName : t.attributeName;
896 return lifecycleOptionalBehaviors.indexOf(name) === -1 && (t.handlesAttached || t.handlesBind || t.handlesCreated || t.handlesDetached || t.handlesUnbind)
897 || t.viewFactory && viewsRequireLifecycle(t.viewFactory)
898 || instruction.viewFactory && viewsRequireLifecycle(instruction.viewFactory);
899}
900function targetRequiresLifecycle(instruction) {
901 let behaviors = instruction.behaviorInstructions;
902 if (behaviors) {
903 let i = behaviors.length;
904 while (i--) {
905 if (behaviorRequiresLifecycle(behaviors[i])) {
906 return true;
907 }
908 }
909 }
910 return instruction.viewFactory && viewsRequireLifecycle(instruction.viewFactory);
911}
912function viewsRequireLifecycle(viewFactory) {
913 if ('_viewsRequireLifecycle' in viewFactory) {
914 return viewFactory._viewsRequireLifecycle;
915 }
916 viewFactory._viewsRequireLifecycle = false;
917 if (viewFactory.viewFactory) {
918 viewFactory._viewsRequireLifecycle = viewsRequireLifecycle(viewFactory.viewFactory);
919 return viewFactory._viewsRequireLifecycle;
920 }
921 if (viewFactory.template.querySelector('.au-animate')) {
922 viewFactory._viewsRequireLifecycle = true;
923 return true;
924 }
925 for (let id in viewFactory.instructions) {
926 if (targetRequiresLifecycle(viewFactory.instructions[id])) {
927 viewFactory._viewsRequireLifecycle = true;
928 return true;
929 }
930 }
931 viewFactory._viewsRequireLifecycle = false;
932 return false;
933}
934
935class AbstractRepeater {
936 constructor(options) {
937 Object.assign(this, {
938 local: 'items',
939 viewsRequireLifecycle: true
940 }, options);
941 }
942 viewCount() {
943 throw new Error('subclass must implement `viewCount`');
944 }
945 views() {
946 throw new Error('subclass must implement `views`');
947 }
948 view(index) {
949 throw new Error('subclass must implement `view`');
950 }
951 matcher() {
952 throw new Error('subclass must implement `matcher`');
953 }
954 addView(bindingContext, overrideContext) {
955 throw new Error('subclass must implement `addView`');
956 }
957 insertView(index, bindingContext, overrideContext) {
958 throw new Error('subclass must implement `insertView`');
959 }
960 moveView(sourceIndex, targetIndex) {
961 throw new Error('subclass must implement `moveView`');
962 }
963 removeAllViews(returnToCache, skipAnimation) {
964 throw new Error('subclass must implement `removeAllViews`');
965 }
966 removeViews(viewsToRemove, returnToCache, skipAnimation) {
967 throw new Error('subclass must implement `removeView`');
968 }
969 removeView(index, returnToCache, skipAnimation) {
970 throw new Error('subclass must implement `removeView`');
971 }
972 updateBindings(view) {
973 throw new Error('subclass must implement `updateBindings`');
974 }
975}
976
977var Repeat_1;
978const matcherExtractionMarker = '__marker_extracted__';
979let Repeat = Repeat_1 = class Repeat extends AbstractRepeater {
980 constructor(viewFactory, instruction, viewSlot, viewResources, observerLocator, strategyLocator) {
981 super({
982 local: 'item',
983 viewsRequireLifecycle: viewsRequireLifecycle(viewFactory)
984 });
985 this.viewFactory = viewFactory;
986 this.instruction = instruction;
987 this.viewSlot = viewSlot;
988 this.lookupFunctions = viewResources.lookupFunctions;
989 this.observerLocator = observerLocator;
990 this.key = 'key';
991 this.value = 'value';
992 this.strategyLocator = strategyLocator;
993 this.ignoreMutation = false;
994 this.sourceExpression = getItemsSourceExpression(this.instruction, 'repeat.for');
995 this.isOneTime = isOneTime(this.sourceExpression);
996 this.viewsRequireLifecycle = viewsRequireLifecycle(viewFactory);
997 }
998 call(context, changes) {
999 this[context](this.items, changes);
1000 }
1001 bind(bindingContext, overrideContext) {
1002 this.scope = { bindingContext, overrideContext };
1003 const instruction = this.instruction;
1004 if (!(matcherExtractionMarker in instruction)) {
1005 instruction[matcherExtractionMarker] = this._captureAndRemoveMatcherBinding();
1006 }
1007 this.matcherBinding = instruction[matcherExtractionMarker];
1008 this.itemsChanged();
1009 }
1010 unbind() {
1011 this.scope = null;
1012 this.items = null;
1013 this.matcherBinding = null;
1014 this.viewSlot.removeAll(true, true);
1015 this._unsubscribeCollection();
1016 }
1017 _unsubscribeCollection() {
1018 if (this.collectionObserver) {
1019 this.collectionObserver.unsubscribe(this.callContext, this);
1020 this.collectionObserver = null;
1021 this.callContext = null;
1022 }
1023 }
1024 itemsChanged() {
1025 this._unsubscribeCollection();
1026 if (!this.scope) {
1027 return;
1028 }
1029 let items = this.items;
1030 this.strategy = this.strategyLocator.getStrategy(items);
1031 if (!this.strategy) {
1032 throw new Error(`Value for '${this.sourceExpression}' is non-repeatable`);
1033 }
1034 if (!this.isOneTime && !this._observeInnerCollection()) {
1035 this._observeCollection();
1036 }
1037 this.ignoreMutation = true;
1038 this.strategy.instanceChanged(this, items);
1039 this.observerLocator.taskQueue.queueMicroTask(() => {
1040 this.ignoreMutation = false;
1041 });
1042 }
1043 _getInnerCollection() {
1044 let expression = unwrapExpression(this.sourceExpression);
1045 if (!expression) {
1046 return null;
1047 }
1048 return expression.evaluate(this.scope, null);
1049 }
1050 handleCollectionMutated(collection, changes) {
1051 if (!this.collectionObserver) {
1052 return;
1053 }
1054 if (this.ignoreMutation) {
1055 return;
1056 }
1057 this.strategy.instanceMutated(this, collection, changes);
1058 }
1059 handleInnerCollectionMutated(collection, changes) {
1060 if (!this.collectionObserver) {
1061 return;
1062 }
1063 if (this.ignoreMutation) {
1064 return;
1065 }
1066 this.ignoreMutation = true;
1067 let newItems = this.sourceExpression.evaluate(this.scope, this.lookupFunctions);
1068 this.observerLocator.taskQueue.queueMicroTask(() => this.ignoreMutation = false);
1069 if (newItems === this.items) {
1070 this.itemsChanged();
1071 }
1072 else {
1073 this.items = newItems;
1074 }
1075 }
1076 _observeInnerCollection() {
1077 let items = this._getInnerCollection();
1078 let strategy = this.strategyLocator.getStrategy(items);
1079 if (!strategy) {
1080 return false;
1081 }
1082 this.collectionObserver = strategy.getCollectionObserver(this.observerLocator, items);
1083 if (!this.collectionObserver) {
1084 return false;
1085 }
1086 this.callContext = 'handleInnerCollectionMutated';
1087 this.collectionObserver.subscribe(this.callContext, this);
1088 return true;
1089 }
1090 _observeCollection() {
1091 let items = this.items;
1092 this.collectionObserver = this.strategy.getCollectionObserver(this.observerLocator, items);
1093 if (this.collectionObserver) {
1094 this.callContext = 'handleCollectionMutated';
1095 this.collectionObserver.subscribe(this.callContext, this);
1096 }
1097 }
1098 _captureAndRemoveMatcherBinding() {
1099 const viewFactory = this.viewFactory.viewFactory;
1100 if (viewFactory) {
1101 const template = viewFactory.template;
1102 const instructions = viewFactory.instructions;
1103 if (Repeat_1.useInnerMatcher) {
1104 return extractMatcherBindingExpression(instructions);
1105 }
1106 if (getChildrenCount(template) > 1) {
1107 return undefined;
1108 }
1109 const repeatedElement = getFirstElementChild(template);
1110 if (!repeatedElement.hasAttribute('au-target-id')) {
1111 return undefined;
1112 }
1113 const repeatedElementTargetId = repeatedElement.getAttribute('au-target-id');
1114 return extractMatcherBindingExpression(instructions, repeatedElementTargetId);
1115 }
1116 return undefined;
1117 }
1118 viewCount() { return this.viewSlot.children.length; }
1119 views() { return this.viewSlot.children; }
1120 view(index) { return this.viewSlot.children[index]; }
1121 matcher() {
1122 const matcherBinding = this.matcherBinding;
1123 return matcherBinding
1124 ? matcherBinding.sourceExpression.evaluate(this.scope, matcherBinding.lookupFunctions)
1125 : null;
1126 }
1127 addView(bindingContext, overrideContext) {
1128 let view = this.viewFactory.create();
1129 view.bind(bindingContext, overrideContext);
1130 this.viewSlot.add(view);
1131 }
1132 insertView(index, bindingContext, overrideContext) {
1133 let view = this.viewFactory.create();
1134 view.bind(bindingContext, overrideContext);
1135 this.viewSlot.insert(index, view);
1136 }
1137 moveView(sourceIndex, targetIndex) {
1138 this.viewSlot.move(sourceIndex, targetIndex);
1139 }
1140 removeAllViews(returnToCache, skipAnimation) {
1141 return this.viewSlot.removeAll(returnToCache, skipAnimation);
1142 }
1143 removeViews(viewsToRemove, returnToCache, skipAnimation) {
1144 return this.viewSlot.removeMany(viewsToRemove, returnToCache, skipAnimation);
1145 }
1146 removeView(index, returnToCache, skipAnimation) {
1147 return this.viewSlot.removeAt(index, returnToCache, skipAnimation);
1148 }
1149 updateBindings(view) {
1150 const $view = view;
1151 let j = $view.bindings.length;
1152 while (j--) {
1153 updateOneTimeBinding($view.bindings[j]);
1154 }
1155 j = $view.controllers.length;
1156 while (j--) {
1157 let k = $view.controllers[j].boundProperties.length;
1158 while (k--) {
1159 let binding = $view.controllers[j].boundProperties[k].binding;
1160 updateOneTimeBinding(binding);
1161 }
1162 }
1163 }
1164};
1165Repeat.useInnerMatcher = true;
1166__decorate([
1167 bindable
1168], Repeat.prototype, "items", void 0);
1169__decorate([
1170 bindable
1171], Repeat.prototype, "local", void 0);
1172__decorate([
1173 bindable
1174], Repeat.prototype, "key", void 0);
1175__decorate([
1176 bindable
1177], Repeat.prototype, "value", void 0);
1178Repeat = Repeat_1 = __decorate([
1179 customAttribute('repeat'),
1180 templateController,
1181 inject(BoundViewFactory, TargetInstruction, ViewSlot, ViewResources, ObserverLocator, RepeatStrategyLocator)
1182], Repeat);
1183const extractMatcherBindingExpression = (instructions, targetedElementId) => {
1184 const instructionIds = Object.keys(instructions);
1185 for (let i = 0; i < instructionIds.length; i++) {
1186 const instructionId = instructionIds[i];
1187 if (targetedElementId !== undefined && instructionId !== targetedElementId) {
1188 continue;
1189 }
1190 const expressions = instructions[instructionId].expressions;
1191 if (expressions) {
1192 for (let ii = 0; ii < expressions.length; ii++) {
1193 if (expressions[ii].targetProperty === 'matcher') {
1194 const matcherBindingExpression = expressions[ii];
1195 expressions.splice(ii, 1);
1196 return matcherBindingExpression;
1197 }
1198 }
1199 }
1200 }
1201};
1202const getChildrenCount = (el) => {
1203 const childNodes = el.childNodes;
1204 let count = 0;
1205 for (let i = 0, ii = childNodes.length; ii > i; ++i) {
1206 if (childNodes[i].nodeType === 1) {
1207 ++count;
1208 }
1209 }
1210 return count;
1211};
1212const getFirstElementChild = (el) => {
1213 let firstChild = el.firstChild;
1214 while (firstChild !== null) {
1215 if (firstChild.nodeType === 1) {
1216 return firstChild;
1217 }
1218 firstChild = firstChild.nextSibling;
1219 }
1220 return null;
1221};
1222
1223const aureliaHideClassName = 'aurelia-hide';
1224const aureliaHideClass = `.${aureliaHideClassName} { display:none !important; }`;
1225function injectAureliaHideStyleAtHead() {
1226 DOM.injectStyles(aureliaHideClass);
1227}
1228function injectAureliaHideStyleAtBoundary(domBoundary) {
1229 if (FEATURE.shadowDOM && domBoundary && !domBoundary.hasAureliaHideStyle) {
1230 domBoundary.hasAureliaHideStyle = true;
1231 DOM.injectStyles(aureliaHideClass, domBoundary);
1232 }
1233}
1234
1235let Show = class Show {
1236 constructor(element, animator, domBoundary) {
1237 this.element = element;
1238 this.animator = animator;
1239 this.domBoundary = domBoundary;
1240 }
1241 static inject() {
1242 return [DOM.Element, Animator, Optional.of(DOM.boundary, true)];
1243 }
1244 created() {
1245 injectAureliaHideStyleAtBoundary(this.domBoundary);
1246 }
1247 valueChanged(newValue) {
1248 let element = this.element;
1249 let animator = this.animator;
1250 if (newValue) {
1251 animator.removeClass(element, aureliaHideClassName);
1252 }
1253 else {
1254 animator.addClass(element, aureliaHideClassName);
1255 }
1256 }
1257 bind(bindingContext) {
1258 this.valueChanged(this.value);
1259 }
1260};
1261Show = __decorate([
1262 customAttribute('show')
1263], Show);
1264
1265let Hide = class Hide {
1266 constructor(element, animator, domBoundary) {
1267 this.element = element;
1268 this.animator = animator;
1269 this.domBoundary = domBoundary;
1270 }
1271 static inject() {
1272 return [DOM.Element, Animator, Optional.of(DOM.boundary, true)];
1273 }
1274 created() {
1275 injectAureliaHideStyleAtBoundary(this.domBoundary);
1276 }
1277 valueChanged(newValue) {
1278 if (newValue) {
1279 this.animator.addClass(this.element, aureliaHideClassName);
1280 }
1281 else {
1282 this.animator.removeClass(this.element, aureliaHideClassName);
1283 }
1284 }
1285 bind(bindingContext) {
1286 this.valueChanged(this.value);
1287 }
1288 value(value) {
1289 throw new Error('Method not implemented.');
1290 }
1291};
1292Hide = __decorate([
1293 customAttribute('hide')
1294], Hide);
1295
1296class HTMLSanitizer {
1297 sanitize(input) {
1298 throw new Error(`To protect the application against a wide variety of sophisticated XSS attacks.
1299Please see https://aurelia.io/docs/binding/basics#element-content for instructions on how to use a secure solution like DOMPurify or sanitize-html.`);
1300 }
1301}
1302
1303let SanitizeHTMLValueConverter = class SanitizeHTMLValueConverter {
1304 constructor(sanitizer) {
1305 this.sanitizer = sanitizer;
1306 }
1307 toView(untrustedMarkup) {
1308 if (untrustedMarkup === null || untrustedMarkup === undefined) {
1309 return null;
1310 }
1311 return this.sanitizer.sanitize(untrustedMarkup);
1312 }
1313};
1314SanitizeHTMLValueConverter = __decorate([
1315 valueConverter('sanitizeHTML'),
1316 inject(HTMLSanitizer)
1317], SanitizeHTMLValueConverter);
1318
1319let Replaceable = class Replaceable {
1320 constructor(viewFactory, viewSlot) {
1321 this.viewFactory = viewFactory;
1322 this.viewSlot = viewSlot;
1323 this.view = null;
1324 }
1325 bind(bindingContext, overrideContext) {
1326 if (this.view === null) {
1327 this.view = this.viewFactory.create();
1328 this.viewSlot.add(this.view);
1329 }
1330 this.view.bind(bindingContext, overrideContext);
1331 }
1332 unbind() {
1333 this.view.unbind();
1334 }
1335};
1336Replaceable = __decorate([
1337 customAttribute('replaceable'),
1338 templateController,
1339 inject(BoundViewFactory, ViewSlot)
1340], Replaceable);
1341
1342let Focus = class Focus {
1343 constructor(element, taskQueue) {
1344 this.element = element;
1345 this.taskQueue = taskQueue;
1346 this.isAttached = false;
1347 this.needsApply = false;
1348 }
1349 static inject() {
1350 return [DOM.Element, TaskQueue];
1351 }
1352 valueChanged() {
1353 if (this.isAttached) {
1354 this._apply();
1355 }
1356 else {
1357 this.needsApply = true;
1358 }
1359 }
1360 _apply() {
1361 if (this.value) {
1362 this.taskQueue.queueMicroTask(() => {
1363 if (this.value) {
1364 this.element.focus();
1365 }
1366 });
1367 }
1368 else {
1369 this.element.blur();
1370 }
1371 }
1372 attached() {
1373 this.isAttached = true;
1374 if (this.needsApply) {
1375 this.needsApply = false;
1376 this._apply();
1377 }
1378 this.element.addEventListener('focus', this);
1379 this.element.addEventListener('blur', this);
1380 }
1381 detached() {
1382 this.isAttached = false;
1383 this.element.removeEventListener('focus', this);
1384 this.element.removeEventListener('blur', this);
1385 }
1386 handleEvent(e) {
1387 if (e.type === 'focus') {
1388 this.value = true;
1389 }
1390 else if (DOM.activeElement !== this.element) {
1391 this.value = false;
1392 }
1393 }
1394};
1395Focus = __decorate([
1396 customAttribute('focus', bindingMode.twoWay)
1397], Focus);
1398
1399let cssUrlMatcher = /url\((?!['"]data)([^)]+)\)/gi;
1400function fixupCSSUrls(address, css) {
1401 if (typeof css !== 'string') {
1402 throw new Error(`Failed loading required CSS file: ${address}`);
1403 }
1404 return css.replace(cssUrlMatcher, (match, p1) => {
1405 let quote = p1.charAt(0);
1406 if (quote === '\'' || quote === '"') {
1407 p1 = p1.substr(1, p1.length - 2);
1408 }
1409 return 'url(\'' + relativeToFile(p1, address) + '\')';
1410 });
1411}
1412class CSSResource {
1413 constructor(address) {
1414 this.address = address;
1415 this._scoped = null;
1416 this._global = false;
1417 this._alreadyGloballyInjected = false;
1418 }
1419 initialize(container, Target) {
1420 this._scoped = new Target(this);
1421 }
1422 register(registry, name) {
1423 if (name === 'scoped') {
1424 registry.registerViewEngineHooks(this._scoped);
1425 }
1426 else {
1427 this._global = true;
1428 }
1429 }
1430 load(container) {
1431 return container.get(Loader)
1432 .loadText(this.address)
1433 .catch(() => null)
1434 .then(text => {
1435 text = fixupCSSUrls(this.address, text);
1436 this._scoped.css = text;
1437 if (this._global) {
1438 this._alreadyGloballyInjected = true;
1439 DOM.injectStyles(text);
1440 }
1441 return this;
1442 });
1443 }
1444}
1445class CSSViewEngineHooks {
1446 constructor(owner) {
1447 this.owner = owner;
1448 this.css = null;
1449 }
1450 beforeCompile(content, resources, instruction) {
1451 if (instruction.targetShadowDOM) {
1452 DOM.injectStyles(this.css, content, true);
1453 }
1454 else if (FEATURE.scopedCSS) {
1455 let styleNode = DOM.injectStyles(this.css, content, true);
1456 styleNode.setAttribute('scoped', 'scoped');
1457 }
1458 else if (this._global && !this.owner._alreadyGloballyInjected) {
1459 DOM.injectStyles(this.css);
1460 this.owner._alreadyGloballyInjected = true;
1461 }
1462 }
1463}
1464function _createCSSResource(address) {
1465 let ViewCSS = class ViewCSS extends CSSViewEngineHooks {
1466 };
1467 ViewCSS = __decorate([
1468 resource(new CSSResource(address))
1469 ], ViewCSS);
1470 return ViewCSS;
1471}
1472
1473let AttrBindingBehavior = class AttrBindingBehavior {
1474 bind(binding, source) {
1475 binding.targetObserver = new DataAttributeObserver(binding.target, binding.targetProperty);
1476 }
1477 unbind(binding, source) {
1478 }
1479};
1480AttrBindingBehavior = __decorate([
1481 bindingBehavior('attr')
1482], AttrBindingBehavior);
1483
1484let modeBindingBehavior = {
1485 bind(binding, source, lookupFunctions) {
1486 binding.originalMode = binding.mode;
1487 binding.mode = this.mode;
1488 },
1489 unbind(binding, source) {
1490 binding.mode = binding.originalMode;
1491 binding.originalMode = null;
1492 }
1493};
1494let OneTimeBindingBehavior = class OneTimeBindingBehavior {
1495 constructor() {
1496 this.mode = bindingMode.oneTime;
1497 }
1498};
1499OneTimeBindingBehavior = __decorate([
1500 mixin(modeBindingBehavior),
1501 bindingBehavior('oneTime')
1502], OneTimeBindingBehavior);
1503let OneWayBindingBehavior = class OneWayBindingBehavior {
1504 constructor() {
1505 this.mode = bindingMode.toView;
1506 }
1507};
1508OneWayBindingBehavior = __decorate([
1509 mixin(modeBindingBehavior),
1510 bindingBehavior('oneWay')
1511], OneWayBindingBehavior);
1512let ToViewBindingBehavior = class ToViewBindingBehavior {
1513 constructor() {
1514 this.mode = bindingMode.toView;
1515 }
1516};
1517ToViewBindingBehavior = __decorate([
1518 mixin(modeBindingBehavior),
1519 bindingBehavior('toView')
1520], ToViewBindingBehavior);
1521let FromViewBindingBehavior = class FromViewBindingBehavior {
1522 constructor() {
1523 this.mode = bindingMode.fromView;
1524 }
1525};
1526FromViewBindingBehavior = __decorate([
1527 mixin(modeBindingBehavior),
1528 bindingBehavior('fromView')
1529], FromViewBindingBehavior);
1530let TwoWayBindingBehavior = class TwoWayBindingBehavior {
1531 constructor() {
1532 this.mode = bindingMode.twoWay;
1533 }
1534};
1535TwoWayBindingBehavior = __decorate([
1536 mixin(modeBindingBehavior),
1537 bindingBehavior('twoWay')
1538], TwoWayBindingBehavior);
1539
1540function throttle(newValue) {
1541 let state = this.throttleState;
1542 let elapsed = +new Date() - state.last;
1543 if (elapsed >= state.delay) {
1544 clearTimeout(state.timeoutId);
1545 state.timeoutId = null;
1546 state.last = +new Date();
1547 this.throttledMethod(newValue);
1548 return;
1549 }
1550 state.newValue = newValue;
1551 if (state.timeoutId === null) {
1552 state.timeoutId = setTimeout(() => {
1553 state.timeoutId = null;
1554 state.last = +new Date();
1555 this.throttledMethod(state.newValue);
1556 }, state.delay - elapsed);
1557 }
1558}
1559let ThrottleBindingBehavior = class ThrottleBindingBehavior {
1560 bind(binding, source, delay = 200) {
1561 let methodToThrottle = 'updateTarget';
1562 if (binding.callSource) {
1563 methodToThrottle = 'callSource';
1564 }
1565 else if (binding.updateSource && binding.mode === bindingMode.twoWay) {
1566 methodToThrottle = 'updateSource';
1567 }
1568 binding.throttledMethod = binding[methodToThrottle];
1569 binding.throttledMethod.originalName = methodToThrottle;
1570 binding[methodToThrottle] = throttle;
1571 binding.throttleState = {
1572 delay: delay,
1573 last: 0,
1574 timeoutId: null
1575 };
1576 }
1577 unbind(binding, source) {
1578 let methodToRestore = binding.throttledMethod.originalName;
1579 binding[methodToRestore] = binding.throttledMethod;
1580 binding.throttledMethod = null;
1581 clearTimeout(binding.throttleState.timeoutId);
1582 binding.throttleState = null;
1583 }
1584};
1585ThrottleBindingBehavior = __decorate([
1586 bindingBehavior('throttle')
1587], ThrottleBindingBehavior);
1588
1589const unset = {};
1590function debounceCallSource(event) {
1591 const state = this.debounceState;
1592 clearTimeout(state.timeoutId);
1593 state.timeoutId = setTimeout(() => this.debouncedMethod(event), state.delay);
1594}
1595function debounceCall(context, newValue, oldValue) {
1596 const state = this.debounceState;
1597 clearTimeout(state.timeoutId);
1598 if (context !== state.callContextToDebounce) {
1599 state.oldValue = unset;
1600 this.debouncedMethod(context, newValue, oldValue);
1601 return;
1602 }
1603 if (state.oldValue === unset) {
1604 state.oldValue = oldValue;
1605 }
1606 state.timeoutId = setTimeout(() => {
1607 const _oldValue = state.oldValue;
1608 state.oldValue = unset;
1609 this.debouncedMethod(context, newValue, _oldValue);
1610 }, state.delay);
1611}
1612let DebounceBindingBehavior = class DebounceBindingBehavior {
1613 bind(binding, source, delay = 200) {
1614 const isCallSource = binding.callSource !== undefined;
1615 const methodToDebounce = isCallSource ? 'callSource' : 'call';
1616 const debouncer = isCallSource ? debounceCallSource : debounceCall;
1617 const mode = binding.mode;
1618 const callContextToDebounce = mode === bindingMode.twoWay || mode === bindingMode.fromView ? targetContext : sourceContext;
1619 binding.debouncedMethod = binding[methodToDebounce];
1620 binding.debouncedMethod.originalName = methodToDebounce;
1621 binding[methodToDebounce] = debouncer;
1622 binding.debounceState = {
1623 callContextToDebounce,
1624 delay,
1625 timeoutId: 0,
1626 oldValue: unset
1627 };
1628 }
1629 unbind(binding, source) {
1630 const methodToRestore = binding.debouncedMethod.originalName;
1631 binding[methodToRestore] = binding.debouncedMethod;
1632 binding.debouncedMethod = null;
1633 clearTimeout(binding.debounceState.timeoutId);
1634 binding.debounceState = null;
1635 }
1636};
1637DebounceBindingBehavior = __decorate([
1638 bindingBehavior('debounce')
1639], DebounceBindingBehavior);
1640
1641function findOriginalEventTarget(event) {
1642 return (event.path && event.path[0]) || (event.deepPath && event.deepPath[0]) || event.target;
1643}
1644function handleSelfEvent(event) {
1645 let target = findOriginalEventTarget(event);
1646 if (this.target !== target) {
1647 return;
1648 }
1649 this.selfEventCallSource(event);
1650}
1651let SelfBindingBehavior = class SelfBindingBehavior {
1652 bind(binding, source) {
1653 if (!binding.callSource || !binding.targetEvent) {
1654 throw new Error('Self binding behavior only supports event.');
1655 }
1656 binding.selfEventCallSource = binding.callSource;
1657 binding.callSource = handleSelfEvent;
1658 }
1659 unbind(binding, source) {
1660 binding.callSource = binding.selfEventCallSource;
1661 binding.selfEventCallSource = null;
1662 }
1663};
1664SelfBindingBehavior = __decorate([
1665 bindingBehavior('self')
1666], SelfBindingBehavior);
1667
1668class BindingSignaler {
1669 constructor() {
1670 this.signals = {};
1671 }
1672 signal(name) {
1673 let bindings = this.signals[name];
1674 if (!bindings) {
1675 return;
1676 }
1677 let i = bindings.length;
1678 while (i--) {
1679 bindings[i].call(sourceContext);
1680 }
1681 }
1682}
1683
1684let SignalBindingBehavior = class SignalBindingBehavior {
1685 constructor(bindingSignaler) {
1686 this.signals = bindingSignaler.signals;
1687 }
1688 static inject() { return [BindingSignaler]; }
1689 bind(binding, source, ...names) {
1690 if (!binding.updateTarget) {
1691 throw new Error('Only property bindings and string interpolation bindings can be signaled. Trigger, delegate and call bindings cannot be signaled.');
1692 }
1693 let signals = this.signals;
1694 if (names.length === 1) {
1695 let name = names[0];
1696 let bindings = signals[name] || (signals[name] = []);
1697 bindings.push(binding);
1698 binding.signalName = name;
1699 }
1700 else if (names.length > 1) {
1701 let i = names.length;
1702 while (i--) {
1703 let name = names[i];
1704 let bindings = signals[name] || (signals[name] = []);
1705 bindings.push(binding);
1706 }
1707 binding.signalName = names;
1708 }
1709 else {
1710 throw new Error('Signal name is required.');
1711 }
1712 }
1713 unbind(binding, source) {
1714 let signals = this.signals;
1715 let name = binding.signalName;
1716 binding.signalName = null;
1717 if (Array.isArray(name)) {
1718 let names = name;
1719 let i = names.length;
1720 while (i--) {
1721 let n = names[i];
1722 let bindings = signals[n];
1723 bindings.splice(bindings.indexOf(binding), 1);
1724 }
1725 }
1726 else {
1727 let bindings = signals[name];
1728 bindings.splice(bindings.indexOf(binding), 1);
1729 }
1730 }
1731};
1732SignalBindingBehavior = __decorate([
1733 bindingBehavior('signal')
1734], SignalBindingBehavior);
1735
1736const eventNamesRequired = 'The updateTrigger binding behavior requires at least one event name argument: eg <input value.bind="firstName & updateTrigger:\'blur\'">';
1737const notApplicableMessage = 'The updateTrigger binding behavior can only be applied to two-way/ from-view bindings on input/select elements.';
1738let UpdateTriggerBindingBehavior = class UpdateTriggerBindingBehavior {
1739 bind(binding, source, ...events) {
1740 if (events.length === 0) {
1741 throw new Error(eventNamesRequired);
1742 }
1743 if (binding.mode !== bindingMode.twoWay && binding.mode !== bindingMode.fromView) {
1744 throw new Error(notApplicableMessage);
1745 }
1746 let targetObserver = binding.observerLocator.getObserver(binding.target, binding.targetProperty);
1747 if (!targetObserver.handler) {
1748 throw new Error(notApplicableMessage);
1749 }
1750 binding.targetObserver = targetObserver;
1751 targetObserver.originalHandler = binding.targetObserver.handler;
1752 let handler = new EventSubscriber(events);
1753 targetObserver.handler = handler;
1754 }
1755 unbind(binding, source) {
1756 let targetObserver = binding.targetObserver;
1757 targetObserver.handler.dispose();
1758 targetObserver.handler = targetObserver.originalHandler;
1759 targetObserver.originalHandler = null;
1760 }
1761};
1762UpdateTriggerBindingBehavior = __decorate([
1763 bindingBehavior('updateTrigger')
1764], UpdateTriggerBindingBehavior);
1765
1766function _createDynamicElement({ name, viewUrl, bindableNames, useShadowDOMmode }) {
1767 let DynamicElement = class DynamicElement {
1768 bind(bindingContext) {
1769 this.$parent = bindingContext;
1770 }
1771 };
1772 DynamicElement = __decorate([
1773 customElement(name),
1774 useView(viewUrl)
1775 ], DynamicElement);
1776 for (let i = 0, ii = bindableNames.length; i < ii; ++i) {
1777 bindable(bindableNames[i])(DynamicElement);
1778 }
1779 switch (useShadowDOMmode) {
1780 case 'open':
1781 useShadowDOM({ mode: 'open' })(DynamicElement);
1782 break;
1783 case 'closed':
1784 useShadowDOM({ mode: 'closed' })(DynamicElement);
1785 break;
1786 case '':
1787 useShadowDOM(DynamicElement);
1788 break;
1789 case null:
1790 break;
1791 default:
1792 getLogger('aurelia-html-only-element')
1793 .warn(`Expected 'use-shadow-dom' value to be "close", "open" or "", received ${useShadowDOMmode}`);
1794 break;
1795 }
1796 return DynamicElement;
1797}
1798
1799function getElementName(address) {
1800 return /([^\/^\?]+)\.html/i.exec(address)[1].toLowerCase();
1801}
1802function configure$1(config) {
1803 const viewEngine = config.container.get(ViewEngine);
1804 const loader = config.aurelia.loader;
1805 viewEngine.addResourcePlugin('.html', {
1806 'fetch': function (viewUrl) {
1807 return loader.loadTemplate(viewUrl).then(registryEntry => {
1808 let bindableNames = registryEntry.template.getAttribute('bindable');
1809 const useShadowDOMmode = registryEntry.template.getAttribute('use-shadow-dom');
1810 const name = getElementName(viewUrl);
1811 if (bindableNames) {
1812 bindableNames = bindableNames.split(',').map(x => x.trim());
1813 registryEntry.template.removeAttribute('bindable');
1814 }
1815 else {
1816 bindableNames = [];
1817 }
1818 return { [name]: _createDynamicElement({ name, viewUrl, bindableNames, useShadowDOMmode }) };
1819 });
1820 }
1821 });
1822}
1823
1824function configure(config) {
1825 injectAureliaHideStyleAtHead();
1826 config.globalResources(Compose, If, Else, With, Repeat, Show, Hide, Replaceable, Focus, SanitizeHTMLValueConverter, OneTimeBindingBehavior, OneWayBindingBehavior, ToViewBindingBehavior, FromViewBindingBehavior, TwoWayBindingBehavior, ThrottleBindingBehavior, DebounceBindingBehavior, SelfBindingBehavior, SignalBindingBehavior, UpdateTriggerBindingBehavior, AttrBindingBehavior);
1827 configure$1(config);
1828 let viewEngine = config.container.get(ViewEngine);
1829 let styleResourcePlugin = {
1830 fetch(address) {
1831 return { [address]: _createCSSResource(address) };
1832 }
1833 };
1834 ['.css', '.less', '.sass', '.scss', '.styl'].forEach(ext => viewEngine.addResourcePlugin(ext, styleResourcePlugin));
1835}
1836
1837export { AbstractRepeater, ArrayRepeatStrategy, AttrBindingBehavior, BindingSignaler, Compose, DebounceBindingBehavior, Else, Focus, FromViewBindingBehavior, HTMLSanitizer, Hide, If, MapRepeatStrategy, NullRepeatStrategy, NumberRepeatStrategy, OneTimeBindingBehavior, OneWayBindingBehavior, Repeat, RepeatStrategyLocator, Replaceable, SanitizeHTMLValueConverter, SelfBindingBehavior, SetRepeatStrategy, Show, SignalBindingBehavior, ThrottleBindingBehavior, ToViewBindingBehavior, TwoWayBindingBehavior, UpdateTriggerBindingBehavior, With, configure, createFullOverrideContext, getItemsSourceExpression, isOneTime, unwrapExpression, updateOneTimeBinding, updateOverrideContext, viewsRequireLifecycle };
1838//# sourceMappingURL=aurelia-templating-resources.js.map