|
1 | 1 | (function () {
|
2 | 2 | 'use strict';
|
3 | 3 |
|
| 4 | + var _$$mdLayout, _$parse; |
| 5 | + |
4 | 6 | /**
|
5 | 7 | *
|
6 | 8 | * The original ngMaterial Layout solution used attribute selectors and CSS.
|
|
42 | 44 | */
|
43 | 45 | angular.module('material.core.layout', [ 'ng' ])
|
44 | 46 |
|
| 47 | + /** |
| 48 | + * Model of flags used by the Layout directives |
| 49 | + * Allows changes while running tests or runtime app changes |
| 50 | + */ |
| 51 | + .factory("$$mdLayout", function() { |
| 52 | + return { |
| 53 | + /** |
| 54 | + * Should we remove the original layout Attribute selectors |
| 55 | + * after translation injection |
| 56 | + */ |
| 57 | + removeAttributes : true, |
| 58 | + |
| 59 | + /** |
| 60 | + * Special internal flag used to optimize |
| 61 | + * noop(s) for the directive postLinks below |
| 62 | + */ |
| 63 | + disablePostLinks : undefined |
| 64 | + }; |
| 65 | + }) |
| 66 | + |
45 | 67 | // Attribute directives with optional value(s)
|
46 | 68 |
|
47 | 69 | .directive('layout' , attributeWithObserve('layout' , true) )
|
|
136 | 158 | * @param {boolean=} addDirectiveAsClass
|
137 | 159 | */
|
138 | 160 | function attributeWithObserve(className, addDirectiveAsClass) {
|
139 |
| - return function() { |
| 161 | + return ['$$mdLayout', '$document', '$parse', function($$mdLayout, $document, $parse) { |
| 162 | + _$$mdLayout = $$mdLayout; |
| 163 | + _$parse = $parse; |
| 164 | + |
140 | 165 | return {
|
141 | 166 | restrict : 'A',
|
142 | 167 | compile: function(element, attr) {
|
| 168 | + if ( postLinkIsDisabled($document[0]) ) return angular.noop; |
| 169 | + |
143 | 170 | attributeValueToClass(null, element, attr);
|
144 | 171 |
|
145 | 172 | // Use for postLink to account for transforms after ng-transclude.
|
146 | 173 | return attributeValueToClass;
|
147 | 174 | }
|
148 | 175 | };
|
149 |
| - }; |
| 176 | + }]; |
| 177 | + |
| 178 | + |
150 | 179 |
|
151 | 180 | /**
|
152 | 181 | * Add as transformed class selector(s), then
|
153 | 182 | * remove the deprecated attribute selector
|
154 | 183 | */
|
155 | 184 | function attributeValueToClass(scope, element, attr) {
|
156 | 185 | var directive = attr.$normalize(className);
|
| 186 | + var attrExpression = _$parse( directive[directive] ); |
157 | 187 |
|
158 | 188 | // Add transformed class selector(s)
|
159 | 189 | if (addDirectiveAsClass) {
|
160 | 190 | element.addClass(className);
|
161 | 191 | }
|
162 | 192 |
|
163 |
| - if (attr[directive]) { |
| 193 | + if ( attr[directive] ) { |
164 | 194 | element.addClass(className + "-" + attr[directive].replace(/\s+/g, "-"));
|
| 195 | + |
| 196 | + if ( _$$mdLayout.removeAttributes ) { |
| 197 | + element.removeAttr(directive); |
| 198 | + } |
165 | 199 | }
|
166 | 200 |
|
167 | 201 | if ( scope ) {
|
|
170 | 204 | * Instead watch the attribute so interpolated data-bindings to layout
|
171 | 205 | * selectors will continue to be supported.
|
172 | 206 | *
|
173 |
| - * $observe the className and update with new class (after removing the last one) |
| 207 | + * $observe() the className and update with new class (after removing the last one) |
174 | 208 | *
|
175 | 209 | * e.g. `layout="{{layoutDemo.direction}}"` will update...
|
176 | 210 | */
|
177 | 211 | var lastClass;
|
178 | 212 |
|
179 | 213 | attr.$observe(function() {
|
180 | 214 |
|
181 |
| - return attr[className]; |
| 215 | + return attrExpression(scope); |
182 | 216 |
|
183 | 217 | }, function(newVal) {
|
184 | 218 |
|
|
200 | 234 | * This is a `simple` transpose of attribute usage to class usage
|
201 | 235 | */
|
202 | 236 | function attributeWithoutValue(className) {
|
203 |
| - return function() { |
| 237 | + return ['$$mdLayout', '$document', function($$mdLayout, $document) { |
| 238 | + _$$mdLayout = $$mdLayout; |
204 | 239 | return {
|
205 | 240 | restrict : 'A',
|
206 | 241 | compile: function(element, attr) {
|
| 242 | + if ( postLinkIsDisabled($document[0]) ) return angular.noop; |
| 243 | + |
207 | 244 | attributeToClass(null, element);
|
208 | 245 |
|
209 | 246 | // Use for postLink to account for transforms after ng-transclude.
|
210 | 247 | return attributeToClass;
|
211 | 248 | }
|
212 | 249 | };
|
213 |
| - }; |
| 250 | + }]; |
214 | 251 |
|
215 | 252 | /**
|
216 | 253 | * Add as transformed class selector, then
|
|
219 | 256 | function attributeToClass(scope, element) {
|
220 | 257 | element.addClass(className);
|
221 | 258 |
|
222 |
| - if ( scope ) { |
| 259 | + if ( scope && _$$mdLayout.removeAttributes ) { |
223 | 260 | // After link-phase, remove deprecated layout attribute selector
|
224 | 261 | element.removeAttr(className);
|
225 | 262 | }
|
|
239 | 276 |
|
240 | 277 | }
|
241 | 278 |
|
| 279 | + /** |
| 280 | + * Scan the body element. If it has a class 'md-css-only', then do NOT |
| 281 | + * postLink process the directives for Attribute selectors. |
| 282 | + * (recall that postlink injects Class selectors based on attribute selector settings) |
| 283 | + * |
| 284 | + * Instead the Layout CSS for Attributes is used: |
| 285 | + * e.g |
| 286 | + * .md-css-only [layout=row] { |
| 287 | + * flex-direction: row; |
| 288 | + * -webkit-flex-direction: row; |
| 289 | + * } |
| 290 | + * |
| 291 | + * Note: this means that 'md-css-only' will not work for IE (due to performance issues) |
| 292 | + * In these cases, the Layout translators (directives) should be enabled. |
| 293 | + */ |
| 294 | + function postLinkIsDisabled(document) { |
| 295 | + var disablePostLinks = _$$mdLayout.disablePostLinks; |
| 296 | + |
| 297 | + if ( angular.isUndefined(disablePostLinks) ) { |
| 298 | + var body = document.querySelectorAll("body")[0]; |
| 299 | + var styles = body.getAttribute('class'); |
| 300 | + |
| 301 | + disablePostLinks = styles ? (styles.indexOf('md-css-only') > -1) : false; |
| 302 | + } |
| 303 | + |
| 304 | + return _$$mdLayout.disablePostLinks = disablePostLinks; |
| 305 | + } |
| 306 | + |
242 | 307 | })();
|
0 commit comments