PageSourceSearch

https://account.leyserkids.jp/libs/angular-messages/angular-messages.js

js leyserkids.jp collected 2026-10-04 18:53:35 UTC 27,829 bytes, 722 lines download raw bytes

1/**
2 * @license AngularJS v1.5.5
3 * (c) 2010-2016 Google, Inc. http://angularjs.org
4 * License: MIT
5 */
6(function(window, angular) {'use strict';
7
8/* jshint ignore:start */
9// this code is in the core, but not in angular-messages.js
10var isArray = angular.isArray;
11var forEach = angular.forEach;
12var isString = angular.isString;
13var jqLite = angular.element;
14/* jshint ignore:end */
15
16/**
17 * @ngdoc module
18 * @name ngMessages
19 * @description
20 *
21 * The `ngMessages` module provides enhanced support for displaying messages within templates
22 * (typically within forms or when rendering message objects that return key/value data).
23 * Instead of relying on JavaScript code and/or complex ng-if statements within your form template to
24 * show and hide error messages specific to the state of an input field, the `ngMessages` and
25 * `ngMessage` directives are designed to handle the complexity, inheritance and priority
26 * sequencing based on the order of how the messages are defined in the template.
27 *
28 * Currently, the ngMessages module only contains the code for the `ngMessages`, `ngMessagesInclude`
29 * `ngMessage` and `ngMessageExp` directives.
30 *
31 * # Usage
32 * The `ngMessages` directive allows keys in a key/value collection to be associated with a child element
33 * (or 'message') that will show or hide based on the truthiness of that key's value in the collection. A common use
34 * case for `ngMessages` is to display error messages for inputs using the `$error` object exposed by the
35 * {@link ngModel ngModel} directive.
36 *
37 * The child elements of the `ngMessages` directive are matched to the collection keys by a `ngMessage` or
38 * `ngMessageExp` directive. The value of these attributes must match a key in the collection that is provided by
39 * the `ngMessages` directive.
40 *
41 * Consider the following example, which illustrates a typical use case of `ngMessages`. Within the form `myForm` we
42 * have a text input named `myField` which is bound to the scope variable `field` using the {@link ngModel ngModel}
43 * directive.
44 *
45 * The `myField` field is a required input of type `email` with a maximum length of 15 characters.
46 *
47 * ```html
48 * <form name="myForm">
49 *   <label>
50 *     Enter text:
51 *     <input type="email" ng-model="field" name="myField" required maxlength="15" />
52 *   </label>
53 *   <div ng-messages="myForm.myField.$error" role="alert">
54 *     <div ng-message="required">Please enter a value for this field.</div>
55 *     <div ng-message="email">This field must be a valid email address.</div>
56 *     <div ng-message="maxlength">This field can be at most 15 characters long.</div>
57 *   </div>
58 * </form>
59 * ```
60 *
61 * In order to show error messages corresponding to `myField` we first create an element with an `ngMessages` attribute
62 * set to the `$error` object owned by the `myField` input in our `myForm` form.
63 *
64 * Within this element we then create separate elements for each of the possible errors that `myField` could have.
65 * The `ngMessage` attribute is used to declare which element(s) will appear for which error - for example,
66 * setting `ng-message="required"` specifies that this particular element should be displayed when there
67 * is no value present for the required field `myField` (because the key `required` will be `true` in the object
68 * `myForm.myField.$error`).
69 *
70 * ### Message order
71 *
72 * By default, `ngMessages` will only display one message for a particular key/value collection at any time. If more
73 * than one message (or error) key is currently true, then which message is shown is determined by the order of messages
74 * in the HTML template code (messages declared first are prioritised). This mechanism means the developer does not have
75 * to prioritise messages using custom JavaScript code.
76 *
77 * Given the following error object for our example (which informs us that the field `myField` currently has both the
78 * `required` and `email` errors):
79 *
80 * ```javascript
81 * <!-- keep in mind that ngModel automatically sets these error flags -->
82 * myField.$error = { required : true, email: true, maxlength: false };
83 * ```
84 * The `required` message will be displayed to the user since it appears before the `email` message in the DOM.
85 * Once the user types a single character, the `required` message will disappear (since the field now has a value)
86 * but the `email` message will be visible because it is still applicable.
87 *
88 * ### Displaying multiple messages at the same time
89 *
90 * While `ngMessages` will by default only display one error element at a time, the `ng-messages-multiple` attribute can
91 * be applied to the `ngMessages` container element to cause it to display all applicable error messages at once:
92 *
93 * ```html
94 * <!-- attribute-style usage -->
95 * <div ng-messages="myForm.myField.$error" ng-messages-multiple>...</div>
96 *
97 * <!-- element-style usage -->
98 * <ng-messages for="myForm.myField.$error" multiple>...</ng-messages>
99 * ```
100 *
101 * ## Reusing and Overriding Messages
102 * In addition to prioritization, ngMessages also allows for including messages from a remote or an inline
103 * template. This allows for generic collection of messages to be reused across multiple parts of an
104 * application.
105 *
106 * ```html
107 * <script type="text/ng-template" id="error-messages">
108 *   <div ng-message="required">This field is required</div>
109 *   <div ng-message="minlength">This field is too short</div>
110 * </script>
111 *
112 * <div ng-messages="myForm.myField.$error" role="alert">
113 *   <div ng-messages-include="error-messages"></div>
114 * </div>
115 * ```
116 *
117 * However, including generic messages may not be useful enough to match all input fields, therefore,
118 * `ngMessages` provides the ability to override messages defined in the remote template by redefining
119 * them within the directive container.
120 *
121 * ```html
122 * <!-- a generic template of error messages known as "my-custom-messages" -->
123 * <script type="text/ng-template" id="my-custom-messages">
124 *   <div ng-message="required">This field is required</div>
125 *   <div ng-message="minlength">This field is too short</div>
126 * </script>
127 *
128 * <form name="myForm">
129 *   <label>
130 *     Email address
131 *     <input type="email"
132 *            id="email"
133 *            name="myEmail"
134 *            ng-model="email"
135 *            minlength="5"
136 *            required />
137 *   </label>
138 *   <!-- any ng-message elements that appear BEFORE the ng-messages-include will
139 *        override the messages present in the ng-messages-include template -->
140 *   <div ng-messages="myForm.myEmail.$error" role="alert">
141 *     <!-- this required message has overridden the template message -->
142 *     <div ng-message="required">You did not enter your email address</div>
143 *
144 *     <!-- this is a brand new message and will appear last in the prioritization -->
145 *     <div ng-message="email">
145Your email address is invalid</div>
146 *
147 *     <!-- and here are the generic error messages -->
148 *     <div ng-messages-include="my-custom-messages"></div>
149 *   </div>
150 * </form>
151 * ```
152 *
153 * In the example HTML code above the message that is set on required will override the corresponding
154 * required message defined within the remote template. Therefore, with particular input fields (such
155 * email addresses, date fields, autocomplete inputs, etc...), specialized error messages can be applied
156 * while more generic messages can be used to handle other, more general input errors.
157 *
158 * ## Dynamic Messaging
159 * ngMessages also supports using expressions to dynamically change key values. Using arrays and
160 * repeaters to list messages is also supported. This means that the code below will be able to
161 * fully adapt itself and display the appropriate message when any of the expression data changes:
162 *
163 * ```html
164 * <form name="myForm">
165 *   <label>
166 *     Email address
167 *     <input type="email"
168 *            name="myEmail"
169 *            ng-model="email"
170 *            minlength="5"
171 *            required />
172 *   </label>
173 *   <div ng-messages="myForm.myEmail.$error" role="alert">
174 *     <div ng-message="required">You did not enter your email address</div>
175 *     <div ng-repeat="errorMessage in errorMessages">
176 *       <!-- use ng-message-exp for a message whose key is given by an expression -->
177 *       <div ng-message-exp="errorMessage.type">{{ errorMessage.text }}</div>
178 *     </div>
179 *   </div>
180 * </form>
181 * ```
182 *
183 * The `errorMessage.type` expression can be a string value or it can be an array so
184 * that multiple errors can be associated with a single error message:
185 *
186 * ```html
187 *   <label>
188 *     Email address
189 *     <input type="email"
190 *            ng-model="data.email"
191 *            name="myEmail"
192 *            ng-minlength="5"
193 *            ng-maxlength="100"
194 *            required />
195 *   </label>
196 *   <div ng-messages="myForm.myEmail.$error" role="alert">
197 *     <div ng-message-exp="'required'">You did not enter your email address</div>
198 *     <div ng-message-exp="['minlength', 'maxlength']">
199 *       Your email must be between 5 and 100 characters long
200 *     </div>
201 *   </div>
202 * ```
203 *
204 * Feel free to use other structural directives such as ng-if and ng-switch to further control
205 * what messages are active and when. Be careful, if you place ng-message on the same element
206 * as these structural directives, Angular may not be able to determine if a message is active
207 * or not. Therefore it is best to place the ng-message on a child element of the structural
208 * directive.
209 *
210 * ```html
211 * <div ng-messages="myForm.myEmail.$error" role="alert">
212 *   <div ng-if="showRequiredError">
213 *     <div ng-message="required">Please enter something</div>
214 *   </div>
215 * </div>
216 * ```
217 *
218 * ## Animations
219 * If the `ngAnimate` module is active within the application then the `ngMessages`, `ngMessage` and
220 * `ngMessageExp` directives will trigger animations whenever any messages are added and removed from
221 * the DOM by the `ngMessages` directive.
222 *
223 * Whenever the `ngMessages` directive contains one or more visible messages then the `.ng-active` CSS
224 * class will be added to the element. The `.ng-inactive` CSS class will be applied when there are no
225 * messages present. Therefore, CSS transitions and keyframes as well as JavaScript animations can
226 * hook into the animations whenever these classes are added/removed.
227 *
228 * Let's say that our HTML code for our messages container looks like so:
229 *
230 * ```html
231 * <div ng-messages="myMessages" class="my-messages" role="alert">
232 *   <div ng-message="alert" class="some-message">...</div>
233 *   <div ng-message="fail" class="some-message">...</div>
234 * </div>
235 * ```
236 *
237 * Then the CSS animation code for the message container looks like so:
238 *
239 * ```css
240 * .my-messages {
241 *   transition:1s linear all;
242 * }
243 * .my-messages.ng-active {
244 *   // messages are visible
245 * }
246 * .my-messages.ng-inactive {
247 *   // messages are hidden
248 * }
249 * ```
250 *
251 * Whenever an inner message is attached (becomes visible) or removed (becomes hidden) then the enter
252 * and leave animation is triggered for each particular element bound to the `ngMessage` directive.
253 *
254 * Therefore, the CSS code for the inner messages looks like so:
255 *
256 * ```css
257 * .some-message {
258 *   transition:1s linear all;
259 * }
260 *
261 * .some-message.ng-enter {}
262 * .some-message.ng-enter.ng-enter-active {}
263 *
264 * .some-message.ng-leave {}
265 * .some-message.ng-leave.ng-leave-active {}
266 * ```
267 *
268 * {@link ngAnimate Click here} to learn how to use JavaScript animations or to learn more about ngAnimate.
269 */
270angular.module('ngMessages', [])
271
272   /**
273    * @ngdoc directive
274    * @module ngMessages
275    * @name ngMessages
276    * @restrict AE
277    *
278    * @description
279    * `ngMessages` is a directive that is designed to show and hide messages based on the state
280    * of a key/value object that it listens on. The directive itself complements error message
281    * reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
282    *
283    * `ngMessages` manages the state of internal messages within its container element. The internal
284    * messages use the `ngMessage` directive and will be inserted/removed from the page depending
285    * on if they're present within the key/value object. By default, only one message will be displayed
286    * at a time and this depends on the prioritization of the messages within the template. (This can
287    * be changed by using the `ng-messages-multiple` or `multiple` attribute on the directive container.)
288    *
289    * A remote template can also be used to promote message reusability and messages can also be
290    * overridden.
291    *
292    * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
293    *
294    * @usage
295    * ```html
296    * <!-- using attribute directives -->
297    * <ANY ng-messages="expression" role="alert">
298    *   <ANY ng-message="stringValue">...</ANY>
299    *   <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
300    *   <ANY ng-message-exp="expressionValue">...</ANY>
301    * </ANY>
302    *
303    * <!-- or by using element directives -->
304    * <ng-messages for="expression" role="alert">
305    *   <ng-message when="stringValue">...</ng-message>
306    *   <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
307    *   <ng-message when-exp="expressionValue">...</ng-message>
308    * </ng-messages>
309    * ```
310    *
311    * @param {string} ngMessages an angular expression evaluating to a key/value object
312    *                 (this is typically the $error object on an ngModel instance).
313    * @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true
314    *
315    * @example
316    * <example name="ngMessages-directive" module="ngMessagesExample"
317    *          deps="angular-messages.js"
318    *          animations="true" fixBase="true">
319    *   <file name="index.html">
320    *     <form name="myForm">
321    *       <label>
322    *         Enter your name:
323    *         <input type="text"
324    *                name="myName"
325    *                ng-model="name"
326    *                ng-minlength="5"
327    *                ng-maxlength="20"
328    *                required />
329    *       </label>
330    *       <pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
331    *
332    *       <div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
333    *         <div ng-message="required">You did not enter a field</div>
334    *         <div ng-message="minlength">Your field is too short</div>
335    *         <div ng-message="maxlength">Your field is too long</div>
336    *       </div>
337    *     </form>
338    *   </file>
339    *   <file name="script.js">
340    *     angular.module('ngMessagesExample', ['ngMessages']);
341    *   </file>
342    * </example>
343    */
344   .directive('ngMessages', ['$animate', function($animate) {
345     var ACTIVE_CLASS = 'ng-active';
346     var INACTIVE_CLASS = 'ng-inactive';
347
348     return {
349       require: 'ngMessages',
350       restrict: 'AE',
351       controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
352         var ctrl = this;
353         var latestKey = 0;
354         var nextAttachId = 0;
355
356         this.getAttachId = function getAttachId() { return nextAttachId++; };
357
358         var messages = this.messages = {};
359         var renderLater, cachedCollection;
360
361         this.render = function(collection) {
362           collection = collection || {};
363
364           renderLater = false;
365           cachedCollection = collection;
366
367           // this is true if the attribute is empty or if the attribute value is truthy
368           var multiple = isAttrTruthy($scope, $attrs.ngMessagesMultiple) ||
369                          isAttrTruthy($scope, $attrs.multiple);
370
371           var unmatchedMessages = [];
372           var matchedKeys = {};
373           var messageItem = ctrl.head;
374           var messageFound = false;
375           var totalMessages = 0;
376
377           // we use != instead of !== to allow for both undefined and null values
378           while (messageItem != null) {
379             totalMessages++;
380             var messageCtrl = messageItem.message;
381
382             var messageUsed = false;
383             if (!messageFound) {
384               forEach(collection, function(value, key) {
385                 if (!messageUsed && truthy(value) && messageCtrl.test(key)) {
386                   // this is to prevent the same error name from showing up twice
387                   if (matchedKeys[key]) return;
388                   matchedKeys[key] = true;
389
390                   messageUsed = true;
391                   messageCtrl.attach();
392                 }
393               });
394             }
395
396             if (messageUsed) {
397               // unless we want to display multiple messages then we should
398               // set a flag here to avoid displaying the next message in the list
399               messageFound = !multiple;
400             } else {
401               unmatchedMessages.push(messageCtrl);
402             }
403
404             messageItem = messageItem.next;
405           }
406
407           forEach(unmatchedMessages, function(messageCtrl) {
408             messageCtrl.detach();
409           });
410
411           unmatchedMessages.length !== totalMessages
412              ? $animate.setClass($element, ACTIVE_CLASS, INACTIVE_CLASS)
413              : $animate.setClass($element, INACTIVE_CLASS, ACTIVE_CLASS);
414         };
415
416         $scope.$watchCollection($attrs.ngMessages || $attrs['for'], ctrl.render);
417
418         // If the element is destroyed, proactively destroy all the currently visible messages
419         $element.on('$destroy', function() {
420           forEach(messages, function(item) {
421             item.message.detach();
422           });
423         });
424
425         this.reRender = function() {
426           if (!renderLater) {
427             renderLater = true;
428             $scope.$evalAsync(function() {
429               if (renderLater) {
430                 cachedCollection && ctrl.render(cachedCollection);
431               }
432             });
433           }
434         };
435
436         this.register = function(comment, messageCtrl) {
437           var nextKey = latestKey.toString();
438           messages[nextKey] = {
439             message: messageCtrl
440           };
441           insertMessageNode($element[0], comment, nextKey);
442           comment.$$ngMessageNode = nextKey;
443           latestKey++;
444
445           ctrl.reRender();
446         };
447
448         this.deregister = function(comment) {
449           var key = comment.$$ngMessageNode;
450           delete comment.$$ngMessageNode;
451           removeMessageNode($element[0], comment, key);
452           delete messages[key];
453           ctrl.reRender();
454         };
455
456         function findPreviousMessage(parent, comment) {
457           var prevNode = comment;
458           var parentLookup = [];
459
460           while (prevNode && prevNode !== parent) {
461             var prevKey = prevNode.$$ngMessageNode;
462             if (prevKey && prevKey.length) {
463               return messages[prevKey];
464             }
465
466             // dive deeper into the DOM and examine its children for any ngMessage
467             // comments that may be in an element that appears deeper in the list
468             if (prevNode.childNodes.length && parentLookup.indexOf(prevNode) == -1) {
469               parentLookup.push(prevNode);
470               prevNode = prevNode.childNodes[prevNode.childNodes.length - 1];
471             } else if (prevNode.previousSibling) {
472               prevNode = prevNode.previousSibling;
473             } else {
474               prevNode = prevNode.parentNode;
475               parentLookup.push(prevNode);
476             }
477           }
478         }
479
480         function insertMessageNode(parent, comment, key) {
481           var messageNode = messages[key];
482           if (!ctrl.head) {
483             ctrl.head = messageNode;
484           } else {
485             var match = findPreviousMessage(parent, comment);
486             if (match) {
487               messageNode.next = match.next;
488               match.next = messageNode;
489             } else {
490               messageNode.next = ctrl.head;
491               ctrl.head = messageNode;
492             }
493           }
494         }
495
496         function removeMessageNode(parent, comment, key) {
497           var messageNode = messages[key];
498
499           var match = findPreviousMessage(parent, comment);
500           if (match) {
501             match.next = messageNode.next;
502           } else {
503             ctrl.head = messageNode.next;
504           }
505         }
506       }]
507     };
508
509     function isAttrTruthy(scope, attr) {
510      return (isString(attr) && attr.length === 0) || //empty attribute
511             truthy(scope.$eval(attr));
512     }
513
514     function truthy(val) {
515       return isString(val) ? val.length : !!val;
516     }
517   }])
518
519   /**
520    * @ngdoc directive
521    * @name ngMessagesInclude
522    * @restrict AE
523    * @scope
524    *
525    * @description
526    * `ngMessagesInclude` is a directive with the purpose to import existing ngMessage template
527    * code from a remote template and place the downloaded template code into the exact spot
528    * that the ngMessagesInclude directive is placed within the ngMessages container. This allows
529    * for a series of pre-defined messages to be reused and also allows for the developer to
530    * determine what messages are overridden due to the placement of the ngMessagesInclude directive.
531    *
532    * @usage
533    * ```html
534    * <!-- using attribute directives -->
535    * <ANY ng-messages="expression" role="alert">
536    *   <ANY ng-messages-include="remoteTplString">...</ANY>
537    * </ANY>
538    *
539    * <!-- or by using element directives -->
540    * <ng-messages for="expression" role="alert">
541    *   <ng-messages-include src="expressionValue1">...</ng-messages-include>
542    * </ng-messages>
543    * ```
544    *
545    * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
546    *
547    * @param {string} ngMessagesInclude|src a string value corresponding to the remote template.
548    */
549   .directive('ngMessagesInclude',
550     ['$templateRequest', '$document', '$compile', function($templateRequest, $document, $compile) {
551
552     return {
553       restrict: 'AE',
554       require: '^^ngMessages', // we only require this for validation sake
555       link: function($scope, element, attrs) {
556         var src = attrs.ngMessagesInclude || attrs.src;
557         $templateRequest(src).then(function(html) {
558           $compile(html)($scope, function(contents) {
559             element.after(contents);
560
561             // the anchor is placed for debugging purposes
562             var comment = $compile.$$createComment ?
563                 $compile.$$createComment('ngMessagesInclude', src) :
564                 $document[0].createComment(' ngMessagesInclude: ' + src + ' ');
565             var anchor = jqLite(comment);
566             element.after(anchor);
567
568             // we don't want to pollute the DOM anymore by keeping an empty directive element
569             element.remove();
570           });
571         });
572       }
573     };
574   }])
575
576   /**
577    * @ngdoc directive
578    * @name ngMessage
579    * @restrict AE
580    * @scope
581    *
582    * @description
583    * `ngMessage` is a directive with the purpose to show and hide a particular message.
584    * For `ngMessage` to operate, a parent `ngMessages` directive on a parent DOM element
585    * must be situated since it determines which messages are visible based on the state
586    * of the provided key/value map that `ngMessages` listens on.
587    *
588    * More information about using `ngMessage` can be found in the
589    * {@link module:ngMessages `ngMessages` module documentation}.
590    *
591    * @usage
592    * ```html
593    * <!-- using attribute directives -->
594    * <ANY ng-messages="expression" role="alert">
595    *   <ANY ng-message="stringValue">...</ANY>
596    *   <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
597    * </ANY>
598    *
599    * <!-- or by using element directives -->
600    * <ng-messages for="expression" role="alert">
601    *   <ng-message when="stringValue">...</ng-message>
602    *   <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
603    * </ng-messages>
604    * ```
605    *
606    * @param {expression} ngMessage|when a string value corresponding to the message key.
607    */
608  .directive('ngMessage', ngMessageDirectiveFactory())
609
610
611   /**
612    * @ngdoc directive
613    * @name ngMessageExp
614    * @restrict AE
615    * @priority 1
616    * @scope
617    *
618    * @description
619    * `ngMessageExp` is a directive with the purpose to show and hide a particular message.
620    * For `ngMessageExp` to operate, a parent `ngMessages` directive on a parent DOM element
621    * must be situated since it determines which messages are visible based on the state
622    * of the provided key/value map that `ngMessages` listens on.
623    *
624    * @usage
625    * ```html
626    * <!-- using attribute directives -->
627    * <ANY ng-messages="expression">
628    *   <ANY ng-message-exp="expressionValue">...</ANY>
629    * </ANY>
630    *
631    * <!-- or by using element directives -->
632    * <ng-messages for="expression">
633    *   <ng-message when-exp="expressionValue">...</ng-message>
634    * </ng-messages>
635    * ```
636    *
637    * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
638    *
639    * @param {expression} ngMessageExp|whenExp an expression value corresponding to the message 
639key.
640    */
641  .directive('ngMessageExp', ngMessageDirectiveFactory());
642
643function ngMessageDirectiveFactory() {
644  return ['$animate', function($animate) {
645    return {
646      restrict: 'AE',
647      transclude: 'element',
648      priority: 1, // must run before ngBind, otherwise the text is set on the comment
649      terminal: true,
650      require: '^^ngMessages',
651      link: function(scope, element, attrs, ngMessagesCtrl, $transclude) {
652        var commentNode = element[0];
653
654        var records;
655        var staticExp = attrs.ngMessage || attrs.when;
656        var dynamicExp = attrs.ngMessageExp || attrs.whenExp;
657        var assignRecords = function(items) {
658          records = items
659              ? (isArray(items)
660                    ? items
661                    : items.split(/[\s,]+/))
662              : null;
663          ngMessagesCtrl.reRender();
664        };
665
666        if (dynamicExp) {
667          assignRecords(scope.$eval(dynamicExp));
668          scope.$watchCollection(dynamicExp, assignRecords);
669        } else {
670          assignRecords(staticExp);
671        }
672
673        var currentElement, messageCtrl;
674        ngMessagesCtrl.register(commentNode, messageCtrl = {
675          test: function(name) {
676            return contains(records, name);
677          },
678          attach: function() {
679            if (!currentElement) {
680              $transclude(scope, function(elm) {
681                $animate.enter(elm, null, element);
682                currentElement = elm;
683
684                // Each time we attach this node to a message we get a new id that we can match
685                // when we are destroying the node later.
686                var $$attachId = currentElement.$$attachId = ngMessagesCtrl.getAttachId();
687
688                // in the event that the element or a parent element is destroyed
689                // by another structural directive then it's time
690                // to deregister the message from the controller
691                currentElement.on('$destroy', function() {
692                  if (currentElement && currentElement.$$attachId === $$attachId) {
693                    ngMessagesCtrl.deregister(commentNode);
694                    messageCtrl.detach();
695                  }
696                });
697              });
698            }
699          },
700          detach: function() {
701            if (currentElement) {
702              var elm = currentElement;
703              currentElement = null;
704              $animate.leave(elm);
705            }
706          }
707        });
708      }
709    };
710  }];
711
712  function contains(collection, key) {
713    if (collection) {
714      return isArray(collection)
715          ? collection.indexOf(key) >= 0
716          : collection.hasOwnProperty(key);
717    }
718  }
719}
720
721
722})(window, window.angular);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.