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