1
1
'use strict' ;
2
2
3
- function idDirective ( name , selector ) {
4
- name = 'ngId' + name ;
5
- return [ '$animate' , function ( $animate ) {
3
+ function idDirective ( ) {
4
+ return function ( ) {
6
5
return {
7
- restrict : 'A' ,
8
6
link : function ( scope , element , attr ) {
9
- var oldVal ;
7
+ var oldVal = attr [ 'id' ] ? attr [ 'id' ] : null ;
10
8
11
- scope . $watch ( attr [ name ] , ngIdWatchAction , true ) ;
9
+ scope . $watch ( attr [ 'ngId' ] , ngIdWatchAction , true ) ;
12
10
13
11
attr . $observe ( 'id' , function ( value ) {
14
- ngIdWatchAction ( scope . $eval ( attr [ name ] ) ) ;
12
+ ngIdWatchAction ( scope . $eval ( attr [ 'ngId' ] ) ) ;
15
13
} ) ;
16
14
17
15
18
- if ( name !== 'ngId' ) {
19
- scope . $watch ( '$index' , function ( $index , old$index ) {
20
- // jshint bitwise: false
21
- var mod = $index & 1 ;
22
- if ( mod !== old$index & 1 ) {
23
- var id = typeofId ( scope . $eval ( attr [ name ] ) ) ;
24
- if ( mod === selector ) {
25
- replaceId ( id ) ;
26
- }
27
- }
28
- } ) ;
29
- }
30
-
31
- // Used in place of addClass and removeClass, as it must be unique.
32
- function replaceId ( id ) {
33
- attr . $attr ( 'id' , id )
34
- }
35
-
36
- // New
37
- function uniqueId ( id ) {
38
- /* Check if the id is unique throughout the view
39
- * Should search $index for the ID.
40
- */
41
- }
42
-
43
- // This is the joining function. This shouldn't exist
44
- // function digestIdCounts (ids, count) {
45
- // var idCounts = element.data('$idCounts') || {};
46
- // var idsToUpdate = [];
47
- // forEach(ids, function (idName) {
48
- // if (count > 0 || idCounts[idName]) {
49
- // idCounts[idName] = (idCounts[idName] || 0) + count;
50
- // if (idCounts[idName] === +(count > 0)) {
51
- // idsToUpdate.push(idName);
52
- // }
53
- // }
54
- // });
55
- // element.data('$idCounts', idCounts);
56
- // return idsToUpdate.join(' ');
57
- // }
58
-
59
- //function updateClasses (oldClasses, newClasses) {
60
- // var toAdd = arrayDifference(newClasses, oldClasses);
61
- // var toRemove = arrayDifference(oldClasses, newClasses);
62
- // toRemove = digestClassCounts(toRemove, -1);
63
- // toAdd = digestClassCounts(toAdd, 1);
64
-
65
- // if (toAdd.length === 0) {
66
- // $animate.removeClass(element, toRemove);
67
- // } else if (toRemove.length === 0) {
68
- // $animate.addClass(element, toAdd);
69
- // } else {
70
- // $animate.setClass(element, toAdd, toRemove);
71
- // }
72
- // }
73
-
74
16
function ngIdWatchAction ( newVal ) {
75
- if ( selector === true || scope . $index % 2 === selector ) {
76
- var newId = typeofId ( newVal || [ ] ) ;
77
- if ( ! oldVal ) {
78
- addId ( newId ) ;
79
- } else if ( ! equals ( newVal , oldVal ) ) {
80
- var oldId = typeofId ( oldVal ) ;
81
- updateId ( oldId , newId ) ;
82
- }
17
+ var newId = typeofId ( newVal || [ ] ) ;
18
+ if ( ! newId && ! oldVal ) {
19
+ console . log ( 'Removing id' ) ;
20
+ element . removeAttr ( 'id' ) ;
21
+ } else if ( ! newId && oldVal ) {
22
+ console . log ( 'Setting to old id:' , oldVal , typeof ( oldVal ) ) ;
23
+ element . attr ( 'id' , oldVal ) ;
24
+ } else {
25
+ console . log ( 'Setting to newId:' , newVal , typeof ( newVal ) )
26
+ element . attr ( 'id' , newId ) ;
83
27
}
84
- oldVal = copy ( newVal ) ;
85
- }
28
+ } ;
86
29
}
87
30
} ;
88
31
89
- function arrayDifference ( tokens1 , tokens2 ) {
90
- var values = [ ] ;
91
-
92
- outer:
93
- for ( var i = 0 ; i < tokens1 . length ; i ++ ) {
94
- var token = tokens1 [ i ] ;
95
- for ( var j = 0 ; j < tokens2 . length ; j ++ ) {
96
- if ( token == tokens2 [ j ] ) continue outer;
97
- }
98
- values . push ( token ) ;
99
- }
100
- return values ;
101
- }
102
-
103
32
function typeofId ( idVal ) {
104
- //if (isArray(classVal)) {
105
- // return classVal;
106
- //} else if (isString(classVal)) {
107
33
if ( isString ( idVal ) ) {
34
+ if ( idVal . split ( ' ' ) . length > 0 ) {
35
+ return idVal . split ( ' ' ) [ 0 ] ;
36
+ }
108
37
return idVal ;
109
38
} else if ( isObject ( idVal ) ) {
110
39
var ids = [ ] , i = 0 ;
111
40
forEach ( idVal , function ( v , k ) {
112
- // This should push for all classes. That isn't ideal.
113
- // We want it to only push for one.
114
41
if ( v ) {
115
42
ids . push ( k ) ;
116
- // This should make it break after the first truthy value.
117
- return ids ;
118
43
}
119
44
} ) ;
120
- return ids ;
45
+ return ids [ 0 ] ;
121
46
}
122
47
return idVal ;
123
- }
124
- } ] ;
48
+ } ;
49
+ } ;
125
50
}
126
51
127
52
/**
@@ -136,139 +61,79 @@ function idDirective(name, selector) {
136
61
* The directive operates in two different ways, depending on which of two types the expression
137
62
* evaluates to:
138
63
*
139
- * 1. If the expression evaluates to a string, the string should be one, unique id.
64
+ * 1. If the expression evaluates to a string, the string should be one id. If the string has multiple
65
+ * space-delimited ids, the first id is returned.
140
66
*
141
- * 2. If the expression evaluates to an object, then for each key-value pair of the
142
- * object with a truthy value the corresponding key is used as an id.
67
+ * 2. If the expression evaluates to an object, then the key for the first key-value pair in the object
68
+ * to evaluate with a truthy value is used as an id.
143
69
*
144
- * If the specified value evaluates as truthy, and there is already an existing id on that element,
145
- * it will overwrite that id.
70
+ * If there is already an existing id on that element, it will overwrite that id (if the specified key
71
+ * value pair is truthy, or if a valid string is used). When the expression changes, the previous id is
72
+ * set as the element attribute again. If there was no original id, and the expression does not evaluate
73
+ * as truthy, the id attribute is removed.
146
74
*
147
- * If the specified value evaluates as truthy, but there is already an id or name set elsewhere with the same
148
- * value, it will not apply the id attribute, unless the name attribute is in the same element, and the element
149
- * in question is either: `A`, `APPLET`, `FORM`, `FRAME`, `IFRAME`, `IMG`, or `MAP`.
150
- *
151
- * When the expression changes, the previously added id is removed and only then is the
152
- * new id added.
153
- *
154
- * @animations
155
- * add - happens just before the class is applied to the element
156
- * remove - happens just before the class is removed from the element
75
+ * If there is already an id or name set elsewhere with the same value, it will apply the id attribute,
76
+ * which may result in invalid HTML.
157
77
*
158
78
* @element ANY
159
79
* @param {expression } ngId {@link guide/expression Expression } to eval. The result
160
- * of the evaluation can be a string with a single id name, or a map of unique id names
161
- * to boolean values. In the case of a map, the names of the property whose value
162
- * is truthy will be added as css id to the element.
163
- *
164
- * // Edited up to here.
80
+ * of the evaluation can be a string with a single id name, or a map of id names
81
+ * to boolean values. In the case of a map, the name of the first property whose value
82
+ * to evaluate as truthy will be added as css id to the element.
165
83
*
166
84
* @example Example that demonstrates basic bindings via ngClass directive.
167
85
<example>
168
86
<file name="index.html">
169
- <p ng-class ="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
170
- <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class )<br>
171
- <input type="checkbox" ng-model="important"> important (apply "bold" class )<br>
172
- <input type="checkbox" ng-model="error"> error (apply "red" class )
87
+ <p ng-id ="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
88
+ <input type="checkbox" ng-model="deleted"> deleted (apply "strike" id )<br>
89
+ <input type="checkbox" ng-model="important"> important (apply "bold" id )<br>
90
+ <input type="checkbox" ng-model="error"> error (apply "red" id )
173
91
<hr>
174
- <p ng-class ="style">Using String Syntax</p>
92
+ <p ng-id ="style">Using String Syntax</p>
175
93
<input type="text" ng-model="style" placeholder="Type: bold strike red">
176
- <hr>
177
- <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
178
- <input ng-model="style1" placeholder="Type: bold, strike or red"><br>
179
- <input ng-model="style2" placeholder="Type: bold, strike or red"><br>
180
- <input ng-model="style3" placeholder="Type: bold, strike or red"><br>
181
94
</file>
182
95
<file name="style.css">
183
- . strike {
96
+ # strike {
184
97
text-decoration: line-through;
185
98
}
186
- . bold {
187
- font-weight: bold;
99
+ # bold {
100
+ font-weight: bold;
188
101
}
189
- . red {
190
- color: red;
102
+ # red {
103
+ color: red;
191
104
}
192
105
</file>
193
106
<file name="protractor.js" type="protractor">
194
107
var ps = element.all(by.css('p'));
195
108
196
- it('should let you toggle the class ', function() {
109
+ it('should let you toggle the id ', function() {
197
110
198
- expect(ps.first().getAttribute('class ')).not.toMatch(/bold/);
199
- expect(ps.first().getAttribute('class ')).not.toMatch(/red/);
111
+ expect(ps.first().getAttribute('id ')).not.toMatch(/bold/);
112
+ expect(ps.first().getAttribute('id ')).not.toMatch(/red/);
200
113
201
114
element(by.model('important')).click();
202
- expect(ps.first().getAttribute('class ')).toMatch(/bold/);
115
+ expect(ps.first().getAttribute('id ')).toMatch(/bold/);
203
116
204
117
element(by.model('error')).click();
205
- expect(ps.first().getAttribute('class ')).toMatch(/red/);
118
+ expect(ps.first().getAttribute('id ')).toMatch(/red/);
206
119
});
207
120
208
121
it('should let you toggle string example', function() {
209
- expect(ps.get(1).getAttribute('class ')).toBe('');
122
+ expect(ps.get(1).getAttribute('id ')).toBe('');
210
123
element(by.model('style')).clear();
211
124
element(by.model('style')).sendKeys('red');
212
- expect(ps.get(1).getAttribute('class ')).toBe('red');
125
+ expect(ps.get(1).getAttribute('id ')).toBe('red');
213
126
});
214
127
215
128
it('array example should have 3 classes', function() {
216
129
expect(ps.last().getAttribute('class')).toBe('');
217
130
element(by.model('style1')).sendKeys('bold');
218
131
element(by.model('style2')).sendKeys('strike');
219
132
element(by.model('style3')).sendKeys('red');
220
- expect(ps.last().getAttribute('class ')).toBe('bold strike red ');
133
+ expect(ps.last().getAttribute('id ')).toBe('bold');
221
134
});
222
135
</file>
223
136
</example>
224
-
225
- ## Animations
226
-
227
- The example below demonstrates how to perform animations using ngClass.
228
-
229
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
230
- <file name="index.html">
231
- <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
232
- <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
233
- <br>
234
- <span class="base-class" ng-class="myVar">Sample Text</span>
235
- </file>
236
- <file name="style.css">
237
- .base-class {
238
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
239
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
240
- }
241
-
242
- .base-class.my-class {
243
- color: red;
244
- font-size:3em;
245
- }
246
- </file>
247
- <file name="protractor.js" type="protractor">
248
- it('should check ng-class', function() {
249
- expect(element(by.css('.base-class')).getAttribute('class')).not.
250
- toMatch(/my-class/);
251
-
252
- element(by.id('setbtn')).click();
253
-
254
- expect(element(by.css('.base-class')).getAttribute('class')).
255
- toMatch(/my-class/);
256
-
257
- element(by.id('clearbtn')).click();
258
-
259
- expect(element(by.css('.base-class')).getAttribute('class')).not.
260
- toMatch(/my-class/);
261
- });
262
- </file>
263
- </example>
264
-
265
-
266
- ## ngClass and pre-existing CSS3 Transitions/Animations
267
- The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
268
- Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
269
- any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
270
- to view the step by step details of {@link ngAnimate.$animate#addclass $animate.addClass} and
271
- {@link ngAnimate.$animate#removeclass $animate.removeClass}.
272
137
*/
273
- var ngIdDirective = idDirective ( '' , true ) ;
138
+ var ngIdDirective = idDirective ( ) ;
274
139
0 commit comments