diff --git a/src/core/core.js b/src/core/core.js
index 7a200adb4b5..10d8402e03c 100644
--- a/src/core/core.js
+++ b/src/core/core.js
@@ -7,6 +7,7 @@ angular
'ngAnimate',
'material.animate',
'material.core.gestures',
+ 'material.core.layout',
'material.core.theming'
])
.directive('mdTemplate', MdTemplateDirective)
diff --git a/src/core/services/layout/layouts.js b/src/core/services/layout/layout.js
similarity index 84%
rename from src/core/services/layout/layouts.js
rename to src/core/services/layout/layout.js
index 061b6baba55..7195c700cfb 100644
--- a/src/core/services/layout/layouts.js
+++ b/src/core/services/layout/layout.js
@@ -2,7 +2,46 @@
'use strict';
- angular.module('material.layouts', ['material.core'])
+ /**
+ *
+ * The original ngMaterial Layout solution used attribute selectors and CSS.
+ *
+ * ```html
+ *
My Content
+ * ```
+ *
+ * ```css
+ * [layout] {
+ * box-sizing: border-box;
+ * display:flex;
+ * }
+ * [layout=column] {
+ * flex-direction : column
+ * }
+ * ```
+ *
+ * Use of attribute selectors creates significant performance impacts in some
+ * browsers... mainly IE.
+ *
+ * This module registers directives that allow the same layout attributes to be
+ * interpreted and converted to class selectors. The directive will add equivalent classes to each element that
+ * contains a Layout directive.
+ *
+ * ```html
+ * My Content
+ *```
+ *
+ * ```css
+ * .layout {
+ * box-sizing: border-box;
+ * display:flex;
+ * }
+ * .layout-column {
+ * flex-direction : column
+ * }
+ * ```
+ */
+ angular.module('material.core.layout', [ ])
// Attribute directives with optional value(s)
diff --git a/src/core/services/layout/layout.spec.js b/src/core/services/layout/layout.spec.js
new file mode 100644
index 00000000000..989ee860de0
--- /dev/null
+++ b/src/core/services/layout/layout.spec.js
@@ -0,0 +1,118 @@
+describe('layout directives', function() {
+
+ beforeEach(module('material.core'));
+
+ describe('expecting layout classes', function() {
+
+ var suffixes = ['sm', 'gt-sm', 'md', 'gt-md', 'lg', 'gt-lg'];
+
+ var directionValues = ['row', 'column'];
+ var flexOrderValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+ var flexValues = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 33, 34, 66, 67];
+ var offsetValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 33, 34, 66, 67];
+ var alignmentValues = [
+ 'center', 'center center', 'center start', 'center end',
+ 'end', 'end-center', 'end start', 'end end',
+ 'space-around', 'space-around center', 'space-around start', 'space-around end',
+ 'space-between', 'space-between center', 'space-between start', 'space-between end',
+ 'center center', 'start center', 'end center', 'space-between center', 'space-around center',
+ 'center start', 'start start', 'end start', 'space-between start', 'space-around start',
+ 'center end', 'start end', 'end end', 'space-between end', 'space-around end'
+ ];
+
+ var mappings = [
+ { attribute: 'layout', suffixes: suffixes, values: directionValues, addDirectiveAsClass: true, testStandAlone: true },
+ { attribute: 'layout-align', suffixes: suffixes, values: alignmentValues },
+ { attribute: 'layout-padding', testStandAlone: true },
+ { attribute: 'layout-margin', testStandAlone: true },
+ { attribute: 'layout-wrap', testStandAlone: true },
+ { attribute: 'layout-fill', testStandAlone: true },
+ { attribute: 'flex', suffixes: suffixes, values: flexValues, addDirectiveAsClass: true, testStandAlone: true},
+ { attribute: 'flex-order', suffixes: suffixes, values: flexOrderValues },
+ { attribute: 'offset', suffixes: suffixes, values: offsetValues },
+ { attribute: 'hide', suffixes: suffixes, testStandAlone: true },
+ { attribute: 'show', suffixes: suffixes, testStandAlone: true }
+ ];
+
+ // Run all the tests; iterating the mappings...
+
+ for (var i = 0; i < mappings.length; i++) {
+ var map = mappings[i];
+
+ if (map.testStandAlone) testMapping(map.attribute, map.attribute);
+ if (map.suffixes) testWithSuffix(map.attribute, map.suffixes, map.values, map.testStandAlone, map.addDirectiveAsClass);
+ if (map.values) testWithSuffixAndValue(map.attribute, map.values, undefined, map.addDirectiveAsClass);
+ }
+
+ /**
+ *
+ */
+ function testMapping(attribute, expectedClass) {
+ it('should fail if the class ' + expectedClass + ' was not added for attribute ' + attribute, inject(function($compile, $rootScope) {
+ var element = $compile('Layout
')($rootScope);
+ expect(element.hasClass(expectedClass)).toBe(true);
+ }));
+ }
+
+ /**
+ *
+ */
+ function testWithSuffixAndValue(attribute, values, suffix, addDirectiveAsClass) {
+
+ for (var j = 0; j < values.length; j++) {
+ var value = values[j].toString();
+ var attr = suffix ? attribute + '-' + suffix : attribute;
+
+ var attrWithValue = buildAttributeWithValue(attr, value);
+ var expectedClass = buildExpectedClass(attr, value);
+
+ // Run each test.
+ testMapping(attrWithValue, expectedClass);
+ }
+
+ /**
+ * Build string of expected classes that should be added to the
+ * DOM element.
+ *
+ * Convert directive with value to classes
+ *
+ * @param attrClass String full attribute name; eg 'layout-gt-lg'
+ * @param attrValue String HTML directive; eg "column"
+ *
+ * @returns String to be used with element.addClass(...); eg `layout-gt-lg layout-gt-lg-column`
+ */
+ function buildExpectedClass(attrClass, attrValue) {
+ if (addDirectiveAsClass) attrClass += ' ' + attrClass;
+ return attrClass + "-" + attrValue.replace(/\s+/g, "-");
+ }
+
+ /**
+ * Build full string of expected directive with its value
+ * Note: The expected class always starts with the
+ * attribute name, add the suffix if any.
+ *
+ * @param attrClass String full attribute name; eg 'layout-gt-lg'
+ * @param attrValue String HTML directive; eg "column"
+ *
+ * @returns String like `layout-gt-lg="column"`
+ */
+ function buildAttributeWithValue(attr, value) {
+ return attr + '="' + value + '"';
+ }
+ }
+
+ /**
+ *
+ */
+ function testWithSuffix(attribute, suffixes, values, testStandAlone, addDirectiveAsClass) {
+ for (var j = 0; j < suffixes.length; j++) {
+ var suffix = suffixes[j];
+ var attr = attribute + '-' + suffix;
+
+ if (testStandAlone) testMapping(attr, attr);
+ if (values) testWithSuffixAndValue(attribute, values, suffix, addDirectiveAsClass);
+ }
+ }
+ });
+
+});
diff --git a/src/core/services/layout/layouts.spec.js b/src/core/services/layout/layouts.spec.js
deleted file mode 100644
index 3feffbfef70..00000000000
--- a/src/core/services/layout/layouts.spec.js
+++ /dev/null
@@ -1,87 +0,0 @@
-describe('layouts service', function () {
- beforeEach(module('material.layouts'));
-
- describe('expecting layout classes', function () {
-
- var suffixes = ['sm', 'gt-sm', 'md', 'gt-md', 'lg', 'gt-lg'];
-
- var directionValues = ['row', 'column'];
- var flexValues = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 33, 34, 66, 67];
- var alignmentValues = ['center', 'center center', 'center start', 'center end',
- 'end', 'end-center', 'end start', 'end end',
- 'space-around', 'space-around center', 'space-around start', 'space-around end',
- 'space-between', 'space-between center', 'space-between start', 'space-between end',
- 'center center', 'start center', 'end center', 'space-between center', 'space-around center',
- 'center start', 'start start', 'end start', 'space-between start', 'space-around start',
- 'center end', 'start end', 'end end', 'space-between end', 'space-around end'];
- var flexOrderValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
- var offsetValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 33, 34, 66, 67];
-
- var mappings = [{ attribute: 'layout', suffixes: suffixes, values: directionValues, testStandAlone: true, addDirectiveAsClass: true },
- { attribute: 'flex', suffixes: suffixes, values: flexValues, testStandAlone: true, addDirectiveAsClass: true },
- { attribute: 'layout-align', suffixes: suffixes, values: alignmentValues },
- { attribute: 'flex-order', suffixes: suffixes, values: flexOrderValues },
- { attribute: 'offset', suffixes: suffixes, values: offsetValues },
- { attribute: 'layout-padding', testStandAlone: true },
- { attribute: 'layout-margin', testStandAlone: true },
- { attribute: 'layout-wrap', testStandAlone: true },
- { attribute: 'layout-fill', testStandAlone: true },
- { attribute: 'hide', suffixes: suffixes, testStandAlone: true },
- { attribute: 'show', suffixes: suffixes, testStandAlone: true }];
-
- function testMapping(attribute, expectedClass) {
- it('should fail if the class ' + expectedClass + ' was not added for attribute ' + attribute, inject(function ($compile, $rootScope) {
- var element = $compile('Layout
')($rootScope);
- expect(element.hasClass(expectedClass)).toBe(true);
- }));
- }
-
- function testWithSuffix(attribute, suffixes, values, testStandAlone, addDirectiveAsClass) {
- for (var j = 0; j < suffixes.length; j++) {
- var suffix = suffixes[j];
- // Add the suffix to the attribute.
- var attributeWithValue = attribute + '-' + suffix;
- // Add the suffix to the expected class.
- var expectedClass = attribute + '-' + suffix;
- // Run the test.
- if (testStandAlone)
- testMapping(attributeWithValue, expectedClass);
- // Add suffixes with values.
- if (values)
- testWithSuffixAndValue(attribute, values, suffix, addDirectiveAsClass);
- };
- }
-
- function testWithSuffixAndValue(attribute, values, suffix, addDirectiveAsClass) {
- for (var j = 0; j < values.length; j++) {
- var attributeValue = values[j].toString();
- // If there was a suffix passed in, add it first.
- var attributeWithValue = suffix ? attribute + '-' + suffix : attribute;
- // Add the value.
- attributeWithValue += '="' + attributeValue + '"';
- // The expected class always starts with the attribute name, add the suffix if any.
- var expectedClass = suffix ? attribute + '-' + suffix : attribute;
- // Add the class if necessary.
- if (addDirectiveAsClass)
- expectedClass += ' ' + expectedClass;
- // Add the attribute and suffix to the expected class and replace the spaces with a dash.
- expectedClass += '-' + attributeValue.replace(/\s+/g, "-");
- // Run the test.
- testMapping(attributeWithValue, expectedClass);
- };
- }
-
- for (var i = 0; i < mappings.length; i++) {
- var mapping = mappings[i];
- // First test the mapping without any suffixes or values.
- if (mapping.testStandAlone)
- testMapping(mapping.attribute, mapping.attribute);
- // Check for suffixes.
- if (mapping.suffixes)
- testWithSuffix(mapping.attribute, mapping.suffixes, mapping.values, mapping.testStandAlone, mapping.addDirectiveAsClass);
- // Check for values.
- if (mapping.values)
- testWithSuffixAndValue(mapping.attribute, mapping.values, undefined, mapping.addDirectiveAsClass);
- }
- });
-});