diff --git a/.drone.yml b/.drone.yml index 45000d06c..0e006c76c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -26,7 +26,6 @@ build: - Xvfb $DISPLAY & - curl -sSLo chrome.deb $CHROME && dpkg -i chrome.deb - curl -sSLo driver.zip $WEBDRIVER && unzip -q driver.zip -d /usr/bin - - node test/memory/test.js publish: # see http://addons.drone.io/google_cloud_storage/ for details gcs: diff --git a/.jscsrc b/.jscsrc index ca195c19f..211744d0d 100644 --- a/.jscsrc +++ b/.jscsrc @@ -1,6 +1,5 @@ { "preset": "google", - "esnext": true, "disallowSpacesInAnonymousFunctionExpression": null, "validateLineBreaks": "LF", "validateIndentation": 2, @@ -8,9 +7,7 @@ "maximumLineLength": 130, "validateQuoteMarks": "'", "requireDotNotation": false, - "requireCamelCaseOrUpperCaseIdentifiers": null, - "additionalRules": ["./utils/jscs-rules/*.js", "../utils/jscs-rules/*.js"], - "closureCamelCase": true, + "requireCamelCaseOrUpperCaseIdentifiers": {"allowedPrefixes": ["opt_"]}, "jsDoc": { "checkAnnotations": { "preset": "closurecompiler", diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b57ef6f1..ffdd20d7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -75,7 +75,7 @@ Please provide any URLs or screenshots of good examples of usage of this compone If you would like to implement a new feature then consider what kind of change it is: * **Major Changes** that you wish to contribute to the project should be discussed first on our -[issue tracker][https://github.com/google/material-design-lite/issues] so that we can better coordinate our efforts, prevent +[issue tracker][] so that we can better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project. * **Small Changes** can be crafted and submitted to the [GitHub Repository][github] as a Pull Request. @@ -223,6 +223,7 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise *This guide was inspired by the [AngularJS contribution guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md).* [github]: https://github.com/google/material-design-lite +[issue tracker]: https://github.com/google/material-design-lite/issues [individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html [corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html [js-style-guide]: http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml diff --git a/README.md b/README.md index 8277908ac..04e9ff5b9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ # Material Design Lite -[![GitHub version](https://badge.fury.io/gh/google%2Fmaterial-design-lite.svg)](https://badge.fury.io/gh/google%2Fmaterial-design-lite) -[![npm version](https://badge.fury.io/js/material-design-lite.svg)](https://badge.fury.io/js/material-design-lite) -[![Bower version](https://badge.fury.io/bo/material-design-lite.svg)](https://badge.fury.io/bo/material-design-lite) -[![Gitter version](https://img.shields.io/gitter/room/gitterHQ/gitter.svg)](https://gitter.im/google/material-design-lite) -[![Dependency Status](https://david-dm.org/google/material-design-lite.svg)](https://david-dm.org/google/material-design-lite) +[![npm version](https://img.shields.io/npm/v/material-design-lite.svg)](https://www.npmjs.com/package/material-design-lite) > An implementation of [Material Design](http://www.google.com/design/spec/material-design/introduction.html) components in vanilla CSS, JS, and HTML. @@ -14,25 +10,35 @@ static content websites. It doesn't rely on any JavaScript frameworks or libraries. Optimized for cross-device use, gracefully degrades in older browsers, and offers an experience that is accessible from the get-go. -## Want to contribute? +> ### Limited support -If you found a bug, have any questions or want to contribute. Follow our -[guidelines](https://github.com/google/material-design-lite/blob/master/CONTRIBUTING.md), -and help improve the Material Design Lite. For more information visit our -[wiki](https://github.com/google/material-design-lite/wiki). +> Material Design Lite is now in limited support, with development having moved to the +> [Material Components for the web](https://github.com/material-components/material-components-web) repository. -If you are submitting a bug fix or a new component for the 1.x line, please send those into `mdl-1.x` currently. +> No further development is taking place in MDL by the core team, but we are happy to review PRs, fix critical bugs and +> push out new releases. No breaking changes will be accepted. -The `master` branch is where we are working on 2.0. -It is currently **highly** experimental and no support building or using it will be provided. +> **Heads up:** the old `getmdl.io` site is gone, and the documentation and component gallery +> that used to live there are no longer available. MDL itself still works fine as a vanilla +> set of Material Design CSS, JS, and HTML you can drop into any project — only the hosted +> docs site has been retired. ## Use MDL on your site? -**This document is targeted at developers that will contribute to or compile -MDL. If you are looking to use MDL on your website or web app please head to -[getmdl.io](http://getmdl.io).** +This document is targeted at developers that will contribute to or compile MDL. +If you just want to use MDL on a website or web app, the safest bet is to +**self-host the v1.3.0 release**, since the previously-recommended +`getmdl.io`-hosted assets are no longer available. + +- Grab the prebuilt CSS and JS from the + [v1.3.0 release on GitHub](https://github.com/google/material-design-lite/releases) + and serve them from your own origin. +- Or, if you need a drop-in CDN alternative, MDL is mirrored on + [CDNJS](https://cdnjs.com/libraries/material-design-lite). +- The package is also still published on npm as + [`material-design-lite`](https://www.npmjs.com/package/material-design-lite). -## Browser Support in v1 +## Browser Support | IE9 | IE10 | IE11 | Chrome | Opera | Firefox | Safari | Chrome (Android) | Mobile Safari | @@ -42,21 +48,6 @@ MDL. If you are looking to use MDL on your website or web app please head to A-grade browsers are fully supported. B-grade browsers will gracefully degrade to our CSS-only experience. -## Browser Support in v2 (in development) - -Supported evergreen browsers: - -- Chrome -- Edge -- Firefox -- Opera - -Supported versioned browsers: - -- Internet Explorer 11 -- Safari 8 -- Mobile Safari 8 - ### Download / Clone Clone the repo using Git: @@ -84,12 +75,22 @@ production. Use a tagged state of the repository, npm, or bower for stability! ## Feature requests -If you find MDL doesn't contain a particular component you think would be -useful, please check the issue tracker in case work has already started on it. -If not, you can request a [new component](https://github.com/Google/material-design-lite/issues/new?title=[Component%20Request]%20{Component}&body=Please%20include:%0A*%20Description%0A*%20Material%20Design%20Spec%20link%0A*%20Use%20Case%28s%29). -Please keep in mind that one of the goals of MDL is to adhere to the Material -Design specs and therefore some requests might not be within the scope of this -project. +MDL is currently in limited support mode, with no further development taking place by the core team. +We are happy to accept and review pull requests for new functionality, however, as long as there are no breaking +changes. + +## Want to contribute? + +If you found a bug, have any questions or want to contribute. Follow our +[guidelines](https://github.com/google/material-design-lite/blob/mdl-1.x/CONTRIBUTING.md), +and help improve the Material Design Lite. For more information visit our +[wiki](https://github.com/google/material-design-lite/wiki). + +Please use the default branch, `mdl-1.x`. + +Take note that [Material Components for Web](https://github.com/material-components/material-components-web), which is MDL v2, is under early Alpha stages (which means everything is a moving target, and we can change anything at any moment). Use with caution. + +However, we would absolutely love to have people testing MCW and provide feedback about their experiences using it, especially integrating with other frameworks and libraries. ## License diff --git a/bower.json b/bower.json index 9ae50d2d6..2a826c951 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "material-design-lite", - "version": "1.2.0", + "version": "1.3.0", "homepage": "https://github.com/google/material-design-lite", "authors": [ "Material Design Lite team" diff --git a/docs/_pages/components.md b/docs/_pages/components.md index 94801540f..b070f3922 100644 --- a/docs/_pages/components.md +++ b/docs/_pages/components.md @@ -127,6 +127,17 @@ categories: limited cross-browser support. To ensure support across all modern browsers, please consider using a polyfill or creating your own. There is no polyfill included with MDL. + - name: expansion + title: Expansion + description: Collapsible content sections. + components: + - name: expansion + class: mdl-expansion + snippets: + - snippet_group: + - caption: Example Expansion + file: expansion.html + full_width: true - name: layout title: Layout description: Building blocks for constructing a page layout. diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 6bd08c948..d5b70d8d7 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -17,7 +17,7 @@ * */ - // jscs:disable jsDoc +// jscs:disable jsDoc 'use strict'; @@ -26,7 +26,7 @@ import fs from 'fs'; import path from 'path'; import mergeStream from 'merge-stream'; import del from 'del'; -import vinylPaths from'vinyl-paths'; +import vinylPaths from 'vinyl-paths'; import runSequence from 'run-sequence'; import browserSync from 'browser-sync'; import through from 'through2'; @@ -219,12 +219,12 @@ gulp.task('closure', () => { compilerPath: 'node_modules/google-closure-compiler/compiler.jar', fileName: 'material.closure.min.js', compilerFlags: { - // jscs:disable closureCamelCase + // jscs:disable requireCamelCaseOrUpperCaseIdentifiers compilation_level: 'ADVANCED_OPTIMIZATIONS', language_in: 'ECMASCRIPT6_STRICT', language_out: 'ECMASCRIPT5_STRICT', warning_level: 'VERBOSE' - // jscs:enable closureCamelCase + // jscs:enable requireCamelCaseOrUpperCaseIdentifiers } })) .pipe(gulp.dest('./dist')); diff --git a/package.json b/package.json index e0ed05bbd..9e42b4a34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "material-design-lite", - "version": "1.2.0", + "version": "1.3.0", "description": "Material Design Components in CSS, JS and HTML", "private": true, "license": "Apache-2.0", @@ -8,50 +8,52 @@ "repository": "google/material-design-lite", "main": "dist/material.min.js", "devDependencies": { - "acorn": "^3.3.0", - "babel-core": "^5.8.25", + "acorn": "^4.0.3", + "babel-core": "^6.20.0", + "babel-preset-es2015": "^6.18.0", "browser-sync": "^2.2.3", "chai": "^3.3.0", "chai-jquery": "^2.0.0", "del": "^2.0.2", - "drool": "^0.3.1", + "drool": "^0.4.0", "escodegen": "^1.6.1", "google-closure-compiler": "", "gulp": "^3.9.0", "gulp-autoprefixer": "^3.0.2", - "gulp-cache": "^0.3.0", - "gulp-closure-compiler": "^0.3.1", + "gulp-cache": "^0.4.5", + "gulp-closure-compiler": "^0.4.0", "gulp-concat": "^2.4.1", "gulp-connect": "^5.0.0", "gulp-css-inline-images": "^0.1.1", "gulp-csso": "1.0.0", - "gulp-file": "^0.2.0", + "gulp-file": "^0.3.0", "gulp-flatten": "^0.3.1", "gulp-front-matter": "^1.2.2", "gulp-header": "^1.2.2", "gulp-if": "^2.0.0", - "gulp-iife": "^0.1.0", - "gulp-imagemin": "^2.2.1", - "gulp-jscs": "^3.0.1", - "gulp-jshint": "^1.6.3", - "gulp-load-plugins": "^0.10.0", + "gulp-iife": "^0.3.0", + "gulp-imagemin": "^3.1.0", + "gulp-jscs": "^4.0.0", + "gulp-jshint": "^2.0.4", + "gulp-load-plugins": "^1.3.0", "gulp-marked": "^1.0.0", - "gulp-mocha-phantomjs": "^0.10.1", - "gulp-open": "^1.0.0", + "gulp-mocha-phantomjs": "^0.12.0", + "gulp-open": "^2.0.0", "gulp-rename": "^1.2.0", "gulp-replace": "^0.5.3", - "gulp-sass": "2.0.*", - "gulp-shell": "^0.4.2", + "gulp-sass": "3.0.0", + "gulp-shell": "^0.5.2", "gulp-size": "^2.0.0", - "gulp-sourcemaps": "^1.3.0", + "gulp-sourcemaps": "^2.0.1", "gulp-subtree": "^0.1.0", "gulp-tap": "^0.1.3", "gulp-uglify": "^2.0.0", "gulp-util": "^3.0.4", - "gulp-zip": "^3.0.2", + "gulp-zip": "^4.0.0", "humanize": "0.0.9", - "jquery": "^2.1.3", - "jshint-stylish": "^2.0.1", + "jquery": "^3.1.1", + "jshint": "^2.9.4", + "jshint-stylish": "^2.2.1", "merge-stream": "^1.0.0", "mocha": "^3.0.2", "prismjs": "0.0.1", @@ -67,6 +69,9 @@ "test": "gulp && git status | grep 'working directory clean' >/dev/null || (echo 'Please commit all changes generated by building'; exit 1)" }, "babel": { - "only": "gulpfile.babel.js" + "only": "gulpfile.babel.js", + "presets": [ + "es2015" + ] } } diff --git a/src/_variables.scss b/src/_variables.scss index 78be5a4ea..e7ead73f2 100644 --- a/src/_variables.scss +++ b/src/_variables.scss @@ -46,7 +46,7 @@ * -----Chip * * Even though all variables have the `!default` directive, most of them - * should not be changed as they are dependent one another. This can cause + * should not be changed as they are dependent on one another. This can cause * visual distortions (like alignment issues) that are hard to track down * and fix. */ diff --git a/src/animation/demo.js b/src/animation/demo.js index a4800ebe8..839f0152d 100644 --- a/src/animation/demo.js +++ b/src/animation/demo.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - /** * Class constructor for Animation MDL component. * Implements MDL component design pattern defined at: diff --git a/src/badge/snippets/badge-on-icon-icon.html b/src/badge/snippets/badge-on-icon-icon.html index 670570ecb..3b2396797 100644 --- a/src/badge/snippets/badge-on-icon-icon.html +++ b/src/badge/snippets/badge-on-icon-icon.html @@ -1 +1,2 @@ +
account_box
diff --git a/src/button/button.js b/src/button/button.js index cc9ba8d09..55d62c72c 100644 --- a/src/button/button.js +++ b/src/button/button.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; diff --git a/src/card/README.md b/src/card/README.md index 567c5b37e..2611892a5 100755 --- a/src/card/README.md +++ b/src/card/README.md @@ -125,3 +125,4 @@ The MDL CSS classes apply various predefined visual and behavioral enhancements | `mdl-card__media` | Defines div as a card media container | Required on "inner" media div | | `mdl-card__supporting-text` | Defines div as a card body text container and assigns appropriate text characteristics to body text | Required on "inner" body text div; text goes directly inside the div with no intervening containers | | `mdl-card__actions` | Defines div as a card actions container and assigns appropriate text characteristics to actions text | Required on "inner" actions div; content goes directly inside the div with no intervening containers | +| `mdl-card__menu` | Defines element as top right menu button | Optional. Should be a child of the `mdl-card` element. | diff --git a/src/card/_card.scss b/src/card/_card.scss index 8bd7cbd43..7f2ff30d8 100644 --- a/src/card/_card.scss +++ b/src/card/_card.scss @@ -46,7 +46,6 @@ color: $card-text-color; display: block; display: flex; - justify-content: stretch; line-height: normal; padding: $card-vertical-padding $card-horizontal-padding; perspective-origin: $card-title-perspective-origin-x $card-title-perspective-origin-y; @@ -84,6 +83,10 @@ overflow: hidden; padding: $card-vertical-padding $card-horizontal-padding; width: 90%; + + &.mdl-card--border { + border-bottom: 1px solid $card-border-color; + } } .mdl-card__actions { diff --git a/src/checkbox/_checkbox.scss b/src/checkbox/_checkbox.scss index 3dd265ed4..a3c4bb65c 100644 --- a/src/checkbox/_checkbox.scss +++ b/src/checkbox/_checkbox.scss @@ -122,15 +122,16 @@ background: transparent; @include material-animation-default(0.28s); - transition-property: background; + transition-property: background-image; .mdl-checkbox.is-checked & { - background: $checkbox-color url("#{$checkbox-image-path}/tick.svg?embed"); + background-color: $checkbox-color; + background-image: url("#{$checkbox-image-path}/tick.svg?embed"); } fieldset[disabled] .mdl-checkbox.is-checked &, .mdl-checkbox.is-checked.is-disabled & { - background: $checkbox-disabled-color url("#{$checkbox-image-path}/tick.svg?embed"); + background-color: $checkbox-disabled-color; } } diff --git a/src/checkbox/checkbox.js b/src/checkbox/checkbox.js index 148035b68..2e5ca1a5f 100644 --- a/src/checkbox/checkbox.js +++ b/src/checkbox/checkbox.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; diff --git a/src/data-table/data-table.js b/src/data-table/data-table.js index f2d7983a9..d9be91b5f 100644 --- a/src/data-table/data-table.js +++ b/src/data-table/data-table.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; @@ -77,6 +76,9 @@ row.classList.add(this.CssClasses_.IS_SELECTED); } else { row.classList.remove(this.CssClasses_.IS_SELECTED); + if (this.headerCheckbox['MaterialCheckbox'].inputElement_.checked) { + this.headerCheckbox['MaterialCheckbox'].uncheck(); + } } }.bind(this); } @@ -147,8 +149,8 @@ if (this.element_.classList.contains(this.CssClasses_.SELECTABLE)) { var th = document.createElement('th'); - var headerCheckbox = this.createCheckbox_(null, rows); - th.appendChild(headerCheckbox); + this.headerCheckbox = this.createCheckbox_(null, rows); + th.appendChild(this.headerCheckbox); firstHeader.parentElement.insertBefore(th, firstHeader); for (var i = 0; i < rows.length; i++) { diff --git a/src/dialog/README.md b/src/dialog/README.md index 6faff7e69..ff22c45ba 100644 --- a/src/dialog/README.md +++ b/src/dialog/README.md @@ -12,7 +12,7 @@ For other browsers you will need to include the [dialog polyfill](https://github Once you have dialog support create a dialog element. The element when using the polyfill **must** be a child of the `body` element. Within that container, add a content element with the class `mdl-dialog__content`. -Add you content, then create an action container with the class `mdl-dialog__actions`. +Add your content, then create an action container with the class `mdl-dialog__actions`. Finally for the markup, add your buttons within this container for triggering dialog functions. Keep in mind, the order is automatically reversed for actions. diff --git a/src/dialog/_dialog.scss b/src/dialog/_dialog.scss index 9f2c3e630..a13ca61a5 100644 --- a/src/dialog/_dialog.scss +++ b/src/dialog/_dialog.scss @@ -43,7 +43,8 @@ padding: 0 0 8px 0; > * { height: 48px; - flex: 0 0 100%; + flex: 0 0 auto; + width: 100%; //@see https://github.com/philipwalton/flexbugs#7-flex-basis-doesnt-account-for-box-sizingborder-box padding-right: 16px; margin-right: 0; text-align: right; diff --git a/src/expansion/README.md b/src/expansion/README.md new file mode 100644 index 000000000..d68626b47 --- /dev/null +++ b/src/expansion/README.md @@ -0,0 +1,42 @@ +## Introduction + +The Material Design Lite (MDL) **expansion** component provides a clean interface +to show collapsable content areas to users. + +## Basic Usage + +To use the expansion panel component browsers must support the [details element](https://www.w3.org/TR/2011/WD-html5-author-20110809/the-details-element.html). Currently only [IE and Edge](http://caniuse.com/#feat=details) do not provide support for this. For support there you'll need to include a polyfill for the `
` element. There are a few available which each have different pitfalls to test them to find the one that best suites your needs. + +Once you have support for detail elements all you need to do is make them with a summary and content containers. Remember that the content element comes directly after the summary element and contains all the rest of the content for the block. If your content has a form or some kind of actions for the user to carry out, include an actions container with actions in the content container. + +Keep in mind, the order is automatically reversed for actions. +Material Design requires that the primary (confirmation) action be displayed last. +So, the first action you create will appear last on the action bar. +This allows for more natural coding and tab ordering while following the specification. + +Remember to add the event handlers for your action items. + +## CSS Classes + +### Blocks + +| MDL Class | Effect | Remarks | +|-----------|--------|---------| +| `mdl-expansion` | Defines the container of the expansion component. | Required on expansion container. | + +### Elements + + +| MDL Class | Effect | Remarks | +|-----------|--------|---------| +| `mdl-expansion__summary` | Defines the summary container for the expansion panel. | Required on summary container. | +| `mdl-expansion__header` | Defines the primary header for the summary. | Required on the header container within the summary. | +| `mdl-expansion__subheader` | Defines the subheading for the summary. | Optional on a node within the header container. | +| `mdl-expansion__secondary-header` | Defines auxiliary content for the summary. | Optional on a node within the summary container. | +| `mdl-expansion__content` | Defines the container node for the content that is toggled. | Required on container node after the summary. | +| `mdl-expansion__actions` | Defines the container node for the actions for any forms within the content. | Optional on container within the content | +| `mdl-expansion__action` | Defines an action trigger to provide the appropriate margin. | Optional on trigger within the actions. | + +### Modifiers + +There are no modifiers for the expansion panel. diff --git a/src/expansion/_expansion.scss b/src/expansion/_expansion.scss new file mode 100644 index 000000000..fb8c428af --- /dev/null +++ b/src/expansion/_expansion.scss @@ -0,0 +1,109 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "../variables"; +@import "../mixins"; + +.mdl-expansion { + border-bottom: 1px solid rgba(0, 0, 0, .12); + box-sizing: border-box; + + &__summary { + @include typo-preferred-font; + padding-left: 24px; + padding-right: 24px; + height: 48px; + display: flex; + outline: none; + + &::-webkit-details-marker { + display: none; + } + + &::after { + @include typo-icon; + content: '\e313'; + display: inline-flex; + flex-direction: column; + user-select: none; + justify-content: center; + transition: transform 200ms, color 200ms; + margin-left: auto; + color: rgba(0, 0, 0, .38); + } + + &:focus { + background-color: unquote("rgba(#{$palette-grey-200}, 1)"); + &::after { + color: rgba(0, 0, 0, .54); + } + } + } + + &__header { + display: flex; + flex-direction: column; + justify-content: center; + font-size: 0.9375rem; + font-weight: 500; + flex-basis: 30%; + margin-right: 16px; + } + + &__subheader { + font-size: .75rem; + color: rgba(0, 0, 0, .54); + } + + &__secondary-header { + display: flex; + flex-direction: column; + justify-content: center; + font-size: 0.9375rem; + font-weight: 500; + flex-basis: 30%; + color: rgba(0, 0, 0, .87); + margin-right: 16px; + } + + &__content { + @include typo-preferred-font; + padding-left: 24px; + padding-right: 24px; + padding-top: 16px; + padding-bottom: 16px; + &+.mdl-expansion__actions { + border-top: 1px solid rgba(0, 0, 0, .12); + } + } + + &__actions { + display: flex; + flex-direction: row-reverse; + padding-top: 16px; + padding-bottom: 16px; + } + + &__action { + margin-right: 8px; + } + + &[open] { + .mdl-expansion__summary::after { + transform: rotate(180deg); + } + } +} diff --git a/src/expansion/snippets/expansion.html b/src/expansion/snippets/expansion.html new file mode 100644 index 000000000..2cf05f39b --- /dev/null +++ b/src/expansion/snippets/expansion.html @@ -0,0 +1,49 @@ +
+ + Trip name + Caribbean Cruise + +
+
+ + Location + Barbados + + +
+ +
+
+ + +
+
+
+ + Start and end dates + Start date: Feb 29, 2016 + End date: Not set + +
+
+ + Carrier + The best cruise line + +
+
+ + + Meal preferences + + Optional + + + + Vegetarian + + +
diff --git a/src/icon-toggle/icon-toggle.js b/src/icon-toggle/icon-toggle.js index 5d5a17c6d..285f6a06f 100644 --- a/src/icon-toggle/icon-toggle.js +++ b/src/icon-toggle/icon-toggle.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; diff --git a/src/layout/README.md b/src/layout/README.md index a535e5cb4..9c8238ce9 100644 --- a/src/layout/README.md +++ b/src/layout/README.md @@ -336,4 +336,5 @@ The MDL CSS classes apply various predefined visual and behavioral enhancements | `mdl-layout__tab` | Defines anchor as MDL tab link | Required on tab bar anchor elements | | `is-active` | Defines tab as default active tab | Optional; goes on tab bar anchor element and associated tab section element| | `mdl-layout__tab-panel` | Defines container as tab content panel | Required on tab section elements | +| `mdl-layout__tab-manual-switch` | Disables tab switching when clicking on tab separators. Useful for disabling default behavior and setting up your own event listeners. | Optional; goes on tab bar element | | `mdl-layout--fixed-tabs` | Uses fixed tabs instead of the default scrollable tabs | Optional; goes on outer div element (not div inside header) | diff --git a/src/layout/_layout.scss b/src/layout/_layout.scss index 05a317a49..844f9cd9a 100644 --- a/src/layout/_layout.scss +++ b/src/layout/_layout.scss @@ -629,7 +629,7 @@ left: 0; position: absolute; background: $layout-header-tab-highlight; - animation: border-expand 0.2s cubic-bezier(0.4, 0.0, 0.4, 1) 0.01s alternate forwards; + animation: border-expand 0.2s cubic-bezier(0.4, 0.0, 0.4, 1) alternate forwards; transition: all 1s cubic-bezier(0.4, 0.0, 1, 1); } diff --git a/src/layout/layout.js b/src/layout/layout.js index 9e1e4e685..e9979acc9 100644 --- a/src/layout/layout.js +++ b/src/layout/layout.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; @@ -102,6 +101,7 @@ HEADER_SCROLL: 'mdl-layout__header--scroll', FIXED_HEADER: 'mdl-layout--fixed-header', + FIXED_DRAWER: 'mdl-layout--fixed-drawer', OBFUSCATOR: 'mdl-layout__obfuscator', TAB_BAR: 'mdl-layout__tab-bar', @@ -110,6 +110,7 @@ TAB_BAR_BUTTON: 'mdl-layout__tab-bar-button', TAB_BAR_LEFT_BUTTON: 'mdl-layout__tab-bar-left-button', TAB_BAR_RIGHT_BUTTON: 'mdl-layout__tab-bar-right-button', + TAB_MANUAL_SWITCH: 'mdl-layout__tab-manual-switch', PANEL: 'mdl-layout__tab-panel', HAS_DRAWER: 'has-drawer', @@ -128,6 +129,17 @@ }; + /** + * Provide local version of matchMedia. This is needed in order to support + * monkey-patching of matchMedia in the unit tests. Due to peculiarities in + * PhantomJS, it doesn't work to monkey patch window.matchMedia directly. + * + * @private + */ + MaterialLayout.prototype.matchMedia_ = function(query) { + return window.matchMedia(query); + }; + /** * Handles scrolling on the content. * @@ -181,12 +193,20 @@ MaterialLayout.prototype.screenSizeHandler_ = function() { if (this.screenSizeMediaQuery_.matches) { this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN); + + if (this.drawer_) { + this.drawer_.setAttribute('aria-hidden', 'true'); + } } else { this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN); // Collapse drawer (if any) when moving to a large screen size. if (this.drawer_) { this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN); this.obfuscator_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN); + + if (this.element_.classList.contains(this.CssClasses_.FIXED_DRAWER)) { + this.drawer_.setAttribute('aria-hidden', 'false'); + } } } }; @@ -423,7 +443,7 @@ // Keep an eye on screen size, and add/remove auxiliary class for styling // of small screens. - this.screenSizeMediaQuery_ = window.matchMedia( + this.screenSizeMediaQuery_ = this.matchMedia_( /** @type {string} */ (this.Constant_.MAX_WIDTH)); this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this)); this.screenSizeHandler_(); @@ -549,12 +569,15 @@ tab.appendChild(rippleContainer); } - tab.addEventListener('click', function(e) { - if (tab.getAttribute('href').charAt(0) === '#') { - e.preventDefault(); - selectTab(); - } - }); + if (!layout.tabBar_.classList.contains( + layout.CssClasses_.TAB_MANUAL_SWITCH)) { + tab.addEventListener('click', function(e) { + if (tab.getAttribute('href').charAt(0) === '#') { + e.preventDefault(); + selectTab(); + } + }); + } tab.show = selectTab; } diff --git a/src/list/README.md b/src/list/README.md index 042dc62c9..a90999099 100644 --- a/src/list/README.md +++ b/src/list/README.md @@ -48,7 +48,7 @@ The MDL CSS classes apply various predefined visual enhancements to the list. Th | .mdl-list__item-primary-content | Defines the primary content sub-division |-| | .mdl-list__item-avatar | Defines the avatar sub-division |-| | .mdl-list__item-icon | Defines the icon sub-division |-| -| .mdl-list__item-secondary-content | Defines the secondary content sub-division | requires `.mdl-list__item-two-line` or `.mdl-list__item-three-line` | -| .mdl-list__item-secondary-info | Defines the information sub-division |requires `.mdl-list__item-two-line` or `.mdl-list__item-three-line` | -| .mdl-list__item-secondary-action | Defines the Action sub-division | requires `.mdl-list__item-two-line` or `.mdl-list__item-three-line` | -| .mdl-list__item-text-body | Defines the Text Body sub-division | requires `.mdl-list__item-three-line` | +| .mdl-list__item-secondary-content | Defines the secondary content sub-division | requires `.mdl-list__item--two-line` or `.mdl-list__item--three-line` | +| .mdl-list__item-secondary-info | Defines the information sub-division |requires `.mdl-list__item--two-line` or `.mdl-list__item--three-line` | +| .mdl-list__item-secondary-action | Defines the Action sub-division | requires `.mdl-list__item--two-line` or `.mdl-list__item--three-line` | +| .mdl-list__item-text-body | Defines the Text Body sub-division | requires `.mdl-list__item--three-line` | diff --git a/src/list/snippets/list-control.html b/src/list/snippets/list-control.html index c69ba9227..dbbf312ef 100644 --- a/src/list/snippets/list-control.html +++ b/src/list/snippets/list-control.html @@ -26,10 +26,10 @@ person Aaron Paul - - + +
  • @@ -37,10 +37,10 @@ person Bob Odenkirk - - + +
  • diff --git a/src/material-design-lite.scss b/src/material-design-lite.scss index 512360e15..391da2016 100644 --- a/src/material-design-lite.scss +++ b/src/material-design-lite.scss @@ -35,6 +35,7 @@ @import "chip/chip"; @import "data-table/data-table"; @import "dialog/dialog"; +@import "expansion/expansion"; @import "footer/mega_footer"; @import "footer/mini_footer"; @import "icon-toggle/icon-toggle"; diff --git a/src/mdlComponentHandler.js b/src/mdlComponentHandler.js index e4e652395..0d8834e1a 100644 --- a/src/mdlComponentHandler.js +++ b/src/mdlComponentHandler.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - /** * A component handler interface using the revealing module design pattern. * More details on this design pattern here: @@ -141,6 +140,27 @@ componentHandler = (function() { return upgradedList.indexOf(jsClass) !== -1; } + /** + * Create an event object. + * + * @param {string} eventType The type name of the event. + * @param {boolean} bubbles Whether the event should bubble up the DOM. + * @param {boolean} cancelable Whether the event can be canceled. + * @returns {!Event} + */ + function createEvent_(eventType, bubbles, cancelable) { + if ('CustomEvent' in window && typeof window.CustomEvent === 'function') { + return new CustomEvent(eventType, { + bubbles: bubbles, + cancelable: cancelable + }); + } else { + var ev = document.createEvent('Events'); + ev.initEvent(eventType, bubbles, cancelable); + return ev; + } + } + /** * Searches existing DOM for elements of our component type and upgrades them * if they have not already been upgraded. @@ -185,6 +205,13 @@ componentHandler = (function() { if (!(typeof element === 'object' && element instanceof Element)) { throw new Error('Invalid argument provided to upgrade MDL element.'); } + // Allow upgrade to be canceled by canceling emitted event. + var upgradingEv = createEvent_('mdl-componentupgrading', true, true); + element.dispatchEvent(upgradingEv); + if (upgradingEv.defaultPrevented) { + return; + } + var upgradedList = getUpgradedListOfElement_(element); var classesToUpgrade = []; // If jsClass is not provided scan the registered components to find the @@ -227,16 +254,8 @@ componentHandler = (function() { 'Unable to find a registered component for the given class.'); } - var ev; - if ('CustomEvent' in window && typeof window.CustomEvent === 'function') { - ev = new CustomEvent('mdl-componentupgraded', { - bubbles: true, cancelable: false - }); - } else { - ev = document.createEvent('Events'); - ev.initEvent('mdl-componentupgraded', true, true); - } - element.dispatchEvent(ev); + var upgradedEv = createEvent_('mdl-componentupgraded', true, false); + element.dispatchEvent(upgradedEv); } } @@ -358,15 +377,7 @@ componentHandler = (function() { upgrades.splice(componentPlace, 1); component.element_.setAttribute('data-upgraded', upgrades.join(',')); - var ev; - if ('CustomEvent' in window && typeof window.CustomEvent === 'function') { - ev = new CustomEvent('mdl-componentdowngraded', { - bubbles: true, cancelable: false - }); - } else { - ev = document.createEvent('Events'); - ev.initEvent('mdl-componentdowngraded', true, true); - } + var ev = createEvent_('mdl-componentdowngraded', true, false); component.element_.dispatchEvent(ev); } } diff --git a/src/menu/menu.js b/src/menu/menu.js index de5b3b996..869c727c4 100644 --- a/src/menu/menu.js +++ b/src/menu/menu.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; diff --git a/src/progress/progress.js b/src/progress/progress.js index 442e2d68e..cb8ca725b 100644 --- a/src/progress/progress.js +++ b/src/progress/progress.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; diff --git a/src/radio/_radio.scss b/src/radio/_radio.scss index 73110a011..e2268265a 100644 --- a/src/radio/_radio.scss +++ b/src/radio/_radio.scss @@ -25,7 +25,10 @@ display: inline-block; + vertical-align: middle; + box-sizing: border-box; + height: $radio-label-height; margin: 0; padding-left: 0; @@ -98,13 +101,13 @@ @include material-animation-default(0.28s); transition-property: transform; - transform: scale3d(0, 0, 0); + transform: scale(0, 0); border-radius: 50%; background: $radio-color; .mdl-radio.is-checked & { - transform: scale3d(1, 1, 1); + transform: scale(1, 1); } fieldset[disabled] .mdl-radio &, diff --git a/src/radio/radio.js b/src/radio/radio.js index 084c6ef55..697f5d2ce 100644 --- a/src/radio/radio.js +++ b/src/radio/radio.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; @@ -82,7 +81,9 @@ var button = radios[i].querySelector('.' + this.CssClasses_.RADIO_BTN); // Different name == different group, so no point updating those. if (button.getAttribute('name') === this.btnElement_.getAttribute('name')) { - radios[i]['MaterialRadio'].updateClasses_(); + if (typeof radios[i]['MaterialRadio'] !== 'undefined') { + radios[i]['MaterialRadio'].updateClasses_(); + } } } }; diff --git a/src/ripple/ripple.js b/src/ripple/ripple.js index c39ed8ad1..ead5832ec 100644 --- a/src/ripple/ripple.js +++ b/src/ripple/ripple.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; @@ -102,8 +101,8 @@ x = Math.round(bound.width / 2); y = Math.round(bound.height / 2); } else { - var clientX = event.clientX ? event.clientX : event.touches[0].clientX; - var clientY = event.clientY ? event.clientY : event.touches[0].clientY; + var clientX = event.clientX !== undefined ? event.clientX : event.touches[0].clientX; + var clientY = event.clientY !== undefined ? event.clientY : event.touches[0].clientY; x = Math.round(clientX - bound.left); y = Math.round(clientY - bound.top); } diff --git a/src/slider/slider.js b/src/slider/slider.js index b34b8b6ba..b37267993 100644 --- a/src/slider/slider.js +++ b/src/slider/slider.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; @@ -83,16 +82,6 @@ this.updateValueStyles_(); }; - /** - * Handle mouseup on element. - * - * @param {Event} event The event that fired. - * @private - */ - MaterialSlider.prototype.onMouseUp_ = function(event) { - event.target.blur(); - }; - /** * Handle mousedown on container element. * This handler is purpose is to not require the use to click @@ -221,11 +210,9 @@ this.boundInputHandler = this.onInput_.bind(this); this.boundChangeHandler = this.onChange_.bind(this); - this.boundMouseUpHandler = this.onMouseUp_.bind(this); this.boundContainerMouseDownHandler = this.onContainerMouseDown_.bind(this); this.element_.addEventListener('input', this.boundInputHandler); this.element_.addEventListener('change', this.boundChangeHandler); - this.element_.addEventListener('mouseup', this.boundMouseUpHandler); this.element_.parentElement.addEventListener('mousedown', this.boundContainerMouseDownHandler); this.updateValueStyles_(); diff --git a/src/snackbar/snackbar.js b/src/snackbar/snackbar.js index 7a855abf3..92a2a5236 100644 --- a/src/snackbar/snackbar.js +++ b/src/snackbar/snackbar.js @@ -38,6 +38,7 @@ this.actionHandler_ = undefined; this.message_ = undefined; this.actionText_ = undefined; + this.timeoutID_ = undefined; this.queuedNotifications_ = []; this.setActionHidden_(true); }; @@ -86,7 +87,7 @@ this.textElement_.textContent = this.message_; this.element_.classList.add(this.cssClasses_.ACTIVE); this.element_.setAttribute('aria-hidden', 'false'); - setTimeout(this.cleanup_.bind(this), this.timeout_); + this.timeoutID_ = setTimeout(this.cleanup_.bind(this), this.timeout_); }; @@ -127,7 +128,21 @@ } }; MaterialSnackbar.prototype['showSnackbar'] = MaterialSnackbar.prototype.showSnackbar; - + /** + * Hide the snackbar. + * + * @public + */ + MaterialSnackbar.prototype.hideSnackbar = function() { + if (!this.active) { + return; + } + if (typeof this.timeoutID_ === 'number') { + clearTimeout(this.timeoutID_); + this.cleanup_(); + } + }; + MaterialSnackbar.prototype['hideSnackbar'] = MaterialSnackbar.prototype.hideSnackbar; /** * Check if the queue has items within it. * If it does, display the next entry. @@ -158,6 +173,7 @@ this.actionHandler_ = undefined; this.message_ = undefined; this.actionText_ = undefined; + this.timeoutID_ = undefined; this.active = false; this.checkQueue_(); }.bind(this), /** @type {number} */ (this.Constant_.ANIMATION_LENGTH)); diff --git a/src/spinner/_spinner.scss b/src/spinner/_spinner.scss index 34ac0dfca..602e597df 100644 --- a/src/spinner/_spinner.scss +++ b/src/spinner/_spinner.scss @@ -192,6 +192,14 @@ overflow: hidden; border-color: inherit; + &.mdl-spinner__left { + float: left; + } + + &.mdl-spinner__right { + float: right; + } + & .mdl-spinner__circle { width: 200%; } diff --git a/src/spinner/spinner.js b/src/spinner/spinner.js index 8159fb303..54f24af23 100644 --- a/src/spinner/spinner.js +++ b/src/spinner/spinner.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; diff --git a/src/switch/switch.js b/src/switch/switch.js index e71a591ed..ab4006e32 100644 --- a/src/switch/switch.js +++ b/src/switch/switch.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; diff --git a/src/tabs/_tabs.scss b/src/tabs/_tabs.scss index a9ec51d60..16ae9c207 100644 --- a/src/tabs/_tabs.scss +++ b/src/tabs/_tabs.scss @@ -69,7 +69,7 @@ left: 0px; position: absolute; background: $tab-highlight-color; - animation: border-expand 0.2s cubic-bezier(0.4, 0.0, 0.4, 1) 0.01s alternate forwards; + animation: border-expand 0.2s cubic-bezier(0.4, 0.0, 0.4, 1) alternate forwards; transition: all 1s cubic-bezier(0.4, 0.0, 1, 1); } diff --git a/src/tabs/tabs.js b/src/tabs/tabs.js index 3f4d005c7..0bb5b0aa9 100644 --- a/src/tabs/tabs.js +++ b/src/tabs/tabs.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; @@ -111,6 +110,24 @@ } }; + /** + * Set the active tab. + * + * @public + * @param {Element|number} tab The tab element or index to set active. + */ + MaterialTabs.prototype.setTab = function(tab) { + tab = (typeof tab === 'number') ? this.tabs_[tab] : tab; + if (tab && tab.getAttribute('href').charAt(0) === '#') { + var href = tab.href.split('#')[1]; + var panel = this.element_.querySelector('#' + href); + this.resetTabState_(); + this.resetPanelState_(); + tab.classList.add(this.CssClasses_.ACTIVE_CLASS); + panel.classList.add(this.CssClasses_.ACTIVE_CLASS); + } + }; + /** * Initialize element. */ @@ -140,13 +157,10 @@ } tab.addEventListener('click', function(e) { - e.preventDefault(); - var href = tab.href.split('#')[1]; - var panel = ctx.element_.querySelector('#' + href); - ctx.resetTabState_(); - ctx.resetPanelState_(); - tab.classList.add(ctx.CssClasses_.ACTIVE_CLASS); - panel.classList.add(ctx.CssClasses_.ACTIVE_CLASS); + if (tab.getAttribute('href').charAt(0) === '#') { + e.preventDefault(); + ctx.setTab(tab); + } }); } diff --git a/src/textfield/textfield.js b/src/textfield/textfield.js index 23883f3d1..1ee036eb5 100644 --- a/src/textfield/textfield.js +++ b/src/textfield/textfield.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; @@ -176,7 +175,10 @@ * @public */ MaterialTextfield.prototype.checkDirty = function() { - if (this.input_.value && this.input_.value.length > 0) { + if ( + (this.input_.value && this.input_.value.length > 0) || + (this.input_.placeholder.trim() !== '') + ) { this.element_.classList.add(this.CssClasses_.IS_DIRTY); } else { this.element_.classList.remove(this.CssClasses_.IS_DIRTY); diff --git a/src/third_party/rAF.js b/src/third_party/rAF.js index d2e8d7774..863f561fd 100644 --- a/src/third_party/rAF.js +++ b/src/third_party/rAF.js @@ -9,42 +9,42 @@ // MIT license (function() { -'use strict'; + 'use strict'; -if (!Date.now) { - /** - * Date.now polyfill. - * @return {number} the current Date - */ - Date.now = function() { return new Date().getTime(); }; - Date['now'] = Date.now; -} + if (!Date.now) { + /** + * Date.now polyfill. + * @return {number} the current Date + */ + Date.now = function() { return new Date().getTime(); }; + Date['now'] = Date.now; + } -var vendors = ['webkit', 'moz']; -for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { - var vp = vendors[i]; - window.requestAnimationFrame = window[vp + 'RequestAnimationFrame']; - window.cancelAnimationFrame = (window[vp + 'CancelAnimationFrame'] || - window[vp + 'CancelRequestAnimationFrame']); - window['requestAnimationFrame'] = window.requestAnimationFrame; - window['cancelAnimationFrame'] = window.cancelAnimationFrame; -} + var vendors = ['webkit', 'moz']; + for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { + var vp = vendors[i]; + window.requestAnimationFrame = window[vp + 'RequestAnimationFrame']; + window.cancelAnimationFrame = (window[vp + 'CancelAnimationFrame'] || + window[vp + 'CancelRequestAnimationFrame']); + window['requestAnimationFrame'] = window.requestAnimationFrame; + window['cancelAnimationFrame'] = window.cancelAnimationFrame; + } -if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) { - var lastTime = 0; - /** - * requestAnimationFrame polyfill. - * @param {!Function} callback the callback function. - */ - window.requestAnimationFrame = function(callback) { - var now = Date.now(); - var nextTime = Math.max(lastTime + 16, now); - return setTimeout(function() { callback(lastTime = nextTime); }, - nextTime - now); - }; - window.cancelAnimationFrame = clearTimeout; - window['requestAnimationFrame'] = window.requestAnimationFrame; - window['cancelAnimationFrame'] = window.cancelAnimationFrame; -} + if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) { + var lastTime = 0; + /** + * requestAnimationFrame polyfill. + * @param {!Function} callback the callback function. + */ + window.requestAnimationFrame = function(callback) { + var now = Date.now(); + var nextTime = Math.max(lastTime + 16, now); + return setTimeout(function() { callback(lastTime = nextTime); }, + nextTime - now); + }; + window.cancelAnimationFrame = clearTimeout; + window['requestAnimationFrame'] = window.requestAnimationFrame; + window['cancelAnimationFrame'] = window.cancelAnimationFrame; + } })(); diff --git a/src/tooltip/tooltip.js b/src/tooltip/tooltip.js index bfdacca2f..54fda9c9e 100644 --- a/src/tooltip/tooltip.js +++ b/src/tooltip/tooltip.js @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - (function() { 'use strict'; diff --git a/templates/dashboard/styles.css b/templates/dashboard/styles.css index bf1f748ee..5e5fcc827 100644 --- a/templates/dashboard/styles.css +++ b/templates/dashboard/styles.css @@ -22,13 +22,6 @@ html, body { height: 48px; border-radius: 24px; } -.demo-layout .demo-header .mdl-textfield { - padding: 0px; - margin-top: 41px; -} -.demo-layout .demo-header .mdl-textfield .mdl-textfield__expandable-holder { - bottom: 19px; -} .demo-layout .mdl-layout__header .mdl-layout__drawer-button { color: rgba(0, 0, 0, 0.54); } diff --git a/test/unit/data-table.js b/test/unit/data-table.js index 65a63d2d6..2821f8a45 100644 --- a/test/unit/data-table.js +++ b/test/unit/data-table.js @@ -14,48 +14,49 @@ * limitations under the License. */ -/*global describe, it, expect, MaterialDataTable, componentHandler */ +var TABLE_TEMPLATE = '' + + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + + '
    MaterialQuantityUnit price
    Acrylic (Transparent)25$2.90
    Plywood (Birch)50$1.25
    '; describe('MaterialDataTable', function () { - function createTable() { - var table = document.createElement('table'); - table.classList.add('mdl-data-table'); - table.classList.add('mdl-js-data-table'); - - table.createTHead(); - var headTh = document.createElement('th'); - table.querySelector('thead').appendChild(headTh); - - var tBodyRow = table.insertRow(0); - tBodyRow.insertCell(0); - - return table; - } - it('should be globally available', function () { expect(MaterialDataTable).to.be.a('function'); }); it('should upgrade successfully', function () { - var table = createTable(); + var el = document.createElement('div'); + el.innerHTML = TABLE_TEMPLATE; - componentHandler.upgradeElement(table, 'MaterialDataTable'); - expect($(table)).to.have.data('upgraded', ',MaterialDataTable'); + componentHandler.upgradeElement(el, 'MaterialDataTable'); + expect($(el)).to.have.data('upgraded', ',MaterialDataTable'); }); it('should have is-checked class when the row has the is-selected class', function () { - var table = createTable(); - table.classList.add('mdl-data-table--selectable'); - var row = table.insertRow(); - row.classList.add('is-selected'); - row.insertCell(); - - document.body.appendChild(table); - + var el = document.createElement('div'); + el.innerHTML = TABLE_TEMPLATE; + document.body.appendChild(el); + table = document.querySelector('#data-table-test') componentHandler.upgradeElement(table, 'MaterialDataTable'); - expect(table.querySelector('tbody:nth-child(2) label').classList.contains('is-checked')).to.be.true; - document.body.removeChild(table); + expect(table.querySelector('.second-row label').classList.contains('is-checked')).to.be.true; }); -}); +}); \ No newline at end of file diff --git a/test/unit/layout.js b/test/unit/layout.js index 8a9d53bf9..688314f45 100644 --- a/test/unit/layout.js +++ b/test/unit/layout.js @@ -16,6 +16,33 @@ describe('MaterialLayout', function () { + MockMediaQueryList = function(media) { + this.media = media; + this.listeners = []; + } + + MockMediaQueryList.registry = {}; + + MockMediaQueryList.mockMatchMedia = function(query) { + if (! MockMediaQueryList.registry.hasOwnProperty(query)) { + MockMediaQueryList.registry[query] = new MockMediaQueryList(query); + } + return MockMediaQueryList.registry[query]; + } + + MockMediaQueryList.prototype.addListener = function(listener) { + this.listeners.push(listener); + } + + MockMediaQueryList.prototype.triggerMatch = function(matches) { + this.matches = matches; + this.listeners.forEach(function(listener) { + // PhantomJS doesn't support MediaQueryListEvent() so mock the event. + var event = {media: this.media, matches: this.matches}; + listener(event); + }.bind(this)); + } + it('should be globally available', function () { expect(MaterialLayout).to.be.a('function'); }); @@ -99,13 +126,18 @@ describe('MaterialLayout', function () { }); describe('Drawer', function () { + var el; var drawer, drawerBtn; var navLink; beforeEach(function() { - var el = document.createElement('div'); + this.originalMatchMedia = window.MaterialLayout.prototype.matchMedia_; + window.MaterialLayout.prototype.matchMedia_ = MockMediaQueryList.mockMatchMedia; + window.patched = 'yes patched'; + + el = document.createElement('div'); el.innerHTML = '
    ' + - '