Merge ~blr/maas:bug-1787628-node-listing into maas:master

Proposed by Kit Randel on 2018-08-19
Status: Merged
Approved by: Kit Randel on 2018-08-20
Approved revision: b2d861d22d18384f05af87bc24602d0eb0795d29
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~blr/maas:bug-1787628-node-listing
Merge into: maas:master
Diff against target: 1415 lines (+593/-641)
11 files modified
src/maasserver/static/js/angular/3rdparty/vs-repeat.js (+580/-628)
src/maasserver/static/js/bundle/vendor-min.js (+1/-1)
src/maasserver/static/js/bundle/vendor-min.js.map (+1/-1)
src/maasserver/static/partials/dashboard.html (+1/-1)
src/maasserver/static/partials/machines-table.html (+1/-1)
src/maasserver/static/partials/networks-list.html (+2/-2)
src/maasserver/static/partials/node-events.html (+1/-1)
src/maasserver/static/partials/nodes-list.html (+3/-3)
src/maasserver/static/partials/pods-list.html (+1/-1)
src/maasserver/static/partials/switches-table.html (+1/-1)
src/maasserver/static/partials/zones-list.html (+1/-1)
Reviewer Review Type Date Requested Status
Andres Rodriguez (community) 2018-08-19 Approve on 2018-08-19
MAAS Lander unittests Pending
Review via email: mp+353376@code.launchpad.net

Commit message

LP: #1787628 - Downgrade angular-vs-repeat to v1.1.11.

Description of the change

Unfortunately the 2.x series of angular-vs-repeat suffers from a bug (https://github.com/kamilkp/angular-vs-repeat/issues/192) which in certain cases will only display the first element of an ng-repeat until a scroll event is triggered.

This branch reverts to the latest release on 1.x which does not have this issue.

To post a comment you must log in.
Andres Rodriguez (andreserl) wrote :

lgtm!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/static/js/angular/3rdparty/vs-repeat.js b/src/maasserver/static/js/angular/3rdparty/vs-repeat.js
2old mode 100755
3new mode 100644
4index e789333..b42a6e0
5--- a/src/maasserver/static/js/angular/3rdparty/vs-repeat.js
6+++ b/src/maasserver/static/js/angular/3rdparty/vs-repeat.js
7@@ -1,5 +1,5 @@
8 /*!
9- * Angular Virtual Scroll Repeat v2.0.9
10+ * Angular Virtual Scroll Repeat v1.1.11
11 * https://github.com/kamilkp/angular-vs-repeat/
12 *
13 * Copyright Kamil Pękala
14@@ -8,672 +8,624 @@
15 * Released under the MIT License
16 * https://opensource.org/licenses/MIT
17 *
18- * Date: 2018/04/02
19+ * Date: 2018/03/09
20+ *
21 */
22
23-function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
24-
25-function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
26-
27-function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
28-
29-function _sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
30-
31-function _slicedToArray(arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return _sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }
32-
33-/* global console, setTimeout, module */
34-(function (window, angular) {
35- /**
36- * DESCRIPTION:
37- * vsRepeat directive stands for Virtual Scroll Repeat. It turns a standard ngRepeated set of elements in a scrollable container
38- * into a component, where the user thinks he has all the elements rendered and all he needs to do is scroll (without any kind of
39- * pagination - which most users loath) and at the same time the browser isn't overloaded by that many elements/angular bindings etc.
40- * The directive renders only so many elements that can fit into current container's clientHeight/clientWidth.
41- * LIMITATIONS:
42- * - current version only supports an Array as a right-hand-side object for ngRepeat
43- * - all rendered elements must have the same height/width or the sizes of the elements must be known up front
44- * USAGE:
45- * In order to use the vsRepeat directive you need to place a vs-repeat attribute on a direct parent of an element with ng-repeat
46- * example:
47- * <div vs-repeat="options">
48- * <div ng-repeat="item in someArray">
49- * <!-- content -->
50- * </div>
51- * </div>
52- * or:
53- * <div vs-repeat="options">
54- * <div ng-repeat-start="item in someArray">
55- * <!-- content -->
56- * </div>
57- * <div>
58- * <!-- something in the middle -->
59- * </div>
60- * <div ng-repeat-end>
61- * <!-- content -->
62- * </div>
63- * </div>
64- * You can also measure the single element's height/width (including all paddings and margins), and then speficy it as a value
65- * of the option's `size` property. This can be used if one wants to override the automatically computed element size.
66- * example:
67- * <div vs-repeat="{size: 50}"> <!-- the specified element height is 50px -->
68- * <div ng-repeat="item in someArray">
69- * <!-- content -->
70- * </div>
71- * </div>
72- * IMPORTANT!
73- * - the vsRepeat directive must be applied to a direct parent of an element with ngRepeat
74- * - the value of vsRepeat attribute is the single element's height/width measured in pixels. If none provided, the directive
75- * will compute it automatically
76- * OPTIONAL PARAMETERS (attributes):
77- * vs-repeat-container="selector" - selector for element containing ng-repeat. (defaults to the current element)
78- * OPTIONS:
79- * Options shall be passed as an object to the `vs-repeat` attribute e.g.: `<div vs-repeat="{scrollParent: 'window', size: 20}"></div>`
80- *
81- * Available options:
82- * `horizontal` - stack repeated elements horizontally instead of vertically
83- * `offset-before` - top/left offset in pixels (defaults to 0)
84- * `offset-after` - bottom/right offset in pixels (defaults to 0)
85- * `scroll-margin` - how many pixels ahead should elements be rendered while scrolling
86- * `latch` - if true, elements will be rendered gradually but won't be removed when scrolled away (defaults to false)
87- * `size` - a property name of the items in collection that is a number denoting the element size (in pixels)
88- * `autoresize` - use this attribute without vs-size and without specifying element's size. The automatically computed element style will
89- * readjust upon window resize if the size is dependable on the viewport size
90- * `scrolled-to-end` - callback will be called when the last item of the list is rendered
91- * `scrolled-to-end-offset` - set this number to trigger the scrolledToEnd callback n items before the last gets rendered
92- * `scrolled-to-beginning` - callback will be called when the first item of the list is rendered
93- * `scrolled-to-beginning-offset` - set this number to trigger the scrolledToBeginning callback n items before the first gets rendered
94- * EVENTS:
95- * - `vsRepeatTrigger` - an event the directive listens for to manually trigger reinitialization
96- * - `vsRepeatReinitialized` - an event the directive emits upon reinitialization done
97- */
98- var closestElement = angular.element.prototype.closest;
99-
100- if (!closestElement) {
101- var matchingFunction = ['matches', 'matchesSelector', 'webkitMatches', 'webkitMatchesSelector', 'msMatches', 'msMatchesSelector', 'mozMatches', 'mozMatchesSelector'].reduce(function (res, prop) {
102- var _res;
103-
104- return (_res = res) !== null && _res !== void 0 ? _res : prop in document.documentElement ? prop : null;
105- }, null);
106-
107- closestElement = function closestElement(selector) {
108- var _el;
109-
110- var el = this[0].parentNode;
111-
112- while (el !== document.documentElement && el != null && !el[matchingFunction](selector)) {
113- el = el.parentNode;
114- }
115-
116- if ((_el = el) === null || _el === void 0 ? void 0 : _el[matchingFunction](selector)) {
117- return angular.element(el);
118- }
119-
120- return angular.element();
121- };
122- }
123-
124- function getWindowScroll() {
125- var _ref, _document$documentEle, _ref2, _document$documentEle2;
126-
127- if ('pageYOffset' in window) {
128- return {
129- scrollTop: window.pageYOffset,
130- scrollLeft: window.pageXOffset
131- };
132- }
133+(function(window, angular) {
134+ 'use strict';
135+ /* jshint eqnull:true */
136+ /* jshint -W038 */
137+
138+ // DESCRIPTION:
139+ // vsRepeat directive stands for Virtual Scroll Repeat. It turns a standard ngRepeated set of elements in a scrollable container
140+ // into a component, where the user thinks he has all the elements rendered and all he needs to do is scroll (without any kind of
141+ // pagination - which most users loath) and at the same time the browser isn't overloaded by that many elements/angular bindings etc.
142+ // The directive renders only so many elements that can fit into current container's clientHeight/clientWidth.
143+
144+ // LIMITATIONS:
145+ // - current version only supports an Array as a right-hand-side object for ngRepeat
146+ // - all rendered elements must have the same height/width or the sizes of the elements must be known up front
147+
148+ // USAGE:
149+ // In order to use the vsRepeat directive you need to place a vs-repeat attribute on a direct parent of an element with ng-repeat
150+ // example:
151+ // <div vs-repeat>
152+ // <div ng-repeat="item in someArray">
153+ // <!-- content -->
154+ // </div>
155+ // </div>
156+ //
157+ // or:
158+ // <div vs-repeat>
159+ // <div ng-repeat-start="item in someArray">
160+ // <!-- content -->
161+ // </div>
162+ // <div>
163+ // <!-- something in the middle -->
164+ // </div>
165+ // <div ng-repeat-end>
166+ // <!-- content -->
167+ // </div>
168+ // </div>
169+ //
170+ // You can also measure the single element's height/width (including all paddings and margins), and then speficy it as a value
171+ // of the attribute 'vs-repeat'. This can be used if one wants to override the automatically computed element size.
172+ // example:
173+ // <div vs-repeat="50"> <!-- the specified element height is 50px -->
174+ // <div ng-repeat="item in someArray">
175+ // <!-- content -->
176+ // </div>
177+ // </div>
178+ //
179+ // IMPORTANT!
180+ //
181+ // - the vsRepeat directive must be applied to a direct parent of an element with ngRepeat
182+ // - the value of vsRepeat attribute is the single element's height/width measured in pixels. If none provided, the directive
183+ // will compute it automatically
184+
185+ // OPTIONAL PARAMETERS (attributes):
186+ // vs-repeat-container="selector" - selector for element containing ng-repeat. (defaults to the current element)
187+ // vs-scroll-parent="selector" - selector to the scrollable container. The directive will look for a closest parent matching
188+ // the given selector (defaults to the current element)
189+ // vs-horizontal - stack repeated elements horizontally instead of vertically
190+ // vs-offset-before="value" - top/left offset in pixels (defaults to 0)
191+ // vs-offset-after="value" - bottom/right offset in pixels (defaults to 0)
192+ // vs-excess="value" - an integer number representing the number of elements to be rendered outside of the current container's viewport
193+ // (defaults to 2)
194+ // vs-size - a property name of the items in collection that is a number denoting the element size (in pixels)
195+ // vs-autoresize - use this attribute without vs-size and without specifying element's size. The automatically computed element style will
196+ // readjust upon window resize if the size is dependable on the viewport size
197+ // vs-scrolled-to-end="callback" - callback will be called when the last item of the list is rendered
198+ // vs-scrolled-to-end-offset="integer" - set this number to trigger the scrolledToEnd callback n items before the last gets rendered
199+ // vs-scrolled-to-beginning="callback" - callback will be called when the first item of the list is rendered
200+ // vs-scrolled-to-beginning-offset="integer" - set this number to trigger the scrolledToBeginning callback n items before the first gets rendered
201+
202+ // EVENTS:
203+ // - 'vsRepeatTrigger' - an event the directive listens for to manually trigger reinitialization
204+ // - 'vsRepeatReinitialized' - an event the directive emits upon reinitialization done
205+
206+ var dde = document.documentElement,
207+ matchingFunction = dde.matches ? 'matches' :
208+ dde.matchesSelector ? 'matchesSelector' :
209+ dde.webkitMatches ? 'webkitMatches' :
210+ dde.webkitMatchesSelector ? 'webkitMatchesSelector' :
211+ dde.msMatches ? 'msMatches' :
212+ dde.msMatchesSelector ? 'msMatchesSelector' :
213+ dde.mozMatches ? 'mozMatches' :
214+ dde.mozMatchesSelector ? 'mozMatchesSelector' : null;
215+
216+ var closestElement = angular.element.prototype.closest || function (selector) {
217+ var el = this[0].parentNode;
218+ while (el !== document.documentElement && el != null && !el[matchingFunction](selector)) {
219+ el = el.parentNode;
220+ }
221
222- return {
223- scrollTop: (_ref = (_document$documentEle = document.documentElement.scrollTop) !== null && _document$documentEle !== void 0 ? _document$documentEle : document.body.scrollTop) !== null && _ref !== void 0 ? _ref : 0,
224- scrollLeft: (_ref2 = (_document$documentEle2 = document.documentElement.scrollLeft) !== null && _document$documentEle2 !== void 0 ? _document$documentEle2 : document.body.scrollLeft) !== null && _ref2 !== void 0 ? _ref2 : 0
225+ if (el && el[matchingFunction](selector)) {
226+ return angular.element(el);
227+ }
228+ else {
229+ return angular.element();
230+ }
231 };
232- }
233
234- function getClientSize(element, sizeProp) {
235- if (element === window) {
236- return sizeProp === 'clientWidth' ? window.innerWidth : window.innerHeight;
237+ function getWindowScroll() {
238+ if ('pageYOffset' in window) {
239+ return {
240+ scrollTop: pageYOffset,
241+ scrollLeft: pageXOffset
242+ };
243+ }
244+ else {
245+ var sx, sy, d = document, r = d.documentElement, b = d.body;
246+ sx = r.scrollLeft || b.scrollLeft || 0;
247+ sy = r.scrollTop || b.scrollTop || 0;
248+ return {
249+ scrollTop: sy,
250+ scrollLeft: sx
251+ };
252+ }
253 }
254
255- return element[sizeProp];
256- }
257-
258- function getScrollPos(element, scrollProp) {
259- return element === window ? getWindowScroll()[scrollProp] : element[scrollProp];
260- }
261-
262- function getScrollOffset(vsElement, scrollElement, isHorizontal) {
263- var vsPos = vsElement.getBoundingClientRect()[isHorizontal ? 'left' : 'top'];
264- var scrollPos = scrollElement === window ? 0 : scrollElement.getBoundingClientRect()[isHorizontal ? 'left' : 'top'];
265- var scrollValue = (scrollElement === window ? getWindowScroll() : scrollElement)[isHorizontal ? 'scrollLeft' : 'scrollTop'];
266- return vsPos - scrollPos + scrollValue;
267- }
268+ function getClientSize(element, sizeProp) {
269+ if (element === window) {
270+ return sizeProp === 'clientWidth' ? window.innerWidth : window.innerHeight;
271+ }
272+ else {
273+ return element[sizeProp];
274+ }
275+ }
276
277- function analyzeNgRepeatUsage(element) {
278- var options = ['ng-repeat', 'data-ng-repeat', 'ng-repeat-start', 'data-ng-repeat-start'];
279+ function getScrollPos(element, scrollProp) {
280+ return element === window ? getWindowScroll()[scrollProp] : element[scrollProp];
281+ }
282
283- for (var _i = 0; _i < options.length; _i++) {
284- var opt = options[_i];
285+ function getScrollOffset(vsElement, scrollElement, isHorizontal) {
286+ var vsPos = vsElement.getBoundingClientRect()[isHorizontal ? 'left' : 'top'];
287+ var scrollPos = scrollElement === window ? 0 : scrollElement.getBoundingClientRect()[isHorizontal ? 'left' : 'top'];
288+ var correction = vsPos - scrollPos +
289+ (scrollElement === window ? getWindowScroll() : scrollElement)[isHorizontal ? 'scrollLeft' : 'scrollTop'];
290
291- if (element.attr(opt)) {
292- return [opt, element.attr(opt), opt.indexOf('-start') >= 0];
293- }
294+ return correction;
295 }
296
297- throw new Error('angular-vs-repeat: no ng-repeat directive on a child element');
298- }
299-
300- function printDeprecationWarning($element, message) {
301- console.warn("vs-repeat deprecation: ".concat(message), $element[0]);
302- }
303-
304- function attrDeprecated(attrname, $element) {
305- printDeprecationWarning($element, "".concat(attrname, " attribute is deprecated. Pass the options object to vs-repeat attribute instead https://github.com/kamilkp/angular-vs-repeat#options"));
306- }
307-
308- var defaultOptions = {
309- latch: false,
310- container: null,
311- scrollParent: null,
312- size: null,
313- offsetBefore: 0,
314- offsetAfter: 0,
315- scrolledToBeginning: angular.noop,
316- scrolledToEnd: angular.noop,
317- scrolledToBeginningOffset: 0,
318- scrolledToEndOffset: 0,
319- scrollMargin: 0,
320- horizontal: false,
321- autoresize: false,
322- hunked: false,
323- hunkSize: 0
324- };
325- var vsRepeatModule = angular.module('vs-repeat', []).directive('vsRepeat', ['$compile', '$parse', function ($compile, $parse) {
326- return {
327- restrict: 'A',
328- scope: true,
329- compile: function compile(compileElement, compileAttrs) {
330- var compileRepeatContainer = 'vsRepeatContainer' in compileAttrs ? angular.element(compileElement[0].querySelector(compileAttrs.vsRepeatContainer)) : compileElement;
331- var repeatContainerChildren = compileRepeatContainer.children();
332- var ngRepeatChild = repeatContainerChildren.eq(0);
333- var childCloneHtml = ngRepeatChild[0].outerHTML;
334- var collectionName = '$vs_collection'; // TODO: make configurable?
335-
336- ['vsSize', 'vsScrollParent', 'vsSizeProperty', 'vsHorizontal', 'vsOffsetBefore', 'vsOffsetAfter', 'vsScrolledToEndOffset', 'vsScrolledToBeginningOffset', 'vsExcess', 'vsScrollMargin'].forEach(function (attrname) {
337- if (attrname in compileAttrs) {
338- attrDeprecated(attrname, compileElement);
339- }
340- });
341-
342- var _analyzeNgRepeatUsage = analyzeNgRepeatUsage(ngRepeatChild),
343- _analyzeNgRepeatUsage2 = _slicedToArray(_analyzeNgRepeatUsage, 3),
344- originalNgRepeatAttr = _analyzeNgRepeatUsage2[0],
345- ngRepeatExpression = _analyzeNgRepeatUsage2[1],
346- isNgRepeatStart = _analyzeNgRepeatUsage2[2];
347-
348- var expressionMatches = /^\s*(\S+)\s+in\s+([\S\s]+?)(track\s+by\s+\S+)?$/.exec(ngRepeatExpression);
349-
350- var _expressionMatches = _slicedToArray(expressionMatches, 4),
351- lhs = _expressionMatches[1],
352- rhs = _expressionMatches[2],
353- rhsSuffix = _expressionMatches[3];
354-
355- if (isNgRepeatStart) {
356- var index = 0;
357- var repeaterElement = repeatContainerChildren.eq(index);
358-
359- while (repeaterElement.attr('ng-repeat-end') == null && repeaterElement.attr('data-ng-repeat-end') == null) {
360- index++;
361- repeaterElement = repeatContainerChildren.eq(index);
362- childCloneHtml += repeaterElement[0].outerHTML;
363- }
364- }
365-
366- compileRepeatContainer.empty();
367+ var vsRepeatModule = angular.module('vs-repeat', []).directive('vsRepeat', ['$compile', '$parse', function($compile, $parse) {
368 return {
369- pre: function pre($scope, $element, $attrs) {
370- var _$scope$$eval;
371-
372- function _parseSize(options) {
373- if (typeof options.size === 'number') {
374- options.getSize = function () {
375- return options.size;
376- };
377- } else {
378- var parsed = $parse(String(options.size));
379-
380- options.getSize = function (item) {
381- return parsed($scope, _defineProperty({}, lhs, item));
382- };
383- }
384- }
385-
386- $scope.vsRepeat = {
387- options: _extends({}, defaultOptions, (_$scope$$eval = $scope.$eval($attrs.vsRepeat)) !== null && _$scope$$eval !== void 0 ? _$scope$$eval : {})
388- };
389- var options = $scope.vsRepeat.options;
390-
391- _parseSize(options);
392-
393- var repeatContainer = angular.isDefined($attrs.vsRepeatContainer) ? angular.element($element[0].querySelector($attrs.vsRepeatContainer)) : $element;
394- var childClone = angular.element(childCloneHtml);
395- var childTagName = childClone[0].tagName.toLowerCase();
396- var originalCollection = [];
397- var originalLength;
398- var $beforeContent = angular.element('<' + childTagName + ' class="vs-repeat-before-content"></' + childTagName + '>');
399- var $afterContent = angular.element('<' + childTagName + ' class="vs-repeat-after-content"></' + childTagName + '>');
400- var autosizingRequired = options.size === null;
401- var $scrollParent = options.scrollParent ? options.scrollParent === 'window' ? angular.element(window) : closestElement.call(repeatContainer, options.scrollParent) : repeatContainer;
402- var clientSize = options.horizontal ? 'clientWidth' : 'clientHeight';
403- var offsetSize = options.horizontal ? 'offsetWidth' : 'offsetHeight';
404- var scrollSize = options.horizontal ? 'scrollWidth' : 'scrollHeight';
405- var scrollPos = options.horizontal ? 'scrollLeft' : 'scrollTop';
406- $scope.vsRepeat.totalSize = 0;
407-
408- if ($scrollParent.length === 0) {
409- throw 'Specified scroll parent selector did not match any element';
410- }
411-
412- $scope.vsRepeat.$scrollParent = $scrollParent;
413- $scope.vsRepeat.sizesCumulative = [];
414-
415- if (options.debug) {
416- var $debugParent = options.scrollParent === 'window' ? angular.element(document.body) : $scrollParent;
417- var $debug = angular.element('<div class="vs-repeat-debug-element"></div>');
418- $debug.css('position', options.scrollParent === 'window' ? 'fixed' : 'absolute');
419- $debugParent.append($debug);
420- $scope.$on('$destroy', function () {
421- $debug.remove();
422- });
423- }
424-
425- var measuredSize = getClientSize($scrollParent[0], clientSize) || 50;
426-
427- if (options.horizontal) {
428- $beforeContent.css('height', '100%');
429- $afterContent.css('height', '100%');
430- } else {
431- $beforeContent.css('width', '100%');
432- $afterContent.css('width', '100%');
433- }
434-
435- if ($attrs.vsRepeatOptions) {
436- $scope.$watchCollection($attrs.vsRepeatOptions, function (newOpts) {
437- var mergedOptions = _extends({}, options, newOpts);
438-
439- if (JSON.stringify(mergedOptions) !== JSON.stringify(options)) {
440- Object.assign(options, newOpts);
441-
442- _parseSize(options);
443-
444- reinitialize();
445+ restrict: 'A',
446+ scope: true,
447+ compile: function($element, $attrs) {
448+ var repeatContainer = angular.isDefined($attrs.vsRepeatContainer) ? angular.element($element[0].querySelector($attrs.vsRepeatContainer)) : $element,
449+ ngRepeatChild = repeatContainer.children().eq(0),
450+ ngRepeatExpression,
451+ childCloneHtml = ngRepeatChild[0].outerHTML,
452+ expressionMatches,
453+ lhs,
454+ rhs,
455+ rhsSuffix,
456+ originalNgRepeatAttr,
457+ collectionName = '$vs_collection',
458+ isNgRepeatStart = false,
459+ attributesDictionary = {
460+ 'vsRepeat': 'elementSize',
461+ 'vsOffsetBefore': 'offsetBefore',
462+ 'vsOffsetAfter': 'offsetAfter',
463+ 'vsScrolledToEndOffset': 'scrolledToEndOffset',
464+ 'vsScrolledToBeginningOffset': 'scrolledToBeginningOffset',
465+ 'vsExcess': 'excess',
466+ 'vsScrollMargin': 'scrollMargin'
467+ };
468+
469+ if (ngRepeatChild.attr('ng-repeat')) {
470+ originalNgRepeatAttr = 'ng-repeat';
471+ ngRepeatExpression = ngRepeatChild.attr('ng-repeat');
472 }
473- });
474- }
475-
476- $scope.$watchCollection(rhs, function () {
477- var coll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
478- originalCollection = coll;
479- refresh();
480- });
481-
482- function refresh() {
483- if (!originalCollection || originalCollection.length < 1) {
484- $scope[collectionName] = [];
485- originalLength = 0;
486- $scope.vsRepeat.sizesCumulative = [0];
487- } else {
488- originalLength = originalCollection.length;
489-
490- if (options.size) {
491- _mapSize();
492- } else {
493- getFromMeasured();
494- }
495- }
496-
497- reinitialize();
498- }
499-
500- function _mapSize() {
501- var hardSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
502- var sizes = originalCollection.map(function (item) {
503- var _hardSize;
504-
505- return (_hardSize = hardSize) !== null && _hardSize !== void 0 ? _hardSize : options.getSize(item);
506- });
507- var sum = 0;
508- $scope.vsRepeat.sizesCumulative = [0].concat(_toConsumableArray(sizes.map(function (size) {
509- return sum += size;
510- })));
511- }
512-
513- function getFromMeasured() {
514- if (autosizingRequired) {
515- $scope.$$postDigest(function () {
516- if (repeatContainer[0].offsetHeight || repeatContainer[0].offsetWidth) {
517- // element is visible
518- var children = repeatContainer.children();
519- var i = 0;
520- var gotSomething = false;
521- var insideStartEndSequence = false;
522-
523- while (i < children.length) {
524- if (children[i].attributes[originalNgRepeatAttr] != null || insideStartEndSequence) {
525- if (!gotSomething) {
526- measuredSize = 0;
527- }
528-
529- gotSomething = true;
530-
531- if (children[i][offsetSize]) {
532- measuredSize += children[i][offsetSize];
533- }
534-
535- if (isNgRepeatStart) {
536- if (children[i].attributes['ng-repeat-end'] != null || children[i].attributes['data-ng-repeat-end'] != null) {
537- break;
538- } else {
539- insideStartEndSequence = true;
540- }
541- } else {
542- break;
543- }
544- }
545-
546- i++;
547- }
548-
549- if (gotSomething) {
550- _mapSize(measuredSize);
551-
552- reinitialize();
553- autosizingRequired = false;
554-
555- if ($scope.$root && !$scope.$root.$$phase) {
556- $scope.$digest();
557- }
558- }
559- } else {
560- var dereg = $scope.$watch(function () {
561- if (repeatContainer[0].offsetHeight || repeatContainer[0].offsetWidth) {
562- dereg();
563- getFromMeasured();
564- }
565- });
566- }
567- });
568- } else {
569- _mapSize(measuredSize);
570- }
571- }
572-
573- function getLayoutProps(value) {
574- var layoutProp = options.horizontal ? 'width' : 'height';
575- return ['', 'min-', 'max-'].reduce(function (acc, prop) {
576- return acc["".concat(prop).concat(layoutProp)] = value, acc;
577- }, {});
578- }
579-
580- childClone.eq(0).attr(originalNgRepeatAttr, lhs + ' in ' + collectionName + (rhsSuffix ? ' ' + rhsSuffix : ''));
581- childClone.addClass('vs-repeat-repeated-element');
582- repeatContainer.append($beforeContent);
583- repeatContainer.append(childClone);
584- $compile(childClone)($scope);
585- repeatContainer.append($afterContent);
586- $scope.vsRepeat.startIndex = 0;
587- $scope.vsRepeat.endIndex = 0;
588-
589- function scrollHandler() {
590- var pos = $scrollParent[0][scrollPos];
591-
592- if (updateInnerCollection()) {
593- $scope.$digest();
594-
595- if (options._ensureScrollIntegrity) {
596- $scrollParent[0][scrollPos] = pos;
597+ else if (ngRepeatChild.attr('data-ng-repeat')) {
598+ originalNgRepeatAttr = 'data-ng-repeat';
599+ ngRepeatExpression = ngRepeatChild.attr('data-ng-repeat');
600 }
601- }
602- }
603-
604- $scrollParent.on('scroll', scrollHandler);
605-
606- function onWindowResize() {
607- if (options.autoresize) {
608- autosizingRequired = true;
609- getFromMeasured();
610-
611- if ($scope.$root && !$scope.$root.$$phase) {
612- $scope.$digest();
613+ else if (ngRepeatChild.attr('ng-repeat-start')) {
614+ isNgRepeatStart = true;
615+ originalNgRepeatAttr = 'ng-repeat-start';
616+ ngRepeatExpression = ngRepeatChild.attr('ng-repeat-start');
617 }
618- }
619-
620- if (updateInnerCollection()) {
621- $scope.$digest();
622- }
623- }
624-
625- angular.element(window).on('resize', onWindowResize);
626- $scope.$on('$destroy', function () {
627- angular.element(window).off('resize', onWindowResize);
628- $scrollParent.off('scroll', scrollHandler);
629- });
630- $scope.$on('vsRepeatTrigger', refresh);
631- $scope.$on('vsRepeatResize', function () {
632- autosizingRequired = true;
633- getFromMeasured();
634- });
635-
636- var _prevStartIndex, _prevEndIndex, _minStartIndex, _maxEndIndex;
637-
638- $scope.$on('vsRenderAll', function () {
639- if (!options.latch) {
640- return;
641- }
642-
643- if ($scope.vsRepeat.endIndex === originalLength) {
644- $scope.$emit('vsRenderAllDone');
645- return;
646- }
647-
648- setTimeout(function () {
649- // var __endIndex = Math.min($scope.vsRepeat.endIndex + (quantum || 1), originalLength);
650- var __endIndex = originalLength;
651- _maxEndIndex = Math.max(__endIndex, _maxEndIndex);
652- $scope.vsRepeat.endIndex = options.latch ? _maxEndIndex : __endIndex;
653- $scope[collectionName] = originalCollection.slice($scope.vsRepeat.startIndex, $scope.vsRepeat.endIndex);
654- _prevEndIndex = $scope.vsRepeat.endIndex;
655- $beforeContent.css(getLayoutProps(0));
656- $afterContent.css(getLayoutProps(0));
657- $scope.$emit('vsRenderAllDone');
658-
659- if ($scope.$root && !$scope.$root.$$phase) {
660- $scope.$digest();
661+ else if (ngRepeatChild.attr('data-ng-repeat-start')) {
662+ isNgRepeatStart = true;
663+ originalNgRepeatAttr = 'data-ng-repeat-start';
664+ ngRepeatExpression = ngRepeatChild.attr('data-ng-repeat-start');
665 }
666- });
667- });
668-
669- function reinitialize() {
670- _prevStartIndex = void 0;
671- _prevEndIndex = void 0;
672- _minStartIndex = originalLength;
673- _maxEndIndex = 0;
674- updateTotalSize($scope.vsRepeat.sizesCumulative[originalLength]);
675- updateInnerCollection();
676- $scope.$emit('vsRepeatReinitialized', $scope.vsRepeat.startIndex, $scope.vsRepeat.endIndex);
677- }
678-
679- function updateTotalSize(size) {
680- $scope.vsRepeat.totalSize = options.offsetBefore + size + options.offsetAfter;
681- }
682-
683- var _prevClientSize;
684-
685- function reinitOnClientHeightChange() {
686- var ch = getClientSize($scrollParent[0], clientSize);
687-
688- if (ch !== _prevClientSize) {
689- reinitialize();
690-
691- if ($scope.$root && !$scope.$root.$$phase) {
692- $scope.$digest();
693+ else {
694+ throw new Error('angular-vs-repeat: no ng-repeat directive on a child element');
695 }
696- }
697-
698- _prevClientSize = ch;
699- }
700
701- $scope.$watch(function () {
702- if (typeof window.requestAnimationFrame === 'function') {
703- window.requestAnimationFrame(reinitOnClientHeightChange);
704- } else {
705- reinitOnClientHeightChange();
706- }
707- });
708-
709- function binaryFind(array, threshold) {
710- var a = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
711- var b = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : array.length - 1;
712- var d = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
713-
714- if (array[a] === threshold) {
715- return [a, a, d];
716- }
717-
718- if (array[b] === threshold) {
719- return [b, b, d];
720- }
721-
722- if (b - a > 1) {
723- var m = Math.floor((a + b) / 2);
724-
725- if (array[m] > threshold) {
726- return binaryFind(array, threshold, a, m, d + 1);
727+ expressionMatches = /^\s*(\S+)\s+in\s+([\S\s]+?)(track\s+by\s+\S+)?$/.exec(ngRepeatExpression);
728+ lhs = expressionMatches[1];
729+ rhs = expressionMatches[2];
730+ rhsSuffix = expressionMatches[3];
731+
732+ if (isNgRepeatStart) {
733+ var index = 0;
734+ var repeaterElement = repeatContainer.children().eq(0);
735+ while(repeaterElement.attr('ng-repeat-end') == null && repeaterElement.attr('data-ng-repeat-end') == null) {
736+ index++;
737+ repeaterElement = repeatContainer.children().eq(index);
738+ childCloneHtml += repeaterElement[0].outerHTML;
739+ }
740 }
741
742- return binaryFind(array, threshold, m, b, d + 1);
743- }
744-
745- return [threshold > array[b] ? b : a, threshold < array[a] ? a : b, d];
746- }
747-
748- function updateInnerCollection() {
749- var $scrollPosition = getScrollPos($scrollParent[0], scrollPos);
750- var $clientSize = getClientSize($scrollParent[0], clientSize);
751-
752- if (options.debug) {
753- $clientSize /= 2;
754- }
755-
756- var scrollOffset = repeatContainer[0] === $scrollParent[0] ? 0 : getScrollOffset(repeatContainer[0], $scrollParent[0], options.horizontal);
757- var __startIndex = $scope.vsRepeat.startIndex;
758- var __endIndex = $scope.vsRepeat.endIndex;
759-
760- if (autosizingRequired && !options.size) {
761- __startIndex = 0;
762- __endIndex = 1;
763- } else {
764- _warnMismatch();
765-
766- var relativeScroll = $scrollPosition - options.offsetBefore - scrollOffset;
767+ repeatContainer.empty();
768+ return {
769+ pre: function($scope, $element, $attrs) {
770+ var repeatContainer = angular.isDefined($attrs.vsRepeatContainer) ? angular.element($element[0].querySelector($attrs.vsRepeatContainer)) : $element,
771+ childClone = angular.element(childCloneHtml),
772+ childTagName = childClone[0].tagName.toLowerCase(),
773+ originalCollection = [],
774+ originalLength,
775+ $$horizontal = typeof $attrs.vsHorizontal !== 'undefined',
776+ $beforeContent = angular.element('<' + childTagName + ' class="vs-repeat-before-content"></' + childTagName + '>'),
777+ $afterContent = angular.element('<' + childTagName + ' class="vs-repeat-after-content"></' + childTagName + '>'),
778+ autoSize = !$attrs.vsRepeat,
779+ sizesPropertyExists = !!$attrs.vsSize || !!$attrs.vsSizeProperty,
780+ $scrollParent = $attrs.vsScrollParent ?
781+ $attrs.vsScrollParent === 'window' ? angular.element(window) :
782+ closestElement.call(repeatContainer, $attrs.vsScrollParent) : repeatContainer,
783+ $$options = 'vsOptions' in $attrs ? $scope.$eval($attrs.vsOptions) : {},
784+ clientSize = $$horizontal ? 'clientWidth' : 'clientHeight',
785+ offsetSize = $$horizontal ? 'offsetWidth' : 'offsetHeight',
786+ scrollPos = $$horizontal ? 'scrollLeft' : 'scrollTop';
787+
788+ $scope.totalSize = 0;
789+ if (!('vsSize' in $attrs) && 'vsSizeProperty' in $attrs) {
790+ console.warn('vs-size-property attribute is deprecated. Please use vs-size attribute which also accepts angular expressions.');
791+ }
792
793- var _binaryFind = binaryFind($scope.vsRepeat.sizesCumulative, relativeScroll - options.scrollMargin);
794+ if ($scrollParent.length === 0) {
795+ throw 'Specified scroll parent selector did not match any element';
796+ }
797+ $scope.$scrollParent = $scrollParent;
798
799- var _binaryFind2 = _slicedToArray(_binaryFind, 1);
800+ if (sizesPropertyExists) {
801+ $scope.sizesCumulative = [];
802+ }
803
804- __startIndex = _binaryFind2[0];
805- __startIndex = Math.max(__startIndex, 0);
806+ //initial defaults
807+ $scope.elementSize = (+$attrs.vsRepeat) || getClientSize($scrollParent[0], clientSize) || 50;
808+ $scope.offsetBefore = 0;
809+ $scope.offsetAfter = 0;
810+ $scope.scrollMargin = 0;
811+ $scope.excess = 2;
812
813- var _binaryFind3 = binaryFind($scope.vsRepeat.sizesCumulative, relativeScroll + options.scrollMargin + $clientSize, __startIndex);
814+ if ($$horizontal) {
815+ $beforeContent.css('height', '100%');
816+ $afterContent.css('height', '100%');
817+ }
818+ else {
819+ $beforeContent.css('width', '100%');
820+ $afterContent.css('width', '100%');
821+ }
822
823- var _binaryFind4 = _slicedToArray(_binaryFind3, 2);
824+ Object.keys(attributesDictionary).forEach(function(key) {
825+ if ($attrs[key]) {
826+ $attrs.$observe(key, function(value) {
827+ // '+' serves for getting a number from the string as the attributes are always strings
828+ $scope[attributesDictionary[key]] = +value;
829+ reinitialize();
830+ });
831+ }
832+ });
833+
834+
835+ $scope.$watchCollection(rhs, function(coll) {
836+ originalCollection = coll || [];
837+ refresh();
838+ });
839+
840+ function refresh() {
841+ if (!originalCollection || originalCollection.length < 1) {
842+ $scope[collectionName] = [];
843+ originalLength = 0;
844+ $scope.sizesCumulative = [0];
845+ }
846+ else {
847+ originalLength = originalCollection.length;
848+ if (sizesPropertyExists) {
849+ $scope.sizes = originalCollection.map(function(item) {
850+ var s = $scope.$new(false);
851+ angular.extend(s, item);
852+ s[lhs] = item;
853+ var size = ($attrs.vsSize || $attrs.vsSizeProperty) ?
854+ s.$eval($attrs.vsSize || $attrs.vsSizeProperty) :
855+ $scope.elementSize;
856+ s.$destroy();
857+ return size;
858+ });
859+ var sum = 0;
860+ $scope.sizesCumulative = $scope.sizes.map(function(size) {
861+ var res = sum;
862+ sum += size;
863+ return res;
864+ });
865+ $scope.sizesCumulative.push(sum);
866+ }
867+ else {
868+ setAutoSize();
869+ }
870+ }
871+
872+ reinitialize();
873+ }
874
875- __endIndex = _binaryFind4[1];
876- __endIndex = Math.min(__endIndex, originalLength);
877- }
878+ function setAutoSize() {
879+ if (autoSize) {
880+ $scope.$$postDigest(function() {
881+ if (repeatContainer[0].offsetHeight || repeatContainer[0].offsetWidth) { // element is visible
882+ var children = repeatContainer.children(),
883+ i = 0,
884+ gotSomething = false,
885+ insideStartEndSequence = false;
886+
887+ while (i < children.length) {
888+ if (children[i].attributes[originalNgRepeatAttr] != null || insideStartEndSequence) {
889+ if (!gotSomething) {
890+ $scope.elementSize = 0;
891+ }
892+
893+ gotSomething = true;
894+ if (children[i][offsetSize]) {
895+ $scope.elementSize += children[i][offsetSize];
896+ }
897+
898+ if (isNgRepeatStart) {
899+ if (children[i].attributes['ng-repeat-end'] != null || children[i].attributes['data-ng-repeat-end'] != null) {
900+ break;
901+ }
902+ else {
903+ insideStartEndSequence = true;
904+ }
905+ }
906+ else {
907+ break;
908+ }
909+ }
910+ i++;
911+ }
912+
913+ if (gotSomething) {
914+ reinitialize();
915+ autoSize = false;
916+ if ($scope.$root && !$scope.$root.$$phase) {
917+ $scope.$apply();
918+ }
919+ }
920+ }
921+ else {
922+ var dereg = $scope.$watch(function() {
923+ if (repeatContainer[0].offsetHeight || repeatContainer[0].offsetWidth) {
924+ dereg();
925+ setAutoSize();
926+ }
927+ });
928+ }
929+ });
930+ }
931+ }
932
933- _minStartIndex = Math.min(__startIndex, _minStartIndex);
934- _maxEndIndex = Math.max(__endIndex, _maxEndIndex);
935- $scope.vsRepeat.startIndex = options.latch ? _minStartIndex : __startIndex;
936- $scope.vsRepeat.endIndex = options.latch ? _maxEndIndex : __endIndex; // Move to the end of the collection if we are now past it
937+ function getLayoutProp() {
938+ var layoutPropPrefix = childTagName === 'tr' ? '' : 'min-';
939+ var layoutProp = $$horizontal ? layoutPropPrefix + 'width' : layoutPropPrefix + 'height';
940+ return layoutProp;
941+ }
942
943- if (_maxEndIndex < $scope.vsRepeat.startIndex) $scope.vsRepeat.startIndex = _maxEndIndex;
944- var digestRequired = false;
945+ childClone.eq(0).attr(originalNgRepeatAttr, lhs + ' in ' + collectionName + (rhsSuffix ? ' ' + rhsSuffix : ''));
946+ childClone.addClass('vs-repeat-repeated-element');
947
948- if (_prevStartIndex == null) {
949- digestRequired = true;
950- } else if (_prevEndIndex == null) {
951- digestRequired = true;
952- }
953+ repeatContainer.append($beforeContent);
954+ repeatContainer.append(childClone);
955+ $compile(childClone)($scope);
956+ repeatContainer.append($afterContent);
957
958- if (!digestRequired) {
959- if (options.hunked) {
960- if (Math.abs($scope.vsRepeat.startIndex - _prevStartIndex) >= options.hunkSize || $scope.vsRepeat.startIndex === 0 && _prevStartIndex !== 0) {
961- digestRequired = true;
962- } else if (Math.abs($scope.vsRepeat.endIndex - _prevEndIndex) >= options.hunkSize || $scope.vsRepeat.endIndex === originalLength && _prevEndIndex !== originalLength) {
963- digestRequired = true;
964- }
965- } else {
966- digestRequired = $scope.vsRepeat.startIndex !== _prevStartIndex || $scope.vsRepeat.endIndex !== _prevEndIndex;
967- }
968- }
969+ $scope.startIndex = 0;
970+ $scope.endIndex = 0;
971
972- if (digestRequired) {
973- $scope[collectionName] = originalCollection.slice($scope.vsRepeat.startIndex, $scope.vsRepeat.endIndex); // Emit the event
974+ function scrollHandler() {
975+ if (updateInnerCollection()) {
976+ $scope.$digest();
977
978- $scope.$emit('vsRepeatInnerCollectionUpdated', $scope.vsRepeat.startIndex, $scope.vsRepeat.endIndex, _prevStartIndex, _prevEndIndex);
979- var triggerIndex;
980+ var expectedSize = sizesPropertyExists ?
981+ $scope.sizesCumulative[originalLength] :
982+ $scope.elementSize * originalLength;
983
984- if (options.scrolledToEnd) {
985- triggerIndex = originalCollection.length - options.scrolledToEndOffset;
986-
987- if ($scope.vsRepeat.endIndex >= triggerIndex && _prevEndIndex < triggerIndex || originalCollection.length && $scope.vsRepeat.endIndex === originalCollection.length) {
988- $scope.$eval(options.scrolledToEnd);
989- }
990- }
991+ if (expectedSize !== $element[0].clientHeight) {
992+ console.warn('vsRepeat: size mismatch. Expected size ' + expectedSize + 'px whereas actual size is ' + $element[0].clientHeight + 'px. Fix vsSize on element:', $element[0]);
993+ }
994+ }
995+ }
996
997- if (options.scrolledToBeginning) {
998- triggerIndex = options.scrolledToBeginningOffset;
999+ $scrollParent.on('scroll', scrollHandler);
1000+
1001+ function onWindowResize() {
1002+ if (typeof $attrs.vsAutoresize !== 'undefined') {
1003+ autoSize = true;
1004+ setAutoSize();
1005+ if ($scope.$root && !$scope.$root.$$phase) {
1006+ $scope.$apply();
1007+ }
1008+ }
1009+ if (updateInnerCollection()) {
1010+ $scope.$apply();
1011+ }
1012+ }
1013
1014- if ($scope.vsRepeat.startIndex <= triggerIndex && _prevStartIndex > $scope.vsRepeat.startIndex) {
1015- $scope.$eval(options.scrolledToBeginning);
1016- }
1017- }
1018+ angular.element(window).on('resize', onWindowResize);
1019+ $scope.$on('$destroy', function() {
1020+ angular.element(window).off('resize', onWindowResize);
1021+ $scrollParent.off('scroll', scrollHandler);
1022+ });
1023+
1024+ $scope.$on('vsRepeatTrigger', refresh);
1025+
1026+ $scope.$on('vsRepeatResize', function() {
1027+ autoSize = true;
1028+ setAutoSize();
1029+ });
1030+
1031+ var _prevStartIndex,
1032+ _prevEndIndex,
1033+ _minStartIndex,
1034+ _maxEndIndex;
1035+
1036+ $scope.$on('vsRenderAll', function() {//e , quantum) {
1037+ if($$options.latch) {
1038+ setTimeout(function() {
1039+ // var __endIndex = Math.min($scope.endIndex + (quantum || 1), originalLength);
1040+ var __endIndex = originalLength;
1041+ _maxEndIndex = Math.max(__endIndex, _maxEndIndex);
1042+ $scope.endIndex = $$options.latch ? _maxEndIndex : __endIndex;
1043+ $scope[collectionName] = originalCollection.slice($scope.startIndex, $scope.endIndex);
1044+ _prevEndIndex = $scope.endIndex;
1045+
1046+ $scope.$$postDigest(function() {
1047+ $beforeContent.css(getLayoutProp(), 0);
1048+ $afterContent.css(getLayoutProp(), 0);
1049+ });
1050+
1051+ $scope.$apply(function() {
1052+ $scope.$emit('vsRenderAllDone');
1053+ });
1054+ });
1055+ }
1056+ });
1057+
1058+ function reinitialize() {
1059+ _prevStartIndex = void 0;
1060+ _prevEndIndex = void 0;
1061+ _minStartIndex = originalLength;
1062+ _maxEndIndex = 0;
1063+ updateTotalSize(sizesPropertyExists ?
1064+ $scope.sizesCumulative[originalLength] :
1065+ $scope.elementSize * originalLength
1066+ );
1067+ updateInnerCollection();
1068+
1069+ $scope.$emit('vsRepeatReinitialized', $scope.startIndex, $scope.endIndex);
1070+ }
1071
1072- _prevStartIndex = $scope.vsRepeat.startIndex;
1073- _prevEndIndex = $scope.vsRepeat.endIndex;
1074- var o1 = $scope.vsRepeat.sizesCumulative[$scope.vsRepeat.startIndex] + options.offsetBefore;
1075- var o2 = $scope.vsRepeat.sizesCumulative[$scope.vsRepeat.startIndex + $scope[collectionName].length] + options.offsetBefore;
1076- var total = $scope.vsRepeat.totalSize;
1077- $beforeContent.css(getLayoutProps(o1 + 'px'));
1078- $afterContent.css(getLayoutProps(total - o2 + 'px'));
1079- }
1080+ function updateTotalSize(size) {
1081+ $scope.totalSize = $scope.offsetBefore + size + $scope.offsetAfter;
1082+ }
1083
1084- return digestRequired;
1085- }
1086+ var _prevClientSize;
1087+ function reinitOnClientHeightChange() {
1088+ var ch = getClientSize($scrollParent[0], clientSize);
1089+ if (ch !== _prevClientSize) {
1090+ reinitialize();
1091+ if ($scope.$root && !$scope.$root.$$phase) {
1092+ $scope.$apply();
1093+ }
1094+ }
1095+ _prevClientSize = ch;
1096+ }
1097
1098- function _warnMismatch() {
1099- $scope.$$postDigest(function () {
1100- window.requestAnimationFrame(function () {
1101- var expectedSize = $scope.vsRepeat.sizesCumulative[originalLength];
1102- var compStyle = window.getComputedStyle(repeatContainer[0]);
1103- var paddings = options.horizontal ? ['paddingLeft', 'paddingRight'] : ['paddingTop', 'paddingBottom'];
1104- var containerSize = repeatContainer[0][scrollSize] - paddings.reduce(function (acc, prop) {
1105- return acc + Number(compStyle[prop].slice(0, -2));
1106- }, 0);
1107-
1108- if (repeatContainer[0][scrollSize] && expectedSize !== containerSize) {
1109- console.warn('vsRepeat: size mismatch. Expected size ' + expectedSize + 'px whereas actual size is ' + containerSize + 'px. Fix vsSize on element:', $element[0]);
1110- }
1111- });
1112- });
1113+ $scope.$watch(function() {
1114+ if (typeof window.requestAnimationFrame === 'function') {
1115+ window.requestAnimationFrame(reinitOnClientHeightChange);
1116+ }
1117+ else {
1118+ reinitOnClientHeightChange();
1119+ }
1120+ });
1121+
1122+ function updateInnerCollection() {
1123+ var $scrollPosition = getScrollPos($scrollParent[0], scrollPos);
1124+ var $clientSize = getClientSize($scrollParent[0], clientSize);
1125+
1126+ var scrollOffset = repeatContainer[0] === $scrollParent[0] ? 0 : getScrollOffset(
1127+ repeatContainer[0],
1128+ $scrollParent[0],
1129+ $$horizontal
1130+ );
1131+
1132+ var __startIndex = $scope.startIndex;
1133+ var __endIndex = $scope.endIndex;
1134+
1135+ if (sizesPropertyExists) {
1136+ __startIndex = 0;
1137+ while ($scope.sizesCumulative[__startIndex] < $scrollPosition - $scope.offsetBefore - scrollOffset - $scope.scrollMargin) {
1138+ __startIndex++;
1139+ }
1140+ if (__startIndex > 0) { __startIndex--; }
1141+
1142+ // Adjust the start index according to the excess
1143+ __startIndex = Math.max(
1144+ Math.floor(__startIndex - $scope.excess / 2),
1145+ 0
1146+ );
1147+
1148+ __endIndex = __startIndex;
1149+ while ($scope.sizesCumulative[__endIndex] < $scrollPosition - $scope.offsetBefore - scrollOffset + $scope.scrollMargin + $clientSize) {
1150+ __endIndex++;
1151+ }
1152+
1153+ // Adjust the end index according to the excess
1154+ __endIndex = Math.min(
1155+ Math.ceil(__endIndex + $scope.excess / 2),
1156+ originalLength
1157+ );
1158+ }
1159+ else {
1160+ __startIndex = Math.max(
1161+ Math.floor(
1162+ ($scrollPosition - $scope.offsetBefore - scrollOffset) / $scope.elementSize
1163+ ) - $scope.excess / 2,
1164+ 0
1165+ );
1166+
1167+ __endIndex = Math.min(
1168+ __startIndex + Math.ceil(
1169+ $clientSize / $scope.elementSize
1170+ ) + $scope.excess,
1171+ originalLength
1172+ );
1173+ }
1174+
1175+ _minStartIndex = Math.min(__startIndex, _minStartIndex);
1176+ _maxEndIndex = Math.max(__endIndex, _maxEndIndex);
1177+
1178+ $scope.startIndex = $$options.latch ? _minStartIndex : __startIndex;
1179+ $scope.endIndex = $$options.latch ? _maxEndIndex : __endIndex;
1180+
1181+ // Move to the end of the collection if we are now past it
1182+ if (_maxEndIndex < $scope.startIndex)
1183+ $scope.startIndex = _maxEndIndex;
1184+
1185+ var digestRequired = false;
1186+ if (_prevStartIndex == null) {
1187+ digestRequired = true;
1188+ }
1189+ else if (_prevEndIndex == null) {
1190+ digestRequired = true;
1191+ }
1192+
1193+ if (!digestRequired) {
1194+ if ($$options.hunked) {
1195+ if (Math.abs($scope.startIndex - _prevStartIndex) >= $scope.excess / 2 ||
1196+ ($scope.startIndex === 0 && _prevStartIndex !== 0)) {
1197+ digestRequired = true;
1198+ }
1199+ else if (Math.abs($scope.endIndex - _prevEndIndex) >= $scope.excess / 2 ||
1200+ ($scope.endIndex === originalLength && _prevEndIndex !== originalLength)) {
1201+ digestRequired = true;
1202+ }
1203+ }
1204+ else {
1205+ digestRequired = $scope.startIndex !== _prevStartIndex ||
1206+ $scope.endIndex !== _prevEndIndex;
1207+ }
1208+ }
1209+
1210+ if (digestRequired) {
1211+ $scope[collectionName] = originalCollection.slice($scope.startIndex, $scope.endIndex);
1212+
1213+ // Emit the event
1214+ $scope.$emit('vsRepeatInnerCollectionUpdated', $scope.startIndex, $scope.endIndex, _prevStartIndex, _prevEndIndex);
1215+ var triggerIndex;
1216+ if ($attrs.vsScrolledToEnd) {
1217+ triggerIndex = originalCollection.length - ($scope.scrolledToEndOffset || 0);
1218+ if (($scope.endIndex >= triggerIndex && _prevEndIndex < triggerIndex) || (originalCollection.length && $scope.endIndex === originalCollection.length)) {
1219+ $scope.$eval($attrs.vsScrolledToEnd);
1220+ }
1221+ }
1222+ if ($attrs.vsScrolledToBeginning) {
1223+ triggerIndex = $scope.scrolledToBeginningOffset || 0;
1224+ if (($scope.startIndex <= triggerIndex && _prevStartIndex > $scope.startIndex)) {
1225+ $scope.$eval($attrs.vsScrolledToBeginning);
1226+ }
1227+ }
1228+
1229+ _prevStartIndex = $scope.startIndex;
1230+ _prevEndIndex = $scope.endIndex;
1231+
1232+ var offsetCalculationString = sizesPropertyExists ?
1233+ '(sizesCumulative[$index + startIndex] + offsetBefore)' :
1234+ '(($index + startIndex) * elementSize + offsetBefore)';
1235+
1236+ var parsed = $parse(offsetCalculationString);
1237+ var o1 = parsed($scope, {$index: 0});
1238+ var o2 = parsed($scope, {$index: $scope[collectionName].length});
1239+ var total = $scope.totalSize;
1240+
1241+ $beforeContent.css(getLayoutProp(), o1 + 'px');
1242+ $afterContent.css(getLayoutProp(), (total - o2) + 'px');
1243+ }
1244+
1245+ return digestRequired;
1246+ }
1247+ }
1248+ };
1249 }
1250- }
1251 };
1252- }
1253- };
1254- }]);
1255- angular.element(document.head).append("<style id=\"angular-vs-repeat-style\">\n\t \t.vs-repeat-debug-element {\n top: 50%;\n left: 0;\n right: 0;\n height: 1px;\n background: red;\n z-index: 99999999;\n box-shadow: 0 0 20px red;\n }\n\n .vs-repeat-debug-element + .vs-repeat-debug-element {\n display: none;\n }\n\n .vs-repeat-before-content,\n .vs-repeat-after-content {\n border: none !important;\n padding: 0 !important;\n }\n </style>");
1256+ }]);
1257
1258- if (typeof module !== 'undefined' && module.exports) {
1259- module.exports = vsRepeatModule.name;
1260- }
1261-})(window, window.angular);
1262\ No newline at end of file
1263+ if (typeof module !== 'undefined' && module.exports) {
1264+ module.exports = vsRepeatModule.name;
1265+ }
1266+})(window, window.angular);
1267diff --git a/src/maasserver/static/js/bundle/vendor-min.js b/src/maasserver/static/js/bundle/vendor-min.js
1268index 26725ae..36bca11 100644
1269--- a/src/maasserver/static/js/bundle/vendor-min.js
1270+++ b/src/maasserver/static/js/bundle/vendor-min.js
1271@@ -1,2 +1,2 @@
1272-!function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={i:moduleId,l:!1,exports:{}};return modules[moduleId].call(module.exports,module,module.exports,__webpack_require__),module.l=!0,module.exports}__webpack_require__.m=modules,__webpack_require__.c=installedModules,__webpack_require__.d=function(exports,name,getter){__webpack_require__.o(exports,name)||Object.defineProperty(exports,name,{configurable:!1,enumerable:!0,get:getter})},__webpack_require__.r=function(exports){Object.defineProperty(exports,"__esModule",{value:!0})},__webpack_require__.n=function(module){var getter=module&&module.__esModule?function(){return module.default}:function(){return module};return __webpack_require__.d(getter,"a",getter),getter},__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)},__webpack_require__.p="",__webpack_require__(__webpack_require__.s=0)}({"./src/maasserver/static/js/angular/3rdparty/ng-tags-input.js":function(module,exports){!function(){"use strict";var KEYS_backspace=8,KEYS_tab=9,KEYS_enter=13,KEYS_escape=27,KEYS_space=32,KEYS_up=38,KEYS_down=40,KEYS_left=37,KEYS_right=39,KEYS_delete=46,KEYS_comma=188,SUPPORTED_INPUT_TYPES=["text","email","url"],tagsInput=angular.module("ngTagsInput",[]);tagsInput.directive("tagsInput",["$timeout","$document","$window","tagsInputConfig","tiUtil",function($timeout,$document,$window,tagsInputConfig,tiUtil){function validateType(type){return-1!==SUPPORTED_INPUT_TYPES.indexOf(type)}return{restrict:"E",require:"ngModel",scope:{tags:"=ngModel",onTagAdding:"&",onTagAdded:"&",onInvalidTag:"&",onTagRemoving:"&",onTagRemoved:"&"},replace:!1,transclude:!0,templateUrl:"ngTagsInput/tags-input.html",controller:["$scope","$attrs","$element",function($scope,$attrs,$element){$scope.events=tiUtil.simplePubSub(),tagsInputConfig.load("tagsInput",$scope,$attrs,{template:[String,"ngTagsInput/tag-item.html"],type:[String,"text",validateType],placeholder:[String,"Add a tag"],tabindex:[Number,null],removeTagSymbol:[String,String.fromCharCode(215)],replaceSpacesWithDashes:[Boolean,!0],minLength:[Number,3],maxLength:[Number,9007199254740991],addOnEnter:[Boolean,!0],addOnSpace:[Boolean,!1],addOnComma:[Boolean,!0],addOnBlur:[Boolean,!0],addOnPaste:[Boolean,!1],pasteSplitPattern:[RegExp,/,/],allowedTagsPattern:[RegExp,/.+/],enableEditingLastTag:[Boolean,!1],minTags:[Number,0],maxTags:[Number,9007199254740991],displayProperty:[String,"text"],keyProperty:[String,""],allowLeftoverText:[Boolean,!1],addFromAutocompleteOnly:[Boolean,!1],spellcheck:[Boolean,!0]}),$scope.tagList=new function(options,events,onTagAdding,onTagRemoving){var getTagText,setTagText,tagIsValid,self={};return getTagText=function(tag){return tiUtil.safeToString(tag[options.displayProperty])},setTagText=function(tag,text){tag[options.displayProperty]=text},tagIsValid=function(tag){var tagText=getTagText(tag);return tagText&&tagText.length>=options.minLength&&tagText.length<=options.maxLength&&options.allowedTagsPattern.test(tagText)&&!tiUtil.findInObjectArray(self.items,tag,options.keyProperty||options.displayProperty)&&onTagAdding({$tag:tag})},self.items=[],self.addText=function(text){var tag={};return setTagText(tag,text),self.add(tag)},self.add=function(tag){var tagText=getTagText(tag);return options.replaceSpacesWithDashes&&(tagText=tiUtil.replaceSpacesWithDashes(tagText)),setTagText(tag,tagText),tagIsValid(tag)?(self.items.push(tag),events.trigger("tag-added",{$tag:tag})):tagText&&events.trigger("invalid-tag",{$tag:tag}),tag},self.remove=function(index){var tag=self.items[index];if(onTagRemoving({$tag:tag}))return self.items.splice(index,1),self.clearSelection(),events.trigger("tag-removed",{$tag:tag}),tag},self.select=function(index){index<0?index=self.items.length-1:index>=self.items.length&&(index=0),self.index=index,self.selected=self.items[index]},self.selectPrior=function(){self.select(--self.index)},self.selectNext=function(){self.select(++self.index)},self.removeSelected=function(){return self.remove(self.index)},self.clearSelection=function(){self.selected=null,self.index=-1},self.clearSelection(),self}($scope.options,$scope.events,tiUtil.handleUndefinedResult($scope.onTagAdding,!0),tiUtil.handleUndefinedResult($scope.onTagRemoving,!0)),this.registerAutocomplete=function(){$element.find("input");return{addTag:function(tag){return $scope.tagList.add(tag)},focusInput:function(){},getTags:function(){return $scope.tags},getCurrentTagText:function(){return $scope.newTag.text},getOptions:function(){return $scope.options},on:function(name,handler){return $scope.events.on(name,handler),this}}},this.registerTagItem=function(){return{getOptions:function(){return $scope.options},removeTag:function(index){$scope.disabled||$scope.tagList.remove(index)}}}}],link:function(scope,element,attrs,ngModelCtrl){var setElementValidity,hotkeys=[KEYS_enter,KEYS_comma,KEYS_space,KEYS_backspace,KEYS_delete,KEYS_left,KEYS_right],tagList=scope.tagList,events=scope.events,options=scope.options,input=element.find("input"),validationOptions=["minTags","maxTags","allowLeftoverText"];setElementValidity=function(){ngModelCtrl.$setValidity("maxTags",scope.tags.length<=options.maxTags),ngModelCtrl.$setValidity("minTags",scope.tags.length>=options.minTags),ngModelCtrl.$setValidity("leftoverText",!(!scope.hasFocus&&!options.allowLeftoverText)||!scope.newTag.text)},ngModelCtrl.$isEmpty=function(value){return!value||!value.length},scope.newTag={text:"",invalid:null,setText:function(value){this.text=value,events.trigger("input-change",value)}},scope.track=function(tag){return tag[options.keyProperty||options.displayProperty]},scope.$watch("tags",function(value){scope.tags=tiUtil.makeObjectArray(value,options.displayProperty),tagList.items=scope.tags}),scope.$watch("tags.length",function(){setElementValidity()}),attrs.$observe("disabled",function(value){scope.disabled=value}),scope.eventHandlers={input:{change:function(text){events.trigger("input-change",text)},keydown:function($event){events.trigger("input-keydown",$event)},focus:function(){scope.hasFocus||(scope.hasFocus=!0,events.trigger("input-focus"))},blur:function(){$timeout(function(){var activeElement=$document.prop("activeElement"),lostFocusToBrowserWindow=activeElement===input[0],lostFocusToChildElement=element[0].contains(activeElement);!lostFocusToBrowserWindow&&lostFocusToChildElement||(scope.hasFocus=!1,events.trigger("input-blur"))})},paste:function($event){$event.getTextData=function(){var clipboardData=$event.clipboardData||$event.originalEvent&&$event.originalEvent.clipboardData;return clipboardData?clipboardData.getData("text/plain"):$window.clipboardData.getData("Text")},events.trigger("input-paste",$event)}},host:{click:function(){scope.disabled}}},events.on("tag-added",scope.onTagAdded).on("invalid-tag",scope.onInvalidTag).on("tag-removed",scope.onTagRemoved).on("tag-added",function(){scope.newTag.setText("")}).on("tag-added tag-removed",function(){ngModelCtrl.$setViewValue(scope.tags)}).on("invalid-tag",function(){scope.newTag.invalid=!0}).on("option-change",function(e){-1!==validationOptions.indexOf(e.name)&&setElementValidity()}).on("input-change",function(){tagList.clearSelection(),scope.newTag.invalid=null}).on("input-focus",function(){element.triggerHandler("focus"),ngModelCtrl.$setValidity("leftoverText",!0)}).on("input-blur",function(){options.addOnBlur&&!options.addFromAutocompleteOnly&&tagList.addText(scope.newTag.text),element.triggerHandler("blur"),setElementValidity()}).on("input-keydown",function(event){var shouldAdd,shouldRemove,shouldSelect,shouldEditLastTag,key=event.keyCode,addKeys={};if(!(event.shiftKey||event.altKey||event.ctrlKey||event.metaKey)&&-1!==hotkeys.indexOf(key)){if(addKeys[KEYS_enter]=options.addOnEnter,addKeys[KEYS_comma]=options.addOnComma,addKeys[KEYS_space]=options.addOnSpace,shouldAdd=!options.addFromAutocompleteOnly&&addKeys[key],shouldRemove=(key===KEYS_backspace||key===KEYS_delete)&&tagList.selected,shouldEditLastTag=key===KEYS_backspace&&0===scope.newTag.text.length&&options.enableEditingLastTag,shouldSelect=(key===KEYS_backspace||key===KEYS_left||key===KEYS_right)&&0===scope.newTag.text.length&&!options.enableEditingLastTag,shouldAdd)tagList.addText(scope.newTag.text);else if(shouldEditLastTag){var tag;tagList.selectPrior(),(tag=tagList.removeSelected())&&scope.newTag.setText(tag[options.displayProperty])}else shouldRemove?tagList.removeSelected():shouldSelect&&(key===KEYS_left||key===KEYS_backspace?tagList.selectPrior():key===KEYS_right&&tagList.selectNext());(shouldAdd||shouldSelect||shouldRemove||shouldEditLastTag)&&event.preventDefault()}}).on("input-paste",function(event){if(options.addOnPaste){var tags=event.getTextData().split(options.pasteSplitPattern);tags.length>1&&(tags.forEach(function(tag){tagList.addText(tag)}),event.preventDefault())}})}}}]),tagsInput.directive("tiTagItem",["tiUtil",function(tiUtil){return{restrict:"E",require:"^tagsInput",template:'<ng-include src="$$template"></ng-include>',scope:{data:"="},link:function(scope,element,attrs,tagsInputCtrl){var tagsInput=tagsInputCtrl.registerTagItem(),options=tagsInput.getOptions();scope.$$template=options.template,scope.$$removeTagSymbol=options.removeTagSymbol,scope.$getDisplayText=function(){return tiUtil.safeToString(scope.data[options.displayProperty])},scope.$removeTag=function(){tagsInput.removeTag(scope.$index)},scope.$watch("$parent.$index",function(value){scope.$index=value})}}}]),tagsInput.directive("autoComplete",["$document","$timeout","$sce","$q","tagsInputConfig","tiUtil",function($document,$timeout,$sce,$q,tagsInputConfig,tiUtil){return{restrict:"E",require:"^tagsInput",scope:{source:"&"},templateUrl:"ngTagsInput/auto-complete.html",controller:["$scope","$element","$attrs",function($scope,$element,$attrs){$scope.events=tiUtil.simplePubSub(),tagsInputConfig.load("autoComplete",$scope,$attrs,{template:[String,"ngTagsInput/auto-complete-match.html"],debounceDelay:[Number,100],minLength:[Number,3],highlightMatchedText:[Boolean,!0],maxResultsToShow:[Number,10],loadOnDownArrow:[Boolean,!1],loadOnEmpty:[Boolean,!1],loadOnFocus:[Boolean,!1],selectFirstMatch:[Boolean,!0],displayProperty:[String,""]}),$scope.suggestionList=new function(loadFn,options,events){var getDifference,lastPromise,getTagId,self={};return getTagId=function(){return options.tagsInput.keyProperty||options.tagsInput.displayProperty},getDifference=function(array1,array2){return array1.filter(function(item){return!tiUtil.findInObjectArray(array2,item,getTagId(),function(a,b){return options.tagsInput.replaceSpacesWithDashes&&(a=tiUtil.replaceSpacesWithDashes(a),b=tiUtil.replaceSpacesWithDashes(b)),tiUtil.defaultComparer(a,b)})})},self.reset=function(){lastPromise=null,self.items=[],self.visible=!1,self.index=-1,self.selected=null,self.query=null},self.show=function(){options.selectFirstMatch?self.select(0):self.selected=null,self.visible=!0},self.load=tiUtil.debounce(function(query,tags){self.query=query;var promise=$q.when(loadFn({$query:query}));lastPromise=promise,promise.then(function(items){promise===lastPromise&&(items=tiUtil.makeObjectArray(items.data||items,getTagId()),items=getDifference(items,tags),self.items=items.slice(0,options.maxResultsToShow),self.items.length>0?self.show():self.reset())})},options.debounceDelay),self.selectNext=function(){self.select(++self.index)},self.selectPrior=function(){self.select(--self.index)},self.select=function(index){index<0?index=self.items.length-1:index>=self.items.length&&(index=0),self.index=index,self.selected=self.items[index],events.trigger("suggestion-selected",index)},self.reset(),self}($scope.source,$scope.options,$scope.events),this.registerAutocompleteMatch=function(){return{getOptions:function(){return $scope.options},getQuery:function(){return $scope.suggestionList.query}}}}],link:function(scope,element,attrs,tagsInputCtrl){var shouldLoadSuggestions,hotkeys=[KEYS_enter,KEYS_tab,KEYS_escape,KEYS_up,KEYS_down],suggestionList=scope.suggestionList,tagsInput=tagsInputCtrl.registerAutocomplete(),options=scope.options,events=scope.events;options.tagsInput=tagsInput.getOptions(),shouldLoadSuggestions=function(value){return value&&value.length>=options.minLength||!value&&options.loadOnEmpty},scope.addSuggestionByIndex=function(index){suggestionList.select(index),scope.addSuggestion()},scope.addSuggestion=function(){var added=!1;return suggestionList.selected&&(tagsInput.addTag(angular.copy(suggestionList.selected)),suggestionList.reset(),tagsInput.focusInput(),added=!0),added},scope.track=function(item){return item[options.tagsInput.keyProperty||options.tagsInput.displayProperty]},tagsInput.on("tag-added invalid-tag input-blur",function(){suggestionList.reset()}).on("input-change",function(value){shouldLoadSuggestions(value)?suggestionList.load(value,tagsInput.getTags()):suggestionList.reset()}).on("input-focus",function(){var value=tagsInput.getCurrentTagText();options.loadOnFocus&&shouldLoadSuggestions(value)&&suggestionList.load(value,tagsInput.getTags())}).on("input-keydown",function(event){var key=event.keyCode,handled=!1;if(-1!==hotkeys.indexOf(key))return suggestionList.visible?key===KEYS_down?(suggestionList.selectNext(),handled=!0):key===KEYS_up?(suggestionList.selectPrior(),handled=!0):key===KEYS_escape?(suggestionList.reset(),handled=!0):key!==KEYS_enter&&key!==KEYS_tab||(handled=scope.addSuggestion()):key===KEYS_down&&scope.options.loadOnDownArrow&&(suggestionList.load(tagsInput.getCurrentTagText(),tagsInput.getTags()),handled=!0),handled?(event.preventDefault(),event.stopImmediatePropagation(),!1):void 0}),events.on("suggestion-selected",function(index){!function(root,index){var element=root.find("li").eq(index),parent=element.parent(),elementTop=element.prop("offsetTop"),elementHeight=element.prop("offsetHeight"),parentHeight=parent.prop("clientHeight"),parentScrollTop=parent.prop("scrollTop");elementTop<parentScrollTop?parent.prop("scrollTop",elementTop):elementTop+elementHeight>parentHeight+parentScrollTop&&parent.prop("scrollTop",elementTop+elementHeight-parentHeight)}(element,index)})}}}]),tagsInput.directive("tiAutocompleteMatch",["$sce","tiUtil",function($sce,tiUtil){return{restrict:"E",require:"^autoComplete",template:'<ng-include src="$$template"></ng-include>',scope:{data:"="},link:function(scope,element,attrs,autoCompleteCtrl){var autoComplete=autoCompleteCtrl.registerAutocompleteMatch(),options=autoComplete.getOptions();scope.$$template=options.template,scope.$index=scope.$parent.$index,scope.$highlight=function(text){return options.highlightMatchedText&&(text=tiUtil.safeHighlight(text,autoComplete.getQuery())),$sce.trustAsHtml(text)},scope.$getDisplayText=function(){return tiUtil.safeToString(scope.data[options.displayProperty||options.tagsInput.displayProperty])}}}}]),tagsInput.directive("tiTranscludeAppend",function(){return function(scope,element,attrs,ctrl,transcludeFn){transcludeFn(function(clone){element.append(clone)})}}),tagsInput.directive("tiAutosize",["tagsInputConfig",function(tagsInputConfig){return{restrict:"A",require:"ngModel",link:function(scope,element,attrs,ctrl){var span,resize,threshold=tagsInputConfig.getTextAutosizeThreshold();(span=angular.element('<span class="input"></span>')).css("display","none").css("visibility","hidden").css("width","auto").css("white-space","pre"),element.parent().append(span),resize=function(originalValue){var width,value=originalValue;return angular.isString(value)&&0===value.length&&(value=attrs.placeholder),value&&(span.text(value),span.css("display",""),width=span.prop("offsetWidth"),span.css("display","none")),element.css("width",width?width+threshold+"px":""),originalValue},ctrl.$parsers.unshift(resize),ctrl.$formatters.unshift(resize),attrs.$observe("placeholder",function(value){ctrl.$modelValue||resize(value)})}}}]),tagsInput.directive("tiBindAttrs",function(){return function(scope,element,attrs){scope.$watch(attrs.tiBindAttrs,function(value){angular.forEach(value,function(value,key){"type"===key?element[0].type=value:attrs.$set(key,value)})},!0)}}),tagsInput.provider("tagsInputConfig",function(){var globalDefaults={},interpolationStatus={},autosizeThreshold=3;this.setDefaults=function(directive,defaults){return globalDefaults[directive]=defaults,this},this.setActiveInterpolation=function(directive,options){return interpolationStatus[directive]=options,this},this.setTextAutosizeThreshold=function(threshold){return autosizeThreshold=threshold,this},this.$get=["$interpolate",function($interpolate){var converters={};return converters[String]=function(value){return value},converters[Number]=function(value){return parseInt(value,10)},converters[Boolean]=function(value){return"true"===value.toLowerCase()},converters[RegExp]=function(value){return new RegExp(value)},{load:function(directive,scope,attrs,options){var defaultValidator=function(){return!0};scope.options={},angular.forEach(options,function(value,key){var type,localDefault,validator,converter,getDefault,updateValue;type=value[0],localDefault=value[1],validator=value[2]||defaultValidator,converter=converters[type],getDefault=function(){var globalValue=globalDefaults[directive]&&globalDefaults[directive][key];return angular.isDefined(globalValue)?globalValue:localDefault},updateValue=function(value){scope.options[key]=value&&validator(value)?converter(value):getDefault()},interpolationStatus[directive]&&interpolationStatus[directive][key]?attrs.$observe(key,function(value){updateValue(value),scope.events.trigger("option-change",{name:key,newValue:value})}):updateValue(attrs[key]&&$interpolate(attrs[key])(scope.$parent))})},getTextAutosizeThreshold:function(){return autosizeThreshold}}}]}),tagsInput.factory("tiUtil",["$timeout",function($timeout){var self={debounce:function(fn,delay){var timeoutId;return function(){var args=arguments;$timeout.cancel(timeoutId),timeoutId=$timeout(function(){fn.apply(null,args)},delay)}},makeObjectArray:function(array,key){return(array=array||[]).length>0&&!angular.isObject(array[0])&&array.forEach(function(item,index){array[index]={},array[index][key]=item}),array},findInObjectArray:function(array,obj,key,comparer){var item=null;return comparer=comparer||self.defaultComparer,array.some(function(element){if(comparer(element[key],obj[key]))return item=element,!0}),item},defaultComparer:function(a,b){return self.safeToString(a).toLowerCase()===self.safeToString(b).toLowerCase()},safeHighlight:function(str,value){if(!value)return str;str=self.encodeHTML(str),value=self.encodeHTML(value);var expression=new RegExp("&[^;]+;|"+function(str){return str.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}(value),"gi");return str.replace(expression,function(match){return match.toLowerCase()===value.toLowerCase()?"<em>"+match+"</em>":match})},safeToString:function(value){return angular.isUndefined(value)||null==value?"":value.toString().trim()},encodeHTML:function(value){return self.safeToString(value).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")},handleUndefinedResult:function(fn,valueIfUndefined){return function(){var result=fn.apply(null,arguments);return angular.isUndefined(result)?valueIfUndefined:result}},replaceSpacesWithDashes:function(str){return self.safeToString(str).replace(/\s/g,"-")},simplePubSub:function(){var events={};return{on:function(names,handler){return names.split(" ").forEach(function(name){events[name]||(events[name]=[]),events[name].push(handler)}),this},trigger:function(name,args){return(events[name]||[]).every(function(handler){return self.handleUndefinedResult(handler,!0)(args)}),this}}}};return self}]),tagsInput.run(["$templateCache",function($templateCache){$templateCache.put("ngTagsInput/tags-input.html",'<div class="host" tabindex="-1" data-ng-click="eventHandlers.host.click()" ti-transclude-append=""><div class="tags" data-ng-class="{focused: hasFocus}"><ul class="tag-list"><li class="tag-item" data-ng-repeat="tag in tagList.items track by track(tag)" data-ng-class="{ selected: tag == tagList.selected }"><ti-tag-item data="tag"></ti-tag-item></li></ul><input class="input u-no-margin--top" autocomplete="off" data-ng-model="newTag.text" data-ng-change="eventHandlers.input.change(newTag.text)" data-ng-keydown="eventHandlers.input.keydown($event)" data-ng-focus="eventHandlers.input.focus($event)" data-ng-blur="eventHandlers.input.blur($event)" data-ng-paste="eventHandlers.input.paste($event)" data-ng-trim="false" data-ng-class="{\'invalid-tag\': newTag.invalid}" data-ng-disabled="disabled" ti-bind-attrs="{type: options.type, placeholder: options.placeholder, tabindex: options.tabindex, spellcheck: options.spellcheck}" ti-autosize=""></div></div>'),$templateCache.put("ngTagsInput/tag-item.html",'<span ng-bind="$getDisplayText()"></span> <a class="p-icon--close" data-ng-click="$removeTag()" data-ng-bind="$$removeTagSymbol">Remove tag</a>'),$templateCache.put("ngTagsInput/auto-complete.html",'<div class="autocomplete" data-ng-if="suggestionList.visible"><ul class="p-list suggestion-list"><li class="suggestion-item" data-ng-repeat="item in suggestionList.items track by track(item)" data-ng-class="{selected: item == suggestionList.selected}" data-ng-click="addSuggestionByIndex($index)" data-ng-mouseenter="suggestionList.select($index)"><ti-autocomplete-match data="item"></ti-autocomplete-match></li></ul></div>'),$templateCache.put("ngTagsInput/auto-complete-match.html",'<span data-ng-bind-html="$highlight($getDisplayText())"></span>')}])}()},"./src/maasserver/static/js/angular/3rdparty/vs-repeat.js":function(module,exports){function _extends(){return(_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source)Object.prototype.hasOwnProperty.call(source,key)&&(target[key]=source[key])}return target}).apply(this,arguments)}function _slicedToArray(arr,i){if(Array.isArray(arr))return arr;if(Symbol.iterator in Object(arr))return function(arr,i){var _arr=[],_n=!0,_d=!1,_e=void 0;try{for(var _s,_i=arr[Symbol.iterator]();!(_n=(_s=_i.next()).done)&&(_arr.push(_s.value),!i||_arr.length!==i);_n=!0);}catch(err){_d=!0,_e=err}finally{try{_n||null==_i.return||_i.return()}finally{if(_d)throw _e}}return _arr}(arr,i);throw new TypeError("Invalid attempt to destructure non-iterable instance")}!function(window,angular){var closestElement=angular.element.prototype.closest;if(!closestElement){var matchingFunction=["matches","matchesSelector","webkitMatches","webkitMatchesSelector","msMatches","msMatchesSelector","mozMatches","mozMatchesSelector"].reduce(function(res,prop){var _res;return null!==(_res=res)&&void 0!==_res?_res:prop in document.documentElement?prop:null},null);closestElement=function(selector){for(var _el,el=this[0].parentNode;el!==document.documentElement&&null!=el&&!el[matchingFunction](selector);)el=el.parentNode;return(null===(_el=el)||void 0===_el?void 0:_el[matchingFunction](selector))?angular.element(el):angular.element()}}function getWindowScroll(){var _ref,_document$documentEle,_ref2,_document$documentEle2;return"pageYOffset"in window?{scrollTop:window.pageYOffset,scrollLeft:window.pageXOffset}:{scrollTop:null!==(_ref=null!==(_document$documentEle=document.documentElement.scrollTop)&&void 0!==_document$documentEle?_document$documentEle:document.body.scrollTop)&&void 0!==_ref?_ref:0,scrollLeft:null!==(_ref2=null!==(_document$documentEle2=document.documentElement.scrollLeft)&&void 0!==_document$documentEle2?_document$documentEle2:document.body.scrollLeft)&&void 0!==_ref2?_ref2:0}}function getClientSize(element,sizeProp){return element===window?"clientWidth"===sizeProp?window.innerWidth:window.innerHeight:element[sizeProp]}function attrDeprecated(attrname,$element){!function($element,message){console.warn("vs-repeat deprecation: ".concat(message),$element[0])}($element,"".concat(attrname," attribute is deprecated. Pass the options object to vs-repeat attribute instead https://github.com/kamilkp/angular-vs-repeat#options"))}var defaultOptions={latch:!1,container:null,scrollParent:null,size:null,offsetBefore:0,offsetAfter:0,scrolledToBeginning:angular.noop,scrolledToEnd:angular.noop,scrolledToBeginningOffset:0,scrolledToEndOffset:0,scrollMargin:0,horizontal:!1,autoresize:!1,hunked:!1,hunkSize:0},vsRepeatModule=angular.module("vs-repeat",[]).directive("vsRepeat",["$compile","$parse",function($compile,$parse){return{restrict:"A",scope:!0,compile:function(compileElement,compileAttrs){var compileRepeatContainer="vsRepeatContainer"in compileAttrs?angular.element(compileElement[0].querySelector(compileAttrs.vsRepeatContainer)):compileElement,repeatContainerChildren=compileRepeatContainer.children(),ngRepeatChild=repeatContainerChildren.eq(0),childCloneHtml=ngRepeatChild[0].outerHTML,collectionName="$vs_collection";["vsSize","vsScrollParent","vsSizeProperty","vsHorizontal","vsOffsetBefore","vsOffsetAfter","vsScrolledToEndOffset","vsScrolledToBeginningOffset","vsExcess","vsScrollMargin"].forEach(function(attrname){attrname in compileAttrs&&attrDeprecated(attrname,compileElement)});var _analyzeNgRepeatUsage2=_slicedToArray(function(element){for(var options=["ng-repeat","data-ng-repeat","ng-repeat-start","data-ng-repeat-start"],_i=0;_i<options.length;_i++){var opt=options[_i];if(element.attr(opt))return[opt,element.attr(opt),opt.indexOf("-start")>=0]}throw new Error("angular-vs-repeat: no ng-repeat directive on a child element")}(ngRepeatChild),3),originalNgRepeatAttr=_analyzeNgRepeatUsage2[0],ngRepeatExpression=_analyzeNgRepeatUsage2[1],isNgRepeatStart=_analyzeNgRepeatUsage2[2],_expressionMatches=_slicedToArray(/^\s*(\S+)\s+in\s+([\S\s]+?)(track\s+by\s+\S+)?$/.exec(ngRepeatExpression),4),lhs=_expressionMatches[1],rhs=_expressionMatches[2],rhsSuffix=_expressionMatches[3];if(isNgRepeatStart)for(var index=0,repeaterElement=repeatContainerChildren.eq(index);null==repeaterElement.attr("ng-repeat-end")&&null==repeaterElement.attr("data-ng-repeat-end");)index++,repeaterElement=repeatContainerChildren.eq(index),childCloneHtml+=repeaterElement[0].outerHTML;return compileRepeatContainer.empty(),{pre:function($scope,$element,$attrs){var _$scope$$eval;function _parseSize(options){if("number"==typeof options.size)options.getSize=function(){return options.size};else{var parsed=$parse(String(options.size));options.getSize=function(item){return parsed($scope,(value=item,(key=lhs)in(obj={})?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj));var obj,key,value}}}$scope.vsRepeat={options:_extends({},defaultOptions,null!==(_$scope$$eval=$scope.$eval($attrs.vsRepeat))&&void 0!==_$scope$$eval?_$scope$$eval:{})};var options=$scope.vsRepeat.options;_parseSize(options);var originalLength,repeatContainer=angular.isDefined($attrs.vsRepeatContainer)?angular.element($element[0].querySelector($attrs.vsRepeatContainer)):$element,childClone=angular.element(childCloneHtml),childTagName=childClone[0].tagName.toLowerCase(),originalCollection=[],$beforeContent=angular.element("<"+childTagName+' class="vs-repeat-before-content"></'+childTagName+">"),$afterContent=angular.element("<"+childTagName+' class="vs-repeat-after-content"></'+childTagName+">"),autosizingRequired=null===options.size,$scrollParent=options.scrollParent?"window"===options.scrollParent?angular.element(window):closestElement.call(repeatContainer,options.scrollParent):repeatContainer,clientSize=options.horizontal?"clientWidth":"clientHeight",offsetSize=options.horizontal?"offsetWidth":"offsetHeight",scrollSize=options.horizontal?"scrollWidth":"scrollHeight",scrollPos=options.horizontal?"scrollLeft":"scrollTop";if($scope.vsRepeat.totalSize=0,0===$scrollParent.length)throw"Specified scroll parent selector did not match any element";if($scope.vsRepeat.$scrollParent=$scrollParent,$scope.vsRepeat.sizesCumulative=[],options.debug){var $debugParent="window"===options.scrollParent?angular.element(document.body):$scrollParent,$debug=angular.element('<div class="vs-repeat-debug-element"></div>');$debug.css("position","window"===options.scrollParent?"fixed":"absolute"),$debugParent.append($debug),$scope.$on("$destroy",function(){$debug.remove()})}var _prevStartIndex,_prevEndIndex,_minStartIndex,_maxEndIndex,_prevClientSize,measuredSize=getClientSize($scrollParent[0],clientSize)||50;function refresh(){!originalCollection||originalCollection.length<1?($scope[collectionName]=[],originalLength=0,$scope.vsRepeat.sizesCumulative=[0]):(originalLength=originalCollection.length,options.size?_mapSize():getFromMeasured()),reinitialize()}function _mapSize(){var hardSize=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,sizes=originalCollection.map(function(item){var _hardSize;return null!==(_hardSize=hardSize)&&void 0!==_hardSize?_hardSize:options.getSize(item)}),sum=0;$scope.vsRepeat.sizesCumulative=[0].concat(function(arr){if(Array.isArray(arr)){for(var i=0,arr2=new Array(arr.length);i<arr.length;i++)arr2[i]=arr[i];return arr2}return Array.from(arr)}(sizes.map(function(size){return sum+=size})))}function getFromMeasured(){autosizingRequired?$scope.$$postDigest(function(){if(repeatContainer[0].offsetHeight||repeatContainer[0].offsetWidth){for(var children=repeatContainer.children(),i=0,gotSomething=!1,insideStartEndSequence=!1;i<children.length;){if(null!=children[i].attributes[originalNgRepeatAttr]||insideStartEndSequence){if(gotSomething||(measuredSize=0),gotSomething=!0,children[i][offsetSize]&&(measuredSize+=children[i][offsetSize]),!isNgRepeatStart)break;if(null!=children[i].attributes["ng-repeat-end"]||null!=children[i].attributes["data-ng-repeat-end"])break;insideStartEndSequence=!0}i++}gotSomething&&(_mapSize(measuredSize),reinitialize(),autosizingRequired=!1,$scope.$root&&!$scope.$root.$$phase&&$scope.$digest())}else var dereg=$scope.$watch(function(){(repeatContainer[0].offsetHeight||repeatContainer[0].offsetWidth)&&(dereg(),getFromMeasured())})}):_mapSize(measuredSize)}function getLayoutProps(value){var layoutProp=options.horizontal?"width":"height";return["","min-","max-"].reduce(function(acc,prop){return acc["".concat(prop).concat(layoutProp)]=value,acc},{})}function scrollHandler(){var pos=$scrollParent[0][scrollPos];updateInnerCollection()&&($scope.$digest(),options._ensureScrollIntegrity&&($scrollParent[0][scrollPos]=pos))}function onWindowResize(){options.autoresize&&(autosizingRequired=!0,getFromMeasured(),$scope.$root&&!$scope.$root.$$phase&&$scope.$digest()),updateInnerCollection()&&$scope.$digest()}function reinitialize(){var size;_prevStartIndex=void 0,_prevEndIndex=void 0,_minStartIndex=originalLength,_maxEndIndex=0,size=$scope.vsRepeat.sizesCumulative[originalLength],$scope.vsRepeat.totalSize=options.offsetBefore+size+options.offsetAfter,updateInnerCollection(),$scope.$emit("vsRepeatReinitialized",$scope.vsRepeat.startIndex,$scope.vsRepeat.endIndex)}function reinitOnClientHeightChange(){var ch=getClientSize($scrollParent[0],clientSize);ch!==_prevClientSize&&(reinitialize(),$scope.$root&&!$scope.$root.$$phase&&$scope.$digest()),_prevClientSize=ch}function binaryFind(array,threshold){var a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,b=arguments.length>3&&void 0!==arguments[3]?arguments[3]:array.length-1,d=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1;if(array[a]===threshold)return[a,a,d];if(array[b]===threshold)return[b,b,d];if(b-a>1){var m=Math.floor((a+b)/2);return array[m]>threshold?binaryFind(array,threshold,a,m,d+1):binaryFind(array,threshold,m,b,d+1)}return[threshold>array[b]?b:a,threshold<array[a]?a:b,d]}function updateInnerCollection(){var element,scrollProp,$scrollPosition=(element=$scrollParent[0],scrollProp=scrollPos,element===window?getWindowScroll()[scrollProp]:element[scrollProp]),$clientSize=getClientSize($scrollParent[0],clientSize);options.debug&&($clientSize/=2);var vsElement,scrollElement,isHorizontal,scrollOffset=repeatContainer[0]===$scrollParent[0]?0:(vsElement=repeatContainer[0],scrollElement=$scrollParent[0],isHorizontal=options.horizontal,vsElement.getBoundingClientRect()[isHorizontal?"left":"top"]-(scrollElement===window?0:scrollElement.getBoundingClientRect()[isHorizontal?"left":"top"])+(scrollElement===window?getWindowScroll():scrollElement)[isHorizontal?"scrollLeft":"scrollTop"]),__startIndex=$scope.vsRepeat.startIndex,__endIndex=$scope.vsRepeat.endIndex;if(autosizingRequired&&!options.size)__startIndex=0,__endIndex=1;else{$scope.$$postDigest(function(){window.requestAnimationFrame(function(){var expectedSize=$scope.vsRepeat.sizesCumulative[originalLength],compStyle=window.getComputedStyle(repeatContainer[0]),paddings=options.horizontal?["paddingLeft","paddingRight"]:["paddingTop","paddingBottom"],containerSize=repeatContainer[0][scrollSize]-paddings.reduce(function(acc,prop){return acc+Number(compStyle[prop].slice(0,-2))},0);repeatContainer[0][scrollSize]&&expectedSize!==containerSize&&console.warn("vsRepeat: size mismatch. Expected size "+expectedSize+"px whereas actual size is "+containerSize+"px. Fix vsSize on element:",$element[0])})});var relativeScroll=$scrollPosition-options.offsetBefore-scrollOffset;__startIndex=_slicedToArray(binaryFind($scope.vsRepeat.sizesCumulative,relativeScroll-options.scrollMargin),1)[0],__startIndex=Math.max(__startIndex,0),__endIndex=_slicedToArray(binaryFind($scope.vsRepeat.sizesCumulative,relativeScroll+options.scrollMargin+$clientSize,__startIndex),2)[1],__endIndex=Math.min(__endIndex,originalLength)}_minStartIndex=Math.min(__startIndex,_minStartIndex),_maxEndIndex=Math.max(__endIndex,_maxEndIndex),$scope.vsRepeat.startIndex=options.latch?_minStartIndex:__startIndex,$scope.vsRepeat.endIndex=options.latch?_maxEndIndex:__endIndex,_maxEndIndex<$scope.vsRepeat.startIndex&&($scope.vsRepeat.startIndex=_maxEndIndex);var digestRequired=!1;if(null==_prevStartIndex?digestRequired=!0:null==_prevEndIndex&&(digestRequired=!0),digestRequired||(options.hunked?Math.abs($scope.vsRepeat.startIndex-_prevStartIndex)>=options.hunkSize||0===$scope.vsRepeat.startIndex&&0!==_prevStartIndex?digestRequired=!0:(Math.abs($scope.vsRepeat.endIndex-_prevEndIndex)>=options.hunkSize||$scope.vsRepeat.endIndex===originalLength&&_prevEndIndex!==originalLength)&&(digestRequired=!0):digestRequired=$scope.vsRepeat.startIndex!==_prevStartIndex||$scope.vsRepeat.endIndex!==_prevEndIndex),digestRequired){var triggerIndex;$scope[collectionName]=originalCollection.slice($scope.vsRepeat.startIndex,$scope.vsRepeat.endIndex),$scope.$emit("vsRepeatInnerCollectionUpdated",$scope.vsRepeat.startIndex,$scope.vsRepeat.endIndex,_prevStartIndex,_prevEndIndex),options.scrolledToEnd&&(triggerIndex=originalCollection.length-options.scrolledToEndOffset,($scope.vsRepeat.endIndex>=triggerIndex&&_prevEndIndex<triggerIndex||originalCollection.length&&$scope.vsRepeat.endIndex===originalCollection.length)&&$scope.$eval(options.scrolledToEnd)),options.scrolledToBeginning&&(triggerIndex=options.scrolledToBeginningOffset,$scope.vsRepeat.startIndex<=triggerIndex&&_prevStartIndex>$scope.vsRepeat.startIndex&&$scope.$eval(options.scrolledToBeginning)),_prevStartIndex=$scope.vsRepeat.startIndex,_prevEndIndex=$scope.vsRepeat.endIndex;var o1=$scope.vsRepeat.sizesCumulative[$scope.vsRepeat.startIndex]+options.offsetBefore,o2=$scope.vsRepeat.sizesCumulative[$scope.vsRepeat.startIndex+$scope[collectionName].length]+options.offsetBefore,total=$scope.vsRepeat.totalSize;$beforeContent.css(getLayoutProps(o1+"px")),$afterContent.css(getLayoutProps(total-o2+"px"))}return digestRequired}options.horizontal?($beforeContent.css("height","100%"),$afterContent.css("height","100%")):($beforeContent.css("width","100%"),$afterContent.css("width","100%")),$attrs.vsRepeatOptions&&$scope.$watchCollection($attrs.vsRepeatOptions,function(newOpts){var mergedOptions=_extends({},options,newOpts);JSON.stringify(mergedOptions)!==JSON.stringify(options)&&(Object.assign(options,newOpts),_parseSize(options),reinitialize())}),$scope.$watchCollection(rhs,function(){var coll=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];originalCollection=coll,refresh()}),childClone.eq(0).attr(originalNgRepeatAttr,lhs+" in "+collectionName+(rhsSuffix?" "+rhsSuffix:"")),childClone.addClass("vs-repeat-repeated-element"),repeatContainer.append($beforeContent),repeatContainer.append(childClone),$compile(childClone)($scope),repeatContainer.append($afterContent),$scope.vsRepeat.startIndex=0,$scope.vsRepeat.endIndex=0,$scrollParent.on("scroll",scrollHandler),angular.element(window).on("resize",onWindowResize),$scope.$on("$destroy",function(){angular.element(window).off("resize",onWindowResize),$scrollParent.off("scroll",scrollHandler)}),$scope.$on("vsRepeatTrigger",refresh),$scope.$on("vsRepeatResize",function(){autosizingRequired=!0,getFromMeasured()}),$scope.$on("vsRenderAll",function(){options.latch&&($scope.vsRepeat.endIndex!==originalLength?setTimeout(function(){var __endIndex=originalLength;_maxEndIndex=Math.max(__endIndex,_maxEndIndex),$scope.vsRepeat.endIndex=options.latch?_maxEndIndex:__endIndex,$scope[collectionName]=originalCollection.slice($scope.vsRepeat.startIndex,$scope.vsRepeat.endIndex),_prevEndIndex=$scope.vsRepeat.endIndex,$beforeContent.css(getLayoutProps(0)),$afterContent.css(getLayoutProps(0)),$scope.$emit("vsRenderAllDone"),$scope.$root&&!$scope.$root.$$phase&&$scope.$digest()}):$scope.$emit("vsRenderAllDone"))}),$scope.$watch(function(){"function"==typeof window.requestAnimationFrame?window.requestAnimationFrame(reinitOnClientHeightChange):reinitOnClientHeightChange()})}}}}}]);angular.element(document.head).append('<style id="angular-vs-repeat-style">\n\t \t.vs-repeat-debug-element {\n top: 50%;\n left: 0;\n right: 0;\n height: 1px;\n background: red;\n z-index: 99999999;\n box-shadow: 0 0 20px red;\n }\n\n .vs-repeat-debug-element + .vs-repeat-debug-element {\n display: none;\n }\n\n .vs-repeat-before-content,\n .vs-repeat-after-content {\n border: none !important;\n padding: 0 !important;\n }\n </style>'),void 0!==module&&module.exports&&(module.exports=vsRepeatModule.name)}(window,window.angular)},0:function(module,exports,__webpack_require__){__webpack_require__("./src/maasserver/static/js/angular/3rdparty/ng-tags-input.js"),module.exports=__webpack_require__("./src/maasserver/static/js/angular/3rdparty/vs-repeat.js")}});
1273+!function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={i:moduleId,l:!1,exports:{}};return modules[moduleId].call(module.exports,module,module.exports,__webpack_require__),module.l=!0,module.exports}__webpack_require__.m=modules,__webpack_require__.c=installedModules,__webpack_require__.d=function(exports,name,getter){__webpack_require__.o(exports,name)||Object.defineProperty(exports,name,{configurable:!1,enumerable:!0,get:getter})},__webpack_require__.r=function(exports){Object.defineProperty(exports,"__esModule",{value:!0})},__webpack_require__.n=function(module){var getter=module&&module.__esModule?function(){return module.default}:function(){return module};return __webpack_require__.d(getter,"a",getter),getter},__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)},__webpack_require__.p="",__webpack_require__(__webpack_require__.s=0)}({"./src/maasserver/static/js/angular/3rdparty/ng-tags-input.js":function(module,exports){!function(){"use strict";var KEYS_backspace=8,KEYS_tab=9,KEYS_enter=13,KEYS_escape=27,KEYS_space=32,KEYS_up=38,KEYS_down=40,KEYS_left=37,KEYS_right=39,KEYS_delete=46,KEYS_comma=188,SUPPORTED_INPUT_TYPES=["text","email","url"],tagsInput=angular.module("ngTagsInput",[]);tagsInput.directive("tagsInput",["$timeout","$document","$window","tagsInputConfig","tiUtil",function($timeout,$document,$window,tagsInputConfig,tiUtil){function validateType(type){return-1!==SUPPORTED_INPUT_TYPES.indexOf(type)}return{restrict:"E",require:"ngModel",scope:{tags:"=ngModel",onTagAdding:"&",onTagAdded:"&",onInvalidTag:"&",onTagRemoving:"&",onTagRemoved:"&"},replace:!1,transclude:!0,templateUrl:"ngTagsInput/tags-input.html",controller:["$scope","$attrs","$element",function($scope,$attrs,$element){$scope.events=tiUtil.simplePubSub(),tagsInputConfig.load("tagsInput",$scope,$attrs,{template:[String,"ngTagsInput/tag-item.html"],type:[String,"text",validateType],placeholder:[String,"Add a tag"],tabindex:[Number,null],removeTagSymbol:[String,String.fromCharCode(215)],replaceSpacesWithDashes:[Boolean,!0],minLength:[Number,3],maxLength:[Number,9007199254740991],addOnEnter:[Boolean,!0],addOnSpace:[Boolean,!1],addOnComma:[Boolean,!0],addOnBlur:[Boolean,!0],addOnPaste:[Boolean,!1],pasteSplitPattern:[RegExp,/,/],allowedTagsPattern:[RegExp,/.+/],enableEditingLastTag:[Boolean,!1],minTags:[Number,0],maxTags:[Number,9007199254740991],displayProperty:[String,"text"],keyProperty:[String,""],allowLeftoverText:[Boolean,!1],addFromAutocompleteOnly:[Boolean,!1],spellcheck:[Boolean,!0]}),$scope.tagList=new function(options,events,onTagAdding,onTagRemoving){var getTagText,setTagText,tagIsValid,self={};return getTagText=function(tag){return tiUtil.safeToString(tag[options.displayProperty])},setTagText=function(tag,text){tag[options.displayProperty]=text},tagIsValid=function(tag){var tagText=getTagText(tag);return tagText&&tagText.length>=options.minLength&&tagText.length<=options.maxLength&&options.allowedTagsPattern.test(tagText)&&!tiUtil.findInObjectArray(self.items,tag,options.keyProperty||options.displayProperty)&&onTagAdding({$tag:tag})},self.items=[],self.addText=function(text){var tag={};return setTagText(tag,text),self.add(tag)},self.add=function(tag){var tagText=getTagText(tag);return options.replaceSpacesWithDashes&&(tagText=tiUtil.replaceSpacesWithDashes(tagText)),setTagText(tag,tagText),tagIsValid(tag)?(self.items.push(tag),events.trigger("tag-added",{$tag:tag})):tagText&&events.trigger("invalid-tag",{$tag:tag}),tag},self.remove=function(index){var tag=self.items[index];if(onTagRemoving({$tag:tag}))return self.items.splice(index,1),self.clearSelection(),events.trigger("tag-removed",{$tag:tag}),tag},self.select=function(index){index<0?index=self.items.length-1:index>=self.items.length&&(index=0),self.index=index,self.selected=self.items[index]},self.selectPrior=function(){self.select(--self.index)},self.selectNext=function(){self.select(++self.index)},self.removeSelected=function(){return self.remove(self.index)},self.clearSelection=function(){self.selected=null,self.index=-1},self.clearSelection(),self}($scope.options,$scope.events,tiUtil.handleUndefinedResult($scope.onTagAdding,!0),tiUtil.handleUndefinedResult($scope.onTagRemoving,!0)),this.registerAutocomplete=function(){$element.find("input");return{addTag:function(tag){return $scope.tagList.add(tag)},focusInput:function(){},getTags:function(){return $scope.tags},getCurrentTagText:function(){return $scope.newTag.text},getOptions:function(){return $scope.options},on:function(name,handler){return $scope.events.on(name,handler),this}}},this.registerTagItem=function(){return{getOptions:function(){return $scope.options},removeTag:function(index){$scope.disabled||$scope.tagList.remove(index)}}}}],link:function(scope,element,attrs,ngModelCtrl){var setElementValidity,hotkeys=[KEYS_enter,KEYS_comma,KEYS_space,KEYS_backspace,KEYS_delete,KEYS_left,KEYS_right],tagList=scope.tagList,events=scope.events,options=scope.options,input=element.find("input"),validationOptions=["minTags","maxTags","allowLeftoverText"];setElementValidity=function(){ngModelCtrl.$setValidity("maxTags",scope.tags.length<=options.maxTags),ngModelCtrl.$setValidity("minTags",scope.tags.length>=options.minTags),ngModelCtrl.$setValidity("leftoverText",!(!scope.hasFocus&&!options.allowLeftoverText)||!scope.newTag.text)},ngModelCtrl.$isEmpty=function(value){return!value||!value.length},scope.newTag={text:"",invalid:null,setText:function(value){this.text=value,events.trigger("input-change",value)}},scope.track=function(tag){return tag[options.keyProperty||options.displayProperty]},scope.$watch("tags",function(value){scope.tags=tiUtil.makeObjectArray(value,options.displayProperty),tagList.items=scope.tags}),scope.$watch("tags.length",function(){setElementValidity()}),attrs.$observe("disabled",function(value){scope.disabled=value}),scope.eventHandlers={input:{change:function(text){events.trigger("input-change",text)},keydown:function($event){events.trigger("input-keydown",$event)},focus:function(){scope.hasFocus||(scope.hasFocus=!0,events.trigger("input-focus"))},blur:function(){$timeout(function(){var activeElement=$document.prop("activeElement"),lostFocusToBrowserWindow=activeElement===input[0],lostFocusToChildElement=element[0].contains(activeElement);!lostFocusToBrowserWindow&&lostFocusToChildElement||(scope.hasFocus=!1,events.trigger("input-blur"))})},paste:function($event){$event.getTextData=function(){var clipboardData=$event.clipboardData||$event.originalEvent&&$event.originalEvent.clipboardData;return clipboardData?clipboardData.getData("text/plain"):$window.clipboardData.getData("Text")},events.trigger("input-paste",$event)}},host:{click:function(){scope.disabled}}},events.on("tag-added",scope.onTagAdded).on("invalid-tag",scope.onInvalidTag).on("tag-removed",scope.onTagRemoved).on("tag-added",function(){scope.newTag.setText("")}).on("tag-added tag-removed",function(){ngModelCtrl.$setViewValue(scope.tags)}).on("invalid-tag",function(){scope.newTag.invalid=!0}).on("option-change",function(e){-1!==validationOptions.indexOf(e.name)&&setElementValidity()}).on("input-change",function(){tagList.clearSelection(),scope.newTag.invalid=null}).on("input-focus",function(){element.triggerHandler("focus"),ngModelCtrl.$setValidity("leftoverText",!0)}).on("input-blur",function(){options.addOnBlur&&!options.addFromAutocompleteOnly&&tagList.addText(scope.newTag.text),element.triggerHandler("blur"),setElementValidity()}).on("input-keydown",function(event){var shouldAdd,shouldRemove,shouldSelect,shouldEditLastTag,key=event.keyCode,addKeys={};if(!(event.shiftKey||event.altKey||event.ctrlKey||event.metaKey)&&-1!==hotkeys.indexOf(key)){if(addKeys[KEYS_enter]=options.addOnEnter,addKeys[KEYS_comma]=options.addOnComma,addKeys[KEYS_space]=options.addOnSpace,shouldAdd=!options.addFromAutocompleteOnly&&addKeys[key],shouldRemove=(key===KEYS_backspace||key===KEYS_delete)&&tagList.selected,shouldEditLastTag=key===KEYS_backspace&&0===scope.newTag.text.length&&options.enableEditingLastTag,shouldSelect=(key===KEYS_backspace||key===KEYS_left||key===KEYS_right)&&0===scope.newTag.text.length&&!options.enableEditingLastTag,shouldAdd)tagList.addText(scope.newTag.text);else if(shouldEditLastTag){var tag;tagList.selectPrior(),(tag=tagList.removeSelected())&&scope.newTag.setText(tag[options.displayProperty])}else shouldRemove?tagList.removeSelected():shouldSelect&&(key===KEYS_left||key===KEYS_backspace?tagList.selectPrior():key===KEYS_right&&tagList.selectNext());(shouldAdd||shouldSelect||shouldRemove||shouldEditLastTag)&&event.preventDefault()}}).on("input-paste",function(event){if(options.addOnPaste){var tags=event.getTextData().split(options.pasteSplitPattern);tags.length>1&&(tags.forEach(function(tag){tagList.addText(tag)}),event.preventDefault())}})}}}]),tagsInput.directive("tiTagItem",["tiUtil",function(tiUtil){return{restrict:"E",require:"^tagsInput",template:'<ng-include src="$$template"></ng-include>',scope:{data:"="},link:function(scope,element,attrs,tagsInputCtrl){var tagsInput=tagsInputCtrl.registerTagItem(),options=tagsInput.getOptions();scope.$$template=options.template,scope.$$removeTagSymbol=options.removeTagSymbol,scope.$getDisplayText=function(){return tiUtil.safeToString(scope.data[options.displayProperty])},scope.$removeTag=function(){tagsInput.removeTag(scope.$index)},scope.$watch("$parent.$index",function(value){scope.$index=value})}}}]),tagsInput.directive("autoComplete",["$document","$timeout","$sce","$q","tagsInputConfig","tiUtil",function($document,$timeout,$sce,$q,tagsInputConfig,tiUtil){return{restrict:"E",require:"^tagsInput",scope:{source:"&"},templateUrl:"ngTagsInput/auto-complete.html",controller:["$scope","$element","$attrs",function($scope,$element,$attrs){$scope.events=tiUtil.simplePubSub(),tagsInputConfig.load("autoComplete",$scope,$attrs,{template:[String,"ngTagsInput/auto-complete-match.html"],debounceDelay:[Number,100],minLength:[Number,3],highlightMatchedText:[Boolean,!0],maxResultsToShow:[Number,10],loadOnDownArrow:[Boolean,!1],loadOnEmpty:[Boolean,!1],loadOnFocus:[Boolean,!1],selectFirstMatch:[Boolean,!0],displayProperty:[String,""]}),$scope.suggestionList=new function(loadFn,options,events){var getDifference,lastPromise,getTagId,self={};return getTagId=function(){return options.tagsInput.keyProperty||options.tagsInput.displayProperty},getDifference=function(array1,array2){return array1.filter(function(item){return!tiUtil.findInObjectArray(array2,item,getTagId(),function(a,b){return options.tagsInput.replaceSpacesWithDashes&&(a=tiUtil.replaceSpacesWithDashes(a),b=tiUtil.replaceSpacesWithDashes(b)),tiUtil.defaultComparer(a,b)})})},self.reset=function(){lastPromise=null,self.items=[],self.visible=!1,self.index=-1,self.selected=null,self.query=null},self.show=function(){options.selectFirstMatch?self.select(0):self.selected=null,self.visible=!0},self.load=tiUtil.debounce(function(query,tags){self.query=query;var promise=$q.when(loadFn({$query:query}));lastPromise=promise,promise.then(function(items){promise===lastPromise&&(items=tiUtil.makeObjectArray(items.data||items,getTagId()),items=getDifference(items,tags),self.items=items.slice(0,options.maxResultsToShow),self.items.length>0?self.show():self.reset())})},options.debounceDelay),self.selectNext=function(){self.select(++self.index)},self.selectPrior=function(){self.select(--self.index)},self.select=function(index){index<0?index=self.items.length-1:index>=self.items.length&&(index=0),self.index=index,self.selected=self.items[index],events.trigger("suggestion-selected",index)},self.reset(),self}($scope.source,$scope.options,$scope.events),this.registerAutocompleteMatch=function(){return{getOptions:function(){return $scope.options},getQuery:function(){return $scope.suggestionList.query}}}}],link:function(scope,element,attrs,tagsInputCtrl){var shouldLoadSuggestions,hotkeys=[KEYS_enter,KEYS_tab,KEYS_escape,KEYS_up,KEYS_down],suggestionList=scope.suggestionList,tagsInput=tagsInputCtrl.registerAutocomplete(),options=scope.options,events=scope.events;options.tagsInput=tagsInput.getOptions(),shouldLoadSuggestions=function(value){return value&&value.length>=options.minLength||!value&&options.loadOnEmpty},scope.addSuggestionByIndex=function(index){suggestionList.select(index),scope.addSuggestion()},scope.addSuggestion=function(){var added=!1;return suggestionList.selected&&(tagsInput.addTag(angular.copy(suggestionList.selected)),suggestionList.reset(),tagsInput.focusInput(),added=!0),added},scope.track=function(item){return item[options.tagsInput.keyProperty||options.tagsInput.displayProperty]},tagsInput.on("tag-added invalid-tag input-blur",function(){suggestionList.reset()}).on("input-change",function(value){shouldLoadSuggestions(value)?suggestionList.load(value,tagsInput.getTags()):suggestionList.reset()}).on("input-focus",function(){var value=tagsInput.getCurrentTagText();options.loadOnFocus&&shouldLoadSuggestions(value)&&suggestionList.load(value,tagsInput.getTags())}).on("input-keydown",function(event){var key=event.keyCode,handled=!1;if(-1!==hotkeys.indexOf(key))return suggestionList.visible?key===KEYS_down?(suggestionList.selectNext(),handled=!0):key===KEYS_up?(suggestionList.selectPrior(),handled=!0):key===KEYS_escape?(suggestionList.reset(),handled=!0):key!==KEYS_enter&&key!==KEYS_tab||(handled=scope.addSuggestion()):key===KEYS_down&&scope.options.loadOnDownArrow&&(suggestionList.load(tagsInput.getCurrentTagText(),tagsInput.getTags()),handled=!0),handled?(event.preventDefault(),event.stopImmediatePropagation(),!1):void 0}),events.on("suggestion-selected",function(index){!function(root,index){var element=root.find("li").eq(index),parent=element.parent(),elementTop=element.prop("offsetTop"),elementHeight=element.prop("offsetHeight"),parentHeight=parent.prop("clientHeight"),parentScrollTop=parent.prop("scrollTop");elementTop<parentScrollTop?parent.prop("scrollTop",elementTop):elementTop+elementHeight>parentHeight+parentScrollTop&&parent.prop("scrollTop",elementTop+elementHeight-parentHeight)}(element,index)})}}}]),tagsInput.directive("tiAutocompleteMatch",["$sce","tiUtil",function($sce,tiUtil){return{restrict:"E",require:"^autoComplete",template:'<ng-include src="$$template"></ng-include>',scope:{data:"="},link:function(scope,element,attrs,autoCompleteCtrl){var autoComplete=autoCompleteCtrl.registerAutocompleteMatch(),options=autoComplete.getOptions();scope.$$template=options.template,scope.$index=scope.$parent.$index,scope.$highlight=function(text){return options.highlightMatchedText&&(text=tiUtil.safeHighlight(text,autoComplete.getQuery())),$sce.trustAsHtml(text)},scope.$getDisplayText=function(){return tiUtil.safeToString(scope.data[options.displayProperty||options.tagsInput.displayProperty])}}}}]),tagsInput.directive("tiTranscludeAppend",function(){return function(scope,element,attrs,ctrl,transcludeFn){transcludeFn(function(clone){element.append(clone)})}}),tagsInput.directive("tiAutosize",["tagsInputConfig",function(tagsInputConfig){return{restrict:"A",require:"ngModel",link:function(scope,element,attrs,ctrl){var span,resize,threshold=tagsInputConfig.getTextAutosizeThreshold();(span=angular.element('<span class="input"></span>')).css("display","none").css("visibility","hidden").css("width","auto").css("white-space","pre"),element.parent().append(span),resize=function(originalValue){var width,value=originalValue;return angular.isString(value)&&0===value.length&&(value=attrs.placeholder),value&&(span.text(value),span.css("display",""),width=span.prop("offsetWidth"),span.css("display","none")),element.css("width",width?width+threshold+"px":""),originalValue},ctrl.$parsers.unshift(resize),ctrl.$formatters.unshift(resize),attrs.$observe("placeholder",function(value){ctrl.$modelValue||resize(value)})}}}]),tagsInput.directive("tiBindAttrs",function(){return function(scope,element,attrs){scope.$watch(attrs.tiBindAttrs,function(value){angular.forEach(value,function(value,key){"type"===key?element[0].type=value:attrs.$set(key,value)})},!0)}}),tagsInput.provider("tagsInputConfig",function(){var globalDefaults={},interpolationStatus={},autosizeThreshold=3;this.setDefaults=function(directive,defaults){return globalDefaults[directive]=defaults,this},this.setActiveInterpolation=function(directive,options){return interpolationStatus[directive]=options,this},this.setTextAutosizeThreshold=function(threshold){return autosizeThreshold=threshold,this},this.$get=["$interpolate",function($interpolate){var converters={};return converters[String]=function(value){return value},converters[Number]=function(value){return parseInt(value,10)},converters[Boolean]=function(value){return"true"===value.toLowerCase()},converters[RegExp]=function(value){return new RegExp(value)},{load:function(directive,scope,attrs,options){var defaultValidator=function(){return!0};scope.options={},angular.forEach(options,function(value,key){var type,localDefault,validator,converter,getDefault,updateValue;type=value[0],localDefault=value[1],validator=value[2]||defaultValidator,converter=converters[type],getDefault=function(){var globalValue=globalDefaults[directive]&&globalDefaults[directive][key];return angular.isDefined(globalValue)?globalValue:localDefault},updateValue=function(value){scope.options[key]=value&&validator(value)?converter(value):getDefault()},interpolationStatus[directive]&&interpolationStatus[directive][key]?attrs.$observe(key,function(value){updateValue(value),scope.events.trigger("option-change",{name:key,newValue:value})}):updateValue(attrs[key]&&$interpolate(attrs[key])(scope.$parent))})},getTextAutosizeThreshold:function(){return autosizeThreshold}}}]}),tagsInput.factory("tiUtil",["$timeout",function($timeout){var self={debounce:function(fn,delay){var timeoutId;return function(){var args=arguments;$timeout.cancel(timeoutId),timeoutId=$timeout(function(){fn.apply(null,args)},delay)}},makeObjectArray:function(array,key){return(array=array||[]).length>0&&!angular.isObject(array[0])&&array.forEach(function(item,index){array[index]={},array[index][key]=item}),array},findInObjectArray:function(array,obj,key,comparer){var item=null;return comparer=comparer||self.defaultComparer,array.some(function(element){if(comparer(element[key],obj[key]))return item=element,!0}),item},defaultComparer:function(a,b){return self.safeToString(a).toLowerCase()===self.safeToString(b).toLowerCase()},safeHighlight:function(str,value){if(!value)return str;str=self.encodeHTML(str),value=self.encodeHTML(value);var expression=new RegExp("&[^;]+;|"+function(str){return str.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}(value),"gi");return str.replace(expression,function(match){return match.toLowerCase()===value.toLowerCase()?"<em>"+match+"</em>":match})},safeToString:function(value){return angular.isUndefined(value)||null==value?"":value.toString().trim()},encodeHTML:function(value){return self.safeToString(value).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")},handleUndefinedResult:function(fn,valueIfUndefined){return function(){var result=fn.apply(null,arguments);return angular.isUndefined(result)?valueIfUndefined:result}},replaceSpacesWithDashes:function(str){return self.safeToString(str).replace(/\s/g,"-")},simplePubSub:function(){var events={};return{on:function(names,handler){return names.split(" ").forEach(function(name){events[name]||(events[name]=[]),events[name].push(handler)}),this},trigger:function(name,args){return(events[name]||[]).every(function(handler){return self.handleUndefinedResult(handler,!0)(args)}),this}}}};return self}]),tagsInput.run(["$templateCache",function($templateCache){$templateCache.put("ngTagsInput/tags-input.html",'<div class="host" tabindex="-1" data-ng-click="eventHandlers.host.click()" ti-transclude-append=""><div class="tags" data-ng-class="{focused: hasFocus}"><ul class="tag-list"><li class="tag-item" data-ng-repeat="tag in tagList.items track by track(tag)" data-ng-class="{ selected: tag == tagList.selected }"><ti-tag-item data="tag"></ti-tag-item></li></ul><input class="input u-no-margin--top" autocomplete="off" data-ng-model="newTag.text" data-ng-change="eventHandlers.input.change(newTag.text)" data-ng-keydown="eventHandlers.input.keydown($event)" data-ng-focus="eventHandlers.input.focus($event)" data-ng-blur="eventHandlers.input.blur($event)" data-ng-paste="eventHandlers.input.paste($event)" data-ng-trim="false" data-ng-class="{\'invalid-tag\': newTag.invalid}" data-ng-disabled="disabled" ti-bind-attrs="{type: options.type, placeholder: options.placeholder, tabindex: options.tabindex, spellcheck: options.spellcheck}" ti-autosize=""></div></div>'),$templateCache.put("ngTagsInput/tag-item.html",'<span ng-bind="$getDisplayText()"></span> <a class="p-icon--close" data-ng-click="$removeTag()" data-ng-bind="$$removeTagSymbol">Remove tag</a>'),$templateCache.put("ngTagsInput/auto-complete.html",'<div class="autocomplete" data-ng-if="suggestionList.visible"><ul class="p-list suggestion-list"><li class="suggestion-item" data-ng-repeat="item in suggestionList.items track by track(item)" data-ng-class="{selected: item == suggestionList.selected}" data-ng-click="addSuggestionByIndex($index)" data-ng-mouseenter="suggestionList.select($index)"><ti-autocomplete-match data="item"></ti-autocomplete-match></li></ul></div>'),$templateCache.put("ngTagsInput/auto-complete-match.html",'<span data-ng-bind-html="$highlight($getDisplayText())"></span>')}])}()},"./src/maasserver/static/js/angular/3rdparty/vs-repeat.js":function(module,exports){!function(window,angular){"use strict";var dde=document.documentElement,matchingFunction=dde.matches?"matches":dde.matchesSelector?"matchesSelector":dde.webkitMatches?"webkitMatches":dde.webkitMatchesSelector?"webkitMatchesSelector":dde.msMatches?"msMatches":dde.msMatchesSelector?"msMatchesSelector":dde.mozMatches?"mozMatches":dde.mozMatchesSelector?"mozMatchesSelector":null,closestElement=angular.element.prototype.closest||function(selector){for(var el=this[0].parentNode;el!==document.documentElement&&null!=el&&!el[matchingFunction](selector);)el=el.parentNode;return el&&el[matchingFunction](selector)?angular.element(el):angular.element()};function getWindowScroll(){if("pageYOffset"in window)return{scrollTop:pageYOffset,scrollLeft:pageXOffset};var sx,d=document,r=d.documentElement,b=d.body;return sx=r.scrollLeft||b.scrollLeft||0,{scrollTop:r.scrollTop||b.scrollTop||0,scrollLeft:sx}}function getClientSize(element,sizeProp){return element===window?"clientWidth"===sizeProp?window.innerWidth:window.innerHeight:element[sizeProp]}var vsRepeatModule=angular.module("vs-repeat",[]).directive("vsRepeat",["$compile","$parse",function($compile,$parse){return{restrict:"A",scope:!0,compile:function($element,$attrs){var ngRepeatExpression,expressionMatches,lhs,rhs,rhsSuffix,originalNgRepeatAttr,repeatContainer=angular.isDefined($attrs.vsRepeatContainer)?angular.element($element[0].querySelector($attrs.vsRepeatContainer)):$element,ngRepeatChild=repeatContainer.children().eq(0),childCloneHtml=ngRepeatChild[0].outerHTML,collectionName="$vs_collection",isNgRepeatStart=!1,attributesDictionary={vsRepeat:"elementSize",vsOffsetBefore:"offsetBefore",vsOffsetAfter:"offsetAfter",vsScrolledToEndOffset:"scrolledToEndOffset",vsScrolledToBeginningOffset:"scrolledToBeginningOffset",vsExcess:"excess"};if(ngRepeatChild.attr("ng-repeat"))originalNgRepeatAttr="ng-repeat",ngRepeatExpression=ngRepeatChild.attr("ng-repeat");else if(ngRepeatChild.attr("data-ng-repeat"))originalNgRepeatAttr="data-ng-repeat",ngRepeatExpression=ngRepeatChild.attr("data-ng-repeat");else if(ngRepeatChild.attr("ng-repeat-start"))isNgRepeatStart=!0,originalNgRepeatAttr="ng-repeat-start",ngRepeatExpression=ngRepeatChild.attr("ng-repeat-start");else{if(!ngRepeatChild.attr("data-ng-repeat-start"))throw new Error("angular-vs-repeat: no ng-repeat directive on a child element");isNgRepeatStart=!0,originalNgRepeatAttr="data-ng-repeat-start",ngRepeatExpression=ngRepeatChild.attr("data-ng-repeat-start")}if(expressionMatches=/^\s*(\S+)\s+in\s+([\S\s]+?)(track\s+by\s+\S+)?$/.exec(ngRepeatExpression),lhs=expressionMatches[1],rhs=expressionMatches[2],rhsSuffix=expressionMatches[3],isNgRepeatStart)for(var index=0,repeaterElement=repeatContainer.children().eq(0);null==repeaterElement.attr("ng-repeat-end")&&null==repeaterElement.attr("data-ng-repeat-end");)index++,repeaterElement=repeatContainer.children().eq(index),childCloneHtml+=repeaterElement[0].outerHTML;return repeatContainer.empty(),{pre:function($scope,$element,$attrs){var originalLength,_prevStartIndex,_prevEndIndex,_minStartIndex,_maxEndIndex,_prevClientSize,repeatContainer=angular.isDefined($attrs.vsRepeatContainer)?angular.element($element[0].querySelector($attrs.vsRepeatContainer)):$element,childClone=angular.element(childCloneHtml),childTagName=childClone[0].tagName.toLowerCase(),originalCollection=[],$$horizontal=void 0!==$attrs.vsHorizontal,$beforeContent=angular.element("<"+childTagName+' class="vs-repeat-before-content"></'+childTagName+">"),$afterContent=angular.element("<"+childTagName+' class="vs-repeat-after-content"></'+childTagName+">"),autoSize=!$attrs.vsRepeat,sizesPropertyExists=!!$attrs.vsSize||!!$attrs.vsSizeProperty,$scrollParent=$attrs.vsScrollParent?"window"===$attrs.vsScrollParent?angular.element(window):closestElement.call(repeatContainer,$attrs.vsScrollParent):repeatContainer,$$options="vsOptions"in $attrs?$scope.$eval($attrs.vsOptions):{},clientSize=$$horizontal?"clientWidth":"clientHeight",offsetSize=$$horizontal?"offsetWidth":"offsetHeight",scrollPos=$$horizontal?"scrollLeft":"scrollTop";if($scope.totalSize=0,!("vsSize"in $attrs)&&"vsSizeProperty"in $attrs&&console.warn("vs-size-property attribute is deprecated. Please use vs-size attribute which also accepts angular expressions."),0===$scrollParent.length)throw"Specified scroll parent selector did not match any element";function refresh(){if(!originalCollection||originalCollection.length<1)$scope[collectionName]=[],originalLength=0,$scope.sizesCumulative=[0];else if(originalLength=originalCollection.length,sizesPropertyExists){$scope.sizes=originalCollection.map(function(item){var s=$scope.$new(!1);angular.extend(s,item),s[lhs]=item;var size=$attrs.vsSize||$attrs.vsSizeProperty?s.$eval($attrs.vsSize||$attrs.vsSizeProperty):$scope.elementSize;return s.$destroy(),size});var sum=0;$scope.sizesCumulative=$scope.sizes.map(function(size){var res=sum;return sum+=size,res}),$scope.sizesCumulative.push(sum)}else setAutoSize();reinitialize()}function setAutoSize(){autoSize&&$scope.$$postDigest(function(){if(repeatContainer[0].offsetHeight||repeatContainer[0].offsetWidth){for(var children=repeatContainer.children(),i=0,gotSomething=!1,insideStartEndSequence=!1;i<children.length;){if(null!=children[i].attributes[originalNgRepeatAttr]||insideStartEndSequence){if(gotSomething||($scope.elementSize=0),gotSomething=!0,children[i][offsetSize]&&($scope.elementSize+=children[i][offsetSize]),!isNgRepeatStart)break;if(null!=children[i].attributes["ng-repeat-end"]||null!=children[i].attributes["data-ng-repeat-end"])break;insideStartEndSequence=!0}i++}gotSomething&&(reinitialize(),autoSize=!1,$scope.$root&&!$scope.$root.$$phase&&$scope.$apply())}else var dereg=$scope.$watch(function(){(repeatContainer[0].offsetHeight||repeatContainer[0].offsetWidth)&&(dereg(),setAutoSize())})})}function getLayoutProp(){var layoutPropPrefix="tr"===childTagName?"":"min-";return $$horizontal?layoutPropPrefix+"width":layoutPropPrefix+"height"}function scrollHandler(){updateInnerCollection()&&$scope.$digest()}function onWindowResize(){void 0!==$attrs.vsAutoresize&&(autoSize=!0,setAutoSize(),$scope.$root&&!$scope.$root.$$phase&&$scope.$apply()),updateInnerCollection()&&$scope.$apply()}function reinitialize(){var size;_prevStartIndex=void 0,_prevEndIndex=void 0,_minStartIndex=originalLength,_maxEndIndex=0,size=sizesPropertyExists?$scope.sizesCumulative[originalLength]:$scope.elementSize*originalLength,$scope.totalSize=$scope.offsetBefore+size+$scope.offsetAfter,updateInnerCollection(),$scope.$emit("vsRepeatReinitialized",$scope.startIndex,$scope.endIndex)}function reinitOnClientHeightChange(){var ch=getClientSize($scrollParent[0],clientSize);ch!==_prevClientSize&&(reinitialize(),$scope.$root&&!$scope.$root.$$phase&&$scope.$apply()),_prevClientSize=ch}function updateInnerCollection(){var element,scrollProp,vsElement,scrollElement,isHorizontal,$scrollPosition=(element=$scrollParent[0],scrollProp=scrollPos,element===window?getWindowScroll()[scrollProp]:element[scrollProp]),$clientSize=getClientSize($scrollParent[0],clientSize),scrollOffset=repeatContainer[0]===$scrollParent[0]?0:(vsElement=repeatContainer[0],scrollElement=$scrollParent[0],isHorizontal=$$horizontal,vsElement.getBoundingClientRect()[isHorizontal?"left":"top"]-(scrollElement===window?0:scrollElement.getBoundingClientRect()[isHorizontal?"left":"top"])+(scrollElement===window?getWindowScroll():scrollElement)[isHorizontal?"scrollLeft":"scrollTop"]),__startIndex=$scope.startIndex,__endIndex=$scope.endIndex;if(sizesPropertyExists){for(__startIndex=0;$scope.sizesCumulative[__startIndex]<$scrollPosition-$scope.offsetBefore-scrollOffset;)__startIndex++;for(__startIndex>0&&__startIndex--,__endIndex=__startIndex=Math.max(Math.floor(__startIndex-$scope.excess/2),0);$scope.sizesCumulative[__endIndex]<$scrollPosition-$scope.offsetBefore-scrollOffset+$clientSize;)__endIndex++;__endIndex=Math.min(Math.ceil(__endIndex+$scope.excess/2),originalLength)}else __startIndex=Math.max(Math.floor(($scrollPosition-$scope.offsetBefore-scrollOffset)/$scope.elementSize)-$scope.excess/2,0),__endIndex=Math.min(__startIndex+Math.ceil($clientSize/$scope.elementSize)+$scope.excess,originalLength);_minStartIndex=Math.min(__startIndex,_minStartIndex),_maxEndIndex=Math.max(__endIndex,_maxEndIndex),$scope.startIndex=$$options.latch?_minStartIndex:__startIndex,$scope.endIndex=$$options.latch?_maxEndIndex:__endIndex;var digestRequired=!1;if(null==_prevStartIndex?digestRequired=!0:null==_prevEndIndex&&(digestRequired=!0),digestRequired||($$options.hunked?Math.abs($scope.startIndex-_prevStartIndex)>=$scope.excess/2||0===$scope.startIndex&&0!==_prevStartIndex?digestRequired=!0:(Math.abs($scope.endIndex-_prevEndIndex)>=$scope.excess/2||$scope.endIndex===originalLength&&_prevEndIndex!==originalLength)&&(digestRequired=!0):digestRequired=$scope.startIndex!==_prevStartIndex||$scope.endIndex!==_prevEndIndex),digestRequired){var triggerIndex;$scope[collectionName]=originalCollection.slice($scope.startIndex,$scope.endIndex),$scope.$emit("vsRepeatInnerCollectionUpdated",$scope.startIndex,$scope.endIndex,_prevStartIndex,_prevEndIndex),$attrs.vsScrolledToEnd&&(triggerIndex=originalCollection.length-($scope.scrolledToEndOffset||0),($scope.endIndex>=triggerIndex&&_prevEndIndex<triggerIndex||originalCollection.length&&$scope.endIndex===originalCollection.length)&&$scope.$eval($attrs.vsScrolledToEnd)),$attrs.vsScrolledToBeginning&&(triggerIndex=$scope.scrolledToBeginningOffset||0,$scope.startIndex<=triggerIndex&&_prevStartIndex>$scope.startIndex&&$scope.$eval($attrs.vsScrolledToBeginning)),_prevStartIndex=$scope.startIndex,_prevEndIndex=$scope.endIndex;var parsed=$parse(sizesPropertyExists?"(sizesCumulative[$index + startIndex] + offsetBefore)":"(($index + startIndex) * elementSize + offsetBefore)"),o1=parsed($scope,{$index:0}),o2=parsed($scope,{$index:$scope[collectionName].length}),total=$scope.totalSize;$beforeContent.css(getLayoutProp(),o1+"px"),$afterContent.css(getLayoutProp(),total-o2+"px")}return digestRequired}$scope.$scrollParent=$scrollParent,sizesPropertyExists&&($scope.sizesCumulative=[]),$scope.elementSize=+$attrs.vsRepeat||getClientSize($scrollParent[0],clientSize)||50,$scope.offsetBefore=0,$scope.offsetAfter=0,$scope.excess=2,$$horizontal?($beforeContent.css("height","100%"),$afterContent.css("height","100%")):($beforeContent.css("width","100%"),$afterContent.css("width","100%")),Object.keys(attributesDictionary).forEach(function(key){$attrs[key]&&$attrs.$observe(key,function(value){$scope[attributesDictionary[key]]=+value,reinitialize()})}),$scope.$watchCollection(rhs,function(coll){originalCollection=coll||[],refresh()}),childClone.eq(0).attr(originalNgRepeatAttr,lhs+" in "+collectionName+(rhsSuffix?" "+rhsSuffix:"")),childClone.addClass("vs-repeat-repeated-element"),repeatContainer.append($beforeContent),repeatContainer.append(childClone),$compile(childClone)($scope),repeatContainer.append($afterContent),$scope.startIndex=0,$scope.endIndex=0,$scrollParent.on("scroll",scrollHandler),angular.element(window).on("resize",onWindowResize),$scope.$on("$destroy",function(){angular.element(window).off("resize",onWindowResize),$scrollParent.off("scroll",scrollHandler)}),$scope.$on("vsRepeatTrigger",refresh),$scope.$on("vsRepeatResize",function(){autoSize=!0,setAutoSize()}),$scope.$on("vsRenderAll",function(){$$options.latch&&setTimeout(function(){var __endIndex=originalLength;_maxEndIndex=Math.max(__endIndex,_maxEndIndex),$scope.endIndex=$$options.latch?_maxEndIndex:__endIndex,$scope[collectionName]=originalCollection.slice($scope.startIndex,$scope.endIndex),_prevEndIndex=$scope.endIndex,$scope.$$postDigest(function(){$beforeContent.css(getLayoutProp(),0),$afterContent.css(getLayoutProp(),0)}),$scope.$apply(function(){$scope.$emit("vsRenderAllDone")})})}),$scope.$watch(function(){"function"==typeof window.requestAnimationFrame?window.requestAnimationFrame(reinitOnClientHeightChange):reinitOnClientHeightChange()})}}}}}]);void 0!==module&&module.exports&&(module.exports=vsRepeatModule.name)}(window,window.angular)},0:function(module,exports,__webpack_require__){__webpack_require__("./src/maasserver/static/js/angular/3rdparty/ng-tags-input.js"),module.exports=__webpack_require__("./src/maasserver/static/js/angular/3rdparty/vs-repeat.js")}});
1274 //# sourceMappingURL=vendor-min.js.map
1275\ No newline at end of file
1276diff --git a/src/maasserver/static/js/bundle/vendor-min.js.map b/src/maasserver/static/js/bundle/vendor-min.js.map
1277index 4d387bd..3cb19d2 100644
1278--- a/src/maasserver/static/js/bundle/vendor-min.js.map
1279+++ b/src/maasserver/static/js/bundle/vendor-min.js.map
1280@@ -1 +1 @@
1281-{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/maasserver/static/js/angular/3rdparty/ng-tags-input.js","webpack:///./src/maasserver/static/js/angular/3rdparty/vs-repeat.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","r","value","n","__esModule","object","property","prototype","hasOwnProperty","p","s","KEYS","SUPPORTED_INPUT_TYPES","tagsInput","angular","directive","$timeout","$document","$window","tagsInputConfig","tiUtil","validateType","type","indexOf","restrict","require","scope","tags","onTagAdding","onTagAdded","onInvalidTag","onTagRemoving","onTagRemoved","replace","transclude","templateUrl","controller","$scope","$attrs","$element","events","simplePubSub","load","template","String","placeholder","tabindex","Number","removeTagSymbol","fromCharCode","replaceSpacesWithDashes","Boolean","minLength","maxLength","addOnEnter","addOnSpace","addOnComma","addOnBlur","addOnPaste","pasteSplitPattern","RegExp","allowedTagsPattern","enableEditingLastTag","minTags","maxTags","displayProperty","keyProperty","allowLeftoverText","addFromAutocompleteOnly","spellcheck","tagList","options","getTagText","setTagText","tagIsValid","self","tag","safeToString","text","tagText","length","test","findInObjectArray","items","$tag","addText","add","push","trigger","remove","index","splice","clearSelection","select","selected","selectPrior","selectNext","removeSelected","handleUndefinedResult","this","registerAutocomplete","find","addTag","focusInput","getTags","getCurrentTagText","newTag","getOptions","on","handler","registerTagItem","removeTag","disabled","link","element","attrs","ngModelCtrl","setElementValidity","hotkeys","input","validationOptions","$setValidity","hasFocus","$isEmpty","invalid","setText","track","$watch","makeObjectArray","$observe","eventHandlers","change","keydown","$event","focus","blur","activeElement","prop","lostFocusToBrowserWindow","lostFocusToChildElement","contains","paste","getTextData","clipboardData","originalEvent","getData","host","click","$setViewValue","e","triggerHandler","event","shouldAdd","shouldRemove","shouldSelect","shouldEditLastTag","key","keyCode","addKeys","shiftKey","altKey","ctrlKey","metaKey","preventDefault","split","forEach","data","tagsInputCtrl","$$template","$$removeTagSymbol","$getDisplayText","$removeTag","$index","$sce","$q","source","debounceDelay","highlightMatchedText","maxResultsToShow","loadOnDownArrow","loadOnEmpty","loadOnFocus","selectFirstMatch","suggestionList","loadFn","getDifference","lastPromise","getTagId","array1","array2","filter","item","a","b","defaultComparer","reset","visible","query","show","debounce","promise","when","$query","then","slice","registerAutocompleteMatch","getQuery","shouldLoadSuggestions","addSuggestionByIndex","addSuggestion","added","copy","handled","stopImmediatePropagation","root","eq","parent","elementTop","elementHeight","parentHeight","parentScrollTop","scrollToElement","autoCompleteCtrl","autoComplete","$parent","$highlight","safeHighlight","trustAsHtml","ctrl","transcludeFn","clone","append","span","resize","threshold","getTextAutosizeThreshold","css","originalValue","width","isString","$parsers","unshift","$formatters","$modelValue","tiBindAttrs","$set","provider","globalDefaults","interpolationStatus","autosizeThreshold","setDefaults","defaults","setActiveInterpolation","setTextAutosizeThreshold","$get","$interpolate","converters","parseInt","toLowerCase","defaultValidator","localDefault","validator","converter","getDefault","updateValue","globalValue","isDefined","newValue","factory","fn","delay","timeoutId","args","arguments","cancel","apply","array","isObject","obj","comparer","some","str","encodeHTML","expression","escapeRegexChars","match","isUndefined","toString","trim","valueIfUndefined","result","names","every","run","$templateCache","put","_extends","assign","target","_slicedToArray","arr","Array","isArray","Symbol","iterator","_arr","_n","_d","_e","undefined","_s","_i","next","done","err","_sliceIterator","TypeError","window","closestElement","closest","matchingFunction","reduce","res","_res","document","documentElement","selector","_el","el","parentNode","getWindowScroll","_ref","_document$documentEle","_ref2","_document$documentEle2","scrollTop","pageYOffset","scrollLeft","pageXOffset","body","getClientSize","sizeProp","innerWidth","innerHeight","attrDeprecated","attrname","message","console","warn","concat","printDeprecationWarning","defaultOptions","latch","container","scrollParent","size","offsetBefore","offsetAfter","scrolledToBeginning","noop","scrolledToEnd","scrolledToBeginningOffset","scrolledToEndOffset","scrollMargin","horizontal","autoresize","hunked","hunkSize","vsRepeatModule","$compile","$parse","compile","compileElement","compileAttrs","compileRepeatContainer","querySelector","vsRepeatContainer","repeatContainerChildren","children","ngRepeatChild","childCloneHtml","outerHTML","collectionName","_analyzeNgRepeatUsage2","opt","attr","Error","analyzeNgRepeatUsage","originalNgRepeatAttr","ngRepeatExpression","isNgRepeatStart","_expressionMatches","exec","lhs","rhs","rhsSuffix","repeaterElement","empty","pre","_$scope$$eval","_parseSize","getSize","parsed","writable","vsRepeat","$eval","originalLength","repeatContainer","childClone","childTagName","tagName","originalCollection","$beforeContent","$afterContent","autosizingRequired","$scrollParent","clientSize","offsetSize","scrollSize","scrollPos","totalSize","sizesCumulative","debug","$debugParent","$debug","$on","_prevStartIndex","_prevEndIndex","_minStartIndex","_maxEndIndex","_prevClientSize","measuredSize","refresh","_mapSize","getFromMeasured","reinitialize","hardSize","sizes","map","_hardSize","sum","arr2","from","_toConsumableArray","$$postDigest","offsetHeight","offsetWidth","gotSomething","insideStartEndSequence","attributes","$root","$$phase","$digest","dereg","getLayoutProps","layoutProp","acc","scrollHandler","pos","updateInnerCollection","_ensureScrollIntegrity","onWindowResize","$emit","startIndex","endIndex","reinitOnClientHeightChange","ch","binaryFind","Math","floor","scrollProp","$scrollPosition","$clientSize","vsElement","scrollElement","isHorizontal","scrollOffset","getBoundingClientRect","__startIndex","__endIndex","requestAnimationFrame","expectedSize","compStyle","getComputedStyle","paddings","containerSize","relativeScroll","max","min","digestRequired","abs","triggerIndex","o1","o2","total","vsRepeatOptions","$watchCollection","newOpts","mergedOptions","JSON","stringify","coll","addClass","off","setTimeout","head"],"mappings":"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","file":"vendor-min.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/*!\n * ngTagsInput v2.3.0\n * http://mbenford.github.io/ngTagsInput\n *\n * Copyright (c) 2013-2015 Michael Benford\n * License: MIT\n *\n * Generated at 2015-03-24 00:49:44 -0300\n */\n(function() {\n'use strict';\n\nvar KEYS = {\n backspace: 8,\n tab: 9,\n enter: 13,\n escape: 27,\n space: 32,\n up: 38,\n down: 40,\n left: 37,\n right: 39,\n delete: 46,\n comma: 188\n};\n\nvar MAX_SAFE_INTEGER = 9007199254740991;\nvar SUPPORTED_INPUT_TYPES = ['text', 'email', 'url'];\n\nvar tagsInput = angular.module('ngTagsInput', []);\n\n/**\n * @ngdoc directive\n * @name tagsInput\n * @module ngTagsInput\n *\n * @description\n * Renders an input box with tag editing support.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} [displayProperty=text] Property to be rendered as the tag label.\n * @param {string=} [keyProperty=text] Property to be used as a unique identifier for the tag.\n * @param {string=} [type=text] Type of the input element. Only 'text', 'email' and 'url' are supported values.\n * @param {number=} tabindex Tab order of the control.\n * @param {string=} [placeholder=Add a tag] Placeholder text for the control.\n * @param {number=} [minLength=3] Minimum length for a new tag.\n * @param {number=} [maxLength=MAX_SAFE_INTEGER] Maximum length allowed for a new tag.\n * @param {number=} [minTags=0] Sets minTags validation error key if the number of tags added is less than minTags.\n * @param {number=} [maxTags=MAX_SAFE_INTEGER] Sets maxTags validation error key if the number of tags added is greater than maxTags.\n * @param {boolean=} [allowLeftoverText=false] Sets leftoverText validation error key if there is any leftover text in\n * the input element when the directive loses focus.\n * @param {string=} [removeTagSymbol=×] Symbol character for the remove tag button.\n * @param {boolean=} [addOnEnter=true] Flag indicating that a new tag will be added on pressing the ENTER key.\n * @param {boolean=} [addOnSpace=false] Flag indicating that a new tag will be added on pressing the SPACE key.\n * @param {boolean=} [addOnComma=true] Flag indicating that a new tag will be added on pressing the COMMA key.\n * @param {boolean=} [addOnBlur=true] Flag indicating that a new tag will be added when the input field loses focus.\n * @param {boolean=} [addOnPaste=false] Flag indicating that the text pasted into the input field will be split into tags.\n * @param {string=} [pasteSplitPattern=,] Regular expression used to split the pasted text into tags.\n * @param {boolean=} [replaceSpacesWithDashes=true] Flag indicating that spaces will be replaced with dashes.\n * @param {string=} [allowedTagsPattern=.+] Regular expression that determines whether a new tag is valid.\n * @param {boolean=} [enableEditingLastTag=false] Flag indicating that the last tag will be moved back into\n * the new tag input box instead of being removed when the backspace key\n * is pressed and the input box is empty.\n * @param {boolean=} [addFromAutocompleteOnly=false] Flag indicating that only tags coming from the autocomplete list will be allowed.\n * When this flag is true, addOnEnter, addOnComma, addOnSpace, addOnBlur and\n * allowLeftoverText values are ignored.\n * @param {boolean=} [spellcheck=true] Flag indicating whether the browser's spellcheck is enabled for the input field or not.\n * @param {expression} onTagAdding Expression to evaluate that will be invoked before adding a new tag. The new tag is available as $tag. This method must return either true or false. If false, the tag will not be added.\n * @param {expression} onTagAdded Expression to evaluate upon adding a new tag. The new tag is available as $tag.\n * @param {expression} onInvalidTag Expression to evaluate when a tag is invalid. The invalid tag is available as $tag.\n * @param {expression} onTagRemoving Expression to evaluate that will be invoked before removing a tag. The tag is available as $tag. This method must return either true or false. If false, the tag will not be removed.\n * @param {expression} onTagRemoved Expression to evaluate upon removing an existing tag. The removed tag is available as $tag.\n */\ntagsInput.directive('tagsInput', [\"$timeout\",\"$document\",\"$window\",\"tagsInputConfig\",\"tiUtil\", function($timeout, $document, $window, tagsInputConfig, tiUtil) {\n function TagList(options, events, onTagAdding, onTagRemoving) {\n var self = {}, getTagText, setTagText, tagIsValid;\n\n getTagText = function(tag) {\n return tiUtil.safeToString(tag[options.displayProperty]);\n };\n\n setTagText = function(tag, text) {\n tag[options.displayProperty] = text;\n };\n\n tagIsValid = function(tag) {\n var tagText = getTagText(tag);\n\n return tagText &&\n tagText.length >= options.minLength &&\n tagText.length <= options.maxLength &&\n options.allowedTagsPattern.test(tagText) &&\n !tiUtil.findInObjectArray(self.items, tag, options.keyProperty || options.displayProperty) &&\n onTagAdding({ $tag: tag });\n };\n\n self.items = [];\n\n self.addText = function(text) {\n var tag = {};\n setTagText(tag, text);\n return self.add(tag);\n };\n\n self.add = function(tag) {\n var tagText = getTagText(tag);\n\n if (options.replaceSpacesWithDashes) {\n tagText = tiUtil.replaceSpacesWithDashes(tagText);\n }\n\n setTagText(tag, tagText);\n\n if (tagIsValid(tag)) {\n self.items.push(tag);\n events.trigger('tag-added', { $tag: tag });\n }\n else if (tagText) {\n events.trigger('invalid-tag', { $tag: tag });\n }\n\n return tag;\n };\n\n self.remove = function(index) {\n var tag = self.items[index];\n\n if (onTagRemoving({ $tag: tag })) {\n self.items.splice(index, 1);\n self.clearSelection();\n events.trigger('tag-removed', { $tag: tag });\n return tag;\n }\n };\n\n self.select = function(index) {\n if (index < 0) {\n index = self.items.length - 1;\n }\n else if (index >= self.items.length) {\n index = 0;\n }\n\n self.index = index;\n self.selected = self.items[index];\n };\n\n self.selectPrior = function() {\n self.select(--self.index);\n };\n\n self.selectNext = function() {\n self.select(++self.index);\n };\n\n self.removeSelected = function() {\n return self.remove(self.index);\n };\n\n self.clearSelection = function() {\n self.selected = null;\n self.index = -1;\n };\n\n self.clearSelection();\n\n return self;\n }\n\n function validateType(type) {\n return SUPPORTED_INPUT_TYPES.indexOf(type) !== -1;\n }\n\n return {\n restrict: 'E',\n require: 'ngModel',\n scope: {\n tags: '=ngModel',\n onTagAdding: '&',\n onTagAdded: '&',\n onInvalidTag: '&',\n onTagRemoving: '&',\n onTagRemoved: '&'\n },\n replace: false,\n transclude: true,\n templateUrl: 'ngTagsInput/tags-input.html',\n controller: [\"$scope\",\"$attrs\",\"$element\", function($scope, $attrs, $element) {\n $scope.events = tiUtil.simplePubSub();\n\n tagsInputConfig.load('tagsInput', $scope, $attrs, {\n template: [String, 'ngTagsInput/tag-item.html'],\n type: [String, 'text', validateType],\n placeholder: [String, 'Add a tag'],\n tabindex: [Number, null],\n removeTagSymbol: [String, String.fromCharCode(215)],\n replaceSpacesWithDashes: [Boolean, true],\n minLength: [Number, 3],\n maxLength: [Number, MAX_SAFE_INTEGER],\n addOnEnter: [Boolean, true],\n addOnSpace: [Boolean, false],\n addOnComma: [Boolean, true],\n addOnBlur: [Boolean, true],\n addOnPaste: [Boolean, false],\n pasteSplitPattern: [RegExp, /,/],\n allowedTagsPattern: [RegExp, /.+/],\n enableEditingLastTag: [Boolean, false],\n minTags: [Number, 0],\n maxTags: [Number, MAX_SAFE_INTEGER],\n displayProperty: [String, 'text'],\n keyProperty: [String, ''],\n allowLeftoverText: [Boolean, false],\n addFromAutocompleteOnly: [Boolean, false],\n spellcheck: [Boolean, true]\n });\n\n $scope.tagList = new TagList($scope.options, $scope.events,\n tiUtil.handleUndefinedResult($scope.onTagAdding, true),\n tiUtil.handleUndefinedResult($scope.onTagRemoving, true));\n\n this.registerAutocomplete = function() {\n var input = $element.find('input');\n\n return {\n addTag: function(tag) {\n return $scope.tagList.add(tag);\n },\n focusInput: function() {\n // blake_r - Stop the focus as this breaks on the\n // version of AngularJS that ships with MAAS.\n //input[0].focus();\n },\n getTags: function() {\n return $scope.tags;\n },\n getCurrentTagText: function() {\n return $scope.newTag.text;\n },\n getOptions: function() {\n return $scope.options;\n },\n on: function(name, handler) {\n $scope.events.on(name, handler);\n return this;\n }\n };\n };\n\n this.registerTagItem = function() {\n return {\n getOptions: function() {\n return $scope.options;\n },\n removeTag: function(index) {\n if ($scope.disabled) {\n return;\n }\n $scope.tagList.remove(index);\n }\n };\n };\n }],\n link: function(scope, element, attrs, ngModelCtrl) {\n var hotkeys = [KEYS.enter, KEYS.comma, KEYS.space, KEYS.backspace, KEYS.delete, KEYS.left, KEYS.right],\n tagList = scope.tagList,\n events = scope.events,\n options = scope.options,\n input = element.find('input'),\n validationOptions = ['minTags', 'maxTags', 'allowLeftoverText'],\n setElementValidity;\n\n setElementValidity = function() {\n ngModelCtrl.$setValidity('maxTags', scope.tags.length <= options.maxTags);\n ngModelCtrl.$setValidity('minTags', scope.tags.length >= options.minTags);\n ngModelCtrl.$setValidity('leftoverText', scope.hasFocus || options.allowLeftoverText ? true : !scope.newTag.text);\n };\n\n ngModelCtrl.$isEmpty = function(value) {\n return !value || !value.length;\n };\n\n scope.newTag = {\n text: '',\n invalid: null,\n setText: function(value) {\n this.text = value;\n events.trigger('input-change', value);\n }\n };\n\n scope.track = function(tag) {\n return tag[options.keyProperty || options.displayProperty];\n };\n\n scope.$watch('tags', function(value) {\n scope.tags = tiUtil.makeObjectArray(value, options.displayProperty);\n tagList.items = scope.tags;\n });\n\n scope.$watch('tags.length', function() {\n setElementValidity();\n });\n\n attrs.$observe('disabled', function(value) {\n scope.disabled = value;\n });\n\n scope.eventHandlers = {\n input: {\n change: function(text) {\n events.trigger('input-change', text);\n },\n keydown: function($event) {\n events.trigger('input-keydown', $event);\n },\n focus: function() {\n if (scope.hasFocus) {\n return;\n }\n\n scope.hasFocus = true;\n events.trigger('input-focus');\n },\n blur: function() {\n $timeout(function() {\n var activeElement = $document.prop('activeElement'),\n lostFocusToBrowserWindow = activeElement === input[0],\n lostFocusToChildElement = element[0].contains(activeElement);\n\n if (lostFocusToBrowserWindow || !lostFocusToChildElement) {\n scope.hasFocus = false;\n events.trigger('input-blur');\n }\n });\n },\n paste: function($event) {\n $event.getTextData = function() {\n var clipboardData = $event.clipboardData || ($event.originalEvent && $event.originalEvent.clipboardData);\n return clipboardData ? clipboardData.getData('text/plain') : $window.clipboardData.getData('Text');\n };\n events.trigger('input-paste', $event);\n }\n },\n host: {\n click: function() {\n if (scope.disabled) {\n return;\n }\n // blake_r - Stop the focus as this breaks on the\n // version of AngularJS that ships with MAAS.\n //input[0].focus();\n }\n }\n };\n\n events\n .on('tag-added', scope.onTagAdded)\n .on('invalid-tag', scope.onInvalidTag)\n .on('tag-removed', scope.onTagRemoved)\n .on('tag-added', function() {\n scope.newTag.setText('');\n })\n .on('tag-added tag-removed', function() {\n // Sets the element to its dirty state\n // In Angular 1.3 this will be replaced with $setDirty.\n ngModelCtrl.$setViewValue(scope.tags);\n })\n .on('invalid-tag', function() {\n scope.newTag.invalid = true;\n })\n .on('option-change', function(e) {\n if (validationOptions.indexOf(e.name) !== -1) {\n setElementValidity();\n }\n })\n .on('input-change', function() {\n tagList.clearSelection();\n scope.newTag.invalid = null;\n })\n .on('input-focus', function() {\n element.triggerHandler('focus');\n ngModelCtrl.$setValidity('leftoverText', true);\n })\n .on('input-blur', function() {\n if (options.addOnBlur && !options.addFromAutocompleteOnly) {\n tagList.addText(scope.newTag.text);\n }\n element.triggerHandler('blur');\n setElementValidity();\n })\n .on('input-keydown', function(event) {\n var key = event.keyCode,\n isModifier = event.shiftKey || event.altKey || event.ctrlKey || event.metaKey,\n addKeys = {},\n shouldAdd, shouldRemove, shouldSelect, shouldEditLastTag;\n\n if (isModifier || hotkeys.indexOf(key) === -1) {\n return;\n }\n\n addKeys[KEYS.enter] = options.addOnEnter;\n addKeys[KEYS.comma] = options.addOnComma;\n addKeys[KEYS.space] = options.addOnSpace;\n\n shouldAdd = !options.addFromAutocompleteOnly && addKeys[key];\n shouldRemove = (key === KEYS.backspace || key === KEYS.delete) && tagList.selected;\n shouldEditLastTag = key === KEYS.backspace && scope.newTag.text.length === 0 && options.enableEditingLastTag;\n shouldSelect = (key === KEYS.backspace || key === KEYS.left || key === KEYS.right) && scope.newTag.text.length === 0 && !options.enableEditingLastTag;\n\n if (shouldAdd) {\n tagList.addText(scope.newTag.text);\n }\n else if (shouldEditLastTag) {\n var tag;\n\n tagList.selectPrior();\n tag = tagList.removeSelected();\n\n if (tag) {\n scope.newTag.setText(tag[options.displayProperty]);\n }\n }\n else if (shouldRemove) {\n tagList.removeSelected();\n }\n else if (shouldSelect) {\n if (key === KEYS.left || key === KEYS.backspace) {\n tagList.selectPrior();\n }\n else if (key === KEYS.right) {\n tagList.selectNext();\n }\n }\n\n if (shouldAdd || shouldSelect || shouldRemove || shouldEditLastTag) {\n event.preventDefault();\n }\n })\n .on('input-paste', function(event) {\n if (options.addOnPaste) {\n var data = event.getTextData();\n var tags = data.split(options.pasteSplitPattern);\n\n if (tags.length > 1) {\n tags.forEach(function(tag) {\n tagList.addText(tag);\n });\n event.preventDefault();\n }\n }\n });\n }\n };\n}]);\n\n\n/**\n * @ngdoc directive\n * @name tiTagItem\n * @module ngTagsInput\n *\n * @description\n * Represents a tag item. Used internally by the tagsInput directive.\n */\ntagsInput.directive('tiTagItem', [\"tiUtil\", function(tiUtil) {\n return {\n restrict: 'E',\n require: '^tagsInput',\n template: '<ng-include src=\"$$template\"></ng-include>',\n scope: { data: '=' },\n link: function(scope, element, attrs, tagsInputCtrl) {\n var tagsInput = tagsInputCtrl.registerTagItem(),\n options = tagsInput.getOptions();\n\n scope.$$template = options.template;\n scope.$$removeTagSymbol = options.removeTagSymbol;\n\n scope.$getDisplayText = function() {\n return tiUtil.safeToString(scope.data[options.displayProperty]);\n };\n scope.$removeTag = function() {\n tagsInput.removeTag(scope.$index);\n };\n\n scope.$watch('$parent.$index', function(value) {\n scope.$index = value;\n });\n }\n };\n}]);\n\n\n/**\n * @ngdoc directive\n * @name autoComplete\n * @module ngTagsInput\n *\n * @description\n * Provides autocomplete support for the tagsInput directive.\n *\n * @param {expression} source Expression to evaluate upon changing the input content. The input value is available as\n * $query. The result of the expression must be a promise that eventually resolves to an\n * array of strings.\n * @param {string=} [displayProperty=text] Property to be rendered as the autocomplete label.\n * @param {number=} [debounceDelay=100] Amount of time, in milliseconds, to wait before evaluating the expression in\n * the source option after the last keystroke.\n * @param {number=} [minLength=3] Minimum number of characters that must be entered before evaluating the expression\n * in the source option.\n * @param {boolean=} [highlightMatchedText=true] Flag indicating that the matched text will be highlighted in the\n * suggestions list.\n * @param {number=} [maxResultsToShow=10] Maximum number of results to be displayed at a time.\n * @param {boolean=} [loadOnDownArrow=false] Flag indicating that the source option will be evaluated when the down arrow\n * key is pressed and the suggestion list is closed. The current input value\n * is available as $query.\n * @param {boolean=} {loadOnEmpty=false} Flag indicating that the source option will be evaluated when the input content\n * becomes empty. The $query variable will be passed to the expression as an empty string.\n * @param {boolean=} {loadOnFocus=false} Flag indicating that the source option will be evaluated when the input element\n * gains focus. The current input value is available as $query.\n * @param {boolean=} [selectFirstMatch=true] Flag indicating that the first match will be automatically selected once\n * the suggestion list is shown.\n * @param {string=} [template=] URL or id of a custom template for rendering each element of the autocomplete list.\n */\ntagsInput.directive('autoComplete', [\"$document\",\"$timeout\",\"$sce\",\"$q\",\"tagsInputConfig\",\"tiUtil\", function($document, $timeout, $sce, $q, tagsInputConfig, tiUtil) {\n function SuggestionList(loadFn, options, events) {\n var self = {}, getDifference, lastPromise, getTagId;\n\n getTagId = function() {\n return options.tagsInput.keyProperty || options.tagsInput.displayProperty;\n };\n\n getDifference = function(array1, array2) {\n return array1.filter(function(item) {\n return !tiUtil.findInObjectArray(array2, item, getTagId(), function(a, b) {\n if (options.tagsInput.replaceSpacesWithDashes) {\n a = tiUtil.replaceSpacesWithDashes(a);\n b = tiUtil.replaceSpacesWithDashes(b);\n }\n return tiUtil.defaultComparer(a, b);\n });\n });\n };\n\n self.reset = function() {\n lastPromise = null;\n\n self.items = [];\n self.visible = false;\n self.index = -1;\n self.selected = null;\n self.query = null;\n };\n self.show = function() {\n if (options.selectFirstMatch) {\n self.select(0);\n }\n else {\n self.selected = null;\n }\n self.visible = true;\n };\n self.load = tiUtil.debounce(function(query, tags) {\n self.query = query;\n\n var promise = $q.when(loadFn({ $query: query }));\n lastPromise = promise;\n\n promise.then(function(items) {\n if (promise !== lastPromise) {\n return;\n }\n\n items = tiUtil.makeObjectArray(items.data || items, getTagId());\n items = getDifference(items, tags);\n self.items = items.slice(0, options.maxResultsToShow);\n\n if (self.items.length > 0) {\n self.show();\n }\n else {\n self.reset();\n }\n });\n }, options.debounceDelay);\n\n self.selectNext = function() {\n self.select(++self.index);\n };\n self.selectPrior = function() {\n self.select(--self.index);\n };\n self.select = function(index) {\n if (index < 0) {\n index = self.items.length - 1;\n }\n else if (index >= self.items.length) {\n index = 0;\n }\n self.index = index;\n self.selected = self.items[index];\n events.trigger('suggestion-selected', index);\n };\n\n self.reset();\n\n return self;\n }\n\n function scrollToElement(root, index) {\n var element = root.find('li').eq(index),\n parent = element.parent(),\n elementTop = element.prop('offsetTop'),\n elementHeight = element.prop('offsetHeight'),\n parentHeight = parent.prop('clientHeight'),\n parentScrollTop = parent.prop('scrollTop');\n\n if (elementTop < parentScrollTop) {\n parent.prop('scrollTop', elementTop);\n }\n else if (elementTop + elementHeight > parentHeight + parentScrollTop) {\n parent.prop('scrollTop', elementTop + elementHeight - parentHeight);\n }\n }\n\n return {\n restrict: 'E',\n require: '^tagsInput',\n scope: { source: '&' },\n templateUrl: 'ngTagsInput/auto-complete.html',\n controller: [\"$scope\",\"$element\",\"$attrs\", function($scope, $element, $attrs) {\n $scope.events = tiUtil.simplePubSub();\n\n tagsInputConfig.load('autoComplete', $scope, $attrs, {\n template: [String, 'ngTagsInput/auto-complete-match.html'],\n debounceDelay: [Number, 100],\n minLength: [Number, 3],\n highlightMatchedText: [Boolean, true],\n maxResultsToShow: [Number, 10],\n loadOnDownArrow: [Boolean, false],\n loadOnEmpty: [Boolean, false],\n loadOnFocus: [Boolean, false],\n selectFirstMatch: [Boolean, true],\n displayProperty: [String, '']\n });\n\n $scope.suggestionList = new SuggestionList($scope.source, $scope.options, $scope.events);\n\n this.registerAutocompleteMatch = function() {\n return {\n getOptions: function() {\n return $scope.options;\n },\n getQuery: function() {\n return $scope.suggestionList.query;\n }\n };\n };\n }],\n link: function(scope, element, attrs, tagsInputCtrl) {\n var hotkeys = [KEYS.enter, KEYS.tab, KEYS.escape, KEYS.up, KEYS.down],\n suggestionList = scope.suggestionList,\n tagsInput = tagsInputCtrl.registerAutocomplete(),\n options = scope.options,\n events = scope.events,\n shouldLoadSuggestions;\n\n options.tagsInput = tagsInput.getOptions();\n\n shouldLoadSuggestions = function(value) {\n return value && value.length >= options.minLength || !value && options.loadOnEmpty;\n };\n\n scope.addSuggestionByIndex = function(index) {\n suggestionList.select(index);\n scope.addSuggestion();\n };\n\n scope.addSuggestion = function() {\n var added = false;\n\n if (suggestionList.selected) {\n tagsInput.addTag(angular.copy(suggestionList.selected));\n suggestionList.reset();\n tagsInput.focusInput();\n\n added = true;\n }\n return added;\n };\n\n scope.track = function(item) {\n return item[options.tagsInput.keyProperty || options.tagsInput.displayProperty];\n };\n\n tagsInput\n .on('tag-added invalid-tag input-blur', function() {\n suggestionList.reset();\n })\n .on('input-change', function(value) {\n if (shouldLoadSuggestions(value)) {\n suggestionList.load(value, tagsInput.getTags());\n }\n else {\n suggestionList.reset();\n }\n })\n .on('input-focus', function() {\n var value = tagsInput.getCurrentTagText();\n if (options.loadOnFocus && shouldLoadSuggestions(value)) {\n suggestionList.load(value, tagsInput.getTags());\n }\n })\n .on('input-keydown', function(event) {\n var key = event.keyCode,\n handled = false;\n\n if (hotkeys.indexOf(key) === -1) {\n return;\n }\n\n if (suggestionList.visible) {\n\n if (key === KEYS.down) {\n suggestionList.selectNext();\n handled = true;\n }\n else if (key === KEYS.up) {\n suggestionList.selectPrior();\n handled = true;\n }\n else if (key === KEYS.escape) {\n suggestionList.reset();\n handled = true;\n }\n else if (key === KEYS.enter || key === KEYS.tab) {\n handled = scope.addSuggestion();\n }\n }\n else {\n if (key === KEYS.down && scope.options.loadOnDownArrow) {\n suggestionList.load(tagsInput.getCurrentTagText(), tagsInput.getTags());\n handled = true;\n }\n }\n\n if (handled) {\n event.preventDefault();\n event.stopImmediatePropagation();\n return false;\n }\n });\n\n events.on('suggestion-selected', function(index) {\n scrollToElement(element, index);\n });\n }\n };\n}]);\n\n\n/**\n * @ngdoc directive\n * @name tiAutocompleteMatch\n * @module ngTagsInput\n *\n * @description\n * Represents an autocomplete match. Used internally by the autoComplete directive.\n */\ntagsInput.directive('tiAutocompleteMatch', [\"$sce\",\"tiUtil\", function($sce, tiUtil) {\n return {\n restrict: 'E',\n require: '^autoComplete',\n template: '<ng-include src=\"$$template\"></ng-include>',\n scope: { data: '=' },\n link: function(scope, element, attrs, autoCompleteCtrl) {\n var autoComplete = autoCompleteCtrl.registerAutocompleteMatch(),\n options = autoComplete.getOptions();\n\n scope.$$template = options.template;\n scope.$index = scope.$parent.$index;\n\n scope.$highlight = function(text) {\n if (options.highlightMatchedText) {\n text = tiUtil.safeHighlight(text, autoComplete.getQuery());\n }\n return $sce.trustAsHtml(text);\n };\n scope.$getDisplayText = function() {\n return tiUtil.safeToString(scope.data[options.displayProperty || options.tagsInput.displayProperty]);\n };\n }\n };\n}]);\n\n\n/**\n * @ngdoc directive\n * @name tiTranscludeAppend\n * @module ngTagsInput\n *\n * @description\n * Re-creates the old behavior of ng-transclude. Used internally by tagsInput directive.\n */\ntagsInput.directive('tiTranscludeAppend', function() {\n return function(scope, element, attrs, ctrl, transcludeFn) {\n transcludeFn(function(clone) {\n element.append(clone);\n });\n };\n});\n\n/**\n * @ngdoc directive\n * @name tiAutosize\n * @module ngTagsInput\n *\n * @description\n * Automatically sets the input's width so its content is always visible. Used internally by tagsInput directive.\n */\ntagsInput.directive('tiAutosize', [\"tagsInputConfig\", function(tagsInputConfig) {\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function(scope, element, attrs, ctrl) {\n var threshold = tagsInputConfig.getTextAutosizeThreshold(),\n span, resize;\n\n span = angular.element('<span class=\"input\"></span>');\n span.css('display', 'none')\n .css('visibility', 'hidden')\n .css('width', 'auto')\n .css('white-space', 'pre');\n\n element.parent().append(span);\n\n resize = function(originalValue) {\n var value = originalValue, width;\n\n if (angular.isString(value) && value.length === 0) {\n value = attrs.placeholder;\n }\n\n if (value) {\n span.text(value);\n span.css('display', '');\n width = span.prop('offsetWidth');\n span.css('display', 'none');\n }\n\n element.css('width', width ? width + threshold + 'px' : '');\n\n return originalValue;\n };\n\n ctrl.$parsers.unshift(resize);\n ctrl.$formatters.unshift(resize);\n\n attrs.$observe('placeholder', function(value) {\n if (!ctrl.$modelValue) {\n resize(value);\n }\n });\n }\n };\n}]);\n\n/**\n * @ngdoc directive\n * @name tiBindAttrs\n * @module ngTagsInput\n *\n * @description\n * Binds attributes to expressions. Used internally by tagsInput directive.\n */\ntagsInput.directive('tiBindAttrs', function() {\n return function(scope, element, attrs) {\n scope.$watch(attrs.tiBindAttrs, function(value) {\n angular.forEach(value, function(value, key) {\n /**\n * blake_r - Added to work around the version of jQuery that\n * MAAS currently ships with. Once packaging for jQuery is\n * version >1.9 this can be removed.\n */\n if(key === \"type\") {\n element[0].type = value;\n } else {\n attrs.$set(key, value);\n }\n });\n }, true);\n };\n});\n\n/**\n * @ngdoc service\n * @name tagsInputConfig\n * @module ngTagsInput\n *\n * @description\n * Sets global configuration settings for both tagsInput and autoComplete directives. It's also used internally to parse and\n * initialize options from HTML attributes.\n */\ntagsInput.provider('tagsInputConfig', function() {\n var globalDefaults = {},\n interpolationStatus = {},\n autosizeThreshold = 3;\n\n /**\n * @ngdoc method\n * @name setDefaults\n * @description Sets the default configuration option for a directive.\n * @methodOf tagsInputConfig\n *\n * @param {string} directive Name of the directive to be configured. Must be either 'tagsInput' or 'autoComplete'.\n * @param {object} defaults Object containing options and their values.\n *\n * @returns {object} The service itself for chaining purposes.\n */\n this.setDefaults = function(directive, defaults) {\n globalDefaults[directive] = defaults;\n return this;\n };\n\n /***\n * @ngdoc method\n * @name setActiveInterpolation\n * @description Sets active interpolation for a set of options.\n * @methodOf tagsInputConfig\n *\n * @param {string} directive Name of the directive to be configured. Must be either 'tagsInput' or 'autoComplete'.\n * @param {object} options Object containing which options should have interpolation turned on at all times.\n *\n * @returns {object} The service itself for chaining purposes.\n */\n this.setActiveInterpolation = function(directive, options) {\n interpolationStatus[directive] = options;\n return this;\n };\n\n /***\n * @ngdoc method\n * @name setTextAutosizeThreshold\n * @description Sets the threshold used by the tagsInput directive to re-size the inner input field element based on its contents.\n * @methodOf tagsInputConfig\n *\n * @param {number} threshold Threshold value, in pixels.\n *\n * @returns {object} The service itself for chaining purposes.\n */\n this.setTextAutosizeThreshold = function(threshold) {\n autosizeThreshold = threshold;\n return this;\n };\n\n this.$get = [\"$interpolate\", function($interpolate) {\n var converters = {};\n converters[String] = function(value) { return value; };\n converters[Number] = function(value) { return parseInt(value, 10); };\n converters[Boolean] = function(value) { return value.toLowerCase() === 'true'; };\n converters[RegExp] = function(value) { return new RegExp(value); };\n\n return {\n load: function(directive, scope, attrs, options) {\n var defaultValidator = function() { return true; };\n\n scope.options = {};\n\n angular.forEach(options, function(value, key) {\n var type, localDefault, validator, converter, getDefault, updateValue;\n\n type = value[0];\n localDefault = value[1];\n validator = value[2] || defaultValidator;\n converter = converters[type];\n\n getDefault = function() {\n var globalValue = globalDefaults[directive] && globalDefaults[directive][key];\n return angular.isDefined(globalValue) ? globalValue : localDefault;\n };\n\n updateValue = function(value) {\n scope.options[key] = value && validator(value) ? converter(value) : getDefault();\n };\n\n if (interpolationStatus[directive] && interpolationStatus[directive][key]) {\n attrs.$observe(key, function(value) {\n updateValue(value);\n scope.events.trigger('option-change', { name: key, newValue: value });\n });\n }\n else {\n updateValue(attrs[key] && $interpolate(attrs[key])(scope.$parent));\n }\n });\n },\n getTextAutosizeThreshold: function() {\n return autosizeThreshold;\n }\n };\n }];\n});\n\n\n/***\n * @ngdoc factory\n * @name tiUtil\n * @module ngTagsInput\n *\n * @description\n * Helper methods used internally by the directive. Should not be called directly from user code.\n */\ntagsInput.factory('tiUtil', [\"$timeout\", function($timeout) {\n var self = {};\n\n self.debounce = function(fn, delay) {\n var timeoutId;\n return function() {\n var args = arguments;\n $timeout.cancel(timeoutId);\n timeoutId = $timeout(function() { fn.apply(null, args); }, delay);\n };\n };\n\n self.makeObjectArray = function(array, key) {\n array = array || [];\n if (array.length > 0 && !angular.isObject(array[0])) {\n array.forEach(function(item, index) {\n array[index] = {};\n array[index][key] = item;\n });\n }\n return array;\n };\n\n self.findInObjectArray = function(array, obj, key, comparer) {\n var item = null;\n comparer = comparer || self.defaultComparer;\n\n array.some(function(element) {\n if (comparer(element[key], obj[key])) {\n item = element;\n return true;\n }\n });\n\n return item;\n };\n\n self.defaultComparer = function(a, b) {\n // I'm aware of the internationalization issues regarding toLowerCase()\n // but I couldn't come up with a better solution right now\n return self.safeToString(a).toLowerCase() === self.safeToString(b).toLowerCase();\n };\n\n self.safeHighlight = function(str, value) {\n if (!value) {\n return str;\n }\n\n function escapeRegexChars(str) {\n return str.replace(/([.?*+^$[\\]\\\\(){}|-])/g, '\\\\$1');\n }\n\n str = self.encodeHTML(str);\n value = self.encodeHTML(value);\n\n var expression = new RegExp('&[^;]+;|' + escapeRegexChars(value), 'gi');\n return str.replace(expression, function(match) {\n return match.toLowerCase() === value.toLowerCase() ? '<em>' + match + '</em>' : match;\n });\n };\n\n self.safeToString = function(value) {\n return angular.isUndefined(value) || value == null ? '' : value.toString().trim();\n };\n\n self.encodeHTML = function(value) {\n return self.safeToString(value)\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n };\n\n self.handleUndefinedResult = function(fn, valueIfUndefined) {\n return function() {\n var result = fn.apply(null, arguments);\n return angular.isUndefined(result) ? valueIfUndefined : result;\n };\n };\n\n self.replaceSpacesWithDashes = function(str) {\n return self.safeToString(str).replace(/\\s/g, '-');\n };\n\n self.simplePubSub = function() {\n var events = {};\n return {\n on: function(names, handler) {\n names.split(' ').forEach(function(name) {\n if (!events[name]) {\n events[name] = [];\n }\n events[name].push(handler);\n });\n return this;\n },\n trigger: function(name, args) {\n var handlers = events[name] || [];\n handlers.every(function(handler) {\n return self.handleUndefinedResult(handler, true)(args);\n });\n return this;\n }\n };\n };\n\n return self;\n}]);\n\n/* HTML templates */\ntagsInput.run([\"$templateCache\", function($templateCache) {\n $templateCache.put('ngTagsInput/tags-input.html',\n \"<div class=\\\"host\\\" tabindex=\\\"-1\\\" data-ng-click=\\\"eventHandlers.host.click()\\\" ti-transclude-append=\\\"\\\"><div class=\\\"tags\\\" data-ng-class=\\\"{focused: hasFocus}\\\"><ul class=\\\"tag-list\\\"><li class=\\\"tag-item\\\" data-ng-repeat=\\\"tag in tagList.items track by track(tag)\\\" data-ng-class=\\\"{ selected: tag == tagList.selected }\\\"><ti-tag-item data=\\\"tag\\\"></ti-tag-item></li></ul><input class=\\\"input u-no-margin--top\\\" autocomplete=\\\"off\\\" data-ng-model=\\\"newTag.text\\\" data-ng-change=\\\"eventHandlers.input.change(newTag.text)\\\" data-ng-keydown=\\\"eventHandlers.input.keydown($event)\\\" data-ng-focus=\\\"eventHandlers.input.focus($event)\\\" data-ng-blur=\\\"eventHandlers.input.blur($event)\\\" data-ng-paste=\\\"eventHandlers.input.paste($event)\\\" data-ng-trim=\\\"false\\\" data-ng-class=\\\"{'invalid-tag': newTag.invalid}\\\" data-ng-disabled=\\\"disabled\\\" ti-bind-attrs=\\\"{type: options.type, placeholder: options.placeholder, tabindex: options.tabindex, spellcheck: options.spellcheck}\\\" ti-autosize=\\\"\\\"></div></div>\"\n );\n\n $templateCache.put('ngTagsInput/tag-item.html',\n \"<span ng-bind=\\\"$getDisplayText()\\\"></span> <a class=\\\"p-icon--close\\\" data-ng-click=\\\"$removeTag()\\\" data-ng-bind=\\\"$$removeTagSymbol\\\">Remove tag</a>\"\n );\n\n $templateCache.put('ngTagsInput/auto-complete.html',\n \"<div class=\\\"autocomplete\\\" data-ng-if=\\\"suggestionList.visible\\\"><ul class=\\\"p-list suggestion-list\\\"><li class=\\\"suggestion-item\\\" data-ng-repeat=\\\"item in suggestionList.items track by track(item)\\\" data-ng-class=\\\"{selected: item == suggestionList.selected}\\\" data-ng-click=\\\"addSuggestionByIndex($index)\\\" data-ng-mouseenter=\\\"suggestionList.select($index)\\\"><ti-autocomplete-match data=\\\"item\\\"></ti-autocomplete-match></li></ul></div>\"\n );\n\n $templateCache.put('ngTagsInput/auto-complete-match.html',\n \"<span data-ng-bind-html=\\\"$highlight($getDisplayText())\\\"></span>\"\n );\n}]);\n\n}());\n","/*!\n * Angular Virtual Scroll Repeat v2.0.9\n * https://github.com/kamilkp/angular-vs-repeat/\n *\n * Copyright Kamil Pękala\n * http://github.com/kamilkp\n *\n * Released under the MIT License\n * https://opensource.org/licenses/MIT\n *\n * Date: 2018/04/02\n */\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _slicedToArray(arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return _sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }\n\n/* global console, setTimeout, module */\n(function (window, angular) {\n /**\n * DESCRIPTION:\n * vsRepeat directive stands for Virtual Scroll Repeat. It turns a standard ngRepeated set of elements in a scrollable container\n * into a component, where the user thinks he has all the elements rendered and all he needs to do is scroll (without any kind of\n * pagination - which most users loath) and at the same time the browser isn't overloaded by that many elements/angular bindings etc.\n * The directive renders only so many elements that can fit into current container's clientHeight/clientWidth.\n * LIMITATIONS:\n * - current version only supports an Array as a right-hand-side object for ngRepeat\n * - all rendered elements must have the same height/width or the sizes of the elements must be known up front\n * USAGE:\n * In order to use the vsRepeat directive you need to place a vs-repeat attribute on a direct parent of an element with ng-repeat\n * example:\n * <div vs-repeat=\"options\">\n * <div ng-repeat=\"item in someArray\">\n * <!-- content -->\n * </div>\n * </div>\n * or:\n * <div vs-repeat=\"options\">\n * <div ng-repeat-start=\"item in someArray\">\n * <!-- content -->\n * </div>\n * <div>\n * <!-- something in the middle -->\n * </div>\n * <div ng-repeat-end>\n * <!-- content -->\n * </div>\n * </div>\n * You can also measure the single element's height/width (including all paddings and margins), and then speficy it as a value\n * of the option's `size` property. This can be used if one wants to override the automatically computed element size.\n * example:\n * <div vs-repeat=\"{size: 50}\"> <!-- the specified element height is 50px -->\n * <div ng-repeat=\"item in someArray\">\n * <!-- content -->\n * </div>\n * </div>\n * IMPORTANT!\n * - the vsRepeat directive must be applied to a direct parent of an element with ngRepeat\n * - the value of vsRepeat attribute is the single element's height/width measured in pixels. If none provided, the directive\n * will compute it automatically\n * OPTIONAL PARAMETERS (attributes):\n * vs-repeat-container=\"selector\" - selector for element containing ng-repeat. (defaults to the current element)\n * OPTIONS:\n * Options shall be passed as an object to the `vs-repeat` attribute e.g.: `<div vs-repeat=\"{scrollParent: 'window', size: 20}\"></div>`\n *\n * Available options:\n * `horizontal` - stack repeated elements horizontally instead of vertically\n * `offset-before` - top/left offset in pixels (defaults to 0)\n * `offset-after` - bottom/right offset in pixels (defaults to 0)\n * `scroll-margin` - how many pixels ahead should elements be rendered while scrolling\n * `latch` - if true, elements will be rendered gradually but won't be removed when scrolled away (defaults to false)\n * `size` - a property name of the items in collection that is a number denoting the element size (in pixels)\n * `autoresize` - use this attribute without vs-size and without specifying element's size. The automatically computed element style will\n * readjust upon window resize if the size is dependable on the viewport size\n * `scrolled-to-end` - callback will be called when the last item of the list is rendered\n * `scrolled-to-end-offset` - set this number to trigger the scrolledToEnd callback n items before the last gets rendered\n * `scrolled-to-beginning` - callback will be called when the first item of the list is rendered\n * `scrolled-to-beginning-offset` - set this number to trigger the scrolledToBeginning callback n items before the first gets rendered\n * EVENTS:\n * - `vsRepeatTrigger` - an event the directive listens for to manually trigger reinitialization\n * - `vsRepeatReinitialized` - an event the directive emits upon reinitialization done\n */\n var closestElement = angular.element.prototype.closest;\n\n if (!closestElement) {\n var matchingFunction = ['matches', 'matchesSelector', 'webkitMatches', 'webkitMatchesSelector', 'msMatches', 'msMatchesSelector', 'mozMatches', 'mozMatchesSelector'].reduce(function (res, prop) {\n var _res;\n\n return (_res = res) !== null && _res !== void 0 ? _res : prop in document.documentElement ? prop : null;\n }, null);\n\n closestElement = function closestElement(selector) {\n var _el;\n\n var el = this[0].parentNode;\n\n while (el !== document.documentElement && el != null && !el[matchingFunction](selector)) {\n el = el.parentNode;\n }\n\n if ((_el = el) === null || _el === void 0 ? void 0 : _el[matchingFunction](selector)) {\n return angular.element(el);\n }\n\n return angular.element();\n };\n }\n\n function getWindowScroll() {\n var _ref, _document$documentEle, _ref2, _document$documentEle2;\n\n if ('pageYOffset' in window) {\n return {\n scrollTop: window.pageYOffset,\n scrollLeft: window.pageXOffset\n };\n }\n\n return {\n scrollTop: (_ref = (_document$documentEle = document.documentElement.scrollTop) !== null && _document$documentEle !== void 0 ? _document$documentEle : document.body.scrollTop) !== null && _ref !== void 0 ? _ref : 0,\n scrollLeft: (_ref2 = (_document$documentEle2 = document.documentElement.scrollLeft) !== null && _document$documentEle2 !== void 0 ? _document$documentEle2 : document.body.scrollLeft) !== null && _ref2 !== void 0 ? _ref2 : 0\n };\n }\n\n function getClientSize(element, sizeProp) {\n if (element === window) {\n return sizeProp === 'clientWidth' ? window.innerWidth : window.innerHeight;\n }\n\n return element[sizeProp];\n }\n\n function getScrollPos(element, scrollProp) {\n return element === window ? getWindowScroll()[scrollProp] : element[scrollProp];\n }\n\n function getScrollOffset(vsElement, scrollElement, isHorizontal) {\n var vsPos = vsElement.getBoundingClientRect()[isHorizontal ? 'left' : 'top'];\n var scrollPos = scrollElement === window ? 0 : scrollElement.getBoundingClientRect()[isHorizontal ? 'left' : 'top'];\n var scrollValue = (scrollElement === window ? getWindowScroll() : scrollElement)[isHorizontal ? 'scrollLeft' : 'scrollTop'];\n return vsPos - scrollPos + scrollValue;\n }\n\n function analyzeNgRepeatUsage(element) {\n var options = ['ng-repeat', 'data-ng-repeat', 'ng-repeat-start', 'data-ng-repeat-start'];\n\n for (var _i = 0; _i < options.length; _i++) {\n var opt = options[_i];\n\n if (element.attr(opt)) {\n return [opt, element.attr(opt), opt.indexOf('-start') >= 0];\n }\n }\n\n throw new Error('angular-vs-repeat: no ng-repeat directive on a child element');\n }\n\n function printDeprecationWarning($element, message) {\n console.warn(\"vs-repeat deprecation: \".concat(message), $element[0]);\n }\n\n function attrDeprecated(attrname, $element) {\n printDeprecationWarning($element, \"\".concat(attrname, \" attribute is deprecated. Pass the options object to vs-repeat attribute instead https://github.com/kamilkp/angular-vs-repeat#options\"));\n }\n\n var defaultOptions = {\n latch: false,\n container: null,\n scrollParent: null,\n size: null,\n offsetBefore: 0,\n offsetAfter: 0,\n scrolledToBeginning: angular.noop,\n scrolledToEnd: angular.noop,\n scrolledToBeginningOffset: 0,\n scrolledToEndOffset: 0,\n scrollMargin: 0,\n horizontal: false,\n autoresize: false,\n hunked: false,\n hunkSize: 0\n };\n var vsRepeatModule = angular.module('vs-repeat', []).directive('vsRepeat', ['$compile', '$parse', function ($compile, $parse) {\n return {\n restrict: 'A',\n scope: true,\n compile: function compile(compileElement, compileAttrs) {\n var compileRepeatContainer = 'vsRepeatContainer' in compileAttrs ? angular.element(compileElement[0].querySelector(compileAttrs.vsRepeatContainer)) : compileElement;\n var repeatContainerChildren = compileRepeatContainer.children();\n var ngRepeatChild = repeatContainerChildren.eq(0);\n var childCloneHtml = ngRepeatChild[0].outerHTML;\n var collectionName = '$vs_collection'; // TODO: make configurable?\n\n ['vsSize', 'vsScrollParent', 'vsSizeProperty', 'vsHorizontal', 'vsOffsetBefore', 'vsOffsetAfter', 'vsScrolledToEndOffset', 'vsScrolledToBeginningOffset', 'vsExcess', 'vsScrollMargin'].forEach(function (attrname) {\n if (attrname in compileAttrs) {\n attrDeprecated(attrname, compileElement);\n }\n });\n\n var _analyzeNgRepeatUsage = analyzeNgRepeatUsage(ngRepeatChild),\n _analyzeNgRepeatUsage2 = _slicedToArray(_analyzeNgRepeatUsage, 3),\n originalNgRepeatAttr = _analyzeNgRepeatUsage2[0],\n ngRepeatExpression = _analyzeNgRepeatUsage2[1],\n isNgRepeatStart = _analyzeNgRepeatUsage2[2];\n\n var expressionMatches = /^\\s*(\\S+)\\s+in\\s+([\\S\\s]+?)(track\\s+by\\s+\\S+)?$/.exec(ngRepeatExpression);\n\n var _expressionMatches = _slicedToArray(expressionMatches, 4),\n lhs = _expressionMatches[1],\n rhs = _expressionMatches[2],\n rhsSuffix = _expressionMatches[3];\n\n if (isNgRepeatStart) {\n var index = 0;\n var repeaterElement = repeatContainerChildren.eq(index);\n\n while (repeaterElement.attr('ng-repeat-end') == null && repeaterElement.attr('data-ng-repeat-end') == null) {\n index++;\n repeaterElement = repeatContainerChildren.eq(index);\n childCloneHtml += repeaterElement[0].outerHTML;\n }\n }\n\n compileRepeatContainer.empty();\n return {\n pre: function pre($scope, $element, $attrs) {\n var _$scope$$eval;\n\n function _parseSize(options) {\n if (typeof options.size === 'number') {\n options.getSize = function () {\n return options.size;\n };\n } else {\n var parsed = $parse(String(options.size));\n\n options.getSize = function (item) {\n return parsed($scope, _defineProperty({}, lhs, item));\n };\n }\n }\n\n $scope.vsRepeat = {\n options: _extends({}, defaultOptions, (_$scope$$eval = $scope.$eval($attrs.vsRepeat)) !== null && _$scope$$eval !== void 0 ? _$scope$$eval : {})\n };\n var options = $scope.vsRepeat.options;\n\n _parseSize(options);\n\n var repeatContainer = angular.isDefined($attrs.vsRepeatContainer) ? angular.element($element[0].querySelector($attrs.vsRepeatContainer)) : $element;\n var childClone = angular.element(childCloneHtml);\n var childTagName = childClone[0].tagName.toLowerCase();\n var originalCollection = [];\n var originalLength;\n var $beforeContent = angular.element('<' + childTagName + ' class=\"vs-repeat-before-content\"></' + childTagName + '>');\n var $afterContent = angular.element('<' + childTagName + ' class=\"vs-repeat-after-content\"></' + childTagName + '>');\n var autosizingRequired = options.size === null;\n var $scrollParent = options.scrollParent ? options.scrollParent === 'window' ? angular.element(window) : closestElement.call(repeatContainer, options.scrollParent) : repeatContainer;\n var clientSize = options.horizontal ? 'clientWidth' : 'clientHeight';\n var offsetSize = options.horizontal ? 'offsetWidth' : 'offsetHeight';\n var scrollSize = options.horizontal ? 'scrollWidth' : 'scrollHeight';\n var scrollPos = options.horizontal ? 'scrollLeft' : 'scrollTop';\n $scope.vsRepeat.totalSize = 0;\n\n if ($scrollParent.length === 0) {\n throw 'Specified scroll parent selector did not match any element';\n }\n\n $scope.vsRepeat.$scrollParent = $scrollParent;\n $scope.vsRepeat.sizesCumulative = [];\n\n if (options.debug) {\n var $debugParent = options.scrollParent === 'window' ? angular.element(document.body) : $scrollParent;\n var $debug = angular.element('<div class=\"vs-repeat-debug-element\"></div>');\n $debug.css('position', options.scrollParent === 'window' ? 'fixed' : 'absolute');\n $debugParent.append($debug);\n $scope.$on('$destroy', function () {\n $debug.remove();\n });\n }\n\n var measuredSize = getClientSize($scrollParent[0], clientSize) || 50;\n\n if (options.horizontal) {\n $beforeContent.css('height', '100%');\n $afterContent.css('height', '100%');\n } else {\n $beforeContent.css('width', '100%');\n $afterContent.css('width', '100%');\n }\n\n if ($attrs.vsRepeatOptions) {\n $scope.$watchCollection($attrs.vsRepeatOptions, function (newOpts) {\n var mergedOptions = _extends({}, options, newOpts);\n\n if (JSON.stringify(mergedOptions) !== JSON.stringify(options)) {\n Object.assign(options, newOpts);\n\n _parseSize(options);\n\n reinitialize();\n }\n });\n }\n\n $scope.$watchCollection(rhs, function () {\n var coll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];\n originalCollection = coll;\n refresh();\n });\n\n function refresh() {\n if (!originalCollection || originalCollection.length < 1) {\n $scope[collectionName] = [];\n originalLength = 0;\n $scope.vsRepeat.sizesCumulative = [0];\n } else {\n originalLength = originalCollection.length;\n\n if (options.size) {\n _mapSize();\n } else {\n getFromMeasured();\n }\n }\n\n reinitialize();\n }\n\n function _mapSize() {\n var hardSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var sizes = originalCollection.map(function (item) {\n var _hardSize;\n\n return (_hardSize = hardSize) !== null && _hardSize !== void 0 ? _hardSize : options.getSize(item);\n });\n var sum = 0;\n $scope.vsRepeat.sizesCumulative = [0].concat(_toConsumableArray(sizes.map(function (size) {\n return sum += size;\n })));\n }\n\n function getFromMeasured() {\n if (autosizingRequired) {\n $scope.$$postDigest(function () {\n if (repeatContainer[0].offsetHeight || repeatContainer[0].offsetWidth) {\n // element is visible\n var children = repeatContainer.children();\n var i = 0;\n var gotSomething = false;\n var insideStartEndSequence = false;\n\n while (i < children.length) {\n if (children[i].attributes[originalNgRepeatAttr] != null || insideStartEndSequence) {\n if (!gotSomething) {\n measuredSize = 0;\n }\n\n gotSomething = true;\n\n if (children[i][offsetSize]) {\n measuredSize += children[i][offsetSize];\n }\n\n if (isNgRepeatStart) {\n if (children[i].attributes['ng-repeat-end'] != null || children[i].attributes['data-ng-repeat-end'] != null) {\n break;\n } else {\n insideStartEndSequence = true;\n }\n } else {\n break;\n }\n }\n\n i++;\n }\n\n if (gotSomething) {\n _mapSize(measuredSize);\n\n reinitialize();\n autosizingRequired = false;\n\n if ($scope.$root && !$scope.$root.$$phase) {\n $scope.$digest();\n }\n }\n } else {\n var dereg = $scope.$watch(function () {\n if (repeatContainer[0].offsetHeight || repeatContainer[0].offsetWidth) {\n dereg();\n getFromMeasured();\n }\n });\n }\n });\n } else {\n _mapSize(measuredSize);\n }\n }\n\n function getLayoutProps(value) {\n var layoutProp = options.horizontal ? 'width' : 'height';\n return ['', 'min-', 'max-'].reduce(function (acc, prop) {\n return acc[\"\".concat(prop).concat(layoutProp)] = value, acc;\n }, {});\n }\n\n childClone.eq(0).attr(originalNgRepeatAttr, lhs + ' in ' + collectionName + (rhsSuffix ? ' ' + rhsSuffix : ''));\n childClone.addClass('vs-repeat-repeated-element');\n repeatContainer.append($beforeContent);\n repeatContainer.append(childClone);\n $compile(childClone)($scope);\n repeatContainer.append($afterContent);\n $scope.vsRepeat.startIndex = 0;\n $scope.vsRepeat.endIndex = 0;\n\n function scrollHandler() {\n var pos = $scrollParent[0][scrollPos];\n\n if (updateInnerCollection()) {\n $scope.$digest();\n\n if (options._ensureScrollIntegrity) {\n $scrollParent[0][scrollPos] = pos;\n }\n }\n }\n\n $scrollParent.on('scroll', scrollHandler);\n\n function onWindowResize() {\n if (options.autoresize) {\n autosizingRequired = true;\n getFromMeasured();\n\n if ($scope.$root && !$scope.$root.$$phase) {\n $scope.$digest();\n }\n }\n\n if (updateInnerCollection()) {\n $scope.$digest();\n }\n }\n\n angular.element(window).on('resize', onWindowResize);\n $scope.$on('$destroy', function () {\n angular.element(window).off('resize', onWindowResize);\n $scrollParent.off('scroll', scrollHandler);\n });\n $scope.$on('vsRepeatTrigger', refresh);\n $scope.$on('vsRepeatResize', function () {\n autosizingRequired = true;\n getFromMeasured();\n });\n\n var _prevStartIndex, _prevEndIndex, _minStartIndex, _maxEndIndex;\n\n $scope.$on('vsRenderAll', function () {\n if (!options.latch) {\n return;\n }\n\n if ($scope.vsRepeat.endIndex === originalLength) {\n $scope.$emit('vsRenderAllDone');\n return;\n }\n\n setTimeout(function () {\n // var __endIndex = Math.min($scope.vsRepeat.endIndex + (quantum || 1), originalLength);\n var __endIndex = originalLength;\n _maxEndIndex = Math.max(__endIndex, _maxEndIndex);\n $scope.vsRepeat.endIndex = options.latch ? _maxEndIndex : __endIndex;\n $scope[collectionName] = originalCollection.slice($scope.vsRepeat.startIndex, $scope.vsRepeat.endIndex);\n _prevEndIndex = $scope.vsRepeat.endIndex;\n $beforeContent.css(getLayoutProps(0));\n $afterContent.css(getLayoutProps(0));\n $scope.$emit('vsRenderAllDone');\n\n if ($scope.$root && !$scope.$root.$$phase) {\n $scope.$digest();\n }\n });\n });\n\n function reinitialize() {\n _prevStartIndex = void 0;\n _prevEndIndex = void 0;\n _minStartIndex = originalLength;\n _maxEndIndex = 0;\n updateTotalSize($scope.vsRepeat.sizesCumulative[originalLength]);\n updateInnerCollection();\n $scope.$emit('vsRepeatReinitialized', $scope.vsRepeat.startIndex, $scope.vsRepeat.endIndex);\n }\n\n function updateTotalSize(size) {\n $scope.vsRepeat.totalSize = options.offsetBefore + size + options.offsetAfter;\n }\n\n var _prevClientSize;\n\n function reinitOnClientHeightChange() {\n var ch = getClientSize($scrollParent[0], clientSize);\n\n if (ch !== _prevClientSize) {\n reinitialize();\n\n if ($scope.$root && !$scope.$root.$$phase) {\n $scope.$digest();\n }\n }\n\n _prevClientSize = ch;\n }\n\n $scope.$watch(function () {\n if (typeof window.requestAnimationFrame === 'function') {\n window.requestAnimationFrame(reinitOnClientHeightChange);\n } else {\n reinitOnClientHeightChange();\n }\n });\n\n function binaryFind(array, threshold) {\n var a = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n var b = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : array.length - 1;\n var d = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;\n\n if (array[a] === threshold) {\n return [a, a, d];\n }\n\n if (array[b] === threshold) {\n return [b, b, d];\n }\n\n if (b - a > 1) {\n var m = Math.floor((a + b) / 2);\n\n if (array[m] > threshold) {\n return binaryFind(array, threshold, a, m, d + 1);\n }\n\n return binaryFind(array, threshold, m, b, d + 1);\n }\n\n return [threshold > array[b] ? b : a, threshold < array[a] ? a : b, d];\n }\n\n function updateInnerCollection() {\n var $scrollPosition = getScrollPos($scrollParent[0], scrollPos);\n var $clientSize = getClientSize($scrollParent[0], clientSize);\n\n if (options.debug) {\n $clientSize /= 2;\n }\n\n var scrollOffset = repeatContainer[0] === $scrollParent[0] ? 0 : getScrollOffset(repeatContainer[0], $scrollParent[0], options.horizontal);\n var __startIndex = $scope.vsRepeat.startIndex;\n var __endIndex = $scope.vsRepeat.endIndex;\n\n if (autosizingRequired && !options.size) {\n __startIndex = 0;\n __endIndex = 1;\n } else {\n _warnMismatch();\n\n var relativeScroll = $scrollPosition - options.offsetBefore - scrollOffset;\n\n var _binaryFind = binaryFind($scope.vsRepeat.sizesCumulative, relativeScroll - options.scrollMargin);\n\n var _binaryFind2 = _slicedToArray(_binaryFind, 1);\n\n __startIndex = _binaryFind2[0];\n __startIndex = Math.max(__startIndex, 0);\n\n var _binaryFind3 = binaryFind($scope.vsRepeat.sizesCumulative, relativeScroll + options.scrollMargin + $clientSize, __startIndex);\n\n var _binaryFind4 = _slicedToArray(_binaryFind3, 2);\n\n __endIndex = _binaryFind4[1];\n __endIndex = Math.min(__endIndex, originalLength);\n }\n\n _minStartIndex = Math.min(__startIndex, _minStartIndex);\n _maxEndIndex = Math.max(__endIndex, _maxEndIndex);\n $scope.vsRepeat.startIndex = options.latch ? _minStartIndex : __startIndex;\n $scope.vsRepeat.endIndex = options.latch ? _maxEndIndex : __endIndex; // Move to the end of the collection if we are now past it\n\n if (_maxEndIndex < $scope.vsRepeat.startIndex) $scope.vsRepeat.startIndex = _maxEndIndex;\n var digestRequired = false;\n\n if (_prevStartIndex == null) {\n digestRequired = true;\n } else if (_prevEndIndex == null) {\n digestRequired = true;\n }\n\n if (!digestRequired) {\n if (options.hunked) {\n if (Math.abs($scope.vsRepeat.startIndex - _prevStartIndex) >= options.hunkSize || $scope.vsRepeat.startIndex === 0 && _prevStartIndex !== 0) {\n digestRequired = true;\n } else if (Math.abs($scope.vsRepeat.endIndex - _prevEndIndex) >= options.hunkSize || $scope.vsRepeat.endIndex === originalLength && _prevEndIndex !== originalLength) {\n digestRequired = true;\n }\n } else {\n digestRequired = $scope.vsRepeat.startIndex !== _prevStartIndex || $scope.vsRepeat.endIndex !== _prevEndIndex;\n }\n }\n\n if (digestRequired) {\n $scope[collectionName] = originalCollection.slice($scope.vsRepeat.startIndex, $scope.vsRepeat.endIndex); // Emit the event\n\n $scope.$emit('vsRepeatInnerCollectionUpdated', $scope.vsRepeat.startIndex, $scope.vsRepeat.endIndex, _prevStartIndex, _prevEndIndex);\n var triggerIndex;\n\n if (options.scrolledToEnd) {\n triggerIndex = originalCollection.length - options.scrolledToEndOffset;\n\n if ($scope.vsRepeat.endIndex >= triggerIndex && _prevEndIndex < triggerIndex || originalCollection.length && $scope.vsRepeat.endIndex === originalCollection.length) {\n $scope.$eval(options.scrolledToEnd);\n }\n }\n\n if (options.scrolledToBeginning) {\n triggerIndex = options.scrolledToBeginningOffset;\n\n if ($scope.vsRepeat.startIndex <= triggerIndex && _prevStartIndex > $scope.vsRepeat.startIndex) {\n $scope.$eval(options.scrolledToBeginning);\n }\n }\n\n _prevStartIndex = $scope.vsRepeat.startIndex;\n _prevEndIndex = $scope.vsRepeat.endIndex;\n var o1 = $scope.vsRepeat.sizesCumulative[$scope.vsRepeat.startIndex] + options.offsetBefore;\n var o2 = $scope.vsRepeat.sizesCumulative[$scope.vsRepeat.startIndex + $scope[collectionName].length] + options.offsetBefore;\n var total = $scope.vsRepeat.totalSize;\n $beforeContent.css(getLayoutProps(o1 + 'px'));\n $afterContent.css(getLayoutProps(total - o2 + 'px'));\n }\n\n return digestRequired;\n }\n\n function _warnMismatch() {\n $scope.$$postDigest(function () {\n window.requestAnimationFrame(function () {\n var expectedSize = $scope.vsRepeat.sizesCumulative[originalLength];\n var compStyle = window.getComputedStyle(repeatContainer[0]);\n var paddings = options.horizontal ? ['paddingLeft', 'paddingRight'] : ['paddingTop', 'paddingBottom'];\n var containerSize = repeatContainer[0][scrollSize] - paddings.reduce(function (acc, prop) {\n return acc + Number(compStyle[prop].slice(0, -2));\n }, 0);\n\n if (repeatContainer[0][scrollSize] && expectedSize !== containerSize) {\n console.warn('vsRepeat: size mismatch. Expected size ' + expectedSize + 'px whereas actual size is ' + containerSize + 'px. Fix vsSize on element:', $element[0]);\n }\n });\n });\n }\n }\n };\n }\n };\n }]);\n angular.element(document.head).append(\"<style id=\\\"angular-vs-repeat-style\\\">\\n\\t \\t.vs-repeat-debug-element {\\n top: 50%;\\n left: 0;\\n right: 0;\\n height: 1px;\\n background: red;\\n z-index: 99999999;\\n box-shadow: 0 0 20px red;\\n }\\n\\n .vs-repeat-debug-element + .vs-repeat-debug-element {\\n display: none;\\n }\\n\\n .vs-repeat-before-content,\\n .vs-repeat-after-content {\\n border: none !important;\\n padding: 0 !important;\\n }\\n </style>\");\n\n if (typeof module !== 'undefined' && module.exports) {\n module.exports = vsRepeatModule.name;\n }\n})(window, window.angular);"],"sourceRoot":""}
1282\ No newline at end of file
1283+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/maasserver/static/js/angular/3rdparty/ng-tags-input.js","webpack:///./src/maasserver/static/js/angular/3rdparty/vs-repeat.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","r","value","n","__esModule","object","property","prototype","hasOwnProperty","p","s","KEYS","SUPPORTED_INPUT_TYPES","tagsInput","angular","directive","$timeout","$document","$window","tagsInputConfig","tiUtil","validateType","type","indexOf","restrict","require","scope","tags","onTagAdding","onTagAdded","onInvalidTag","onTagRemoving","onTagRemoved","replace","transclude","templateUrl","controller","$scope","$attrs","$element","events","simplePubSub","load","template","String","placeholder","tabindex","Number","removeTagSymbol","fromCharCode","replaceSpacesWithDashes","Boolean","minLength","maxLength","addOnEnter","addOnSpace","addOnComma","addOnBlur","addOnPaste","pasteSplitPattern","RegExp","allowedTagsPattern","enableEditingLastTag","minTags","maxTags","displayProperty","keyProperty","allowLeftoverText","addFromAutocompleteOnly","spellcheck","tagList","options","getTagText","setTagText","tagIsValid","self","tag","safeToString","text","tagText","length","test","findInObjectArray","items","$tag","addText","add","push","trigger","remove","index","splice","clearSelection","select","selected","selectPrior","selectNext","removeSelected","handleUndefinedResult","this","registerAutocomplete","find","addTag","focusInput","getTags","getCurrentTagText","newTag","getOptions","on","handler","registerTagItem","removeTag","disabled","link","element","attrs","ngModelCtrl","setElementValidity","hotkeys","input","validationOptions","$setValidity","hasFocus","$isEmpty","invalid","setText","track","$watch","makeObjectArray","$observe","eventHandlers","change","keydown","$event","focus","blur","activeElement","prop","lostFocusToBrowserWindow","lostFocusToChildElement","contains","paste","getTextData","clipboardData","originalEvent","getData","host","click","$setViewValue","e","triggerHandler","event","shouldAdd","shouldRemove","shouldSelect","shouldEditLastTag","key","keyCode","addKeys","shiftKey","altKey","ctrlKey","metaKey","preventDefault","split","forEach","data","tagsInputCtrl","$$template","$$removeTagSymbol","$getDisplayText","$removeTag","$index","$sce","$q","source","debounceDelay","highlightMatchedText","maxResultsToShow","loadOnDownArrow","loadOnEmpty","loadOnFocus","selectFirstMatch","suggestionList","loadFn","getDifference","lastPromise","getTagId","array1","array2","filter","item","a","b","defaultComparer","reset","visible","query","show","debounce","promise","when","$query","then","slice","registerAutocompleteMatch","getQuery","shouldLoadSuggestions","addSuggestionByIndex","addSuggestion","added","copy","handled","stopImmediatePropagation","root","eq","parent","elementTop","elementHeight","parentHeight","parentScrollTop","scrollToElement","autoCompleteCtrl","autoComplete","$parent","$highlight","safeHighlight","trustAsHtml","ctrl","transcludeFn","clone","append","span","resize","threshold","getTextAutosizeThreshold","css","originalValue","width","isString","$parsers","unshift","$formatters","$modelValue","tiBindAttrs","$set","provider","globalDefaults","interpolationStatus","autosizeThreshold","setDefaults","defaults","setActiveInterpolation","setTextAutosizeThreshold","$get","$interpolate","converters","parseInt","toLowerCase","defaultValidator","localDefault","validator","converter","getDefault","updateValue","globalValue","isDefined","newValue","factory","fn","delay","timeoutId","args","arguments","cancel","apply","array","isObject","obj","comparer","some","str","encodeHTML","expression","escapeRegexChars","match","isUndefined","toString","trim","valueIfUndefined","result","names","every","run","$templateCache","put","window","dde","document","documentElement","matchingFunction","matches","matchesSelector","webkitMatches","webkitMatchesSelector","msMatches","msMatchesSelector","mozMatches","mozMatchesSelector","closestElement","closest","selector","el","parentNode","getWindowScroll","scrollTop","pageYOffset","scrollLeft","pageXOffset","sx","body","getClientSize","sizeProp","innerWidth","innerHeight","vsRepeatModule","$compile","$parse","compile","ngRepeatExpression","expressionMatches","lhs","rhs","rhsSuffix","originalNgRepeatAttr","repeatContainer","vsRepeatContainer","querySelector","ngRepeatChild","children","childCloneHtml","outerHTML","collectionName","isNgRepeatStart","attributesDictionary","vsRepeat","vsOffsetBefore","vsOffsetAfter","vsScrolledToEndOffset","vsScrolledToBeginningOffset","vsExcess","attr","Error","exec","repeaterElement","empty","pre","originalLength","_prevStartIndex","_prevEndIndex","_minStartIndex","_maxEndIndex","_prevClientSize","childClone","childTagName","tagName","originalCollection","$$horizontal","vsHorizontal","$beforeContent","$afterContent","autoSize","sizesPropertyExists","vsSize","vsSizeProperty","$scrollParent","vsScrollParent","$$options","$eval","vsOptions","clientSize","offsetSize","scrollPos","totalSize","console","warn","refresh","sizesCumulative","sizes","map","$new","extend","size","elementSize","$destroy","sum","res","setAutoSize","reinitialize","$$postDigest","offsetHeight","offsetWidth","gotSomething","insideStartEndSequence","attributes","$root","$$phase","$apply","dereg","getLayoutProp","layoutPropPrefix","scrollHandler","updateInnerCollection","$digest","onWindowResize","vsAutoresize","offsetBefore","offsetAfter","$emit","startIndex","endIndex","reinitOnClientHeightChange","ch","scrollProp","vsElement","scrollElement","isHorizontal","$scrollPosition","$clientSize","scrollOffset","getBoundingClientRect","__startIndex","__endIndex","Math","max","floor","excess","min","ceil","latch","digestRequired","hunked","abs","triggerIndex","vsScrolledToEnd","scrolledToEndOffset","vsScrolledToBeginning","scrolledToBeginningOffset","parsed","o1","o2","total","keys","$watchCollection","coll","addClass","$on","off","setTimeout","requestAnimationFrame"],"mappings":"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","file":"vendor-min.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/*!\n * ngTagsInput v2.3.0\n * http://mbenford.github.io/ngTagsInput\n *\n * Copyright (c) 2013-2015 Michael Benford\n * License: MIT\n *\n * Generated at 2015-03-24 00:49:44 -0300\n */\n(function() {\n'use strict';\n\nvar KEYS = {\n backspace: 8,\n tab: 9,\n enter: 13,\n escape: 27,\n space: 32,\n up: 38,\n down: 40,\n left: 37,\n right: 39,\n delete: 46,\n comma: 188\n};\n\nvar MAX_SAFE_INTEGER = 9007199254740991;\nvar SUPPORTED_INPUT_TYPES = ['text', 'email', 'url'];\n\nvar tagsInput = angular.module('ngTagsInput', []);\n\n/**\n * @ngdoc directive\n * @name tagsInput\n * @module ngTagsInput\n *\n * @description\n * Renders an input box with tag editing support.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} [displayProperty=text] Property to be rendered as the tag label.\n * @param {string=} [keyProperty=text] Property to be used as a unique identifier for the tag.\n * @param {string=} [type=text] Type of the input element. Only 'text', 'email' and 'url' are supported values.\n * @param {number=} tabindex Tab order of the control.\n * @param {string=} [placeholder=Add a tag] Placeholder text for the control.\n * @param {number=} [minLength=3] Minimum length for a new tag.\n * @param {number=} [maxLength=MAX_SAFE_INTEGER] Maximum length allowed for a new tag.\n * @param {number=} [minTags=0] Sets minTags validation error key if the number of tags added is less than minTags.\n * @param {number=} [maxTags=MAX_SAFE_INTEGER] Sets maxTags validation error key if the number of tags added is greater than maxTags.\n * @param {boolean=} [allowLeftoverText=false] Sets leftoverText validation error key if there is any leftover text in\n * the input element when the directive loses focus.\n * @param {string=} [removeTagSymbol=×] Symbol character for the remove tag button.\n * @param {boolean=} [addOnEnter=true] Flag indicating that a new tag will be added on pressing the ENTER key.\n * @param {boolean=} [addOnSpace=false] Flag indicating that a new tag will be added on pressing the SPACE key.\n * @param {boolean=} [addOnComma=true] Flag indicating that a new tag will be added on pressing the COMMA key.\n * @param {boolean=} [addOnBlur=true] Flag indicating that a new tag will be added when the input field loses focus.\n * @param {boolean=} [addOnPaste=false] Flag indicating that the text pasted into the input field will be split into tags.\n * @param {string=} [pasteSplitPattern=,] Regular expression used to split the pasted text into tags.\n * @param {boolean=} [replaceSpacesWithDashes=true] Flag indicating that spaces will be replaced with dashes.\n * @param {string=} [allowedTagsPattern=.+] Regular expression that determines whether a new tag is valid.\n * @param {boolean=} [enableEditingLastTag=false] Flag indicating that the last tag will be moved back into\n * the new tag input box instead of being removed when the backspace key\n * is pressed and the input box is empty.\n * @param {boolean=} [addFromAutocompleteOnly=false] Flag indicating that only tags coming from the autocomplete list will be allowed.\n * When this flag is true, addOnEnter, addOnComma, addOnSpace, addOnBlur and\n * allowLeftoverText values are ignored.\n * @param {boolean=} [spellcheck=true] Flag indicating whether the browser's spellcheck is enabled for the input field or not.\n * @param {expression} onTagAdding Expression to evaluate that will be invoked before adding a new tag. The new tag is available as $tag. This method must return either true or false. If false, the tag will not be added.\n * @param {expression} onTagAdded Expression to evaluate upon adding a new tag. The new tag is available as $tag.\n * @param {expression} onInvalidTag Expression to evaluate when a tag is invalid. The invalid tag is available as $tag.\n * @param {expression} onTagRemoving Expression to evaluate that will be invoked before removing a tag. The tag is available as $tag. This method must return either true or false. If false, the tag will not be removed.\n * @param {expression} onTagRemoved Expression to evaluate upon removing an existing tag. The removed tag is available as $tag.\n */\ntagsInput.directive('tagsInput', [\"$timeout\",\"$document\",\"$window\",\"tagsInputConfig\",\"tiUtil\", function($timeout, $document, $window, tagsInputConfig, tiUtil) {\n function TagList(options, events, onTagAdding, onTagRemoving) {\n var self = {}, getTagText, setTagText, tagIsValid;\n\n getTagText = function(tag) {\n return tiUtil.safeToString(tag[options.displayProperty]);\n };\n\n setTagText = function(tag, text) {\n tag[options.displayProperty] = text;\n };\n\n tagIsValid = function(tag) {\n var tagText = getTagText(tag);\n\n return tagText &&\n tagText.length >= options.minLength &&\n tagText.length <= options.maxLength &&\n options.allowedTagsPattern.test(tagText) &&\n !tiUtil.findInObjectArray(self.items, tag, options.keyProperty || options.displayProperty) &&\n onTagAdding({ $tag: tag });\n };\n\n self.items = [];\n\n self.addText = function(text) {\n var tag = {};\n setTagText(tag, text);\n return self.add(tag);\n };\n\n self.add = function(tag) {\n var tagText = getTagText(tag);\n\n if (options.replaceSpacesWithDashes) {\n tagText = tiUtil.replaceSpacesWithDashes(tagText);\n }\n\n setTagText(tag, tagText);\n\n if (tagIsValid(tag)) {\n self.items.push(tag);\n events.trigger('tag-added', { $tag: tag });\n }\n else if (tagText) {\n events.trigger('invalid-tag', { $tag: tag });\n }\n\n return tag;\n };\n\n self.remove = function(index) {\n var tag = self.items[index];\n\n if (onTagRemoving({ $tag: tag })) {\n self.items.splice(index, 1);\n self.clearSelection();\n events.trigger('tag-removed', { $tag: tag });\n return tag;\n }\n };\n\n self.select = function(index) {\n if (index < 0) {\n index = self.items.length - 1;\n }\n else if (index >= self.items.length) {\n index = 0;\n }\n\n self.index = index;\n self.selected = self.items[index];\n };\n\n self.selectPrior = function() {\n self.select(--self.index);\n };\n\n self.selectNext = function() {\n self.select(++self.index);\n };\n\n self.removeSelected = function() {\n return self.remove(self.index);\n };\n\n self.clearSelection = function() {\n self.selected = null;\n self.index = -1;\n };\n\n self.clearSelection();\n\n return self;\n }\n\n function validateType(type) {\n return SUPPORTED_INPUT_TYPES.indexOf(type) !== -1;\n }\n\n return {\n restrict: 'E',\n require: 'ngModel',\n scope: {\n tags: '=ngModel',\n onTagAdding: '&',\n onTagAdded: '&',\n onInvalidTag: '&',\n onTagRemoving: '&',\n onTagRemoved: '&'\n },\n replace: false,\n transclude: true,\n templateUrl: 'ngTagsInput/tags-input.html',\n controller: [\"$scope\",\"$attrs\",\"$element\", function($scope, $attrs, $element) {\n $scope.events = tiUtil.simplePubSub();\n\n tagsInputConfig.load('tagsInput', $scope, $attrs, {\n template: [String, 'ngTagsInput/tag-item.html'],\n type: [String, 'text', validateType],\n placeholder: [String, 'Add a tag'],\n tabindex: [Number, null],\n removeTagSymbol: [String, String.fromCharCode(215)],\n replaceSpacesWithDashes: [Boolean, true],\n minLength: [Number, 3],\n maxLength: [Number, MAX_SAFE_INTEGER],\n addOnEnter: [Boolean, true],\n addOnSpace: [Boolean, false],\n addOnComma: [Boolean, true],\n addOnBlur: [Boolean, true],\n addOnPaste: [Boolean, false],\n pasteSplitPattern: [RegExp, /,/],\n allowedTagsPattern: [RegExp, /.+/],\n enableEditingLastTag: [Boolean, false],\n minTags: [Number, 0],\n maxTags: [Number, MAX_SAFE_INTEGER],\n displayProperty: [String, 'text'],\n keyProperty: [String, ''],\n allowLeftoverText: [Boolean, false],\n addFromAutocompleteOnly: [Boolean, false],\n spellcheck: [Boolean, true]\n });\n\n $scope.tagList = new TagList($scope.options, $scope.events,\n tiUtil.handleUndefinedResult($scope.onTagAdding, true),\n tiUtil.handleUndefinedResult($scope.onTagRemoving, true));\n\n this.registerAutocomplete = function() {\n var input = $element.find('input');\n\n return {\n addTag: function(tag) {\n return $scope.tagList.add(tag);\n },\n focusInput: function() {\n // blake_r - Stop the focus as this breaks on the\n // version of AngularJS that ships with MAAS.\n //input[0].focus();\n },\n getTags: function() {\n return $scope.tags;\n },\n getCurrentTagText: function() {\n return $scope.newTag.text;\n },\n getOptions: function() {\n return $scope.options;\n },\n on: function(name, handler) {\n $scope.events.on(name, handler);\n return this;\n }\n };\n };\n\n this.registerTagItem = function() {\n return {\n getOptions: function() {\n return $scope.options;\n },\n removeTag: function(index) {\n if ($scope.disabled) {\n return;\n }\n $scope.tagList.remove(index);\n }\n };\n };\n }],\n link: function(scope, element, attrs, ngModelCtrl) {\n var hotkeys = [KEYS.enter, KEYS.comma, KEYS.space, KEYS.backspace, KEYS.delete, KEYS.left, KEYS.right],\n tagList = scope.tagList,\n events = scope.events,\n options = scope.options,\n input = element.find('input'),\n validationOptions = ['minTags', 'maxTags', 'allowLeftoverText'],\n setElementValidity;\n\n setElementValidity = function() {\n ngModelCtrl.$setValidity('maxTags', scope.tags.length <= options.maxTags);\n ngModelCtrl.$setValidity('minTags', scope.tags.length >= options.minTags);\n ngModelCtrl.$setValidity('leftoverText', scope.hasFocus || options.allowLeftoverText ? true : !scope.newTag.text);\n };\n\n ngModelCtrl.$isEmpty = function(value) {\n return !value || !value.length;\n };\n\n scope.newTag = {\n text: '',\n invalid: null,\n setText: function(value) {\n this.text = value;\n events.trigger('input-change', value);\n }\n };\n\n scope.track = function(tag) {\n return tag[options.keyProperty || options.displayProperty];\n };\n\n scope.$watch('tags', function(value) {\n scope.tags = tiUtil.makeObjectArray(value, options.displayProperty);\n tagList.items = scope.tags;\n });\n\n scope.$watch('tags.length', function() {\n setElementValidity();\n });\n\n attrs.$observe('disabled', function(value) {\n scope.disabled = value;\n });\n\n scope.eventHandlers = {\n input: {\n change: function(text) {\n events.trigger('input-change', text);\n },\n keydown: function($event) {\n events.trigger('input-keydown', $event);\n },\n focus: function() {\n if (scope.hasFocus) {\n return;\n }\n\n scope.hasFocus = true;\n events.trigger('input-focus');\n },\n blur: function() {\n $timeout(function() {\n var activeElement = $document.prop('activeElement'),\n lostFocusToBrowserWindow = activeElement === input[0],\n lostFocusToChildElement = element[0].contains(activeElement);\n\n if (lostFocusToBrowserWindow || !lostFocusToChildElement) {\n scope.hasFocus = false;\n events.trigger('input-blur');\n }\n });\n },\n paste: function($event) {\n $event.getTextData = function() {\n var clipboardData = $event.clipboardData || ($event.originalEvent && $event.originalEvent.clipboardData);\n return clipboardData ? clipboardData.getData('text/plain') : $window.clipboardData.getData('Text');\n };\n events.trigger('input-paste', $event);\n }\n },\n host: {\n click: function() {\n if (scope.disabled) {\n return;\n }\n // blake_r - Stop the focus as this breaks on the\n // version of AngularJS that ships with MAAS.\n //input[0].focus();\n }\n }\n };\n\n events\n .on('tag-added', scope.onTagAdded)\n .on('invalid-tag', scope.onInvalidTag)\n .on('tag-removed', scope.onTagRemoved)\n .on('tag-added', function() {\n scope.newTag.setText('');\n })\n .on('tag-added tag-removed', function() {\n // Sets the element to its dirty state\n // In Angular 1.3 this will be replaced with $setDirty.\n ngModelCtrl.$setViewValue(scope.tags);\n })\n .on('invalid-tag', function() {\n scope.newTag.invalid = true;\n })\n .on('option-change', function(e) {\n if (validationOptions.indexOf(e.name) !== -1) {\n setElementValidity();\n }\n })\n .on('input-change', function() {\n tagList.clearSelection();\n scope.newTag.invalid = null;\n })\n .on('input-focus', function() {\n element.triggerHandler('focus');\n ngModelCtrl.$setValidity('leftoverText', true);\n })\n .on('input-blur', function() {\n if (options.addOnBlur && !options.addFromAutocompleteOnly) {\n tagList.addText(scope.newTag.text);\n }\n element.triggerHandler('blur');\n setElementValidity();\n })\n .on('input-keydown', function(event) {\n var key = event.keyCode,\n isModifier = event.shiftKey || event.altKey || event.ctrlKey || event.metaKey,\n addKeys = {},\n shouldAdd, shouldRemove, shouldSelect, shouldEditLastTag;\n\n if (isModifier || hotkeys.indexOf(key) === -1) {\n return;\n }\n\n addKeys[KEYS.enter] = options.addOnEnter;\n addKeys[KEYS.comma] = options.addOnComma;\n addKeys[KEYS.space] = options.addOnSpace;\n\n shouldAdd = !options.addFromAutocompleteOnly && addKeys[key];\n shouldRemove = (key === KEYS.backspace || key === KEYS.delete) && tagList.selected;\n shouldEditLastTag = key === KEYS.backspace && scope.newTag.text.length === 0 && options.enableEditingLastTag;\n shouldSelect = (key === KEYS.backspace || key === KEYS.left || key === KEYS.right) && scope.newTag.text.length === 0 && !options.enableEditingLastTag;\n\n if (shouldAdd) {\n tagList.addText(scope.newTag.text);\n }\n else if (shouldEditLastTag) {\n var tag;\n\n tagList.selectPrior();\n tag = tagList.removeSelected();\n\n if (tag) {\n scope.newTag.setText(tag[options.displayProperty]);\n }\n }\n else if (shouldRemove) {\n tagList.removeSelected();\n }\n else if (shouldSelect) {\n if (key === KEYS.left || key === KEYS.backspace) {\n tagList.selectPrior();\n }\n else if (key === KEYS.right) {\n tagList.selectNext();\n }\n }\n\n if (shouldAdd || shouldSelect || shouldRemove || shouldEditLastTag) {\n event.preventDefault();\n }\n })\n .on('input-paste', function(event) {\n if (options.addOnPaste) {\n var data = event.getTextData();\n var tags = data.split(options.pasteSplitPattern);\n\n if (tags.length > 1) {\n tags.forEach(function(tag) {\n tagList.addText(tag);\n });\n event.preventDefault();\n }\n }\n });\n }\n };\n}]);\n\n\n/**\n * @ngdoc directive\n * @name tiTagItem\n * @module ngTagsInput\n *\n * @description\n * Represents a tag item. Used internally by the tagsInput directive.\n */\ntagsInput.directive('tiTagItem', [\"tiUtil\", function(tiUtil) {\n return {\n restrict: 'E',\n require: '^tagsInput',\n template: '<ng-include src=\"$$template\"></ng-include>',\n scope: { data: '=' },\n link: function(scope, element, attrs, tagsInputCtrl) {\n var tagsInput = tagsInputCtrl.registerTagItem(),\n options = tagsInput.getOptions();\n\n scope.$$template = options.template;\n scope.$$removeTagSymbol = options.removeTagSymbol;\n\n scope.$getDisplayText = function() {\n return tiUtil.safeToString(scope.data[options.displayProperty]);\n };\n scope.$removeTag = function() {\n tagsInput.removeTag(scope.$index);\n };\n\n scope.$watch('$parent.$index', function(value) {\n scope.$index = value;\n });\n }\n };\n}]);\n\n\n/**\n * @ngdoc directive\n * @name autoComplete\n * @module ngTagsInput\n *\n * @description\n * Provides autocomplete support for the tagsInput directive.\n *\n * @param {expression} source Expression to evaluate upon changing the input content. The input value is available as\n * $query. The result of the expression must be a promise that eventually resolves to an\n * array of strings.\n * @param {string=} [displayProperty=text] Property to be rendered as the autocomplete label.\n * @param {number=} [debounceDelay=100] Amount of time, in milliseconds, to wait before evaluating the expression in\n * the source option after the last keystroke.\n * @param {number=} [minLength=3] Minimum number of characters that must be entered before evaluating the expression\n * in the source option.\n * @param {boolean=} [highlightMatchedText=true] Flag indicating that the matched text will be highlighted in the\n * suggestions list.\n * @param {number=} [maxResultsToShow=10] Maximum number of results to be displayed at a time.\n * @param {boolean=} [loadOnDownArrow=false] Flag indicating that the source option will be evaluated when the down arrow\n * key is pressed and the suggestion list is closed. The current input value\n * is available as $query.\n * @param {boolean=} {loadOnEmpty=false} Flag indicating that the source option will be evaluated when the input content\n * becomes empty. The $query variable will be passed to the expression as an empty string.\n * @param {boolean=} {loadOnFocus=false} Flag indicating that the source option will be evaluated when the input element\n * gains focus. The current input value is available as $query.\n * @param {boolean=} [selectFirstMatch=true] Flag indicating that the first match will be automatically selected once\n * the suggestion list is shown.\n * @param {string=} [template=] URL or id of a custom template for rendering each element of the autocomplete list.\n */\ntagsInput.directive('autoComplete', [\"$document\",\"$timeout\",\"$sce\",\"$q\",\"tagsInputConfig\",\"tiUtil\", function($document, $timeout, $sce, $q, tagsInputConfig, tiUtil) {\n function SuggestionList(loadFn, options, events) {\n var self = {}, getDifference, lastPromise, getTagId;\n\n getTagId = function() {\n return options.tagsInput.keyProperty || options.tagsInput.displayProperty;\n };\n\n getDifference = function(array1, array2) {\n return array1.filter(function(item) {\n return !tiUtil.findInObjectArray(array2, item, getTagId(), function(a, b) {\n if (options.tagsInput.replaceSpacesWithDashes) {\n a = tiUtil.replaceSpacesWithDashes(a);\n b = tiUtil.replaceSpacesWithDashes(b);\n }\n return tiUtil.defaultComparer(a, b);\n });\n });\n };\n\n self.reset = function() {\n lastPromise = null;\n\n self.items = [];\n self.visible = false;\n self.index = -1;\n self.selected = null;\n self.query = null;\n };\n self.show = function() {\n if (options.selectFirstMatch) {\n self.select(0);\n }\n else {\n self.selected = null;\n }\n self.visible = true;\n };\n self.load = tiUtil.debounce(function(query, tags) {\n self.query = query;\n\n var promise = $q.when(loadFn({ $query: query }));\n lastPromise = promise;\n\n promise.then(function(items) {\n if (promise !== lastPromise) {\n return;\n }\n\n items = tiUtil.makeObjectArray(items.data || items, getTagId());\n items = getDifference(items, tags);\n self.items = items.slice(0, options.maxResultsToShow);\n\n if (self.items.length > 0) {\n self.show();\n }\n else {\n self.reset();\n }\n });\n }, options.debounceDelay);\n\n self.selectNext = function() {\n self.select(++self.index);\n };\n self.selectPrior = function() {\n self.select(--self.index);\n };\n self.select = function(index) {\n if (index < 0) {\n index = self.items.length - 1;\n }\n else if (index >= self.items.length) {\n index = 0;\n }\n self.index = index;\n self.selected = self.items[index];\n events.trigger('suggestion-selected', index);\n };\n\n self.reset();\n\n return self;\n }\n\n function scrollToElement(root, index) {\n var element = root.find('li').eq(index),\n parent = element.parent(),\n elementTop = element.prop('offsetTop'),\n elementHeight = element.prop('offsetHeight'),\n parentHeight = parent.prop('clientHeight'),\n parentScrollTop = parent.prop('scrollTop');\n\n if (elementTop < parentScrollTop) {\n parent.prop('scrollTop', elementTop);\n }\n else if (elementTop + elementHeight > parentHeight + parentScrollTop) {\n parent.prop('scrollTop', elementTop + elementHeight - parentHeight);\n }\n }\n\n return {\n restrict: 'E',\n require: '^tagsInput',\n scope: { source: '&' },\n templateUrl: 'ngTagsInput/auto-complete.html',\n controller: [\"$scope\",\"$element\",\"$attrs\", function($scope, $element, $attrs) {\n $scope.events = tiUtil.simplePubSub();\n\n tagsInputConfig.load('autoComplete', $scope, $attrs, {\n template: [String, 'ngTagsInput/auto-complete-match.html'],\n debounceDelay: [Number, 100],\n minLength: [Number, 3],\n highlightMatchedText: [Boolean, true],\n maxResultsToShow: [Number, 10],\n loadOnDownArrow: [Boolean, false],\n loadOnEmpty: [Boolean, false],\n loadOnFocus: [Boolean, false],\n selectFirstMatch: [Boolean, true],\n displayProperty: [String, '']\n });\n\n $scope.suggestionList = new SuggestionList($scope.source, $scope.options, $scope.events);\n\n this.registerAutocompleteMatch = function() {\n return {\n getOptions: function() {\n return $scope.options;\n },\n getQuery: function() {\n return $scope.suggestionList.query;\n }\n };\n };\n }],\n link: function(scope, element, attrs, tagsInputCtrl) {\n var hotkeys = [KEYS.enter, KEYS.tab, KEYS.escape, KEYS.up, KEYS.down],\n suggestionList = scope.suggestionList,\n tagsInput = tagsInputCtrl.registerAutocomplete(),\n options = scope.options,\n events = scope.events,\n shouldLoadSuggestions;\n\n options.tagsInput = tagsInput.getOptions();\n\n shouldLoadSuggestions = function(value) {\n return value && value.length >= options.minLength || !value && options.loadOnEmpty;\n };\n\n scope.addSuggestionByIndex = function(index) {\n suggestionList.select(index);\n scope.addSuggestion();\n };\n\n scope.addSuggestion = function() {\n var added = false;\n\n if (suggestionList.selected) {\n tagsInput.addTag(angular.copy(suggestionList.selected));\n suggestionList.reset();\n tagsInput.focusInput();\n\n added = true;\n }\n return added;\n };\n\n scope.track = function(item) {\n return item[options.tagsInput.keyProperty || options.tagsInput.displayProperty];\n };\n\n tagsInput\n .on('tag-added invalid-tag input-blur', function() {\n suggestionList.reset();\n })\n .on('input-change', function(value) {\n if (shouldLoadSuggestions(value)) {\n suggestionList.load(value, tagsInput.getTags());\n }\n else {\n suggestionList.reset();\n }\n })\n .on('input-focus', function() {\n var value = tagsInput.getCurrentTagText();\n if (options.loadOnFocus && shouldLoadSuggestions(value)) {\n suggestionList.load(value, tagsInput.getTags());\n }\n })\n .on('input-keydown', function(event) {\n var key = event.keyCode,\n handled = false;\n\n if (hotkeys.indexOf(key) === -1) {\n return;\n }\n\n if (suggestionList.visible) {\n\n if (key === KEYS.down) {\n suggestionList.selectNext();\n handled = true;\n }\n else if (key === KEYS.up) {\n suggestionList.selectPrior();\n handled = true;\n }\n else if (key === KEYS.escape) {\n suggestionList.reset();\n handled = true;\n }\n else if (key === KEYS.enter || key === KEYS.tab) {\n handled = scope.addSuggestion();\n }\n }\n else {\n if (key === KEYS.down && scope.options.loadOnDownArrow) {\n suggestionList.load(tagsInput.getCurrentTagText(), tagsInput.getTags());\n handled = true;\n }\n }\n\n if (handled) {\n event.preventDefault();\n event.stopImmediatePropagation();\n return false;\n }\n });\n\n events.on('suggestion-selected', function(index) {\n scrollToElement(element, index);\n });\n }\n };\n}]);\n\n\n/**\n * @ngdoc directive\n * @name tiAutocompleteMatch\n * @module ngTagsInput\n *\n * @description\n * Represents an autocomplete match. Used internally by the autoComplete directive.\n */\ntagsInput.directive('tiAutocompleteMatch', [\"$sce\",\"tiUtil\", function($sce, tiUtil) {\n return {\n restrict: 'E',\n require: '^autoComplete',\n template: '<ng-include src=\"$$template\"></ng-include>',\n scope: { data: '=' },\n link: function(scope, element, attrs, autoCompleteCtrl) {\n var autoComplete = autoCompleteCtrl.registerAutocompleteMatch(),\n options = autoComplete.getOptions();\n\n scope.$$template = options.template;\n scope.$index = scope.$parent.$index;\n\n scope.$highlight = function(text) {\n if (options.highlightMatchedText) {\n text = tiUtil.safeHighlight(text, autoComplete.getQuery());\n }\n return $sce.trustAsHtml(text);\n };\n scope.$getDisplayText = function() {\n return tiUtil.safeToString(scope.data[options.displayProperty || options.tagsInput.displayProperty]);\n };\n }\n };\n}]);\n\n\n/**\n * @ngdoc directive\n * @name tiTranscludeAppend\n * @module ngTagsInput\n *\n * @description\n * Re-creates the old behavior of ng-transclude. Used internally by tagsInput directive.\n */\ntagsInput.directive('tiTranscludeAppend', function() {\n return function(scope, element, attrs, ctrl, transcludeFn) {\n transcludeFn(function(clone) {\n element.append(clone);\n });\n };\n});\n\n/**\n * @ngdoc directive\n * @name tiAutosize\n * @module ngTagsInput\n *\n * @description\n * Automatically sets the input's width so its content is always visible. Used internally by tagsInput directive.\n */\ntagsInput.directive('tiAutosize', [\"tagsInputConfig\", function(tagsInputConfig) {\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function(scope, element, attrs, ctrl) {\n var threshold = tagsInputConfig.getTextAutosizeThreshold(),\n span, resize;\n\n span = angular.element('<span class=\"input\"></span>');\n span.css('display', 'none')\n .css('visibility', 'hidden')\n .css('width', 'auto')\n .css('white-space', 'pre');\n\n element.parent().append(span);\n\n resize = function(originalValue) {\n var value = originalValue, width;\n\n if (angular.isString(value) && value.length === 0) {\n value = attrs.placeholder;\n }\n\n if (value) {\n span.text(value);\n span.css('display', '');\n width = span.prop('offsetWidth');\n span.css('display', 'none');\n }\n\n element.css('width', width ? width + threshold + 'px' : '');\n\n return originalValue;\n };\n\n ctrl.$parsers.unshift(resize);\n ctrl.$formatters.unshift(resize);\n\n attrs.$observe('placeholder', function(value) {\n if (!ctrl.$modelValue) {\n resize(value);\n }\n });\n }\n };\n}]);\n\n/**\n * @ngdoc directive\n * @name tiBindAttrs\n * @module ngTagsInput\n *\n * @description\n * Binds attributes to expressions. Used internally by tagsInput directive.\n */\ntagsInput.directive('tiBindAttrs', function() {\n return function(scope, element, attrs) {\n scope.$watch(attrs.tiBindAttrs, function(value) {\n angular.forEach(value, function(value, key) {\n /**\n * blake_r - Added to work around the version of jQuery that\n * MAAS currently ships with. Once packaging for jQuery is\n * version >1.9 this can be removed.\n */\n if(key === \"type\") {\n element[0].type = value;\n } else {\n attrs.$set(key, value);\n }\n });\n }, true);\n };\n});\n\n/**\n * @ngdoc service\n * @name tagsInputConfig\n * @module ngTagsInput\n *\n * @description\n * Sets global configuration settings for both tagsInput and autoComplete directives. It's also used internally to parse and\n * initialize options from HTML attributes.\n */\ntagsInput.provider('tagsInputConfig', function() {\n var globalDefaults = {},\n interpolationStatus = {},\n autosizeThreshold = 3;\n\n /**\n * @ngdoc method\n * @name setDefaults\n * @description Sets the default configuration option for a directive.\n * @methodOf tagsInputConfig\n *\n * @param {string} directive Name of the directive to be configured. Must be either 'tagsInput' or 'autoComplete'.\n * @param {object} defaults Object containing options and their values.\n *\n * @returns {object} The service itself for chaining purposes.\n */\n this.setDefaults = function(directive, defaults) {\n globalDefaults[directive] = defaults;\n return this;\n };\n\n /***\n * @ngdoc method\n * @name setActiveInterpolation\n * @description Sets active interpolation for a set of options.\n * @methodOf tagsInputConfig\n *\n * @param {string} directive Name of the directive to be configured. Must be either 'tagsInput' or 'autoComplete'.\n * @param {object} options Object containing which options should have interpolation turned on at all times.\n *\n * @returns {object} The service itself for chaining purposes.\n */\n this.setActiveInterpolation = function(directive, options) {\n interpolationStatus[directive] = options;\n return this;\n };\n\n /***\n * @ngdoc method\n * @name setTextAutosizeThreshold\n * @description Sets the threshold used by the tagsInput directive to re-size the inner input field element based on its contents.\n * @methodOf tagsInputConfig\n *\n * @param {number} threshold Threshold value, in pixels.\n *\n * @returns {object} The service itself for chaining purposes.\n */\n this.setTextAutosizeThreshold = function(threshold) {\n autosizeThreshold = threshold;\n return this;\n };\n\n this.$get = [\"$interpolate\", function($interpolate) {\n var converters = {};\n converters[String] = function(value) { return value; };\n converters[Number] = function(value) { return parseInt(value, 10); };\n converters[Boolean] = function(value) { return value.toLowerCase() === 'true'; };\n converters[RegExp] = function(value) { return new RegExp(value); };\n\n return {\n load: function(directive, scope, attrs, options) {\n var defaultValidator = function() { return true; };\n\n scope.options = {};\n\n angular.forEach(options, function(value, key) {\n var type, localDefault, validator, converter, getDefault, updateValue;\n\n type = value[0];\n localDefault = value[1];\n validator = value[2] || defaultValidator;\n converter = converters[type];\n\n getDefault = function() {\n var globalValue = globalDefaults[directive] && globalDefaults[directive][key];\n return angular.isDefined(globalValue) ? globalValue : localDefault;\n };\n\n updateValue = function(value) {\n scope.options[key] = value && validator(value) ? converter(value) : getDefault();\n };\n\n if (interpolationStatus[directive] && interpolationStatus[directive][key]) {\n attrs.$observe(key, function(value) {\n updateValue(value);\n scope.events.trigger('option-change', { name: key, newValue: value });\n });\n }\n else {\n updateValue(attrs[key] && $interpolate(attrs[key])(scope.$parent));\n }\n });\n },\n getTextAutosizeThreshold: function() {\n return autosizeThreshold;\n }\n };\n }];\n});\n\n\n/***\n * @ngdoc factory\n * @name tiUtil\n * @module ngTagsInput\n *\n * @description\n * Helper methods used internally by the directive. Should not be called directly from user code.\n */\ntagsInput.factory('tiUtil', [\"$timeout\", function($timeout) {\n var self = {};\n\n self.debounce = function(fn, delay) {\n var timeoutId;\n return function() {\n var args = arguments;\n $timeout.cancel(timeoutId);\n timeoutId = $timeout(function() { fn.apply(null, args); }, delay);\n };\n };\n\n self.makeObjectArray = function(array, key) {\n array = array || [];\n if (array.length > 0 && !angular.isObject(array[0])) {\n array.forEach(function(item, index) {\n array[index] = {};\n array[index][key] = item;\n });\n }\n return array;\n };\n\n self.findInObjectArray = function(array, obj, key, comparer) {\n var item = null;\n comparer = comparer || self.defaultComparer;\n\n array.some(function(element) {\n if (comparer(element[key], obj[key])) {\n item = element;\n return true;\n }\n });\n\n return item;\n };\n\n self.defaultComparer = function(a, b) {\n // I'm aware of the internationalization issues regarding toLowerCase()\n // but I couldn't come up with a better solution right now\n return self.safeToString(a).toLowerCase() === self.safeToString(b).toLowerCase();\n };\n\n self.safeHighlight = function(str, value) {\n if (!value) {\n return str;\n }\n\n function escapeRegexChars(str) {\n return str.replace(/([.?*+^$[\\]\\\\(){}|-])/g, '\\\\$1');\n }\n\n str = self.encodeHTML(str);\n value = self.encodeHTML(value);\n\n var expression = new RegExp('&[^;]+;|' + escapeRegexChars(value), 'gi');\n return str.replace(expression, function(match) {\n return match.toLowerCase() === value.toLowerCase() ? '<em>' + match + '</em>' : match;\n });\n };\n\n self.safeToString = function(value) {\n return angular.isUndefined(value) || value == null ? '' : value.toString().trim();\n };\n\n self.encodeHTML = function(value) {\n return self.safeToString(value)\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n };\n\n self.handleUndefinedResult = function(fn, valueIfUndefined) {\n return function() {\n var result = fn.apply(null, arguments);\n return angular.isUndefined(result) ? valueIfUndefined : result;\n };\n };\n\n self.replaceSpacesWithDashes = function(str) {\n return self.safeToString(str).replace(/\\s/g, '-');\n };\n\n self.simplePubSub = function() {\n var events = {};\n return {\n on: function(names, handler) {\n names.split(' ').forEach(function(name) {\n if (!events[name]) {\n events[name] = [];\n }\n events[name].push(handler);\n });\n return this;\n },\n trigger: function(name, args) {\n var handlers = events[name] || [];\n handlers.every(function(handler) {\n return self.handleUndefinedResult(handler, true)(args);\n });\n return this;\n }\n };\n };\n\n return self;\n}]);\n\n/* HTML templates */\ntagsInput.run([\"$templateCache\", function($templateCache) {\n $templateCache.put('ngTagsInput/tags-input.html',\n \"<div class=\\\"host\\\" tabindex=\\\"-1\\\" data-ng-click=\\\"eventHandlers.host.click()\\\" ti-transclude-append=\\\"\\\"><div class=\\\"tags\\\" data-ng-class=\\\"{focused: hasFocus}\\\"><ul class=\\\"tag-list\\\"><li class=\\\"tag-item\\\" data-ng-repeat=\\\"tag in tagList.items track by track(tag)\\\" data-ng-class=\\\"{ selected: tag == tagList.selected }\\\"><ti-tag-item data=\\\"tag\\\"></ti-tag-item></li></ul><input class=\\\"input u-no-margin--top\\\" autocomplete=\\\"off\\\" data-ng-model=\\\"newTag.text\\\" data-ng-change=\\\"eventHandlers.input.change(newTag.text)\\\" data-ng-keydown=\\\"eventHandlers.input.keydown($event)\\\" data-ng-focus=\\\"eventHandlers.input.focus($event)\\\" data-ng-blur=\\\"eventHandlers.input.blur($event)\\\" data-ng-paste=\\\"eventHandlers.input.paste($event)\\\" data-ng-trim=\\\"false\\\" data-ng-class=\\\"{'invalid-tag': newTag.invalid}\\\" data-ng-disabled=\\\"disabled\\\" ti-bind-attrs=\\\"{type: options.type, placeholder: options.placeholder, tabindex: options.tabindex, spellcheck: options.spellcheck}\\\" ti-autosize=\\\"\\\"></div></div>\"\n );\n\n $templateCache.put('ngTagsInput/tag-item.html',\n \"<span ng-bind=\\\"$getDisplayText()\\\"></span> <a class=\\\"p-icon--close\\\" data-ng-click=\\\"$removeTag()\\\" data-ng-bind=\\\"$$removeTagSymbol\\\">Remove tag</a>\"\n );\n\n $templateCache.put('ngTagsInput/auto-complete.html',\n \"<div class=\\\"autocomplete\\\" data-ng-if=\\\"suggestionList.visible\\\"><ul class=\\\"p-list suggestion-list\\\"><li class=\\\"suggestion-item\\\" data-ng-repeat=\\\"item in suggestionList.items track by track(item)\\\" data-ng-class=\\\"{selected: item == suggestionList.selected}\\\" data-ng-click=\\\"addSuggestionByIndex($index)\\\" data-ng-mouseenter=\\\"suggestionList.select($index)\\\"><ti-autocomplete-match data=\\\"item\\\"></ti-autocomplete-match></li></ul></div>\"\n );\n\n $templateCache.put('ngTagsInput/auto-complete-match.html',\n \"<span data-ng-bind-html=\\\"$highlight($getDisplayText())\\\"></span>\"\n );\n}]);\n\n}());\n","//\n// Copyright Kamil Pękala http://github.com/kamilkp\n// Angular Virtual Scroll Repeat v1.1.7 2016/03/08\n//\n\n(function(window, angular) {\n 'use strict';\n /* jshint eqnull:true */\n /* jshint -W038 */\n\n // DESCRIPTION:\n // vsRepeat directive stands for Virtual Scroll Repeat. It turns a standard ngRepeated set of elements in a scrollable container\n // into a component, where the user thinks he has all the elements rendered and all he needs to do is scroll (without any kind of\n // pagination - which most users loath) and at the same time the browser isn't overloaded by that many elements/angular bindings etc.\n // The directive renders only so many elements that can fit into current container's clientHeight/clientWidth.\n\n // LIMITATIONS:\n // - current version only supports an Array as a right-hand-side object for ngRepeat\n // - all rendered elements must have the same height/width or the sizes of the elements must be known up front\n\n // USAGE:\n // In order to use the vsRepeat directive you need to place a vs-repeat attribute on a direct parent of an element with ng-repeat\n // example:\n // <div vs-repeat>\n // <div ng-repeat=\"item in someArray\">\n // <!-- content -->\n // </div>\n // </div>\n //\n // or:\n // <div vs-repeat>\n // <div ng-repeat-start=\"item in someArray\">\n // <!-- content -->\n // </div>\n // <div>\n // <!-- something in the middle -->\n // </div>\n // <div ng-repeat-end>\n // <!-- content -->\n // </div>\n // </div>\n //\n // You can also measure the single element's height/width (including all paddings and margins), and then speficy it as a value\n // of the attribute 'vs-repeat'. This can be used if one wants to override the automatically computed element size.\n // example:\n // <div vs-repeat=\"50\"> <!-- the specified element height is 50px -->\n // <div ng-repeat=\"item in someArray\">\n // <!-- content -->\n // </div>\n // </div>\n //\n // IMPORTANT!\n //\n // - the vsRepeat directive must be applied to a direct parent of an element with ngRepeat\n // - the value of vsRepeat attribute is the single element's height/width measured in pixels. If none provided, the directive\n // will compute it automatically\n\n // OPTIONAL PARAMETERS (attributes):\n // vs-repeat-container=\"selector\" - selector for element containing ng-repeat. (defaults to the current element)\n // vs-scroll-parent=\"selector\" - selector to the scrollable container. The directive will look for a closest parent matching\n // the given selector (defaults to the current element)\n // vs-horizontal - stack repeated elements horizontally instead of vertically\n // vs-offset-before=\"value\" - top/left offset in pixels (defaults to 0)\n // vs-offset-after=\"value\" - bottom/right offset in pixels (defaults to 0)\n // vs-excess=\"value\" - an integer number representing the number of elements to be rendered outside of the current container's viewport\n // (defaults to 2)\n // vs-size - a property name of the items in collection that is a number denoting the element size (in pixels)\n // vs-autoresize - use this attribute without vs-size and without specifying element's size. The automatically computed element style will\n // readjust upon window resize if the size is dependable on the viewport size\n // vs-scrolled-to-end=\"callback\" - callback will be called when the last item of the list is rendered\n // vs-scrolled-to-end-offset=\"integer\" - set this number to trigger the scrolledToEnd callback n items before the last gets rendered\n // vs-scrolled-to-beginning=\"callback\" - callback will be called when the first item of the list is rendered\n // vs-scrolled-to-beginning-offset=\"integer\" - set this number to trigger the scrolledToBeginning callback n items before the first gets rendered\n\n // EVENTS:\n // - 'vsRepeatTrigger' - an event the directive listens for to manually trigger reinitialization\n // - 'vsRepeatReinitialized' - an event the directive emits upon reinitialization done\n\n var dde = document.documentElement,\n matchingFunction = dde.matches ? 'matches' :\n dde.matchesSelector ? 'matchesSelector' :\n dde.webkitMatches ? 'webkitMatches' :\n dde.webkitMatchesSelector ? 'webkitMatchesSelector' :\n dde.msMatches ? 'msMatches' :\n dde.msMatchesSelector ? 'msMatchesSelector' :\n dde.mozMatches ? 'mozMatches' :\n dde.mozMatchesSelector ? 'mozMatchesSelector' : null;\n\n var closestElement = angular.element.prototype.closest || function (selector) {\n var el = this[0].parentNode;\n while (el !== document.documentElement && el != null && !el[matchingFunction](selector)) {\n el = el.parentNode;\n }\n\n if (el && el[matchingFunction](selector)) {\n return angular.element(el);\n }\n else {\n return angular.element();\n }\n };\n\n function getWindowScroll() {\n if ('pageYOffset' in window) {\n return {\n scrollTop: pageYOffset,\n scrollLeft: pageXOffset\n };\n }\n else {\n var sx, sy, d = document, r = d.documentElement, b = d.body;\n sx = r.scrollLeft || b.scrollLeft || 0;\n sy = r.scrollTop || b.scrollTop || 0;\n return {\n scrollTop: sy,\n scrollLeft: sx\n };\n }\n }\n\n function getClientSize(element, sizeProp) {\n if (element === window) {\n return sizeProp === 'clientWidth' ? window.innerWidth : window.innerHeight;\n }\n else {\n return element[sizeProp];\n }\n }\n\n function getScrollPos(element, scrollProp) {\n return element === window ? getWindowScroll()[scrollProp] : element[scrollProp];\n }\n\n function getScrollOffset(vsElement, scrollElement, isHorizontal) {\n var vsPos = vsElement.getBoundingClientRect()[isHorizontal ? 'left' : 'top'];\n var scrollPos = scrollElement === window ? 0 : scrollElement.getBoundingClientRect()[isHorizontal ? 'left' : 'top'];\n var correction = vsPos - scrollPos +\n (scrollElement === window ? getWindowScroll() : scrollElement)[isHorizontal ? 'scrollLeft' : 'scrollTop'];\n\n return correction;\n }\n\n var vsRepeatModule = angular.module('vs-repeat', []).directive('vsRepeat', ['$compile', '$parse', function($compile, $parse) {\n return {\n restrict: 'A',\n scope: true,\n compile: function($element, $attrs) {\n var repeatContainer = angular.isDefined($attrs.vsRepeatContainer) ? angular.element($element[0].querySelector($attrs.vsRepeatContainer)) : $element,\n ngRepeatChild = repeatContainer.children().eq(0),\n ngRepeatExpression,\n childCloneHtml = ngRepeatChild[0].outerHTML,\n expressionMatches,\n lhs,\n rhs,\n rhsSuffix,\n originalNgRepeatAttr,\n collectionName = '$vs_collection',\n isNgRepeatStart = false,\n attributesDictionary = {\n 'vsRepeat': 'elementSize',\n 'vsOffsetBefore': 'offsetBefore',\n 'vsOffsetAfter': 'offsetAfter',\n 'vsScrolledToEndOffset': 'scrolledToEndOffset',\n 'vsScrolledToBeginningOffset': 'scrolledToBeginningOffset',\n 'vsExcess': 'excess'\n };\n\n if (ngRepeatChild.attr('ng-repeat')) {\n originalNgRepeatAttr = 'ng-repeat';\n ngRepeatExpression = ngRepeatChild.attr('ng-repeat');\n }\n else if (ngRepeatChild.attr('data-ng-repeat')) {\n originalNgRepeatAttr = 'data-ng-repeat';\n ngRepeatExpression = ngRepeatChild.attr('data-ng-repeat');\n }\n else if (ngRepeatChild.attr('ng-repeat-start')) {\n isNgRepeatStart = true;\n originalNgRepeatAttr = 'ng-repeat-start';\n ngRepeatExpression = ngRepeatChild.attr('ng-repeat-start');\n }\n else if (ngRepeatChild.attr('data-ng-repeat-start')) {\n isNgRepeatStart = true;\n originalNgRepeatAttr = 'data-ng-repeat-start';\n ngRepeatExpression = ngRepeatChild.attr('data-ng-repeat-start');\n }\n else {\n throw new Error('angular-vs-repeat: no ng-repeat directive on a child element');\n }\n\n expressionMatches = /^\\s*(\\S+)\\s+in\\s+([\\S\\s]+?)(track\\s+by\\s+\\S+)?$/.exec(ngRepeatExpression);\n lhs = expressionMatches[1];\n rhs = expressionMatches[2];\n rhsSuffix = expressionMatches[3];\n\n if (isNgRepeatStart) {\n var index = 0;\n var repeaterElement = repeatContainer.children().eq(0);\n while(repeaterElement.attr('ng-repeat-end') == null && repeaterElement.attr('data-ng-repeat-end') == null) {\n index++;\n repeaterElement = repeatContainer.children().eq(index);\n childCloneHtml += repeaterElement[0].outerHTML;\n }\n }\n\n repeatContainer.empty();\n return {\n pre: function($scope, $element, $attrs) {\n var repeatContainer = angular.isDefined($attrs.vsRepeatContainer) ? angular.element($element[0].querySelector($attrs.vsRepeatContainer)) : $element,\n childClone = angular.element(childCloneHtml),\n childTagName = childClone[0].tagName.toLowerCase(),\n originalCollection = [],\n originalLength,\n $$horizontal = typeof $attrs.vsHorizontal !== 'undefined',\n $beforeContent = angular.element('<' + childTagName + ' class=\"vs-repeat-before-content\"></' + childTagName + '>'),\n $afterContent = angular.element('<' + childTagName + ' class=\"vs-repeat-after-content\"></' + childTagName + '>'),\n autoSize = !$attrs.vsRepeat,\n sizesPropertyExists = !!$attrs.vsSize || !!$attrs.vsSizeProperty,\n $scrollParent = $attrs.vsScrollParent ?\n $attrs.vsScrollParent === 'window' ? angular.element(window) :\n closestElement.call(repeatContainer, $attrs.vsScrollParent) : repeatContainer,\n $$options = 'vsOptions' in $attrs ? $scope.$eval($attrs.vsOptions) : {},\n clientSize = $$horizontal ? 'clientWidth' : 'clientHeight',\n offsetSize = $$horizontal ? 'offsetWidth' : 'offsetHeight',\n scrollPos = $$horizontal ? 'scrollLeft' : 'scrollTop';\n\n $scope.totalSize = 0;\n if (!('vsSize' in $attrs) && 'vsSizeProperty' in $attrs) {\n console.warn('vs-size-property attribute is deprecated. Please use vs-size attribute which also accepts angular expressions.');\n }\n\n if ($scrollParent.length === 0) {\n throw 'Specified scroll parent selector did not match any element';\n }\n $scope.$scrollParent = $scrollParent;\n\n if (sizesPropertyExists) {\n $scope.sizesCumulative = [];\n }\n\n //initial defaults\n $scope.elementSize = (+$attrs.vsRepeat) || getClientSize($scrollParent[0], clientSize) || 50;\n $scope.offsetBefore = 0;\n $scope.offsetAfter = 0;\n $scope.excess = 2;\n\n if ($$horizontal) {\n $beforeContent.css('height', '100%');\n $afterContent.css('height', '100%');\n }\n else {\n $beforeContent.css('width', '100%');\n $afterContent.css('width', '100%');\n }\n\n Object.keys(attributesDictionary).forEach(function(key) {\n if ($attrs[key]) {\n $attrs.$observe(key, function(value) {\n // '+' serves for getting a number from the string as the attributes are always strings\n $scope[attributesDictionary[key]] = +value;\n reinitialize();\n });\n }\n });\n\n\n $scope.$watchCollection(rhs, function(coll) {\n originalCollection = coll || [];\n refresh();\n });\n\n function refresh() {\n if (!originalCollection || originalCollection.length < 1) {\n $scope[collectionName] = [];\n originalLength = 0;\n $scope.sizesCumulative = [0];\n }\n else {\n originalLength = originalCollection.length;\n if (sizesPropertyExists) {\n $scope.sizes = originalCollection.map(function(item) {\n var s = $scope.$new(false);\n angular.extend(s, item);\n s[lhs] = item;\n var size = ($attrs.vsSize || $attrs.vsSizeProperty) ?\n s.$eval($attrs.vsSize || $attrs.vsSizeProperty) :\n $scope.elementSize;\n s.$destroy();\n return size;\n });\n var sum = 0;\n $scope.sizesCumulative = $scope.sizes.map(function(size) {\n var res = sum;\n sum += size;\n return res;\n });\n $scope.sizesCumulative.push(sum);\n }\n else {\n setAutoSize();\n }\n }\n\n reinitialize();\n }\n\n function setAutoSize() {\n if (autoSize) {\n $scope.$$postDigest(function() {\n if (repeatContainer[0].offsetHeight || repeatContainer[0].offsetWidth) { // element is visible\n var children = repeatContainer.children(),\n i = 0,\n gotSomething = false,\n insideStartEndSequence = false;\n\n while (i < children.length) {\n if (children[i].attributes[originalNgRepeatAttr] != null || insideStartEndSequence) {\n if (!gotSomething) {\n $scope.elementSize = 0;\n }\n\n gotSomething = true;\n if (children[i][offsetSize]) {\n $scope.elementSize += children[i][offsetSize];\n }\n\n if (isNgRepeatStart) {\n if (children[i].attributes['ng-repeat-end'] != null || children[i].attributes['data-ng-repeat-end'] != null) {\n break;\n }\n else {\n insideStartEndSequence = true;\n }\n }\n else {\n break;\n }\n }\n i++;\n }\n\n if (gotSomething) {\n reinitialize();\n autoSize = false;\n if ($scope.$root && !$scope.$root.$$phase) {\n $scope.$apply();\n }\n }\n }\n else {\n var dereg = $scope.$watch(function() {\n if (repeatContainer[0].offsetHeight || repeatContainer[0].offsetWidth) {\n dereg();\n setAutoSize();\n }\n });\n }\n });\n }\n }\n\n function getLayoutProp() {\n var layoutPropPrefix = childTagName === 'tr' ? '' : 'min-';\n var layoutProp = $$horizontal ? layoutPropPrefix + 'width' : layoutPropPrefix + 'height';\n return layoutProp;\n }\n\n childClone.eq(0).attr(originalNgRepeatAttr, lhs + ' in ' + collectionName + (rhsSuffix ? ' ' + rhsSuffix : ''));\n childClone.addClass('vs-repeat-repeated-element');\n\n repeatContainer.append($beforeContent);\n repeatContainer.append(childClone);\n $compile(childClone)($scope);\n repeatContainer.append($afterContent);\n\n $scope.startIndex = 0;\n $scope.endIndex = 0;\n\n function scrollHandler() {\n if (updateInnerCollection()) {\n $scope.$digest();\n }\n }\n\n $scrollParent.on('scroll', scrollHandler);\n\n function onWindowResize() {\n if (typeof $attrs.vsAutoresize !== 'undefined') {\n autoSize = true;\n setAutoSize();\n if ($scope.$root && !$scope.$root.$$phase) {\n $scope.$apply();\n }\n }\n if (updateInnerCollection()) {\n $scope.$apply();\n }\n }\n\n angular.element(window).on('resize', onWindowResize);\n $scope.$on('$destroy', function() {\n angular.element(window).off('resize', onWindowResize);\n $scrollParent.off('scroll', scrollHandler);\n });\n\n $scope.$on('vsRepeatTrigger', refresh);\n\n $scope.$on('vsRepeatResize', function() {\n autoSize = true;\n setAutoSize();\n });\n\n var _prevStartIndex,\n _prevEndIndex,\n _minStartIndex,\n _maxEndIndex;\n\n $scope.$on('vsRenderAll', function() {//e , quantum) {\n if($$options.latch) {\n setTimeout(function() {\n // var __endIndex = Math.min($scope.endIndex + (quantum || 1), originalLength);\n var __endIndex = originalLength;\n _maxEndIndex = Math.max(__endIndex, _maxEndIndex);\n $scope.endIndex = $$options.latch ? _maxEndIndex : __endIndex;\n $scope[collectionName] = originalCollection.slice($scope.startIndex, $scope.endIndex);\n _prevEndIndex = $scope.endIndex;\n\n $scope.$$postDigest(function() {\n $beforeContent.css(getLayoutProp(), 0);\n $afterContent.css(getLayoutProp(), 0);\n });\n\n $scope.$apply(function() {\n $scope.$emit('vsRenderAllDone');\n });\n });\n }\n });\n\n function reinitialize() {\n _prevStartIndex = void 0;\n _prevEndIndex = void 0;\n _minStartIndex = originalLength;\n _maxEndIndex = 0;\n updateTotalSize(sizesPropertyExists ?\n $scope.sizesCumulative[originalLength] :\n $scope.elementSize * originalLength\n );\n updateInnerCollection();\n\n $scope.$emit('vsRepeatReinitialized', $scope.startIndex, $scope.endIndex);\n }\n\n function updateTotalSize(size) {\n $scope.totalSize = $scope.offsetBefore + size + $scope.offsetAfter;\n }\n\n var _prevClientSize;\n function reinitOnClientHeightChange() {\n var ch = getClientSize($scrollParent[0], clientSize);\n if (ch !== _prevClientSize) {\n reinitialize();\n if ($scope.$root && !$scope.$root.$$phase) {\n $scope.$apply();\n }\n }\n _prevClientSize = ch;\n }\n\n $scope.$watch(function() {\n if (typeof window.requestAnimationFrame === 'function') {\n window.requestAnimationFrame(reinitOnClientHeightChange);\n }\n else {\n reinitOnClientHeightChange();\n }\n });\n\n function updateInnerCollection() {\n var $scrollPosition = getScrollPos($scrollParent[0], scrollPos);\n var $clientSize = getClientSize($scrollParent[0], clientSize);\n\n var scrollOffset = repeatContainer[0] === $scrollParent[0] ? 0 : getScrollOffset(\n repeatContainer[0],\n $scrollParent[0],\n $$horizontal\n );\n\n var __startIndex = $scope.startIndex;\n var __endIndex = $scope.endIndex;\n\n if (sizesPropertyExists) {\n __startIndex = 0;\n while ($scope.sizesCumulative[__startIndex] < $scrollPosition - $scope.offsetBefore - scrollOffset) {\n __startIndex++;\n }\n if (__startIndex > 0) { __startIndex--; }\n\n // Adjust the start index according to the excess\n __startIndex = Math.max(\n Math.floor(__startIndex - $scope.excess / 2),\n 0\n );\n\n __endIndex = __startIndex;\n while ($scope.sizesCumulative[__endIndex] < $scrollPosition - $scope.offsetBefore - scrollOffset + $clientSize) {\n __endIndex++;\n }\n\n // Adjust the end index according to the excess\n __endIndex = Math.min(\n Math.ceil(__endIndex + $scope.excess / 2),\n originalLength\n );\n }\n else {\n __startIndex = Math.max(\n Math.floor(\n ($scrollPosition - $scope.offsetBefore - scrollOffset) / $scope.elementSize\n ) - $scope.excess / 2,\n 0\n );\n\n __endIndex = Math.min(\n __startIndex + Math.ceil(\n $clientSize / $scope.elementSize\n ) + $scope.excess,\n originalLength\n );\n }\n\n _minStartIndex = Math.min(__startIndex, _minStartIndex);\n _maxEndIndex = Math.max(__endIndex, _maxEndIndex);\n\n $scope.startIndex = $$options.latch ? _minStartIndex : __startIndex;\n $scope.endIndex = $$options.latch ? _maxEndIndex : __endIndex;\n\n var digestRequired = false;\n if (_prevStartIndex == null) {\n digestRequired = true;\n }\n else if (_prevEndIndex == null) {\n digestRequired = true;\n }\n\n if (!digestRequired) {\n if ($$options.hunked) {\n if (Math.abs($scope.startIndex - _prevStartIndex) >= $scope.excess / 2 ||\n ($scope.startIndex === 0 && _prevStartIndex !== 0)) {\n digestRequired = true;\n }\n else if (Math.abs($scope.endIndex - _prevEndIndex) >= $scope.excess / 2 ||\n ($scope.endIndex === originalLength && _prevEndIndex !== originalLength)) {\n digestRequired = true;\n }\n }\n else {\n digestRequired = $scope.startIndex !== _prevStartIndex ||\n $scope.endIndex !== _prevEndIndex;\n }\n }\n\n if (digestRequired) {\n $scope[collectionName] = originalCollection.slice($scope.startIndex, $scope.endIndex);\n\n // Emit the event\n $scope.$emit('vsRepeatInnerCollectionUpdated', $scope.startIndex, $scope.endIndex, _prevStartIndex, _prevEndIndex);\n var triggerIndex;\n if ($attrs.vsScrolledToEnd) {\n triggerIndex = originalCollection.length - ($scope.scrolledToEndOffset || 0);\n if (($scope.endIndex >= triggerIndex && _prevEndIndex < triggerIndex) || (originalCollection.length && $scope.endIndex === originalCollection.length)) {\n $scope.$eval($attrs.vsScrolledToEnd);\n }\n }\n if ($attrs.vsScrolledToBeginning) {\n triggerIndex = $scope.scrolledToBeginningOffset || 0;\n if (($scope.startIndex <= triggerIndex && _prevStartIndex > $scope.startIndex)) {\n $scope.$eval($attrs.vsScrolledToBeginning);\n }\n }\n\n _prevStartIndex = $scope.startIndex;\n _prevEndIndex = $scope.endIndex;\n\n var offsetCalculationString = sizesPropertyExists ?\n '(sizesCumulative[$index + startIndex] + offsetBefore)' :\n '(($index + startIndex) * elementSize + offsetBefore)';\n\n var parsed = $parse(offsetCalculationString);\n var o1 = parsed($scope, {$index: 0});\n var o2 = parsed($scope, {$index: $scope[collectionName].length});\n var total = $scope.totalSize;\n\n $beforeContent.css(getLayoutProp(), o1 + 'px');\n $afterContent.css(getLayoutProp(), (total - o2) + 'px');\n }\n\n return digestRequired;\n }\n }\n };\n }\n };\n }]);\n\n if (typeof module !== 'undefined' && module.exports) {\n module.exports = vsRepeatModule.name;\n }\n})(window, window.angular);\n"],"sourceRoot":""}
1284\ No newline at end of file
1285diff --git a/src/maasserver/static/partials/dashboard.html b/src/maasserver/static/partials/dashboard.html
1286index 35e670d..b009216 100644
1287--- a/src/maasserver/static/partials/dashboard.html
1288+++ b/src/maasserver/static/partials/dashboard.html
1289@@ -57,7 +57,7 @@
1290 </td>
1291 </tr>
1292 </tbody>
1293- <tbody vs-repeat="{scrollParent: 'window'}">
1294+ <tbody vs-repeat vs-scroll-parent="window">
1295 <tr data-ng-repeat="discovery in discoveredDevices | orderBy:predicate:reverse track by discovery.first_seen"
1296 data-ng-class="{'is-active' : discovery.first_seen === selectedDevice}">
1297 <td class="p-table--network-discovery__name" aria-label="Name" data-ng-if="discovery.first_seen !== selectedDevice">
1298diff --git a/src/maasserver/static/partials/machines-table.html b/src/maasserver/static/partials/machines-table.html
1299index 727d392..1c49dbe 100644
1300--- a/src/maasserver/static/partials/machines-table.html
1301+++ b/src/maasserver/static/partials/machines-table.html
1302@@ -22,7 +22,7 @@
1303 <th class="u-hide--small u-align--right" role="columnheader" data-ng-click="sortTable('storage')" data-ng-class="{'is-sorted': table.predicate === 'storage', 'sort-asc': table.reverse === false, 'sort-desc': table.reverse === true}" title="Storage (GB)">Storage (GB)</th>
1304 </tr>
1305 </thead>
1306- <tbody vs-repeat="{scrollParent: 'window'}">
1307+ <tbody vs-repeat vs-scroll-parent="window">
1308 <tr class="p-table__row" data-ng-repeat="node in table.filteredMachines = (table.machines | nodesFilter:search | orderBy:table.predicate:table.reverse) track by node.system_id" data-ng-class="{ 'table--error': machineHasError({ $machine: node }), 'is-active': node.$selected }">
1309 <td class="u-align--left" aria-label="FQDN" data-ng-if="table.column === 'fqdn'">
1310 <div class="u-float--left" data-ng-if="!hideCheckboxes">
1311diff --git a/src/maasserver/static/partials/networks-list.html b/src/maasserver/static/partials/networks-list.html
1312index 4517c73..9bdd75e 100644
1313--- a/src/maasserver/static/partials/networks-list.html
1314+++ b/src/maasserver/static/partials/networks-list.html
1315@@ -171,7 +171,7 @@
1316 <th><div class="u-align--right">Available IPs</div></th>
1317 </tr>
1318 </thead>
1319- <tbody vs-repeat="{scrollParent: 'window'}">
1320+ <tbody vs-repeat vs-scroll-parent="window">
1321 <tr data-ng-repeat="row in group.spaces.rows">
1322 <!-- <td class="ng-hide">
1323 <div data-ng-if="row.space_name">
1324@@ -241,7 +241,7 @@
1325 <th>Space</th>
1326 </tr>
1327 </thead>
1328- <tbody vs-repeat="{scrollParent: 'window'}">
1329+ <tbody vs-repeat vs-scroll-parent="window">
1330 <tr data-ng-repeat="row in group.fabrics.rows">
1331 <!-- <td class="ng-hide">
1332 <div data-ng-if="row.fabric_name">
1333diff --git a/src/maasserver/static/partials/node-events.html b/src/maasserver/static/partials/node-events.html
1334index 75d6772..10c8d3a 100644
1335--- a/src/maasserver/static/partials/node-events.html
1336+++ b/src/maasserver/static/partials/node-events.html
1337@@ -46,7 +46,7 @@
1338 <th class="col-9">Event</th>
1339 </tr>
1340 </thead>
1341- <tbody vs-repeat="{scrollParent: 'window'}">
1342+ <tbody vs-repeat vs-scroll-parent="window">
1343 <tr data-ng-repeat="event in events | filter:search | orderByDate:'created':'id' track by event.id">
1344 <td class="col-3" title="{$ event.created $}">
1345 <span class="p-icon--{$ event.type.level $}"></span>&nbsp;
1346diff --git a/src/maasserver/static/partials/nodes-list.html b/src/maasserver/static/partials/nodes-list.html
1347index 6662a02..354c12f 100644
1348--- a/src/maasserver/static/partials/nodes-list.html
1349+++ b/src/maasserver/static/partials/nodes-list.html
1350@@ -438,7 +438,7 @@
1351 <th class="p-table__cell">Actions</th>
1352 </tr>
1353 </thead>
1354- <tbody vs-repeat="{scrollParent: 'window'}">
1355+ <tbody vs-repeat vs-scroll-parent="window">
1356 <tr class="p-table__row" data-ng-repeat="interface in device.interfaces">
1357 <td class="p-table__cell" aria-label="MAC address">
1358 <div class="p-form-validation u-no-margin--top" data-ng-class="{ 'is-error': macHasError(interface) }">
1359@@ -868,7 +868,7 @@ sudo maas-rack register --url {$ tabs.controllers.registerUrl $} --secret {$ tab
1360 </th>
1361 </tr>
1362 </thead>
1363- <tbody vs-repeat="{scrollParent: 'window'}">
1364+ <tbody vs-repeat vs-scroll-parent="window">
1365 <!-- XXX rvba 2015-02-25 - Need to add e2e test. This really needs lots of tests. -->
1366 <tr class="p-table__row"
1367 data-ng-repeat="device in tabs.devices.filtered_items = (devices | nodesFilter:tabs.devices.search | orderBy:tabs.devices.predicate:tabs.devices.reverse) track by device.system_id"
1368@@ -1027,7 +1027,7 @@ sudo maas-rack register --url {$ tabs.controllers.registerUrl $} --secret {$ tab
1369 <th class="p-table__cell" role="columnheader" data-ng-click="sortTable('updated', 'controllers')" data-ng-class="{'is-sorted': tabs.controllers.predicate === 'updated', 'sort-asc': tabs.controllers.reverse === false, 'sort-desc': tabs.controllers.reverse === true}">Images Status</th>
1370 </tr>
1371 </thead>
1372- <tbody vs-repeat="{scrollParent: 'window'}">
1373+ <tbody vs-repeat vs-scroll-parent="window">
1374 <!-- XXX rvba 2015-02-25 - Need to add e2e test. This really needs lots of tests. -->
1375 <tr class="p-table__row"
1376 data-ng-repeat="controller in tabs.controllers.filtered_items = (controllers | nodesFilter:tabs.controllers.search | orderBy:tabs.controllers.predicate:tabs.controllers.reverse) track by controller.system_id"
1377diff --git a/src/maasserver/static/partials/pods-list.html b/src/maasserver/static/partials/pods-list.html
1378index a7ff1f6..a692f91 100644
1379--- a/src/maasserver/static/partials/pods-list.html
1380+++ b/src/maasserver/static/partials/pods-list.html
1381@@ -133,7 +133,7 @@
1382 <th class="p-table__cell u-align--right" role="columnheader" data-ng-click="sortTable('composed_machines')" data-ng-class="{'is-sorted': predicate === 'composed_machines', 'sort-asc': reverse === false, 'sort-desc': reverse === true}" title="Composed machines">Composed machines</th>
1383 </tr>
1384 </thead>
1385- <tbody vs-repeat="{scrollParent: 'window'}">
1386+ <tbody vs-repeat vs-scroll-parent="window">
1387 <tr class="p-table__row" data-ng-repeat="pod in filteredItems = (pods | nodesFilter:search | orderBy:predicate:reverse) track by pod.id" data-ng-class="{ selected: pod.$selected, 'is-active': pod.$selected && pod.action_failed }">
1388 <td class="p-table__cell" aria-label="Name" title="{$ pod.name $}">
1389 <div class="u-float--left" data-ng-if="isSuperUser()">
1390diff --git a/src/maasserver/static/partials/switches-table.html b/src/maasserver/static/partials/switches-table.html
1391index 371cbba..106a251 100644
1392--- a/src/maasserver/static/partials/switches-table.html
1393+++ b/src/maasserver/static/partials/switches-table.html
1394@@ -22,7 +22,7 @@
1395 <th class="u-align--right" role="columnheader" data-ng-click="sortTable('serial')" data-ng-class="{'is-sorted': table.predicate === 'serial', 'sort-asc': table.reverse === false, 'sort-desc': table.reverse === true}">Serial</th>
1396 </tr>
1397 </thead>
1398- <tbody vs-repeat="{scrollParent: 'window'}">
1399+ <tbody vs-repeat vs-scroll-parent="window">
1400 <tr
1401 data-ng-repeat="node in table.filteredSwitches = (table.switches | nodesFilter:search | orderBy:table.predicate:table.reverse) track by node.system_id"
1402 data-ng-class="{ 'table--error': machineHasError({ $switch_: node }), selected: node.$selected }">
1403diff --git a/src/maasserver/static/partials/zones-list.html b/src/maasserver/static/partials/zones-list.html
1404index 921db3d..c35cc5e 100755
1405--- a/src/maasserver/static/partials/zones-list.html
1406+++ b/src/maasserver/static/partials/zones-list.html
1407@@ -54,7 +54,7 @@
1408 <th class="u-align--right">Controllers</th>
1409 </tr>
1410 </thead>
1411- <tbody vs-repeat="{scrollParent: 'window'}">
1412+ <tbody vs-repeat vs-scroll-parent="window">
1413 <tr data-ng-repeat="zone in zones">
1414 <td aria-label="Name" title="{$ zone.name $}">
1415 <a href="#/zone/{$ zone.id $}">{$ zone.name $}</a>

Subscribers

People subscribed via source and target branches