diff --git a/config/build.config.js b/config/build.config.js
index db117589ee1..cc748cf001f 100644
--- a/config/build.config.js
+++ b/config/build.config.js
@@ -4,7 +4,7 @@ var fs = require('fs');
var versionFile = __dirname + '/../dist/commit';
module.exports = {
- ngVersion: '1.3.2',
+ ngVersion: '1.3.15',
version: pkg.version,
repository: pkg.repository.url
.replace(/^git/,'https')
diff --git a/docs/app/img/icons/sets/communication-icons.svg b/docs/app/img/icons/sets/communication-icons.svg
new file mode 100644
index 00000000000..1e2fbb0a403
--- /dev/null
+++ b/docs/app/img/icons/sets/communication-icons.svg
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/app/img/icons/sets/core-icons.svg b/docs/app/img/icons/sets/core-icons.svg
index 5f52b2d8100..fff04153670 100644
--- a/docs/app/img/icons/sets/core-icons.svg
+++ b/docs/app/img/icons/sets/core-icons.svg
@@ -23,4 +23,5 @@
-
\ No newline at end of file
+
+
diff --git a/docs/app/img/icons/sets/device-icons.svg b/docs/app/img/icons/sets/device-icons.svg
new file mode 100644
index 00000000000..cc5bfd7f69d
--- /dev/null
+++ b/docs/app/img/icons/sets/device-icons.svg
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/checkbox/checkbox.js b/src/components/checkbox/checkbox.js
index 8ad06b2bd04..ed5de4a881f 100644
--- a/src/components/checkbox/checkbox.js
+++ b/src/components/checkbox/checkbox.js
@@ -103,7 +103,7 @@ function MdCheckboxDirective(inputDirective, $mdInkRipple, $mdAria, $mdConstant,
ngModelCtrl.$render = render;
function keypressHandler(ev) {
- if(ev.which === $mdConstant.KEY_CODE.SPACE) {
+ if(ev.which === $mdConstant.KEY_CODE.SPACE || ev.which === $mdConstant.KEY_CODE.ENTER) {
ev.preventDefault();
listener(ev);
}
diff --git a/src/components/icon/icon-theme.scss b/src/components/icon/icon-theme.scss
index 7042242fc00..ca6a0d09a14 100644
--- a/src/components/icon/icon-theme.scss
+++ b/src/components/icon/icon-theme.scss
@@ -1,4 +1,5 @@
md-icon.md-THEME_NAME-theme {
+ color: '{{foreground-2}}';
&.md-primary {
color: '{{primary-color}}';
diff --git a/src/components/list/demoBasicUsage/index.html b/src/components/list/demoBasicUsage/index.html
index 8dfd50311f5..94a57d1acad 100644
--- a/src/components/list/demoBasicUsage/index.html
+++ b/src/components/list/demoBasicUsage/index.html
@@ -1,25 +1,32 @@
');
+ container.append(tEl.contents());
+ tEl.addClass('md-proxy-focus');
+ } else {
+ container = angular.element('
');
+ container[0].setAttribute('ng-click', tEl[0].getAttribute('ng-click'));
+ tEl[0].removeAttribute('ng-click');
+ container.children().eq(0).append(tEl.contents());
+ }
+
+ tEl[0].setAttribute('tabindex', '-1');
+ tEl.append(container);
+
+ if (secondaryItem && secondaryItem.hasAttribute('ng-click')) {
+ $mdAria.expect(secondaryItem, 'aria-label');
+ }
+
+ // Check for a secondary item and move it outside
+ if ( secondaryItem && (
+ secondaryItem.hasAttribute('ng-click') ||
+ ( tAttrs.ngClick &&
+ isProxiedElement(secondaryItem) )
+ )) {
+ tEl.addClass('md-with-secondary');
+ tEl.append(secondaryItem);
+ }
+ }
+
+ function isProxiedElement(el) {
+ return proxiedTypes.indexOf(el.nodeName.toLowerCase()) != -1;
+ }
+
+ return postLink;
+
+ function postLink($scope, $element, $attr) {
+
+ var proxies = [];
+
+ computeProxies();
+ computeClickable();
+
+ if ($element.hasClass('md-proxy-focus') && proxies.length) {
+ angular.forEach(proxies, function(proxy) {
+ proxy = angular.element(proxy);
+ proxy.on('focus', function() {
+ $element.addClass('md-focused');
+ proxy.on('blur', function() {
+ $element.removeClass('md-focused');
+ proxy.off('blur');
+ });
+ });
+ });
+ }
+
+ function computeProxies() {
+ if (!$element.children()[0].hasAttribute('ng-click')) {
+ angular.forEach(proxiedTypes, function(type) {
+ angular.forEach($element[0].firstElementChild.querySelectorAll(type), function(child) {
+ proxies.push(child);
+ });
+ });
+ }
+ }
+ function computeClickable() {
+ if (proxies.length || $element[0].firstElementChild.hasAttribute('ng-click')) {
+ $element.addClass('md-clickable');
+ }
+ }
+
+ if (!$element[0].firstElementChild.hasAttribute('ng-click') && !proxies.length) {
+ $element[0].firstElementChild.addEventListener('keypress', function(e) {
+ if (e.keyCode == 13 || e.keyCode == 32) {
+ $element[0].firstElementChild.click();
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ });
+ }
+
+ $element.off('click');
+ $element.off('keypress');
+
+ if (proxies.length) {
+ $element.children().eq(0).on('click', function(e) {
+ if ($element[0].firstElementChild.contains(e.target)) {
+ angular.forEach(proxies, function(proxy) {
+ if (e.target !== proxy && !proxy.contains(e.target)) {
+ angular.element(proxy).triggerHandler('click');
+ proxy.focus();
+ }
+ });
+ }
+ });
+ }
+ }
}
};
}
diff --git a/src/components/list/list.scss b/src/components/list/list.scss
index 3171da485fe..d87e9f12bc3 100644
--- a/src/components/list/list.scss
+++ b/src/components/list/list.scss
@@ -1,11 +1,12 @@
-$list-h3-font-size: 1.1em !default;
-$list-h3-margin: 0 0 3px 0 !default;
+$list-h3-font-size: 1em !default;
+$list-h3-margin: 0 0 6px 0 !default;
$list-h3-font-weight: 400 !default;
-$list-h4-font-size: 0.9em !default;
+$list-h4-font-size: 0.875em !default;
$list-h4-font-weight: 400 !default;
-$list-h4-margin: 0 0 3px 0 !default;
+$list-h4-margin: 10px 0 5px 0 !default;
$list-p-font-size: 0.75em !default;
-$list-p-margin: 0 0 3px 0 !default;
+$list-p-margin: 0 0 0px 0 !default;
+$list-p-line-height: 1.6em !default;
$list-padding-top: $baseline-grid !default;
$list-padding-right: 0px !default;
@@ -16,63 +17,165 @@ $item-padding-top: 0px !default;
$item-padding-right: 0px !default;
$item-padding-left: 0px !default;
$item-padding-bottom: 0px !default;
+$list-item-padding-vertical: 0px !default;
+$list-item-padding-horizontal: $baseline-grid * 2 !default;
+$list-item-primary-width: $baseline-grid * 7 !default;
+$list-item-primary-avatar-width: $baseline-grid * 5 !default;
+$list-item-primary-icon-width: $baseline-grid * 3 !default;
+$list-item-secondary-left-margin: $baseline-grid * 2 !default;
+$list-item-text-padding-top: $baseline-grid * 2 !default;
+$list-item-text-padding-bottom: $baseline-grid * 2.5 !default;
md-list {
+ display: block;
padding: $list-padding-top $list-padding-right $list-padding-bottom $list-padding-left;
+
+ .md-subheader {
+ font-weight: 500;
+ font-size: 0.875em;
+ }
}
md-item {
-
+ &.md-no-style,
+ .md-no-style {
+ padding: $list-item-padding-vertical $list-item-padding-horizontal;
+ flex: 1;
+ &:focus {
+ outline: none
+ }
+ }
+ &.md-with-secondary {
+ padding-right: $list-item-padding-horizontal;
+ }
+ &.md-clickable:hover {
+ cursor: pointer;
+ }
}
-md-item-content {
+md-item, md-item .md-item-inner {
display: flex;
+ justify-content: flex-start;
align-items: center;
- flex-direction: row;
- box-sizing: border-box;
- position: relative;
+ // Layout for controls in primary or secondary divs, or auto-infered first child
+ & > div.md-primary > md-icon,
+ & > div.md-secondary > md-icon,
+ & > md-icon:first-child,
+ > md-icon.md-secondary {
+ width: $list-item-primary-icon-width;
+ margin-top: 12px;
+ margin-bottom: 12px;
+ box-sizing: content-box;
+ &:focus {
+ border-radius: 2px;
+ outline: none;
+ padding: 6px;
+ margin-top: 6px;
+ margin-bottom: 6px;
+ }
+ }
+ & > div.md-primary > md-checkbox,
+ & > div.md-secondary > md-checkbox,
+ & > md-checkbox:first-child,
+ md-checkbox.md-secondary {
+ position: relative;
+ top: -2px;
+ margin-top: 14px;
+ margin-bottom: 12px;
+ .md-label { display: none; }
+ &:not(md-checkbox:first-child):focus {
+ padding: 6px;
+ margin-right: -6px;
+ margin-top: 8px;
+ margin-bottom: 6px;
+ }
+ }
- padding: $item-padding-top $item-padding-right $item-padding-bottom $item-padding-left;
-}
+ & > md-icon:first-child {
+ margin-right: $list-item-primary-width - $list-item-primary-icon-width;
+ }
+ & > md-checkbox:first-child {
+ width: 3 * $baseline-grid;
+ margin-left: 3px;
+ margin-right: 29px;
+ }
+ & > .md-avatar:first-child {
+ width: $list-item-primary-avatar-width;
+ height: $list-item-primary-avatar-width;
+ margin-top: $baseline-grid;
+ margin-bottom: $baseline-grid;
+ margin-right: $list-item-primary-width - $list-item-primary-avatar-width;
+ border-radius: 50%;
+ box-sizing: content-box;
+ }
+
+ md-checkbox.md-secondary {
+ margin-right: 0px;
+ }
+ md-switch.md-secondary {
+ margin: 0;
+ position: relative;
+ right: -9px;
+ }
+ .md-secondary {
+ margin-left: $list-item-secondary-left-margin;
+ }
-/**
- * The left tile for a list item.
- */
-.md-tile-left {
- min-width: 56px;
- margin-right: -16px;
+ & > p, & > .md-item-inner > p {
+ flex: 1;
+ margin: 0;
+ }
}
-/**
- * The center content tile for a list item.
- */
-.md-tile-content {
- flex: 1;
- padding: $baseline-grid * 2;
+md-item.md-2-line,
+md-item.md-2-line > .md-no-style,
+md-item.md-3-line,
+md-item.md-3-line > .md-no-style {
+ align-items: flex-start;
- text-overflow: ellipsis;
+ .md-item-text {
+ flex: 1;
+ padding: $baseline-grid * 2 0;
+ text-overflow: ellipsis;
- h3 {
- margin: $list-h3-margin;
- font-weight: $list-h3-font-weight;
- font-size: $list-h3-font-size;
+ h3 {
+ margin: $list-h3-margin;
+ font-weight: $list-h3-font-weight;
+ font-size: $list-h3-font-size;
+ line-height: 0.75em;
+ }
+ h4 {
+ margin: $list-h4-margin;
+ font-weight: $list-h4-font-weight;
+ font-size: $list-h4-font-size;
+ line-height: 0.75em;
+ }
+ p {
+ margin: $list-p-margin;
+ font-size: $list-p-font-size;
+ line-height: $list-p-line-height;
+ }
}
- h4 {
- margin: $list-h4-margin;
- font-weight: $list-h4-font-weight;
- font-size: $list-h4-font-size;
+}
+
+md-item.md-2-line,
+md-item.md-2-line > .md-no-style {
+ > md-icon:first-child,
+ > .md-avatar:first-child {
+ margin-top: $baseline-grid * 1.5;
}
- p {
- margin: $list-p-margin;
- font-size: $list-p-font-size;
+ .md-item-text {
+ flex: 1;
+ padding-top: ($baseline-grid * 2.5) - 1;
}
}
-/**
- * The right tile for a list item.
- */
-.md-tile-right {
- padding-right: $item-padding-right;
+md-item.md-3-line,
+md-item.md-3-line > .md-no-style {
+ > md-icon:first-child,
+ > .md-avatar:first-child {
+ margin-top: $baseline-grid * 2;
+ }
}
diff --git a/src/components/list/list.spec.js b/src/components/list/list.spec.js
index 6bc0fa793d2..3b51f5d601c 100644
--- a/src/components/list/list.spec.js
+++ b/src/components/list/list.spec.js
@@ -1,11 +1,42 @@
-describe('mdList directive', function() {
- function setup(attrs) {
- module('material.components.list');
+describe('mdItem directive', function() {
+ beforeEach(module('material.components.list', 'material.components.checkbox', 'material.components.switch'));
+
+ function setup(html) {
var el;
inject(function($compile, $rootScope) {
- el = $compile('
')($rootScope.$new());
+ el = $compile(html)($rootScope);
$rootScope.$apply();
});
return el;
}
+
+ it('forwards click events for md-checkbox', inject(function($rootScope) {
+ var listItem = setup('
');
+ listItem[0].querySelector('div').click();
+ expect($rootScope.modelVal).toBe(true);
+ }));
+
+ it('forwards click events for md-switch', inject(function($rootScope) {
+ var listItem = setup('
');
+ listItem[0].querySelector('div').click();
+ expect($rootScope.modelVal).toBe(true);
+ }));
+
+ it('creates buttons when used with ng-click', function() {
+ var listItem = setup('
Hello world
');
+ var firstChild = listItem.children()[0];
+ expect(firstChild.nodeName).toBe('BUTTON');
+ expect(firstChild.childNodes[0].nodeName).toBe('DIV');
+ expect(firstChild.childNodes[0].childNodes[0].nodeName).toBe('P');
+ });
+
+ it('moves md-secondary items outside of the button', function() {
+ var listItem = setup('
Hello World
');
+ var firstChild = listItem.children()[0];
+ expect(firstChild.nodeName).toBe('BUTTON');
+ expect(firstChild.childNodes.length).toBe(1);
+ var secondChild = listItem.children()[1];
+ expect(secondChild.nodeName).toBe('MD-ICON');
+ });
+
});
diff --git a/src/components/subheader/subheader.js b/src/components/subheader/subheader.js
index 6dc35c75676..233f06beb0f 100644
--- a/src/components/subheader/subheader.js
+++ b/src/components/subheader/subheader.js
@@ -33,7 +33,9 @@ angular.module('material.components.subheader', [
* @restrict E
*
* @description
- * The `
` directive is a subheader for a section
+ * The `` directive is a subheader for a section. By default it is sticky.
+ * You can make it not sticky by applying the `md-no-sticky` class to the subheader.
+ *
*
* @usage
*
@@ -66,12 +68,14 @@ function MdSubheaderDirective($mdSticky, $compile, $mdTheming) {
// Create another clone, that uses the outer and inner contents
// of the element, that will be 'stickied' as the user scrolls.
- transclude(scope, function(clone) {
- var stickyClone = $compile(angular.element(outerHTML))(scope);
- $mdTheming(stickyClone);
- getContent(stickyClone).append(clone);
- $mdSticky(scope, element, stickyClone);
- });
+ if (!element.hasClass('md-no-sticky')) {
+ transclude(scope, function(clone) {
+ var stickyClone = $compile(angular.element(outerHTML))(scope);
+ $mdTheming(stickyClone);
+ getContent(stickyClone).append(clone);
+ $mdSticky(scope, element, stickyClone);
+ });
+ }
};
}
};
diff --git a/src/core/services/aria/aria.js b/src/core/services/aria/aria.js
index f7aa3948c12..eb67f04da7f 100644
--- a/src/core/services/aria/aria.js
+++ b/src/core/services/aria/aria.js
@@ -19,7 +19,7 @@ function AriaService($$rAF, $log, $window) {
* @param {optional} defaultValue What to set the attr to if no value is found
*/
function expect(element, attrName, defaultValue) {
- var node = element[0];
+ var node = element[0] || element;
// if node exists and neither it nor its children have the attribute
if (node &&
diff --git a/src/core/style/structure.scss b/src/core/style/structure.scss
index ca39ef58cec..f35fde72f57 100644
--- a/src/core/style/structure.scss
+++ b/src/core/style/structure.scss
@@ -17,6 +17,15 @@ body {
padding: 10px;
}
+button.md-no-style {
+ font-weight: normal;
+ background-color: inherit;
+ text-align: left;
+ border: none;
+ padding: 0px;
+ margin: 0px;
+}
+
select,
button,
textarea,