angularjs-rails 1.5.6 → 1.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  }