angularjs-rails 1.5.6 → 1.5.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,14 @@
1
1
  /**
2
- * @license AngularJS v1.5.6
2
+ * @license AngularJS v1.5.8
3
3
  * (c) 2010-2016 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
6
6
  (function(window, angular) {'use strict';
7
7
 
8
- /* jshint ignore:start */
9
- // this code is in the core, but not in angular-messages.js
10
- var isArray = angular.isArray;
11
- var forEach = angular.forEach;
12
- var isString = angular.isString;
13
- var jqLite = angular.element;
14
- /* jshint ignore:end */
8
+ var forEach;
9
+ var isArray;
10
+ var isString;
11
+ var jqLite;
15
12
 
16
13
  /**
17
14
  * @ngdoc module
@@ -267,379 +264,396 @@ var jqLite = angular.element;
267
264
  *
268
265
  * {@link ngAnimate Click here} to learn how to use JavaScript animations or to learn more about ngAnimate.
269
266
  */
270
- angular.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
267
+ angular.module('ngMessages', [], function initAngularHelpers() {
268
+ // Access helpers from angular core.
269
+ // Do it inside a `config` block to ensure `window.angular` is available.
270
+ forEach = angular.forEach;
271
+ isArray = angular.isArray;
272
+ isString = angular.isString;
273
+ jqLite = angular.element;
274
+ })
275
+
276
+ /**
277
+ * @ngdoc directive
278
+ * @module ngMessages
279
+ * @name ngMessages
280
+ * @restrict AE
281
+ *
282
+ * @description
283
+ * `ngMessages` is a directive that is designed to show and hide messages based on the state
284
+ * of a key/value object that it listens on. The directive itself complements error message
285
+ * reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
286
+ *
287
+ * `ngMessages` manages the state of internal messages within its container element. The internal
288
+ * messages use the `ngMessage` directive and will be inserted/removed from the page depending
289
+ * on if they're present within the key/value object. By default, only one message will be displayed
290
+ * at a time and this depends on the prioritization of the messages within the template. (This can
291
+ * be changed by using the `ng-messages-multiple` or `multiple` attribute on the directive container.)
292
+ *
293
+ * A remote template can also be used to promote message reusability and messages can also be
294
+ * overridden.
295
+ *
296
+ * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
297
+ *
298
+ * @usage
299
+ * ```html
300
+ * <!-- using attribute directives -->
301
+ * <ANY ng-messages="expression" role="alert">
302
+ * <ANY ng-message="stringValue">...</ANY>
303
+ * <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
304
+ * <ANY ng-message-exp="expressionValue">...</ANY>
305
+ * </ANY>
306
+ *
307
+ * <!-- or by using element directives -->
308
+ * <ng-messages for="expression" role="alert">
309
+ * <ng-message when="stringValue">...</ng-message>
310
+ * <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
311
+ * <ng-message when-exp="expressionValue">...</ng-message>
312
+ * </ng-messages>
313
+ * ```
314
+ *
315
+ * @param {string} ngMessages an angular expression evaluating to a key/value object
316
+ * (this is typically the $error object on an ngModel instance).
317
+ * @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true
318
+ *
319
+ * @example
320
+ * <example name="ngMessages-directive" module="ngMessagesExample"
321
+ * deps="angular-messages.js"
322
+ * animations="true" fixBase="true">
323
+ * <file name="index.html">
324
+ * <form name="myForm">
325
+ * <label>
326
+ * Enter your name:
327
+ * <input type="text"
328
+ * name="myName"
329
+ * ng-model="name"
330
+ * ng-minlength="5"
331
+ * ng-maxlength="20"
332
+ * required />
333
+ * </label>
334
+ * <pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
335
+ *
336
+ * <div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
337
+ * <div ng-message="required">You did not enter a field</div>
338
+ * <div ng-message="minlength">Your field is too short</div>
339
+ * <div ng-message="maxlength">Your field is too long</div>
340
+ * </div>
341
+ * </form>
342
+ * </file>
343
+ * <file name="script.js">
344
+ * angular.module('ngMessagesExample', ['ngMessages']);
345
+ * </file>
346
+ * </example>
347
+ */
348
+ .directive('ngMessages', ['$animate', function($animate) {
349
+ var ACTIVE_CLASS = 'ng-active';
350
+ var INACTIVE_CLASS = 'ng-inactive';
351
+
352
+ return {
353
+ require: 'ngMessages',
354
+ restrict: 'AE',
355
+ controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
356
+ var ctrl = this;
357
+ var latestKey = 0;
358
+ var nextAttachId = 0;
359
+
360
+ this.getAttachId = function getAttachId() { return nextAttachId++; };
361
+
362
+ var messages = this.messages = {};
363
+ var renderLater, cachedCollection;
364
+
365
+ this.render = function(collection) {
366
+ collection = collection || {};
367
+
368
+ renderLater = false;
369
+ cachedCollection = collection;
370
+
371
+ // this is true if the attribute is empty or if the attribute value is truthy
372
+ var multiple = isAttrTruthy($scope, $attrs.ngMessagesMultiple) ||
373
+ isAttrTruthy($scope, $attrs.multiple);
374
+
375
+ var unmatchedMessages = [];
376
+ var matchedKeys = {};
377
+ var messageItem = ctrl.head;
378
+ var messageFound = false;
379
+ var totalMessages = 0;
380
+
381
+ // we use != instead of !== to allow for both undefined and null values
382
+ while (messageItem != null) {
383
+ totalMessages++;
384
+ var messageCtrl = messageItem.message;
385
+
386
+ var messageUsed = false;
387
+ if (!messageFound) {
388
+ forEach(collection, function(value, key) {
389
+ if (!messageUsed && truthy(value) && messageCtrl.test(key)) {
390
+ // this is to prevent the same error name from showing up twice
391
+ if (matchedKeys[key]) return;
392
+ matchedKeys[key] = true;
393
+
394
+ messageUsed = true;
395
+ messageCtrl.attach();
396
+ }
397
+ });
398
+ }
399
+
400
+ if (messageUsed) {
401
+ // unless we want to display multiple messages then we should
402
+ // set a flag here to avoid displaying the next message in the list
403
+ messageFound = !multiple;
404
+ } else {
405
+ unmatchedMessages.push(messageCtrl);
406
+ }
407
+
408
+ messageItem = messageItem.next;
409
+ }
410
+
411
+ forEach(unmatchedMessages, function(messageCtrl) {
412
+ messageCtrl.detach();
413
+ });
414
+
415
+ unmatchedMessages.length !== totalMessages
412
416
  ? $animate.setClass($element, ACTIVE_CLASS, INACTIVE_CLASS)
413
417
  : $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
- if ($scope.$$destroyed) return;
559
-
560
- $compile(html)($scope, function(contents) {
561
- element.after(contents);
562
-
563
- // the anchor is placed for debugging purposes
564
- var comment = $compile.$$createComment ?
565
- $compile.$$createComment('ngMessagesInclude', src) :
566
- $document[0].createComment(' ngMessagesInclude: ' + src + ' ');
567
- var anchor = jqLite(comment);
568
- element.after(anchor);
569
-
570
- // we don't want to pollute the DOM anymore by keeping an empty directive element
571
- element.remove();
572
- });
573
- });
574
- }
575
- };
576
- }])
577
-
578
- /**
579
- * @ngdoc directive
580
- * @name ngMessage
581
- * @restrict AE
582
- * @scope
583
- *
584
- * @description
585
- * `ngMessage` is a directive with the purpose to show and hide a particular message.
586
- * For `ngMessage` to operate, a parent `ngMessages` directive on a parent DOM element
587
- * must be situated since it determines which messages are visible based on the state
588
- * of the provided key/value map that `ngMessages` listens on.
589
- *
590
- * More information about using `ngMessage` can be found in the
591
- * {@link module:ngMessages `ngMessages` module documentation}.
592
- *
593
- * @usage
594
- * ```html
595
- * <!-- using attribute directives -->
596
- * <ANY ng-messages="expression" role="alert">
597
- * <ANY ng-message="stringValue">...</ANY>
598
- * <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
599
- * </ANY>
600
- *
601
- * <!-- or by using element directives -->
602
- * <ng-messages for="expression" role="alert">
603
- * <ng-message when="stringValue">...</ng-message>
604
- * <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
605
- * </ng-messages>
606
- * ```
607
- *
608
- * @param {expression} ngMessage|when a string value corresponding to the message key.
609
- */
418
+ };
419
+
420
+ $scope.$watchCollection($attrs.ngMessages || $attrs['for'], ctrl.render);
421
+
422
+ // If the element is destroyed, proactively destroy all the currently visible messages
423
+ $element.on('$destroy', function() {
424
+ forEach(messages, function(item) {
425
+ item.message.detach();
426
+ });
427
+ });
428
+
429
+ this.reRender = function() {
430
+ if (!renderLater) {
431
+ renderLater = true;
432
+ $scope.$evalAsync(function() {
433
+ if (renderLater) {
434
+ cachedCollection && ctrl.render(cachedCollection);
435
+ }
436
+ });
437
+ }
438
+ };
439
+
440
+ this.register = function(comment, messageCtrl) {
441
+ var nextKey = latestKey.toString();
442
+ messages[nextKey] = {
443
+ message: messageCtrl
444
+ };
445
+ insertMessageNode($element[0], comment, nextKey);
446
+ comment.$$ngMessageNode = nextKey;
447
+ latestKey++;
448
+
449
+ ctrl.reRender();
450
+ };
451
+
452
+ this.deregister = function(comment) {
453
+ var key = comment.$$ngMessageNode;
454
+ delete comment.$$ngMessageNode;
455
+ removeMessageNode($element[0], comment, key);
456
+ delete messages[key];
457
+ ctrl.reRender();
458
+ };
459
+
460
+ function findPreviousMessage(parent, comment) {
461
+ var prevNode = comment;
462
+ var parentLookup = [];
463
+
464
+ while (prevNode && prevNode !== parent) {
465
+ var prevKey = prevNode.$$ngMessageNode;
466
+ if (prevKey && prevKey.length) {
467
+ return messages[prevKey];
468
+ }
469
+
470
+ // dive deeper into the DOM and examine its children for any ngMessage
471
+ // comments that may be in an element that appears deeper in the list
472
+ if (prevNode.childNodes.length && parentLookup.indexOf(prevNode) === -1) {
473
+ parentLookup.push(prevNode);
474
+ prevNode = prevNode.childNodes[prevNode.childNodes.length - 1];
475
+ } else if (prevNode.previousSibling) {
476
+ prevNode = prevNode.previousSibling;
477
+ } else {
478
+ prevNode = prevNode.parentNode;
479
+ parentLookup.push(prevNode);
480
+ }
481
+ }
482
+ }
483
+
484
+ function insertMessageNode(parent, comment, key) {
485
+ var messageNode = messages[key];
486
+ if (!ctrl.head) {
487
+ ctrl.head = messageNode;
488
+ } else {
489
+ var match = findPreviousMessage(parent, comment);
490
+ if (match) {
491
+ messageNode.next = match.next;
492
+ match.next = messageNode;
493
+ } else {
494
+ messageNode.next = ctrl.head;
495
+ ctrl.head = messageNode;
496
+ }
497
+ }
498
+ }
499
+
500
+ function removeMessageNode(parent, comment, key) {
501
+ var messageNode = messages[key];
502
+
503
+ var match = findPreviousMessage(parent, comment);
504
+ if (match) {
505
+ match.next = messageNode.next;
506
+ } else {
507
+ ctrl.head = messageNode.next;
508
+ }
509
+ }
510
+ }]
511
+ };
512
+
513
+ function isAttrTruthy(scope, attr) {
514
+ return (isString(attr) && attr.length === 0) || //empty attribute
515
+ truthy(scope.$eval(attr));
516
+ }
517
+
518
+ function truthy(val) {
519
+ return isString(val) ? val.length : !!val;
520
+ }
521
+ }])
522
+
523
+ /**
524
+ * @ngdoc directive
525
+ * @name ngMessagesInclude
526
+ * @restrict AE
527
+ * @scope
528
+ *
529
+ * @description
530
+ * `ngMessagesInclude` is a directive with the purpose to import existing ngMessage template
531
+ * code from a remote template and place the downloaded template code into the exact spot
532
+ * that the ngMessagesInclude directive is placed within the ngMessages container. This allows
533
+ * for a series of pre-defined messages to be reused and also allows for the developer to
534
+ * determine what messages are overridden due to the placement of the ngMessagesInclude directive.
535
+ *
536
+ * @usage
537
+ * ```html
538
+ * <!-- using attribute directives -->
539
+ * <ANY ng-messages="expression" role="alert">
540
+ * <ANY ng-messages-include="remoteTplString">...</ANY>
541
+ * </ANY>
542
+ *
543
+ * <!-- or by using element directives -->
544
+ * <ng-messages for="expression" role="alert">
545
+ * <ng-messages-include src="expressionValue1">...</ng-messages-include>
546
+ * </ng-messages>
547
+ * ```
548
+ *
549
+ * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
550
+ *
551
+ * @param {string} ngMessagesInclude|src a string value corresponding to the remote template.
552
+ */
553
+ .directive('ngMessagesInclude',
554
+ ['$templateRequest', '$document', '$compile', function($templateRequest, $document, $compile) {
555
+
556
+ return {
557
+ restrict: 'AE',
558
+ require: '^^ngMessages', // we only require this for validation sake
559
+ link: function($scope, element, attrs) {
560
+ var src = attrs.ngMessagesInclude || attrs.src;
561
+ $templateRequest(src).then(function(html) {
562
+ if ($scope.$$destroyed) return;
563
+
564
+ if (isString(html) && !html.trim()) {
565
+ // Empty template - nothing to compile
566
+ replaceElementWithMarker(element, src);
567
+ } else {
568
+ // Non-empty template - compile and link
569
+ $compile(html)($scope, function(contents) {
570
+ element.after(contents);
571
+ replaceElementWithMarker(element, src);
572
+ });
573
+ }
574
+ });
575
+ }
576
+ };
577
+
578
+ // Helpers
579
+ function replaceElementWithMarker(element, src) {
580
+ // A comment marker is placed for debugging purposes
581
+ var comment = $compile.$$createComment ?
582
+ $compile.$$createComment('ngMessagesInclude', src) :
583
+ $document[0].createComment(' ngMessagesInclude: ' + src + ' ');
584
+ var marker = jqLite(comment);
585
+ element.after(marker);
586
+
587
+ // Don't pollute the DOM anymore by keeping an empty directive element
588
+ element.remove();
589
+ }
590
+ }])
591
+
592
+ /**
593
+ * @ngdoc directive
594
+ * @name ngMessage
595
+ * @restrict AE
596
+ * @scope
597
+ *
598
+ * @description
599
+ * `ngMessage` is a directive with the purpose to show and hide a particular message.
600
+ * For `ngMessage` to operate, a parent `ngMessages` directive on a parent DOM element
601
+ * must be situated since it determines which messages are visible based on the state
602
+ * of the provided key/value map that `ngMessages` listens on.
603
+ *
604
+ * More information about using `ngMessage` can be found in the
605
+ * {@link module:ngMessages `ngMessages` module documentation}.
606
+ *
607
+ * @usage
608
+ * ```html
609
+ * <!-- using attribute directives -->
610
+ * <ANY ng-messages="expression" role="alert">
611
+ * <ANY ng-message="stringValue">...</ANY>
612
+ * <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
613
+ * </ANY>
614
+ *
615
+ * <!-- or by using element directives -->
616
+ * <ng-messages for="expression" role="alert">
617
+ * <ng-message when="stringValue">...</ng-message>
618
+ * <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
619
+ * </ng-messages>
620
+ * ```
621
+ *
622
+ * @param {expression} ngMessage|when a string value corresponding to the message key.
623
+ */
610
624
  .directive('ngMessage', ngMessageDirectiveFactory())
611
625
 
612
626
 
613
- /**
614
- * @ngdoc directive
615
- * @name ngMessageExp
616
- * @restrict AE
617
- * @priority 1
618
- * @scope
619
- *
620
- * @description
621
- * `ngMessageExp` is a directive with the purpose to show and hide a particular message.
622
- * For `ngMessageExp` to operate, a parent `ngMessages` directive on a parent DOM element
623
- * must be situated since it determines which messages are visible based on the state
624
- * of the provided key/value map that `ngMessages` listens on.
625
- *
626
- * @usage
627
- * ```html
628
- * <!-- using attribute directives -->
629
- * <ANY ng-messages="expression">
630
- * <ANY ng-message-exp="expressionValue">...</ANY>
631
- * </ANY>
632
- *
633
- * <!-- or by using element directives -->
634
- * <ng-messages for="expression">
635
- * <ng-message when-exp="expressionValue">...</ng-message>
636
- * </ng-messages>
637
- * ```
638
- *
639
- * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
640
- *
641
- * @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key.
642
- */
627
+ /**
628
+ * @ngdoc directive
629
+ * @name ngMessageExp
630
+ * @restrict AE
631
+ * @priority 1
632
+ * @scope
633
+ *
634
+ * @description
635
+ * `ngMessageExp` is a directive with the purpose to show and hide a particular message.
636
+ * For `ngMessageExp` to operate, a parent `ngMessages` directive on a parent DOM element
637
+ * must be situated since it determines which messages are visible based on the state
638
+ * of the provided key/value map that `ngMessages` listens on.
639
+ *
640
+ * @usage
641
+ * ```html
642
+ * <!-- using attribute directives -->
643
+ * <ANY ng-messages="expression">
644
+ * <ANY ng-message-exp="expressionValue">...</ANY>
645
+ * </ANY>
646
+ *
647
+ * <!-- or by using element directives -->
648
+ * <ng-messages for="expression">
649
+ * <ng-message when-exp="expressionValue">...</ng-message>
650
+ * </ng-messages>
651
+ * ```
652
+ *
653
+ * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
654
+ *
655
+ * @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key.
656
+ */
643
657
  .directive('ngMessageExp', ngMessageDirectiveFactory());
644
658
 
645
659
  function ngMessageDirectiveFactory() {
@@ -659,8 +673,8 @@ function ngMessageDirectiveFactory() {
659
673
  var assignRecords = function(items) {
660
674
  records = items
661
675
  ? (isArray(items)
662
- ? items
663
- : items.split(/[\s,]+/))
676
+ ? items
677
+ : items.split(/[\s,]+/))
664
678
  : null;
665
679
  ngMessagesCtrl.reRender();
666
680
  };
@@ -679,7 +693,7 @@ function ngMessageDirectiveFactory() {
679
693
  },
680
694
  attach: function() {
681
695
  if (!currentElement) {
682
- $transclude(scope, function(elm) {
696
+ $transclude(function(elm, newScope) {
683
697
  $animate.enter(elm, null, element);
684
698
  currentElement = elm;
685
699
 
@@ -695,6 +709,7 @@ function ngMessageDirectiveFactory() {
695
709
  ngMessagesCtrl.deregister(commentNode);
696
710
  messageCtrl.detach();
697
711
  }
712
+ newScope.$destroy();
698
713
  });
699
714
  });
700
715
  }