angularjs-rails 1.2.16 → 1.2.18
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.
- checksums.yaml +4 -4
- data/lib/angularjs-rails/version.rb +2 -2
- data/vendor/assets/javascripts/angular-animate.js +25 -8
- data/vendor/assets/javascripts/angular-cookies.js +21 -13
- data/vendor/assets/javascripts/angular-loader.js +8 -6
- data/vendor/assets/javascripts/angular-mocks.js +8 -6
- data/vendor/assets/javascripts/angular-resource.js +19 -10
- data/vendor/assets/javascripts/angular-route.js +3 -3
- data/vendor/assets/javascripts/angular-sanitize.js +9 -3
- data/vendor/assets/javascripts/angular-scenario.js +874 -620
- data/vendor/assets/javascripts/angular-touch.js +17 -8
- data/vendor/assets/javascripts/angular.js +870 -616
- data/vendor/assets/javascripts/unstable/angular-animate.js +28 -9
- data/vendor/assets/javascripts/unstable/angular-cookies.js +21 -13
- data/vendor/assets/javascripts/unstable/angular-loader.js +13 -6
- data/vendor/assets/javascripts/unstable/angular-messages.js +400 -0
- data/vendor/assets/javascripts/unstable/angular-mocks.js +51 -18
- data/vendor/assets/javascripts/unstable/angular-resource.js +286 -236
- data/vendor/assets/javascripts/unstable/angular-route.js +4 -5
- data/vendor/assets/javascripts/unstable/angular-sanitize.js +9 -3
- data/vendor/assets/javascripts/unstable/angular-scenario.js +2159 -1346
- data/vendor/assets/javascripts/unstable/angular-touch.js +65 -18
- data/vendor/assets/javascripts/unstable/angular.js +2138 -1322
- metadata +3 -2
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.3.0-beta.
|
2
|
+
* @license AngularJS v1.3.0-beta.13
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -35,6 +35,8 @@
|
|
35
35
|
* | {@link ng.directive:ngClass#usage_animations ngClass} | add and remove (the CSS class(es) present) |
|
36
36
|
* | {@link ng.directive:ngShow#usage_animations ngShow} & {@link ng.directive:ngHide#usage_animations ngHide} | add and remove (the ng-hide class value) |
|
37
37
|
* | {@link ng.directive:form#usage_animations form} & {@link ng.directive:ngModel#usage_animations ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
|
38
|
+
* | {@link ngMessages.directive:ngMessage#usage_animations ngMessages} | add and remove (ng-active & ng-inactive) |
|
39
|
+
* | {@link ngMessages.directive:ngMessage#usage_animations ngMessage} | enter and leave |
|
38
40
|
*
|
39
41
|
* You can find out more information about animations upon visiting each directive page.
|
40
42
|
*
|
@@ -358,6 +360,10 @@ angular.module('ngAnimate', ['ng'])
|
|
358
360
|
}
|
359
361
|
}
|
360
362
|
|
363
|
+
function prepareElement(element) {
|
364
|
+
return element && angular.element(element);
|
365
|
+
}
|
366
|
+
|
361
367
|
function stripCommentsFromElement(element) {
|
362
368
|
return angular.element(extractElementNode(element));
|
363
369
|
}
|
@@ -566,7 +572,7 @@ angular.module('ngAnimate', ['ng'])
|
|
566
572
|
/**
|
567
573
|
* @ngdoc service
|
568
574
|
* @name $animate
|
569
|
-
* @function
|
575
|
+
* @kind function
|
570
576
|
*
|
571
577
|
* @description
|
572
578
|
* The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations.
|
@@ -586,7 +592,7 @@ angular.module('ngAnimate', ['ng'])
|
|
586
592
|
/**
|
587
593
|
* @ngdoc method
|
588
594
|
* @name $animate#enter
|
589
|
-
* @function
|
595
|
+
* @kind function
|
590
596
|
*
|
591
597
|
* @description
|
592
598
|
* Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once
|
@@ -616,6 +622,10 @@ angular.module('ngAnimate', ['ng'])
|
|
616
622
|
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
|
617
623
|
*/
|
618
624
|
enter : function(element, parentElement, afterElement, doneCallback) {
|
625
|
+
element = angular.element(element);
|
626
|
+
parentElement = prepareElement(parentElement);
|
627
|
+
afterElement = prepareElement(afterElement);
|
628
|
+
|
619
629
|
this.enabled(false, element);
|
620
630
|
$delegate.enter(element, parentElement, afterElement);
|
621
631
|
$rootScope.$$postDigest(function() {
|
@@ -627,7 +637,7 @@ angular.module('ngAnimate', ['ng'])
|
|
627
637
|
/**
|
628
638
|
* @ngdoc method
|
629
639
|
* @name $animate#leave
|
630
|
-
* @function
|
640
|
+
* @kind function
|
631
641
|
*
|
632
642
|
* @description
|
633
643
|
* Runs the leave animation operation and, upon completion, removes the element from the DOM. Once
|
@@ -655,6 +665,7 @@ angular.module('ngAnimate', ['ng'])
|
|
655
665
|
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
|
656
666
|
*/
|
657
667
|
leave : function(element, doneCallback) {
|
668
|
+
element = angular.element(element);
|
658
669
|
cancelChildAnimations(element);
|
659
670
|
this.enabled(false, element);
|
660
671
|
$rootScope.$$postDigest(function() {
|
@@ -667,7 +678,7 @@ angular.module('ngAnimate', ['ng'])
|
|
667
678
|
/**
|
668
679
|
* @ngdoc method
|
669
680
|
* @name $animate#move
|
670
|
-
* @function
|
681
|
+
* @kind function
|
671
682
|
*
|
672
683
|
* @description
|
673
684
|
* Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or
|
@@ -698,6 +709,10 @@ angular.module('ngAnimate', ['ng'])
|
|
698
709
|
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
|
699
710
|
*/
|
700
711
|
move : function(element, parentElement, afterElement, doneCallback) {
|
712
|
+
element = angular.element(element);
|
713
|
+
parentElement = prepareElement(parentElement);
|
714
|
+
afterElement = prepareElement(afterElement);
|
715
|
+
|
701
716
|
cancelChildAnimations(element);
|
702
717
|
this.enabled(false, element);
|
703
718
|
$delegate.move(element, parentElement, afterElement);
|
@@ -737,6 +752,7 @@ angular.module('ngAnimate', ['ng'])
|
|
737
752
|
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
|
738
753
|
*/
|
739
754
|
addClass : function(element, className, doneCallback) {
|
755
|
+
element = angular.element(element);
|
740
756
|
element = stripCommentsFromElement(element);
|
741
757
|
performAnimation('addClass', className, element, null, null, function() {
|
742
758
|
$delegate.addClass(element, className);
|
@@ -773,6 +789,7 @@ angular.module('ngAnimate', ['ng'])
|
|
773
789
|
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
|
774
790
|
*/
|
775
791
|
removeClass : function(element, className, doneCallback) {
|
792
|
+
element = angular.element(element);
|
776
793
|
element = stripCommentsFromElement(element);
|
777
794
|
performAnimation('removeClass', className, element, null, null, function() {
|
778
795
|
$delegate.removeClass(element, className);
|
@@ -799,7 +816,7 @@ angular.module('ngAnimate', ['ng'])
|
|
799
816
|
* | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
|
800
817
|
* | 9. The doneCallback() callback is fired (if provided) | class="my-animation" |
|
801
818
|
*
|
802
|
-
* @param {DOMElement} element the element which will
|
819
|
+
* @param {DOMElement} element the element which will have its CSS classes changed
|
803
820
|
* removed from it
|
804
821
|
* @param {string} add the CSS classes which will be added to the element
|
805
822
|
* @param {string} remove the CSS class which will be removed from the element
|
@@ -807,6 +824,7 @@ angular.module('ngAnimate', ['ng'])
|
|
807
824
|
* CSS classes have been set on the element
|
808
825
|
*/
|
809
826
|
setClass : function(element, add, remove, doneCallback) {
|
827
|
+
element = angular.element(element);
|
810
828
|
element = stripCommentsFromElement(element);
|
811
829
|
performAnimation('setClass', [add, remove], element, null, null, function() {
|
812
830
|
$delegate.setClass(element, add, remove);
|
@@ -816,7 +834,7 @@ angular.module('ngAnimate', ['ng'])
|
|
816
834
|
/**
|
817
835
|
* @ngdoc method
|
818
836
|
* @name $animate#enabled
|
819
|
-
* @function
|
837
|
+
* @kind function
|
820
838
|
*
|
821
839
|
* @param {boolean=} value If provided then set the animation on or off.
|
822
840
|
* @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation
|
@@ -940,6 +958,7 @@ angular.module('ngAnimate', ['ng'])
|
|
940
958
|
}
|
941
959
|
|
942
960
|
if(skipAnimation) {
|
961
|
+
fireDOMOperation();
|
943
962
|
fireBeforeCallbackAsync();
|
944
963
|
fireAfterCallbackAsync();
|
945
964
|
fireDoneCallbackAsync();
|
@@ -1389,7 +1408,7 @@ angular.module('ngAnimate', ['ng'])
|
|
1389
1408
|
});
|
1390
1409
|
|
1391
1410
|
element.addClass(activeClassName);
|
1392
|
-
var eventCacheKey = elementData.
|
1411
|
+
var eventCacheKey = elementData.cacheKey + ' ' + activeClassName;
|
1393
1412
|
var timings = getElementAnimationDetails(element, eventCacheKey);
|
1394
1413
|
|
1395
1414
|
var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration);
|
@@ -1436,7 +1455,7 @@ angular.module('ngAnimate', ['ng'])
|
|
1436
1455
|
//the jqLite object, so we're safe to use a single variable to house
|
1437
1456
|
//the styles since there is always only one element being animated
|
1438
1457
|
var oldStyle = node.getAttribute('style') || '';
|
1439
|
-
node.setAttribute('style', oldStyle + ' ' + style);
|
1458
|
+
node.setAttribute('style', oldStyle + '; ' + style);
|
1440
1459
|
}
|
1441
1460
|
|
1442
1461
|
var startTime = Date.now();
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.3.0-beta.
|
2
|
+
* @license AngularJS v1.3.0-beta.13
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -37,18 +37,15 @@ angular.module('ngCookies', ['ng']).
|
|
37
37
|
* Requires the {@link ngCookies `ngCookies`} module to be installed.
|
38
38
|
*
|
39
39
|
* @example
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
</script>
|
50
|
-
</file>
|
51
|
-
</example>
|
40
|
+
*
|
41
|
+
* ```js
|
42
|
+
* function ExampleController($cookies) {
|
43
|
+
* // Retrieving a cookie
|
44
|
+
* var favoriteCookie = $cookies.myFavorite;
|
45
|
+
* // Setting a cookie
|
46
|
+
* $cookies.myFavorite = 'oatmeal';
|
47
|
+
* }
|
48
|
+
* ```
|
52
49
|
*/
|
53
50
|
factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
|
54
51
|
var cookies = {},
|
@@ -143,6 +140,17 @@ angular.module('ngCookies', ['ng']).
|
|
143
140
|
* Requires the {@link ngCookies `ngCookies`} module to be installed.
|
144
141
|
*
|
145
142
|
* @example
|
143
|
+
*
|
144
|
+
* ```js
|
145
|
+
* function ExampleController($cookieStore) {
|
146
|
+
* // Put cookie
|
147
|
+
* $cookieStore.put('myFavorite','oatmeal');
|
148
|
+
* // Get cookie
|
149
|
+
* var favoriteCookie = $cookieStore.get('myFavorite');
|
150
|
+
* // Removing a cookie
|
151
|
+
* $cookieStore.remove('myFavorite');
|
152
|
+
* }
|
153
|
+
* ```
|
146
154
|
*/
|
147
155
|
factory('$cookieStore', ['$cookies', function($cookies) {
|
148
156
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.3.0-beta.
|
2
|
+
* @license AngularJS v1.3.0-beta.13
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -69,7 +69,7 @@ function minErr(module) {
|
|
69
69
|
return match;
|
70
70
|
});
|
71
71
|
|
72
|
-
message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.
|
72
|
+
message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.13/' +
|
73
73
|
(module ? module + '/' : '') + code;
|
74
74
|
for (i = 2; i < arguments.length; i++) {
|
75
75
|
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
|
@@ -124,7 +124,7 @@ function setupModuleLoader(window) {
|
|
124
124
|
*
|
125
125
|
* # Module
|
126
126
|
*
|
127
|
-
* A module is a collection of services, directives, filters, and configuration information.
|
127
|
+
* A module is a collection of services, directives, controllers, filters, and configuration information.
|
128
128
|
* `angular.module` is used to configure the {@link auto.$injector $injector}.
|
129
129
|
*
|
130
130
|
* ```js
|
@@ -179,15 +179,19 @@ function setupModuleLoader(window) {
|
|
179
179
|
/** @type {!Array.<Array.<*>>} */
|
180
180
|
var invokeQueue = [];
|
181
181
|
|
182
|
+
/** @type {!Array.<Function>} */
|
183
|
+
var configBlocks = [];
|
184
|
+
|
182
185
|
/** @type {!Array.<Function>} */
|
183
186
|
var runBlocks = [];
|
184
187
|
|
185
|
-
var config = invokeLater('$injector', 'invoke');
|
188
|
+
var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
|
186
189
|
|
187
190
|
/** @type {angular.Module} */
|
188
191
|
var moduleInstance = {
|
189
192
|
// Private state
|
190
193
|
_invokeQueue: invokeQueue,
|
194
|
+
_configBlocks: configBlocks,
|
191
195
|
_runBlocks: runBlocks,
|
192
196
|
|
193
197
|
/**
|
@@ -346,6 +350,8 @@ function setupModuleLoader(window) {
|
|
346
350
|
* configuration.
|
347
351
|
* @description
|
348
352
|
* Use this method to register work which needs to be performed on module loading.
|
353
|
+
* For more about how to configure services, see
|
354
|
+
* {@link providers#providers_provider-recipe Provider Recipe}.
|
349
355
|
*/
|
350
356
|
config: config,
|
351
357
|
|
@@ -377,9 +383,10 @@ function setupModuleLoader(window) {
|
|
377
383
|
* @param {String=} insertMethod
|
378
384
|
* @returns {angular.Module}
|
379
385
|
*/
|
380
|
-
function invokeLater(provider, method, insertMethod) {
|
386
|
+
function invokeLater(provider, method, insertMethod, queue) {
|
387
|
+
if (!queue) queue = invokeQueue;
|
381
388
|
return function() {
|
382
|
-
|
389
|
+
queue[insertMethod || 'push']([provider, method, arguments]);
|
383
390
|
return moduleInstance;
|
384
391
|
};
|
385
392
|
}
|
@@ -0,0 +1,400 @@
|
|
1
|
+
/**
|
2
|
+
* @license AngularJS v1.3.0-beta.13
|
3
|
+
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
|
+
* License: MIT
|
5
|
+
*/
|
6
|
+
(function(window, angular, undefined) {'use strict';
|
7
|
+
|
8
|
+
/**
|
9
|
+
* @ngdoc module
|
10
|
+
* @name ngMessages
|
11
|
+
* @description
|
12
|
+
*
|
13
|
+
* The `ngMessages` module provides enhanced support for displaying messages within templates
|
14
|
+
* (typically within forms or when rendering message objects that return key/value data).
|
15
|
+
* Instead of relying on JavaScript code and/or complex ng-if statements within your form template to
|
16
|
+
* show and hide error messages specific to the state of an input field, the `ngMessages` and
|
17
|
+
* `ngMessage` directives are designed to handle the complexity, inheritance and priority
|
18
|
+
* sequencing based on the order of how the messages are defined in the template.
|
19
|
+
*
|
20
|
+
* Currently, the ngMessages module only contains the code for the `ngMessages`
|
21
|
+
* and `ngMessage` directives.
|
22
|
+
*
|
23
|
+
* # Usage
|
24
|
+
* The `ngMessages` directive listens on a key/value collection which is set on the ngMessages attribute.
|
25
|
+
* Since the {@link ngModel ngModel} directive exposes an `$error` object, this error object can be
|
26
|
+
* used with `ngMessages` to display control error messages in an easier way than with just regular angular
|
27
|
+
* template directives.
|
28
|
+
*
|
29
|
+
* ```html
|
30
|
+
* <form name="myForm">
|
31
|
+
* <input type="text" ng-model="field" name="myField" required minlength="5" />
|
32
|
+
* <div ng-messages="myForm.myField.$error">
|
33
|
+
* <div ng-message="required">You did not enter a field</div>
|
34
|
+
* <div ng-message="minlength">The value entered is too short</div>
|
35
|
+
* </div>
|
36
|
+
* </form>
|
37
|
+
* ```
|
38
|
+
*
|
39
|
+
* Now whatever key/value entries are present within the provided object (in this case `$error`) then
|
40
|
+
* the ngMessages directive will render the inner first ngMessage directive (depending if the key values
|
41
|
+
* match the attribute value present on each ngMessage directive). In other words, if your errors
|
42
|
+
* object contains the following data:
|
43
|
+
*
|
44
|
+
* ```javascript
|
45
|
+
* <!-- keep in mind that ngModel automatically sets these error flags -->
|
46
|
+
* myField.$error = { minlength : true, required : false };
|
47
|
+
* ```
|
48
|
+
*
|
49
|
+
* Then the `required` message will be displayed first. When required is false then the `minlength` message
|
50
|
+
* will be displayed right after (since these messages are ordered this way in the template HTML code).
|
51
|
+
* The prioritization of each message is determined by what order they're present in the DOM.
|
52
|
+
* Therefore, instead of having custom JavaScript code determine the priority of what errors are
|
53
|
+
* present before others, the presentation of the errors are handled within the template.
|
54
|
+
*
|
55
|
+
* By default, ngMessages will only display one error at a time. However, if you wish to display all
|
56
|
+
* messages then the `ng-messages-multiple` attribute flag can be used on the element containing the
|
57
|
+
* ngMessages directive to make this happen.
|
58
|
+
*
|
59
|
+
* ```html
|
60
|
+
* <div ng-messages="myForm.myField.$error" ng-messages-multiple>...</div>
|
61
|
+
* ```
|
62
|
+
*
|
63
|
+
* ## Reusing and Overriding Messages
|
64
|
+
* In addition to prioritization, ngMessages also allows for including messages from a remote or an inline
|
65
|
+
* template. This allows for generic collection of messages to be reused across multiple parts of an
|
66
|
+
* application.
|
67
|
+
*
|
68
|
+
* ```html
|
69
|
+
* <script type="text/ng-template" id="error-messages">
|
70
|
+
* <div ng-message="required">This field is required</div>
|
71
|
+
* <div ng-message="minlength">This field is too short</div>
|
72
|
+
* </script>
|
73
|
+
* <div ng-messages="myForm.myField.$error" ng-messages-include="error-messages"></div>
|
74
|
+
* ```
|
75
|
+
*
|
76
|
+
* However, including generic messages may not be useful enough to match all input fields, therefore,
|
77
|
+
* `ngMessages` provides the ability to override messages defined in the remote template by redefining
|
78
|
+
* then within the directive container.
|
79
|
+
*
|
80
|
+
* ```html
|
81
|
+
* <!-- a generic template of error messages known as "my-custom-messages" -->
|
82
|
+
* <script type="text/ng-template" id="my-custom-messages">
|
83
|
+
* <div ng-message="required">This field is required</div>
|
84
|
+
* <div ng-message="minlength">This field is too short</div>
|
85
|
+
* </script>
|
86
|
+
*
|
87
|
+
* <form name="myForm">
|
88
|
+
* <input type="email"
|
89
|
+
* id="email"
|
90
|
+
* name="myEmail"
|
91
|
+
* ng-model="email"
|
92
|
+
* minlength="5"
|
93
|
+
* required />
|
94
|
+
*
|
95
|
+
* <div ng-messages="myForm.myEmail.$error" ng-messages-include="my-custom-messages">
|
96
|
+
* <!-- this required message has overridden the template message -->
|
97
|
+
* <div ng-message="required">You did not enter your email address</div>
|
98
|
+
*
|
99
|
+
* <!-- this is a brand new message and will appear last in the prioritization -->
|
100
|
+
* <div ng-message="email">Your email address is invalid</div>
|
101
|
+
* </div>
|
102
|
+
* </form>
|
103
|
+
* ```
|
104
|
+
*
|
105
|
+
* In the example HTML code above the message that is set on required will override the corresponding
|
106
|
+
* required message defined within the remote template. Therefore, with particular input fields (such
|
107
|
+
* email addresses, date fields, autocomplete inputs, etc...), specialized error messages can be applied
|
108
|
+
* while more generic messages can be used to handle other, more general input errors.
|
109
|
+
*
|
110
|
+
* ## Animations
|
111
|
+
* If the `ngAnimate` module is active within the application then both the `ngMessages` and
|
112
|
+
* `ngMessage` directives will trigger animations whenever any messages are added and removed
|
113
|
+
* from the DOM by the `ngMessages` directive.
|
114
|
+
*
|
115
|
+
* Whenever the `ngMessages` directive contains one or more visible messages then the `.ng-active` CSS
|
116
|
+
* class will be added to the element. The `.ng-inactive` CSS class will be applied when there are no
|
117
|
+
* animations present. Therefore, CSS transitions and keyframes as well as JavaScript animations can
|
118
|
+
* hook into the animations whenever these classes are added/removed.
|
119
|
+
*
|
120
|
+
* Let's say that our HTML code for our messages container looks like so:
|
121
|
+
*
|
122
|
+
* ```html
|
123
|
+
* <div ng-messages="myMessages" class="my-messages">
|
124
|
+
* <div ng-message="alert" class="some-message">...</div>
|
125
|
+
* <div ng-message="fail" class="some-message">...</div>
|
126
|
+
* </div>
|
127
|
+
* ```
|
128
|
+
*
|
129
|
+
* Then the CSS animation code for the message container looks like so:
|
130
|
+
*
|
131
|
+
* ```css
|
132
|
+
* .my-messages {
|
133
|
+
* transition:1s linear all;
|
134
|
+
* }
|
135
|
+
* .my-messages.ng-active {
|
136
|
+
* // messages are visible
|
137
|
+
* }
|
138
|
+
* .my-messages.ng-inactive {
|
139
|
+
* // messages are hidden
|
140
|
+
* }
|
141
|
+
* ```
|
142
|
+
*
|
143
|
+
* Whenever an inner message is attached (becomes visible) or removed (becomes hidden) then the enter
|
144
|
+
* and leave animation is triggered for each particular element bound to the `ngMessage` directive.
|
145
|
+
*
|
146
|
+
* Therefore, the CSS code for the inner messages looks like so:
|
147
|
+
*
|
148
|
+
* ```css
|
149
|
+
* .some-message {
|
150
|
+
* transition:1s linear all;
|
151
|
+
* }
|
152
|
+
*
|
153
|
+
* .some-message.ng-enter {}
|
154
|
+
* .some-message.ng-enter.ng-enter-active {}
|
155
|
+
*
|
156
|
+
* .some-message.ng-leave {}
|
157
|
+
* .some-message.ng-leave.ng-leave-active {}
|
158
|
+
* ```
|
159
|
+
*
|
160
|
+
* {@link ngAnimate Click here} to learn how to use JavaScript animations or to learn more about ngAnimate.
|
161
|
+
*/
|
162
|
+
angular.module('ngMessages', [])
|
163
|
+
|
164
|
+
/**
|
165
|
+
* @ngdoc directive
|
166
|
+
* @module ngMessages
|
167
|
+
* @name ngMessages
|
168
|
+
* @restrict AE
|
169
|
+
*
|
170
|
+
* @description
|
171
|
+
* `ngMessages` is a directive that is designed to show and hide messages based on the state
|
172
|
+
* of a key/value object that is listens on. The directive itself compliments error message
|
173
|
+
* reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
|
174
|
+
*
|
175
|
+
* `ngMessages` manages the state of internal messages within its container element. The internal
|
176
|
+
* messages use the `ngMessage` directive and will be inserted/removed from the page depending
|
177
|
+
* on if they're present within the key/value object. By default, only one message will be displayed
|
178
|
+
* at a time and this depends on the prioritization of the messages within the template. (This can
|
179
|
+
* be changed by using the ng-messages-multiple on the directive container.)
|
180
|
+
*
|
181
|
+
* A remote template can also be used to promote message reuseability and messages can also be
|
182
|
+
* overridden.
|
183
|
+
*
|
184
|
+
* {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
|
185
|
+
*
|
186
|
+
* @usage
|
187
|
+
* ```html
|
188
|
+
* <!-- using attribute directives -->
|
189
|
+
* <ANY ng-messages="expression">
|
190
|
+
* <ANY ng-message="keyValue1">...</ANY>
|
191
|
+
* <ANY ng-message="keyValue2">...</ANY>
|
192
|
+
* <ANY ng-message="keyValue3">...</ANY>
|
193
|
+
* </ANY>
|
194
|
+
*
|
195
|
+
* <!-- or by using element directives -->
|
196
|
+
* <ng-messages for="expression">
|
197
|
+
* <ng-message when="keyValue1">...</ng-message>
|
198
|
+
* <ng-message when="keyValue2">...</ng-message>
|
199
|
+
* <ng-message when="keyValue3">...</ng-message>
|
200
|
+
* </ng-messages>
|
201
|
+
* ```
|
202
|
+
*
|
203
|
+
* @param {string} ngMessages an angular expression evaluating to a key/value object
|
204
|
+
* (this is typically the $error object on an ngModel instance).
|
205
|
+
* @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true
|
206
|
+
* @param {string=} ngMessagesInclude|include when set, the specified template will be included into the ng-messages container
|
207
|
+
*
|
208
|
+
* @example
|
209
|
+
* <example name="ngMessages-directive" module="ngMessagesExample"
|
210
|
+
* deps="angular-messages.js"
|
211
|
+
* animations="true" fixBase="true">
|
212
|
+
* <file name="index.html">
|
213
|
+
* <form name="myForm">
|
214
|
+
* <label>Enter your name:</label>
|
215
|
+
* <input type="text"
|
216
|
+
* name="myName"
|
217
|
+
* ng-model="name"
|
218
|
+
* ng-minlength="5"
|
219
|
+
* ng-maxlength="20"
|
220
|
+
* required />
|
221
|
+
*
|
222
|
+
* <pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
|
223
|
+
*
|
224
|
+
* <div ng-messages="myForm.myName.$error" style="color:maroon">
|
225
|
+
* <div ng-message="required">You did not enter a field</div>
|
226
|
+
* <div ng-message="minlength">Your field is too short</div>
|
227
|
+
* <div ng-message="maxlength">Your field is too long</div>
|
228
|
+
* </div>
|
229
|
+
* </form>
|
230
|
+
* </file>
|
231
|
+
* <file name="script.js">
|
232
|
+
* angular.module('ngMessagesExample', ['ngMessages']);
|
233
|
+
* </file>
|
234
|
+
* </example>
|
235
|
+
*/
|
236
|
+
.directive('ngMessages', ['$compile', '$animate', '$http', '$templateCache',
|
237
|
+
function($compile, $animate, $http, $templateCache) {
|
238
|
+
var ACTIVE_CLASS = 'ng-active';
|
239
|
+
var INACTIVE_CLASS = 'ng-inactive';
|
240
|
+
|
241
|
+
return {
|
242
|
+
restrict: 'AE',
|
243
|
+
controller: ['$scope', function($scope) {
|
244
|
+
this.$renderNgMessageClasses = angular.noop;
|
245
|
+
|
246
|
+
var messages = [];
|
247
|
+
this.registerMessage = function(index, message) {
|
248
|
+
for(var i = 0; i < messages.length; i++) {
|
249
|
+
if(messages[i].type == message.type) {
|
250
|
+
if(index != i) {
|
251
|
+
var temp = messages[index];
|
252
|
+
messages[index] = messages[i];
|
253
|
+
if(index < messages.length) {
|
254
|
+
messages[i] = temp;
|
255
|
+
} else {
|
256
|
+
messages.splice(0, i); //remove the old one (and shift left)
|
257
|
+
}
|
258
|
+
}
|
259
|
+
return;
|
260
|
+
}
|
261
|
+
}
|
262
|
+
messages.splice(index, 0, message); //add the new one (and shift right)
|
263
|
+
};
|
264
|
+
|
265
|
+
this.renderMessages = function(values, multiple) {
|
266
|
+
values = values || {};
|
267
|
+
|
268
|
+
var found;
|
269
|
+
angular.forEach(messages, function(message) {
|
270
|
+
if((!found || multiple) && truthyVal(values[message.type])) {
|
271
|
+
message.attach();
|
272
|
+
found = true;
|
273
|
+
} else {
|
274
|
+
message.detach();
|
275
|
+
}
|
276
|
+
});
|
277
|
+
|
278
|
+
this.renderElementClasses(found);
|
279
|
+
|
280
|
+
function truthyVal(value) {
|
281
|
+
return value !== null && value !== false && value;
|
282
|
+
}
|
283
|
+
};
|
284
|
+
}],
|
285
|
+
require: 'ngMessages',
|
286
|
+
link: function($scope, element, $attrs, ctrl) {
|
287
|
+
ctrl.renderElementClasses = function(bool) {
|
288
|
+
bool ? $animate.setClass(element, ACTIVE_CLASS, INACTIVE_CLASS)
|
289
|
+
: $animate.setClass(element, INACTIVE_CLASS, ACTIVE_CLASS);
|
290
|
+
};
|
291
|
+
|
292
|
+
//JavaScript treats empty strings as false, but ng-message-multiple by itself is an empty string
|
293
|
+
var multiple = angular.isString($attrs.ngMessagesMultiple) ||
|
294
|
+
angular.isString($attrs.multiple);
|
295
|
+
|
296
|
+
var cachedValues, watchAttr = $attrs.ngMessages || $attrs['for']; //for is a reserved keyword
|
297
|
+
$scope.$watchCollection(watchAttr, function(values) {
|
298
|
+
cachedValues = values;
|
299
|
+
ctrl.renderMessages(values, multiple);
|
300
|
+
});
|
301
|
+
|
302
|
+
var tpl = $attrs.ngMessagesInclude || $attrs.include;
|
303
|
+
if(tpl) {
|
304
|
+
$http.get(tpl, { cache: $templateCache })
|
305
|
+
.success(function processTemplate(html) {
|
306
|
+
var after, container = angular.element('<div/>').html(html);
|
307
|
+
angular.forEach(container.children(), function(elm) {
|
308
|
+
elm = angular.element(elm);
|
309
|
+
after ? after.after(elm)
|
310
|
+
: element.prepend(elm); //start of the container
|
311
|
+
after = elm;
|
312
|
+
$compile(elm)($scope);
|
313
|
+
});
|
314
|
+
ctrl.renderMessages(cachedValues, multiple);
|
315
|
+
});
|
316
|
+
}
|
317
|
+
}
|
318
|
+
};
|
319
|
+
}])
|
320
|
+
|
321
|
+
|
322
|
+
/**
|
323
|
+
* @ngdoc directive
|
324
|
+
* @name ngMessage
|
325
|
+
* @restrict AE
|
326
|
+
* @scope
|
327
|
+
*
|
328
|
+
* @description
|
329
|
+
* `ngMessage` is a directive with the purpose to show and hide a particular message.
|
330
|
+
* For `ngMessage` to operate, a parent `ngMessages` directive on a parent DOM element
|
331
|
+
* must be situated since it determines which messages are visible based on the state
|
332
|
+
* of the provided key/value map that `ngMessages` listens on.
|
333
|
+
*
|
334
|
+
* @usage
|
335
|
+
* ```html
|
336
|
+
* <!-- using attribute directives -->
|
337
|
+
* <ANY ng-messages="expression">
|
338
|
+
* <ANY ng-message="keyValue1">...</ANY>
|
339
|
+
* <ANY ng-message="keyValue2">...</ANY>
|
340
|
+
* <ANY ng-message="keyValue3">...</ANY>
|
341
|
+
* </ANY>
|
342
|
+
*
|
343
|
+
* <!-- or by using element directives -->
|
344
|
+
* <ng-messages for="expression">
|
345
|
+
* <ng-message when="keyValue1">...</ng-message>
|
346
|
+
* <ng-message when="keyValue2">...</ng-message>
|
347
|
+
* <ng-message when="keyValue3">...</ng-message>
|
348
|
+
* </ng-messages>
|
349
|
+
* ```
|
350
|
+
*
|
351
|
+
* {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
|
352
|
+
*
|
353
|
+
* @param {string} ngMessage a string value corresponding to the message key.
|
354
|
+
*/
|
355
|
+
.directive('ngMessage', ['$animate', function($animate) {
|
356
|
+
var COMMENT_NODE = 8;
|
357
|
+
return {
|
358
|
+
require: '^ngMessages',
|
359
|
+
transclude: 'element',
|
360
|
+
terminal: true,
|
361
|
+
restrict: 'AE',
|
362
|
+
link: function($scope, $element, $attrs, ngMessages, $transclude) {
|
363
|
+
var index, element;
|
364
|
+
|
365
|
+
var commentNode = $element[0];
|
366
|
+
var parentNode = commentNode.parentNode;
|
367
|
+
for(var i = 0, j = 0; i < parentNode.childNodes.length; i++) {
|
368
|
+
var node = parentNode.childNodes[i];
|
369
|
+
if(node.nodeType == COMMENT_NODE && node.nodeValue.indexOf('ngMessage') >= 0) {
|
370
|
+
if(node === commentNode) {
|
371
|
+
index = j;
|
372
|
+
break;
|
373
|
+
}
|
374
|
+
j++;
|
375
|
+
}
|
376
|
+
}
|
377
|
+
|
378
|
+
ngMessages.registerMessage(index, {
|
379
|
+
type : $attrs.ngMessage || $attrs.when,
|
380
|
+
attach : function() {
|
381
|
+
if(!element) {
|
382
|
+
$transclude($scope, function(clone) {
|
383
|
+
$animate.enter(clone, null, $element);
|
384
|
+
element = clone;
|
385
|
+
});
|
386
|
+
}
|
387
|
+
},
|
388
|
+
detach : function(now) {
|
389
|
+
if(element) {
|
390
|
+
$animate.leave(element);
|
391
|
+
element = null;
|
392
|
+
}
|
393
|
+
}
|
394
|
+
});
|
395
|
+
}
|
396
|
+
};
|
397
|
+
}]);
|
398
|
+
|
399
|
+
|
400
|
+
})(window, window.angular);
|