Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 2a1de83

Browse files
fix(layouts): register Layout directives for xs, gt-xs, xl
* Refactor Layout API directive registration to iteration all known breakpoints. * Update `layout.spec.js` tests to test all breakpoints Fixes #5995. Fixes #5983. Closes #6037.
1 parent 08b5af5 commit 2a1de83

File tree

2 files changed

+86
-116
lines changed

2 files changed

+86
-116
lines changed

src/core/services/layout/layout.js

+85-115
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
var ALIGNMENT_MAIN_AXIS= [ "", "start", "center", "end", "stretch", "space-around", "space-between" ];
1212
var ALIGNMENT_CROSS_AXIS= [ "", "start", "center", "end", "stretch" ];
1313

14-
1514
var config = {
1615
/**
1716
* Enable directive attribute-to-class conversions
@@ -31,7 +30,11 @@
3130
breakpoints: []
3231
};
3332

33+
registerLayoutAPI( angular.module('material.core.layout', ['ng']) );
34+
3435
/**
36+
* registerLayoutAPI()
37+
*
3538
* The original ngMaterial Layout solution used attribute selectors and CSS.
3639
*
3740
* ```html
@@ -40,12 +43,12 @@
4043
*
4144
* ```css
4245
* [layout] {
43-
* box-sizing: border-box;
44-
* display:flex;
45-
* }
46+
* box-sizing: border-box;
47+
* display:flex;
48+
* }
4649
* [layout=column] {
47-
* flex-direction : column
48-
* }
50+
* flex-direction : column
51+
* }
4952
* ```
5053
*
5154
* Use of attribute selectors creates significant performance impacts in some
@@ -61,117 +64,83 @@
6164
*
6265
* ```css
6366
* .layout {
64-
* box-sizing: border-box;
65-
* display:flex;
66-
* }
67+
* box-sizing: border-box;
68+
* display:flex;
69+
* }
6770
* .layout-column {
68-
* flex-direction : column
69-
* }
71+
* flex-direction : column
72+
* }
7073
* ```
7174
*/
72-
angular.module('material.core.layout', ['ng'])
73-
74-
.directive('mdLayoutCss', disableLayoutDirective )
75-
76-
.directive('layout', attributeWithObserve('layout'))
77-
.directive('layoutSm', attributeWithObserve('layout-sm'))
78-
.directive('layoutGtSm', attributeWithObserve('layout-gt-sm'))
79-
.directive('layoutMd', attributeWithObserve('layout-md'))
80-
.directive('layoutGtMd', attributeWithObserve('layout-gt-md'))
81-
.directive('layoutLg', attributeWithObserve('layout-lg'))
82-
.directive('layoutGtLg', attributeWithObserve('layout-gt-lg'))
83-
84-
.directive('flex', attributeWithObserve('flex'))
85-
.directive('flexSm', attributeWithObserve('flex-sm'))
86-
.directive('flexGtSm', attributeWithObserve('flex-gt-sm'))
87-
.directive('flexMd', attributeWithObserve('flex-md'))
88-
.directive('flexGtMd', attributeWithObserve('flex-gt-md'))
89-
.directive('flexLg', attributeWithObserve('flex-lg'))
90-
.directive('flexGtLg', attributeWithObserve('flex-gt-lg'))
91-
92-
.directive('flexOrder', attributeWithObserve('flex-order'))
93-
.directive('flexOrderSm', attributeWithObserve('flex-order-sm'))
94-
.directive('flexOrderGtSm', attributeWithObserve('flex-order-gt-sm'))
95-
.directive('flexOrderMd', attributeWithObserve('flex-order-md'))
96-
.directive('flexOrderGtMd', attributeWithObserve('flex-order-gt-md'))
97-
.directive('flexOrderLg', attributeWithObserve('flex-order-lg'))
98-
.directive('flexOrderGtLg', attributeWithObserve('flex-order-gt-lg'))
99-
100-
.directive('flexOffset', attributeWithObserve('flex-offset'))
101-
.directive('flexOffsetSm', attributeWithObserve('flex-offset-sm'))
102-
.directive('flexOffsetGtSm', attributeWithObserve('flex-offset-gt-sm'))
103-
.directive('flexOffsetMd', attributeWithObserve('flex-offset-md'))
104-
.directive('flexOffsetGtMd', attributeWithObserve('flex-offset-gt-md'))
105-
.directive('flexOffsetLg', attributeWithObserve('flex-offset-lg'))
106-
.directive('flexOffsetGtLg', attributeWithObserve('flex-offset-gt-lg'))
107-
108-
.directive('layoutAlign', attributeWithObserve('layout-align'))
109-
.directive('layoutAlignSm', attributeWithObserve('layout-align-sm'))
110-
.directive('layoutAlignGtSm', attributeWithObserve('layout-align-gt-sm'))
111-
.directive('layoutAlignMd', attributeWithObserve('layout-align-md'))
112-
.directive('layoutAlignGtMd', attributeWithObserve('layout-align-gt-md'))
113-
.directive('layoutAlignLg', attributeWithObserve('layout-align-lg'))
114-
.directive('layoutAlignGtLg', attributeWithObserve('layout-align-gt-lg'))
115-
116-
// Attribute directives with no value(s)
117-
118-
.directive('hide', attributeWithoutValue('hide'))
119-
.directive('hideSm', attributeWithoutValue('hide-sm'))
120-
.directive('hideGtSm', attributeWithoutValue('hide-gt-sm'))
121-
.directive('hideMd', attributeWithoutValue('hide-md'))
122-
.directive('hideGtMd', attributeWithoutValue('hide-gt-md'))
123-
.directive('hideLg', attributeWithoutValue('hide-lg'))
124-
.directive('hideGtLg', attributeWithoutValue('hide-gt-lg'))
125-
.directive('show', attributeWithoutValue('show'))
126-
.directive('showSm', attributeWithoutValue('show-sm'))
127-
.directive('showGtSm', attributeWithoutValue('show-gt-sm'))
128-
.directive('showMd', attributeWithoutValue('show-md'))
129-
.directive('showGtMd', attributeWithoutValue('show-gt-md'))
130-
.directive('showLg', attributeWithoutValue('show-lg'))
131-
.directive('showGtLg', attributeWithoutValue('show-gt-lg'))
132-
133-
// Attribute directives with no value(s) and NO breakpoints
134-
135-
.directive('layoutPadding', attributeWithoutValue('layout-padding'))
136-
.directive('layoutPaddingSm', attributeWithoutValue('layout-padding-sm'))
137-
.directive('layoutPaddingGtSm', attributeWithoutValue('layout-padding-gt-sm'))
138-
.directive('layoutPaddingMd', attributeWithoutValue('layout-padding-md'))
139-
.directive('layoutPaddingGtMd', attributeWithoutValue('layout-padding-gt-md'))
140-
.directive('layoutPaddingLg', attributeWithoutValue('layout-padding-lg'))
141-
.directive('layoutPaddingGtLg', attributeWithoutValue('layout-padding-gt-lg'))
142-
143-
.directive('layoutMargin', attributeWithoutValue('layout-margin'))
144-
.directive('layoutMarginSm', attributeWithoutValue('layout-margin-sm'))
145-
.directive('layoutMarginGtSm', attributeWithoutValue('layout-margin-gt-sm'))
146-
.directive('layoutMarginMd', attributeWithoutValue('layout-margin-md'))
147-
.directive('layoutMarginGtMd', attributeWithoutValue('layout-margin-gt-md'))
148-
.directive('layoutMarginLg', attributeWithoutValue('layout-margin-lg'))
149-
.directive('layoutMarginGtLg', attributeWithoutValue('layout-margin-gt-lg'))
150-
151-
.directive('layoutWrap', attributeWithoutValue('layout-wrap'))
152-
.directive('layoutNoWrap', attributeWithoutValue('layout-no-wrap'))
153-
.directive('layoutFill', attributeWithoutValue('layout-fill'))
154-
155-
// !! Deprecated attributes: use the `-lt` (aka less-than) notations
156-
157-
.directive('layoutLtMd', warnAttrNotSupported('layout-lt-md', true))
158-
.directive('layoutLtLg', warnAttrNotSupported('layout-lt-lg', true))
159-
.directive('flexLtMd', warnAttrNotSupported('flex-lt-md', true))
160-
.directive('flexLtLg', warnAttrNotSupported('flex-lt-lg', true))
161-
162-
.directive('layoutAlignLtMd', warnAttrNotSupported('layout-align-lt-md'))
163-
.directive('layoutAlignLtLg', warnAttrNotSupported('layout-align-lt-lg'))
164-
.directive('flexOrderLtMd', warnAttrNotSupported('flex-order-lt-md'))
165-
.directive('flexOrderLtLg', warnAttrNotSupported('flex-order-lt-lg'))
166-
.directive('offsetLtMd', warnAttrNotSupported('flex-offset-lt-md'))
167-
.directive('offsetLtLg', warnAttrNotSupported('flex-offset-lt-lg'))
168-
169-
.directive('hideLtMd', warnAttrNotSupported('hide-lt-md'))
170-
.directive('hideLtLg', warnAttrNotSupported('hide-lt-lg'))
171-
.directive('showLtMd', warnAttrNotSupported('show-lt-md'))
172-
.directive('showLtLg', warnAttrNotSupported('show-lt-lg'))
173-
174-
.directive('ngCloak', buildCloakInterceptor('ng-cloak'));
75+
function registerLayoutAPI(module){
76+
var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
77+
var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
78+
79+
// NOTE: these are also defined in constants::MEDIA_PRIORITY and constants::MEDIA
80+
var BREAKPOINTS = [ "", "xs", "gt-xs", "sm", "gt-sm", "md", "gt-md", "lg", "gt-lg", "xl" ];
81+
var API_WITH_VALUES = [ "layout", "flex", "flex-order", "flex-offset", "layout-align" ];
82+
var API_NO_VALUES = [ "show", "hide", "layout-padding", "layout-margin" ];
83+
84+
85+
// Build directive registration functions for the standard Layout API... for all breakpoints.
86+
angular.forEach(BREAKPOINTS, function(mqb) {
87+
88+
// Attribute directives with expected, observable value(s)
89+
angular.forEach( API_WITH_VALUES, function(name){
90+
var fullName = mqb ? name + "-" + mqb : name;
91+
module.directive( directiveNormalize(fullName), attributeWithObserve(fullName));
92+
});
93+
94+
// Attribute directives with no expected value(s)
95+
angular.forEach( API_NO_VALUES, function(name){
96+
var fullName = mqb ? name + "-" + mqb : name;
97+
module.directive( directiveNormalize(fullName), attributeWithoutValue(fullName));
98+
});
99+
100+
});
101+
102+
// Register other, special directive functions for the Layout features:
103+
module
104+
.directive('mdLayoutCss' , disableLayoutDirective )
105+
.directive('ngCloak' , buildCloakInterceptor('ng-cloak'))
106+
107+
.directive('layoutWrap' , attributeWithoutValue('layout-wrap'))
108+
.directive('layoutNoWrap' , attributeWithoutValue('layout-no-wrap'))
109+
.directive('layoutFill' , attributeWithoutValue('layout-fill'))
110+
111+
// !! Deprecated attributes: use the `-lt` (aka less-than) notations
112+
113+
.directive('layoutLtMd' , warnAttrNotSupported('layout-lt-md', true))
114+
.directive('layoutLtLg' , warnAttrNotSupported('layout-lt-lg', true))
115+
.directive('flexLtMd' , warnAttrNotSupported('flex-lt-md', true))
116+
.directive('flexLtLg' , warnAttrNotSupported('flex-lt-lg', true))
117+
118+
.directive('layoutAlignLtMd', warnAttrNotSupported('layout-align-lt-md'))
119+
.directive('layoutAlignLtLg', warnAttrNotSupported('layout-align-lt-lg'))
120+
.directive('flexOrderLtMd' , warnAttrNotSupported('flex-order-lt-md'))
121+
.directive('flexOrderLtLg' , warnAttrNotSupported('flex-order-lt-lg'))
122+
.directive('offsetLtMd' , warnAttrNotSupported('flex-offset-lt-md'))
123+
.directive('offsetLtLg' , warnAttrNotSupported('flex-offset-lt-lg'))
124+
125+
.directive('hideLtMd' , warnAttrNotSupported('hide-lt-md'))
126+
.directive('hideLtLg' , warnAttrNotSupported('hide-lt-lg'))
127+
.directive('showLtMd' , warnAttrNotSupported('show-lt-md'))
128+
.directive('showLtLg' , warnAttrNotSupported('show-lt-lg'));
129+
130+
/**
131+
* Converts snake_case to camelCase.
132+
* Also there is special case for Moz prefix starting with upper case letter.
133+
* @param name Name to normalize
134+
*/
135+
function directiveNormalize(name) {
136+
return name
137+
.replace(PREFIX_REGEXP, '')
138+
.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
139+
return offset ? letter.toUpperCase() : letter;
140+
});
141+
}
142+
143+
}
175144

176145
/**
177146
* Special directive that will disable ALL Layout conversions of layout
@@ -464,7 +433,7 @@
464433
cross: "stretch"
465434
};
466435

467-
var values = (value || "").replace(WHITESPACE, "-").split("-");
436+
var values = (value || "").toLowerCase().trim().replace(WHITESPACE, "-").split("-");
468437
if ( values.length == 3 ) {
469438
values = [ values[0]+"-"+values[1],values[2] ];
470439
}
@@ -478,4 +447,5 @@
478447
return axis;
479448
}
480449

450+
481451
})();

src/core/services/layout/layout.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
describe('layout directives', function() {
2-
var suffixes = ['sm', 'gt-sm', 'md', 'gt-md', 'lg', 'gt-lg'],
2+
var suffixes = ['xs', 'gt-xs', 'sm', 'gt-sm', 'md', 'gt-md', 'lg', 'gt-lg', 'xl'],
33
$mdUtil, $compile, pageScope;
44

55
beforeEach(module('material.core', 'material.core.layout'));

0 commit comments

Comments
 (0)