diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000000..d60776a4c2
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,265 @@
+{
+ "extends": "eslint:recommended",
+ "rules": {
+ "accessor-pairs": "error",
+ "array-bracket-newline": "off",
+ "array-bracket-spacing": "off",
+ "array-callback-return": "error",
+ "array-element-newline": "off",
+ "arrow-body-style": "error",
+ "arrow-parens": "error",
+ "arrow-spacing": "error",
+ "block-scoped-var": "off",
+ "block-spacing": "off",
+ "brace-style": "off",
+ "callback-return": "off",
+ "camelcase": "off",
+ "capitalized-comments": "off",
+ "class-methods-use-this": "error",
+ "comma-dangle": "off",
+ "comma-spacing": "off",
+ "comma-style": [
+ "error",
+ "last"
+ ],
+ "complexity": "off",
+ "computed-property-spacing": "off",
+ "consistent-return": "off",
+ "consistent-this": "off",
+ "curly": "off",
+ "default-case": "off",
+ "dot-location": "off",
+ "dot-notation": "off",
+ "eol-last": "off",
+ "eqeqeq": "off",
+ "for-direction": "error",
+ "func-call-spacing": "off",
+ "func-name-matching": "off",
+ "func-names": "off",
+ "func-style": "off",
+ "generator-star-spacing": "error",
+ "getter-return": "error",
+ "global-require": "error",
+ "guard-for-in": "off",
+ "handle-callback-err": "error",
+ "id-blacklist": "error",
+ "id-length": "off",
+ "id-match": "error",
+ "indent": "off",
+ "indent-legacy": "off",
+ "init-declarations": "off",
+ "jsx-quotes": "error",
+ "key-spacing": "off",
+ "keyword-spacing": "off",
+ "line-comment-position": "off",
+ "linebreak-style": "off",
+ "lines-around-comment": "off",
+ "lines-around-directive": "off",
+ "max-depth": "error",
+ "max-len": "off",
+ "max-lines": "off",
+ "max-nested-callbacks": "error",
+ "max-params": "off",
+ "max-statements": "off",
+ "max-statements-per-line": "off",
+ "multiline-ternary": "off",
+ "new-parens": "error",
+ "newline-after-var": "off",
+ "newline-before-return": "off",
+ "newline-per-chained-call": "off",
+ "no-alert": "off",
+ "no-array-constructor": "error",
+ "no-await-in-loop": "error",
+ "no-bitwise": "off",
+ "no-buffer-constructor": "error",
+ "no-caller": "error",
+ "no-catch-shadow": "error",
+ "no-confusing-arrow": "error",
+ "no-constant-condition": [
+ "error",
+ {
+ "checkLoops": false
+ }
+ ],
+ "no-continue": "off",
+ "no-div-regex": "error",
+ "no-duplicate-imports": "error",
+ "no-else-return": "off",
+ "no-empty-function": "off",
+ "no-eq-null": "off",
+ "no-eval": "error",
+ "no-extend-native": "off",
+ "no-extra-bind": "off",
+ "no-extra-label": "error",
+ "no-extra-parens": "off",
+ "no-floating-decimal": "error",
+ "no-implicit-coercion": [
+ "error",
+ {
+ "boolean": false,
+ "number": false,
+ "string": false
+ }
+ ],
+ "no-implicit-globals": "off",
+ "no-implied-eval": "error",
+ "no-inline-comments": "off",
+ "no-inner-declarations": [
+ "error",
+ "functions"
+ ],
+ "no-invalid-this": "off",
+ "no-iterator": "error",
+ "no-label-var": "error",
+ "no-labels": "error",
+ "no-lone-blocks": "error",
+ "no-lonely-if": "off",
+ "no-loop-func": "error",
+ "no-magic-numbers": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-requires": "error",
+ "no-multi-assign": "off",
+ "no-multi-spaces": "off",
+ "no-multi-str": "off",
+ "no-multiple-empty-lines": "off",
+ "no-native-reassign": "error",
+ "no-negated-condition": "off",
+ "no-negated-in-lhs": "error",
+ "no-nested-ternary": "off",
+ "no-new": "error",
+ "no-new-func": "error",
+ "no-new-object": "error",
+ "no-new-require": "error",
+ "no-new-wrappers": "error",
+ "no-octal-escape": "error",
+ "no-param-reassign": "off",
+ "no-path-concat": "error",
+ "no-plusplus": "off",
+ "no-process-env": "error",
+ "no-process-exit": "error",
+ "no-proto": "error",
+ "no-prototype-builtins": "off",
+ "no-restricted-globals": "error",
+ "no-restricted-imports": "error",
+ "no-restricted-modules": "error",
+ "no-restricted-properties": "error",
+ "no-restricted-syntax": "error",
+ "no-return-assign": "off",
+ "no-return-await": "error",
+ "no-script-url": "error",
+ "no-self-compare": "error",
+ "no-sequences": "off",
+ "no-shadow": "off",
+ "no-shadow-restricted-names": "error",
+ "no-spaced-func": "off",
+ "no-sync": "error",
+ "no-tabs": "off",
+ "no-template-curly-in-string": "error",
+ "no-ternary": "off",
+ "no-throw-literal": "off",
+ "no-trailing-spaces": "off",
+ "no-undef-init": "error",
+ "no-undefined": "off",
+ "no-underscore-dangle": "off",
+ "no-unmodified-loop-condition": "error",
+ "no-unneeded-ternary": "off",
+ "no-unused-expressions": "off",
+ "no-use-before-define": "off",
+ "no-useless-call": "error",
+ "no-useless-computed-key": "error",
+ "no-useless-concat": "off",
+ "no-useless-constructor": "error",
+ "no-useless-rename": "error",
+ "no-useless-return": "error",
+ "no-var": "off",
+ "no-void": "off",
+ "no-warning-comments": "off",
+ "no-whitespace-before-property": "error",
+ "no-with": "error",
+ "nonblock-statement-body-position": [
+ "error",
+ "any"
+ ],
+ "object-curly-newline": "off",
+ "object-curly-spacing": "off",
+ "object-property-newline": "off",
+ "object-shorthand": "off",
+ "one-var": "off",
+ "one-var-declaration-per-line": "off",
+ "operator-assignment": "off",
+ "operator-linebreak": "off",
+ "padded-blocks": "off",
+ "padding-line-between-statements": "error",
+ "prefer-arrow-callback": "off",
+ "prefer-const": "error",
+ "prefer-destructuring": "off",
+ "prefer-numeric-literals": "error",
+ "prefer-promise-reject-errors": "error",
+ "prefer-reflect": "off",
+ "prefer-rest-params": "off",
+ "prefer-spread": "off",
+ "prefer-template": "off",
+ "quote-props": "off",
+ "quotes": "off",
+ "radix": "off",
+ "require-await": "error",
+ "require-jsdoc": "off",
+ "rest-spread-spacing": "error",
+ "semi": "off",
+ "semi-spacing": "off",
+ "semi-style": "off",
+ "sort-imports": "error",
+ "sort-keys": "off",
+ "sort-vars": "off",
+ "space-before-blocks": "off",
+ "space-before-function-paren": "off",
+ "space-in-parens": "off",
+ "space-infix-ops": "off",
+ "space-unary-ops": "off",
+ "spaced-comment": "off",
+ "strict": "off",
+ "switch-colon-spacing": "off",
+ "symbol-description": "error",
+ "template-curly-spacing": "error",
+ "template-tag-spacing": "error",
+ "unicode-bom": [
+ "error",
+ "never"
+ ],
+ "valid-jsdoc": "off",
+ "vars-on-top": "off",
+ "wrap-iife": "off",
+ "wrap-regex": "off",
+ "yield-star-spacing": "error",
+ "yoda": "off",
+ "no-unused-vars": "off",
+ "no-cond-assign": "off",
+ "no-unexpected-multiline": "off"
+ },
+ "globals": {
+ "angular": true
+ },
+ "overrides": [
+ {
+ "files": ["**/*.spec.js"],
+ "env": {
+ "browser": true,
+ "jasmine": true
+ },
+ "rules": {
+ "no-native-reassign": "off",
+ "no-global-assign": "off"
+ },
+ "globals": {
+ "module": true,
+ "inject": true,
+ "disableAnimations": true,
+ "createMockStyleSheet": true,
+ "$mdUtil": false,
+ "$timeout": false,
+ "$animate": false,
+ "$material": false
+ }
+ }
+ ]
+}
diff --git a/.travis.yml b/.travis.yml
index 98900dda74..5c49bdffb8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,6 +28,7 @@ jobs:
- env: "NG_VERSION=1.5"
- env: "NG_VERSION=1.6"
- env: "NG_VERSION=snapshot"
+ - env: "RUN_LINT=true"
- stage: Deploy
script: ./scripts/travis-build-init.sh --sha=$TRAVIS_COMMIT
env: "MODE=release"
diff --git a/package.json b/package.json
index 61a3ad5dfb..9d572bc8c7 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"conventional-changelog": "^1.1.0",
"dgeni": "^0.4.1",
"dgeni-packages": "^0.13.0",
+ "eslint": "^4.3.0",
"github-contributors-list": "^1.2.1",
"glob": "~7.0.5",
"gulp": "^3.9.1",
@@ -83,6 +84,7 @@
"docs:build": "gulp docs",
"docs:watch": "gulp watch site --dev",
"test:fast": "gulp karma-fast",
- "test:full": "gulp karma"
+ "test:full": "gulp karma",
+ "lint": "eslint src"
}
-}
\ No newline at end of file
+}
diff --git a/scripts/travis-run-script.sh b/scripts/travis-run-script.sh
index 6aa48c2620..6007af7369 100755
--- a/scripts/travis-run-script.sh
+++ b/scripts/travis-run-script.sh
@@ -6,6 +6,11 @@ set -xe
# Ensure that scripts will run from project dir.
cd $(dirname $0)/..
+if [[ -n "$RUN_LINT" ]]; then
+ npm run lint
+ exit
+fi
+
# When Travis CI specifies an AngularJS version, try to install those for tests.
if [[ -n "$NG_VERSION" ]]; then
./scripts/fetch-angular-version.sh "$NG_VERSION"
diff --git a/src/components/autocomplete/demoBasicUsage/index.html b/src/components/autocomplete/demoBasicUsage/index.html
index c23b66cc0f..3dd4dad474 100644
--- a/src/components/autocomplete/demoBasicUsage/index.html
+++ b/src/components/autocomplete/demoBasicUsage/index.html
@@ -18,7 +18,7 @@
No states matching "{{ctrl.searchText}}" were found.
- Create a new one!
+ Create a new one!
diff --git a/src/components/autocomplete/demoBasicUsage/script.js b/src/components/autocomplete/demoBasicUsage/script.js
index 35b757d69d..d6af45ec62 100644
--- a/src/components/autocomplete/demoBasicUsage/script.js
+++ b/src/components/autocomplete/demoBasicUsage/script.js
@@ -4,7 +4,7 @@
.module('autocompleteDemo', ['ngMaterial'])
.controller('DemoCtrl', DemoCtrl);
- function DemoCtrl ($timeout, $q, $log) {
+ function DemoCtrl ($timeout, $q, $log, $mdDialog) {
var self = this;
self.simulateQuery = false;
@@ -18,8 +18,14 @@
self.newState = newState;
- function newState(state) {
- alert("Sorry! You'll need to create a Constitution for " + state + " first!");
+ function newState(state, $event) {
+ $mdDialog.show(
+ $mdDialog
+ .alert()
+ .title('state creation failed.')
+ .textContent("Sorry! You'll need to create a Constitution for " + state + " first!")
+ .targetEvent($event)
+ );
}
// ******************************
diff --git a/src/components/autocomplete/demoInsideDialog/script.js b/src/components/autocomplete/demoInsideDialog/script.js
index d794b650a2..449e407ac3 100644
--- a/src/components/autocomplete/demoInsideDialog/script.js
+++ b/src/components/autocomplete/demoInsideDialog/script.js
@@ -4,7 +4,7 @@
.module('autocompleteDemoInsideDialog', ['ngMaterial'])
.controller('DemoCtrl', DemoCtrl);
- function DemoCtrl($mdDialog) {
+ function DemoCtrl($mdDialog, $document) {
var self = this;
self.openDialog = function($event) {
@@ -12,7 +12,7 @@
controller: DialogCtrl,
controllerAs: 'ctrl',
templateUrl: 'dialog.tmpl.html',
- parent: angular.element(document.body),
+ parent: $document.find('body'),
targetEvent: $event,
clickOutsideToClose:true
})
diff --git a/src/components/autocomplete/js/autocompleteController.js b/src/components/autocomplete/js/autocompleteController.js
index c68f88367a..a505dd4996 100644
--- a/src/components/autocomplete/js/autocompleteController.js
+++ b/src/components/autocomplete/js/autocompleteController.js
@@ -8,7 +8,8 @@ var ITEM_HEIGHT = 48,
INPUT_PADDING = 2; // Padding provided by `md-input-container`
function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming, $window,
- $animate, $rootElement, $attrs, $q, $log, $mdLiveAnnouncer) {
+ $animate, $rootElement, $attrs, $q, $log, $mdLiveAnnouncer,
+ $document) {
// Internal Variables.
var ctrl = this,
@@ -22,7 +23,8 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming,
fetchesInProgress = 0,
enableWrapScroll = null,
inputModelCtrl = null,
- debouncedOnResize = $mdUtil.debounce(onWindowResize);
+ debouncedOnResize = $mdUtil.debounce(onWindowResize),
+ document = $document[0];
// Public Exported Variables with handlers
defineProperty('hidden', handleHiddenChange, true);
diff --git a/src/components/autocomplete/js/highlightController.js b/src/components/autocomplete/js/highlightController.js
index a0352fabe3..f424d8d853 100644
--- a/src/components/autocomplete/js/highlightController.js
+++ b/src/components/autocomplete/js/highlightController.js
@@ -2,10 +2,11 @@ angular
.module('material.components.autocomplete')
.controller('MdHighlightCtrl', MdHighlightCtrl);
-function MdHighlightCtrl ($scope, $element, $attrs) {
+function MdHighlightCtrl ($scope, $element, $attrs, $document) {
this.$scope = $scope;
this.$element = $element;
this.$attrs = $attrs;
+ this.$document = $document;
// Cache the Regex to avoid rebuilding each time.
this.regex = null;
@@ -64,7 +65,7 @@ MdHighlightCtrl.prototype.applyRegex = function(text) {
this.$element.append(tokenEl);
} else {
- this.$element.append(document.createTextNode(token));
+ this.$element.append(this.$document[0].createTextNode(token));
}
}.bind(this));
@@ -109,10 +110,10 @@ MdHighlightCtrl.prototype.createRegex = function(term, flags) {
if (flags.indexOf('^') >= 0) startFlag = '^';
if (flags.indexOf('$') >= 0) endFlag = '$';
- return new RegExp(startFlag + regexTerm + endFlag, flags.replace(/[$\^]/g, ''));
+ return new RegExp(startFlag + regexTerm + endFlag, flags.replace(/[$^]/g, ''));
};
/** Sanitizes a regex by removing all common RegExp identifiers */
MdHighlightCtrl.prototype.sanitizeRegex = function(term) {
- return term && term.toString().replace(/[\\\^\$\*\+\?\.\(\)\|\{}\[\]]/g, '\\$&');
+ return term && term.toString().replace(/[\\^$*+?.()|{}[\]]/g, '\\$&');
};
diff --git a/src/components/chips/demoContactChips/index.html b/src/components/chips/demoContactChips/index.html
index a0fbcad628..6662c9663c 100644
--- a/src/components/chips/demoContactChips/index.html
+++ b/src/components/chips/demoContactChips/index.html
@@ -1,6 +1,6 @@
-
+
*
*/
-function GridListDirective($interpolate, $mdConstant, $mdGridLayout, $mdMedia) {
+function GridListDirective($interpolate, $mdConstant, $mdGridLayout, $mdMedia, $document) {
return {
restrict: 'E',
controller: GridListController,
@@ -270,6 +270,7 @@ function GridListDirective($interpolate, $mdConstant, $mdGridLayout, $mdMedia) {
// The width and horizontal position of each tile is always calculated the same way, but the
// height and vertical position depends on the rowMode.
+ var document = $document[0];
var ltr = document.dir != 'rtl' && document.body.dir != 'rtl';
var style = ltr ? {
left: POSITION({ unit: hUnit, offset: position.col, gutter: gutter }),
@@ -316,10 +317,10 @@ function GridListDirective($interpolate, $mdConstant, $mdGridLayout, $mdMedia) {
var vGutterShare = (rowCount - 1) / rowCount;
// Percent of the available vertical space that one row takes up.
- var vShare = (1 / rowCount) * 100;
+ vShare = (1 / rowCount) * 100;
// Base vertical size of a row.
- var vUnit = UNIT({share: vShare, gutterShare: vGutterShare, gutter: gutter});
+ vUnit = UNIT({share: vShare, gutterShare: vGutterShare, gutter: gutter});
style.top = POSITION({unit: vUnit, offset: position.row, gutter: gutter});
style.height = DIMENSION({unit: vUnit, span: spans.row, gutter: gutter});
diff --git a/src/components/icon/icon.spec.js b/src/components/icon/icon.spec.js
index 5f57e644a4..39dbfe46b5 100644
--- a/src/components/icon/icon.spec.js
+++ b/src/components/icon/icon.spec.js
@@ -385,7 +385,7 @@ describe('MdIcon directive', function() {
return style
.replace(/ng-scope|ng-isolate-scope|md-default-theme/gi,'')
.replace(/\s\s+/g,' ')
- .replace(/\s+\"/g,'"')
+ .replace(/\s+"/g,'"')
.trim();
}
diff --git a/src/components/icon/js/iconService.js b/src/components/icon/js/iconService.js
index 0832c1f11b..bd1f9c9fe9 100644
--- a/src/components/icon/js/iconService.js
+++ b/src/components/icon/js/iconService.js
@@ -9,7 +9,7 @@
'mdCalendar': 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTkgM2gtMVYxaC0ydjJIOFYxSDZ2Mkg1Yy0xLjExIDAtMS45OS45LTEuOTkgMkwzIDE5YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjVjMC0xLjEtLjktMi0yLTJ6bTAgMTZINVY4aDE0djExek03IDEwaDV2NUg3eiIvPjwvc3ZnPg==',
'mdChecked': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz48L2c+PC9zdmc+'
})
- .provider('$mdIcon', MdIconProvider);
+ .provider('$mdIcon', mdIconProvider);
/**
* @ngdoc service
@@ -277,75 +277,78 @@
*
*/
-var config = {
- defaultViewBoxSize: 24,
- defaultFontSet: 'material-icons',
- fontSets: []
-};
+function mdIconProvider() {
+ var config = {
+ defaultViewBoxSize: 24,
+ defaultFontSet: 'material-icons',
+ fontSets: []
+ };
-function MdIconProvider() {
-}
-
-MdIconProvider.prototype = {
- icon: function(id, url, viewBoxSize) {
- if (id.indexOf(':') == -1) id = '$default:' + id;
-
- config[id] = new ConfigurationItem(url, viewBoxSize);
- return this;
- },
-
- iconSet: function(id, url, viewBoxSize) {
- config[id] = new ConfigurationItem(url, viewBoxSize);
- return this;
- },
+ function configItem(url, viewBoxSize) {
+ return new ConfigurationItem(url, viewBoxSize || config.defaultViewBoxSize);
+ }
- defaultIconSet: function(url, viewBoxSize) {
- var setName = '$default';
+ return {
+ icon: function(id, url, viewBoxSize) {
+ if (id.indexOf(':') == -1) id = '$default:' + id;
- if (!config[setName]) {
- config[setName] = new ConfigurationItem(url, viewBoxSize);
- }
+ config[id] = configItem(url, viewBoxSize);
+ return this;
+ },
- config[setName].viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
+ iconSet: function(id, url, viewBoxSize) {
+ config[id] = configItem(url, viewBoxSize);
+ return this;
+ },
- return this;
- },
+ defaultIconSet: function(url, viewBoxSize) {
+ var setName = '$default';
- defaultViewBoxSize: function(viewBoxSize) {
- config.defaultViewBoxSize = viewBoxSize;
- return this;
- },
+ if (!config[setName]) {
+ config[setName] = configItem(url, viewBoxSize);
+ }
- /**
- * Register an alias name associated with a font-icon library style ;
- */
- fontSet: function fontSet(alias, className) {
- config.fontSets.push({
- alias: alias,
- fontSet: className || alias
- });
- return this;
- },
+ config[setName].viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
- /**
- * Specify a default style name associated with a font-icon library
- * fallback to Material Icons.
- *
- */
- defaultFontSet: function defaultFontSet(className) {
- config.defaultFontSet = !className ? '' : className;
- return this;
- },
+ return this;
+ },
- defaultIconSize: function defaultIconSize(iconSize) {
- config.defaultIconSize = iconSize;
- return this;
- },
+ defaultViewBoxSize: function(viewBoxSize) {
+ config.defaultViewBoxSize = viewBoxSize;
+ return this;
+ },
- $get: ['$templateRequest', '$q', '$log', '$mdUtil', '$sce', function($templateRequest, $q, $log, $mdUtil, $sce) {
- return MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce);
- }]
-};
+ /**
+ * Register an alias name associated with a font-icon library style ;
+ */
+ fontSet: function fontSet(alias, className) {
+ config.fontSets.push({
+ alias: alias,
+ fontSet: className || alias
+ });
+ return this;
+ },
+
+ /**
+ * Specify a default style name associated with a font-icon library
+ * fallback to Material Icons.
+ *
+ */
+ defaultFontSet: function defaultFontSet(className) {
+ config.defaultFontSet = !className ? '' : className;
+ return this;
+ },
+
+ defaultIconSize: function defaultIconSize(iconSize) {
+ config.defaultIconSize = iconSize;
+ return this;
+ },
+
+ $get: ['$injector', function($injector) {
+ return $injector.invoke(mdIconService, undefined, { config: config });
+ }]
+ };
+}
/**
* Configuration item stored in the Icon registry; used for lookups
@@ -353,7 +356,7 @@ MdIconProvider.prototype = {
*/
function ConfigurationItem(url, viewBoxSize) {
this.url = url;
- this.viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
+ this.viewBoxSize = viewBoxSize;
}
/**
@@ -400,11 +403,11 @@ function ConfigurationItem(url, viewBoxSize) {
*/
/* @ngInject */
-function MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce) {
+function mdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce, $window) {
var iconCache = {};
var svgCache = {};
- var urlRegex = /[-\w@:%\+.~#?&//=]{2,}\.[a-z]{2,4}\b(\/[-\w@:%\+.~#?&//=]*)?/i;
- var dataUrlRegex = /^data:image\/svg\+xml[\s*;\w\-\=]*?(base64)?,(.*)$/i;
+ var urlRegex = /[-\w@:%+.~#?&//=]{2,}\.[a-z]{2,4}\b(\/[-\w@:%+.~#?&//=]*)?/i;
+ var dataUrlRegex = /^data:image\/svg\+xml[\s*;\w\-=]*?(base64)?,(.*)$/i;
Icon.prototype = {clone: cloneSVG, prepare: prepareAndStyle};
getIcon.fontSet = findRegisteredFontSet;
@@ -534,7 +537,7 @@ function MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce) {
function loadByDataUrl(url) {
var results = dataUrlRegex.exec(url);
var isBase64 = /base64/i.test(url);
- var data = isBase64 ? window.atob(results[2]) : results[2];
+ var data = isBase64 ? $window.atob(results[2]) : results[2];
return $q.when(angular.element(data)[0]);
}
diff --git a/src/components/input/input-animations.spec.js b/src/components/input/input-animations.spec.js
index e4d2d054e6..01f3ac5aad 100644
--- a/src/components/input/input-animations.spec.js
+++ b/src/components/input/input-animations.spec.js
@@ -1,6 +1,6 @@
describe('md-input-container animations', function() {
var $rootScope, $compile, $material, $$mdInput, $window, $animate, $rootElement, $document, $timeout,
- el, root, body, pageScope, computedStyle;
+ el, root, body, pageScope, computedStyle, invalidAnimation, messagesAnimation, messageAnimation;
// Load our modules
beforeEach(module('ngAnimate', 'ngMessages', 'material.components.input', 'material.components.checkbox'));
diff --git a/src/components/input/input.js b/src/components/input/input.js
index f904a847ab..7c0b95829c 100644
--- a/src/components/input/input.js
+++ b/src/components/input/input.js
@@ -1,8 +1,17 @@
+function mockService(service) {
+ return ['$injector', '$window', (function ($injector, $window) {
+ if (!$window._mdMocksIncluded) {
+ return;
+ }
+ return $injector.invoke(service);
+ })];
+}
+
/**
* @ngdoc module
* @name material.components.input
*/
-var inputModule = angular.module('material.components.input', [
+angular.module('material.components.input', [
'material.core'
])
.directive('mdInputContainer', mdInputContainerDirective)
@@ -18,26 +27,27 @@ var inputModule = angular.module('material.components.input', [
.animation('.md-input-invalid', mdInputInvalidMessagesAnimation)
.animation('.md-input-messages-animation', ngMessagesAnimation)
- .animation('.md-input-message-animation', ngMessageAnimation);
-
-// If we are running inside of tests; expose some extra services so that we can test them
-if (window._mdMocksIncluded) {
- inputModule.service('$$mdInput', function() {
+ .animation('.md-input-message-animation', ngMessageAnimation)
+ // If we are running inside of tests; expose some extra functions so that we can test them
+ .service('$$mdInput', mockService(['$window', function($window) {
return {
// special accessor to internals... useful for testing
messages: {
- show : showInputMessages,
- hide : hideInputMessages,
+ show : function(element, done) {
+ return showInputMessages($window, element, done);
+ },
+ hide : function(element, done) {
+ return hideInputMessages($window, element, done);
+ },
getElement : getMessagesElement
}
- }
- })
+ };
+ }]))
// Register a service for each animation so that we can easily inject them into unit tests
- .service('mdInputInvalidAnimation', mdInputInvalidMessagesAnimation)
- .service('mdInputMessagesAnimation', ngMessagesAnimation)
- .service('mdInputMessageAnimation', ngMessageAnimation);
-}
+ .service('mdInputInvalidAnimation', mockService(mdInputInvalidMessagesAnimation))
+ .service('mdInputMessagesAnimation', mockService(ngMessagesAnimation))
+ .service('mdInputMessageAnimation', mockService(ngMessageAnimation));
/**
* @ngdoc directive
@@ -858,7 +868,7 @@ function ngMessagesDirective() {
}
}
-function ngMessageDirective($mdUtil) {
+function ngMessageDirective($mdUtil, $window) {
return {
restrict: 'EA',
compile: compile,
@@ -887,7 +897,7 @@ function ngMessageDirective($mdUtil) {
function isInsideFragment() {
var nextNode = tElement[0];
while (nextNode = nextNode.parentNode) {
- if (nextNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
+ if (nextNode.nodeType === $window.Node.DOCUMENT_FRAGMENT_NODE) {
return true;
}
}
@@ -907,33 +917,33 @@ function ngMessageDirective($mdUtil) {
var $$AnimateRunner, $animateCss, $mdUtil, $log;
-function mdInputInvalidMessagesAnimation($$AnimateRunner, $animateCss, $mdUtil, $log) {
+function mdInputInvalidMessagesAnimation($$AnimateRunner, $animateCss, $mdUtil, $log, $window) {
saveSharedServices($$AnimateRunner, $animateCss, $mdUtil, $log);
return {
addClass: function(element, className, done) {
- showInputMessages(element, done);
+ showInputMessages($window, element, done);
}
// NOTE: We do not need the removeClass method, because the message ng-leave animation will fire
};
}
-function ngMessagesAnimation($$AnimateRunner, $animateCss, $mdUtil, $log) {
+function ngMessagesAnimation($$AnimateRunner, $animateCss, $mdUtil, $log, $window) {
saveSharedServices($$AnimateRunner, $animateCss, $mdUtil, $log);
return {
enter: function(element, done) {
- showInputMessages(element, done);
+ showInputMessages($window, element, done);
},
leave: function(element, done) {
- hideInputMessages(element, done);
+ hideInputMessages($window, element, done);
},
addClass: function(element, className, done) {
if (className == "ng-hide") {
- hideInputMessages(element, done);
+ hideInputMessages($window, element, done);
} else {
done();
}
@@ -941,7 +951,7 @@ function ngMessagesAnimation($$AnimateRunner, $animateCss, $mdUtil, $log) {
removeClass: function(element, className, done) {
if (className == "ng-hide") {
- showInputMessages(element, done);
+ showInputMessages($window, element, done);
} else {
done();
}
@@ -949,25 +959,25 @@ function ngMessagesAnimation($$AnimateRunner, $animateCss, $mdUtil, $log) {
};
}
-function ngMessageAnimation($$AnimateRunner, $animateCss, $mdUtil, $log) {
+function ngMessageAnimation($$AnimateRunner, $animateCss, $mdUtil, $log, $window) {
saveSharedServices($$AnimateRunner, $animateCss, $mdUtil, $log);
return {
enter: function(element, done) {
- var animator = showMessage(element);
+ var animator = showMessage($window, element);
animator.start().done(done);
},
leave: function(element, done) {
- var animator = hideMessage(element);
+ var animator = hideMessage($window, element);
animator.start().done(done);
}
};
}
-function showInputMessages(element, done) {
+function showInputMessages($window, element, done) {
var animators = [], animator;
var messages = getMessagesElement(element);
var children = messages.children();
@@ -979,7 +989,7 @@ function showInputMessages(element, done) {
}
angular.forEach(children, function(child) {
- animator = showMessage(angular.element(child));
+ animator = showMessage($window, angular.element(child));
animators.push(animator.start());
});
@@ -987,7 +997,7 @@ function showInputMessages(element, done) {
$$AnimateRunner.all(animators, done);
}
-function hideInputMessages(element, done) {
+function hideInputMessages($window, element, done) {
var animators = [], animator;
var messages = getMessagesElement(element);
var children = messages.children();
@@ -999,7 +1009,7 @@ function hideInputMessages(element, done) {
}
angular.forEach(children, function(child) {
- animator = hideMessage(angular.element(child));
+ animator = hideMessage($window, angular.element(child));
animators.push(animator.start());
});
@@ -1007,9 +1017,9 @@ function hideInputMessages(element, done) {
$$AnimateRunner.all(animators, done);
}
-function showMessage(element) {
- var height = parseInt(window.getComputedStyle(element[0]).height);
- var topMargin = parseInt(window.getComputedStyle(element[0]).marginTop);
+function showMessage($window, element) {
+ var height = parseInt($window.getComputedStyle(element[0]).height);
+ var topMargin = parseInt($window.getComputedStyle(element[0]).marginTop);
var messages = getMessagesElement(element);
var container = getInputElement(element);
@@ -1031,9 +1041,9 @@ function showMessage(element) {
});
}
-function hideMessage(element) {
+function hideMessage($window, element) {
var height = element[0].offsetHeight;
- var styles = window.getComputedStyle(element[0]);
+ var styles = $window.getComputedStyle(element[0]);
// If we are already hidden, just return an empty animation
if (parseInt(styles.opacity) === 0) {
diff --git a/src/components/navBar/demoBasicUsage/index.html b/src/components/navBar/demoBasicUsage/index.html
index d30fb0dc1c..f354401a87 100644
--- a/src/components/navBar/demoBasicUsage/index.html
+++ b/src/components/navBar/demoBasicUsage/index.html
@@ -23,6 +23,7 @@
-->
+ {{status}}
External content for `{{currentNavItem}}`.
@@ -30,4 +31,4 @@
Disable Ink Bar
-
\ No newline at end of file
+
diff --git a/src/components/navBar/demoBasicUsage/script.js b/src/components/navBar/demoBasicUsage/script.js
index d1c15c0764..20c1dcb65b 100644
--- a/src/components/navBar/demoBasicUsage/script.js
+++ b/src/components/navBar/demoBasicUsage/script.js
@@ -8,7 +8,7 @@
$scope.currentNavItem = 'page1';
$scope.goto = function(page) {
- console.log("Goto " + page);
- }
+ $scope.status = "Goto " + page;
+ };
}
})();
diff --git a/src/components/panel/demoBasicUsage/script.js b/src/components/panel/demoBasicUsage/script.js
index 510b6bc87f..4b3496265c 100644
--- a/src/components/panel/demoBasicUsage/script.js
+++ b/src/components/panel/demoBasicUsage/script.js
@@ -6,8 +6,9 @@ angular.module('panelDemo', ['ngMaterial'])
.controller('PanelDialogCtrl', PanelDialogCtrl);
-function BasicDemoCtrl($mdPanel) {
+function BasicDemoCtrl($mdPanel, $document) {
this._mdPanel = $mdPanel;
+ this.$document = $document;
this.desserts = [
'Apple Pie',
@@ -24,12 +25,13 @@ function BasicDemoCtrl($mdPanel) {
BasicDemoCtrl.prototype.showDialog = function() {
+ var $document = this.$document;
var position = this._mdPanel.newPanelPosition()
.absolute()
.center();
var config = {
- attachTo: angular.element(document.body),
+ attachTo: angular.element($document[0].body),
controller: PanelDialogCtrl,
controllerAs: 'ctrl',
disableParentScroll: this.disableParentScroll,
@@ -49,12 +51,13 @@ BasicDemoCtrl.prototype.showDialog = function() {
BasicDemoCtrl.prototype.showMenu = function(ev) {
+ var $document = this.$document;
var position = this._mdPanel.newPanelPosition()
.relativeTo('.demo-menu-open-button')
.addPanelPosition(this._mdPanel.xPosition.ALIGN_START, this._mdPanel.yPosition.BELOW);
var config = {
- attachTo: angular.element(document.body),
+ attachTo: angular.element($document[0].body),
controller: PanelMenuCtrl,
controllerAs: 'ctrl',
template:
@@ -95,10 +98,11 @@ function PanelDialogCtrl(mdPanelRef) {
PanelDialogCtrl.prototype.closeDialog = function() {
+ var $document = this.$document;
var panelRef = this._mdPanelRef;
panelRef && panelRef.close().then(function() {
- angular.element(document.querySelector('.demo-dialog-open-button')).focus();
+ angular.element($document[0].querySelector('.demo-dialog-open-button')).focus();
panelRef.destroy();
});
};
@@ -106,41 +110,44 @@ PanelDialogCtrl.prototype.closeDialog = function() {
function PanelMenuCtrl(mdPanelRef, $timeout) {
+ var $document = this.$document;
this._mdPanelRef = mdPanelRef;
this.favoriteDessert = this.selected.favoriteDessert;
$timeout(function() {
- var selected = document.querySelector('.demo-menu-item.selected');
+ var selected = $document[0].querySelector('.demo-menu-item.selected');
if (selected) {
angular.element(selected).focus();
} else {
- angular.element(document.querySelectorAll('.demo-menu-item')[0]).focus();
+ angular.element($document[0].querySelectorAll('.demo-menu-item')[0]).focus();
}
});
}
PanelMenuCtrl.prototype.selectDessert = function(dessert) {
+ var $document = this.$document;
this.selected.favoriteDessert = dessert;
this._mdPanelRef && this._mdPanelRef.close().then(function() {
- angular.element(document.querySelector('.demo-menu-open-button')).focus();
+ angular.element($document[0].querySelector('.demo-menu-open-button')).focus();
});
};
PanelMenuCtrl.prototype.onKeydown = function($event, dessert) {
+ var $document = this.$document;
var handled, els, index, prevIndex, nextIndex;
switch ($event.which) {
case 38: // Up Arrow.
- els = document.querySelectorAll('.demo-menu-item');
- index = indexOf(els, document.activeElement);
+ els = $document[0].querySelectorAll('.demo-menu-item');
+ index = indexOf(els, $document[0].activeElement);
prevIndex = (index + els.length - 1) % els.length;
els[prevIndex].focus();
handled = true;
break;
case 40: // Down Arrow.
- els = document.querySelectorAll('.demo-menu-item');
- index = indexOf(els, document.activeElement);
+ els = $document[0].querySelectorAll('.demo-menu-item');
+ index = indexOf(els, $document[0].activeElement);
nextIndex = (index + 1) % els.length;
els[nextIndex].focus();
handled = true;
diff --git a/src/components/panel/demoGroups/script.js b/src/components/panel/demoGroups/script.js
index 76443ef564..f2f4b027c5 100644
--- a/src/components/panel/demoGroups/script.js
+++ b/src/components/panel/demoGroups/script.js
@@ -6,7 +6,7 @@
.controller('PanelGroupsCtrl', PanelGroupsCtrl)
.controller('PanelMenuCtrl', PanelMenuCtrl);
- function PanelGroupsCtrl($mdPanel) {
+ function PanelGroupsCtrl($mdPanel, $document) {
this.settings = {
name: 'settings',
items: [
@@ -80,7 +80,7 @@
var config = {
id: 'toolbar_' + menu.name,
- attachTo: angular.element(document.body),
+ attachTo: angular.element($document[0].body),
controller: PanelMenuCtrl,
controllerAs: 'ctrl',
template: template,
@@ -111,7 +111,7 @@
var config = {
id: 'content_' + menu.name,
- attachTo: angular.element(document.body),
+ attachTo: angular.element($document[0].body),
controller: PanelMenuCtrl,
controllerAs: 'ctrl',
template: template,
diff --git a/src/components/panel/demoPanelAnimations/script.js b/src/components/panel/demoPanelAnimations/script.js
index 1731a80a26..04135d6583 100644
--- a/src/components/panel/demoPanelAnimations/script.js
+++ b/src/components/panel/demoPanelAnimations/script.js
@@ -6,7 +6,7 @@ angular.module('panelAnimationsDemo', ['ngMaterial'])
.controller('DialogCtrl', DialogCtrl);
-function AnimationCtrl($mdPanel) {
+function AnimationCtrl($mdPanel, $document) {
this._mdPanel = $mdPanel;
this.openFrom = 'button';
this.closeTo = 'button';
@@ -26,6 +26,7 @@ AnimationCtrl.prototype.showDialog = function() {
.top();
var animation = this._mdPanel.newPanelAnimation();
+ var document = this.$document[0];
animation.duration(this.duration || this.separateDurations);
diff --git a/src/components/panel/demoPanelProvider/script.js b/src/components/panel/demoPanelProvider/script.js
index cdbe42d18e..63871a789d 100644
--- a/src/components/panel/demoPanelProvider/script.js
+++ b/src/components/panel/demoPanelProvider/script.js
@@ -17,32 +17,34 @@
* API.
*/
function PanelProviderConfig($mdPanelProvider) {
- $mdPanelProvider.definePreset('demoPreset', {
- attachTo: angular.element(document.body),
- controller: PanelMenuCtrl,
- controllerAs: 'ctrl',
- template: '' +
- '',
- panelClass: 'menu-panel-container',
- focusOnOpen: false,
- zIndex: 100,
- propagateContainerEvents: true,
- groupName: 'menus'
- });
+ $mdPanelProvider.definePreset('demoPreset', ['$document', function($document) {
+ return {
+ attachTo: angular.element($document[0].body),
+ controller: PanelMenuCtrl,
+ controllerAs: 'ctrl',
+ template: '' +
+ '',
+ panelClass: 'menu-panel-container',
+ focusOnOpen: false,
+ zIndex: 100,
+ propagateContainerEvents: true,
+ groupName: 'menus'
+ };
+ }]);
}
function PanelProviderCtrl($mdPanel) {
diff --git a/src/components/panel/panel.js b/src/components/panel/panel.js
index 4bde463344..a44fd85a63 100644
--- a/src/components/panel/panel.js
+++ b/src/components/panel/panel.js
@@ -1196,12 +1196,19 @@ MdPanelService.prototype.open = function(preset, config) {
* @returns {!Object} The preset configuration object.
*/
MdPanelService.prototype._getPresetByName = function(preset) {
- if (!this._presets[preset]) {
+ var $injector = this._$injector;
+ var v = this._presets[preset];
+ if (!v) {
throw new Error('mdPanel: The panel preset configuration that you ' +
'requested does not exist. Use the $mdPanelProvider to create a ' +
'preset before requesting one.');
}
- return this._presets[preset];
+
+ if (angular.isArray(v) || angular.isFunction(v)) {
+ return $injector.invoke(v);
+ }
+
+ return v;
};
@@ -1378,6 +1385,9 @@ function MdPanelRef(config, $injector) {
/** @private @const {!angular.$window} */
this._$window = $injector.get('$window');
+ /** @private @const {!angular.$document} */
+ this._$document = $injector.get('$document');
+
/** @private @const {!Function} */
this._$$rAF = $injector.get('$$rAF');
@@ -1662,6 +1672,7 @@ MdPanelRef.prototype.show = function() {
* the panel has hidden and animations finish.
*/
MdPanelRef.prototype.hide = function() {
+ var getElement = getElementGetter(this._$document);
if (!this.panelContainer) {
return this._$q(function(resolve, reject) {
reject('mdPanel: Panel does not exist yet. Call open() or attach().');
@@ -1814,6 +1825,7 @@ MdPanelRef.prototype.toggleClass = function(toggleClass, onElement) {
* @private
*/
MdPanelRef.prototype._compile = function() {
+ var getElement = getElementGetter(this._$document);
var self = this;
// Compile the element via $mdCompiler. Note that when using a
@@ -1857,6 +1869,7 @@ MdPanelRef.prototype._compile = function() {
* @private
*/
MdPanelRef.prototype._createPanel = function() {
+ var getElement = getElementGetter(this._$document);
var self = this;
return this._$q(function(resolve, reject) {
@@ -2101,6 +2114,7 @@ MdPanelRef.prototype._removeEventListeners = function() {
* @private
*/
MdPanelRef.prototype._configureEscapeToClose = function() {
+ var getElement = getElementGetter(this._$document);
if (this.config['escapeToClose']) {
var parentTarget = getElement(this.config['attachTo']);
var self = this;
@@ -2132,9 +2146,10 @@ MdPanelRef.prototype._configureEscapeToClose = function() {
* @private
*/
MdPanelRef.prototype._configureClickOutsideToClose = function() {
+ var $document = this._$document;
if (this.config['clickOutsideToClose']) {
var target = this.config['propagateContainerEvents'] ?
- angular.element(document.body) :
+ angular.element($document[0].body) :
this.panelContainer;
var sourceEl;
@@ -2532,6 +2547,9 @@ function MdPanelPosition($injector) {
/** @private @const {!angular.$mdConstant} */
this._$mdConstant = $injector.get('$mdConstant');
+ /** @private @const {!angular.$document} */
+ this._$document = $injector.get('$document');
+
/** @private {boolean} */
this._absolute = false;
@@ -2759,6 +2777,7 @@ MdPanelPosition.prototype.center = function() {
* @returns {!MdPanelPosition}
*/
MdPanelPosition.prototype.relativeTo = function(element) {
+ var getElement = getElementGetter(this._$document);
this._absolute = false;
this._relativeToEl = getElement(element);
return this;
@@ -2941,7 +2960,7 @@ MdPanelPosition.prototype._isOnscreen = function(panelEl) {
if (this._translateX.length || this._translateY.length) {
var prefixedTransform = this._$mdConstant.CSS.TRANSFORM;
- var offsets = getComputedTranslations(panelEl, prefixedTransform);
+ var offsets = getComputedTranslations(this._$window, panelEl, prefixedTransform);
left += offsets.x;
top += offsets.y;
}
@@ -3182,6 +3201,9 @@ function MdPanelAnimation($injector) {
/** @private @const {!angular.$mdUtil} */
this._$mdUtil = $injector.get('$mdUtil');
+ /** @private @const {!angular.$document} */
+ this._$document = $injector.get('$document');
+
/**
* @private {{element: !angular.JQLite|undefined, bounds: !DOMRect}|
* undefined}
@@ -3286,6 +3308,7 @@ MdPanelAnimation.prototype.duration = function(duration) {
* @private
*/
MdPanelAnimation.prototype._getPanelAnimationTarget = function(location) {
+ var getElement = getElementGetter(this._$document);
if (angular.isDefined(location.top) || angular.isDefined(location.left)) {
return {
element: undefined,
@@ -3498,28 +3521,31 @@ MdPanelAnimation.prototype._getBoundingClientRect = function(element) {
/**
- * Returns the angular element associated with a css selector or element.
- * @param el {string|!angular.JQLite|!Element}
- * @returns {!angular.JQLite}
+ * Returns a function that returns the angular element associated with a css selector or element.
+ * @param $document {!angular.JQLite}
+ * @returns {(el: string,!angular.JQLite,!Element) => !angular.JQLite}
*/
-function getElement(el) {
- var queryResult = angular.isString(el) ?
- document.querySelector(el) : el;
- return angular.element(queryResult);
+function getElementGetter($document) {
+ return function getElement(el) {
+ var queryResult = angular.isString(el) ?
+ $document[0].querySelector(el) : el;
+ return angular.element(queryResult);
+ };
}
/**
* Gets the computed values for an element's translateX and translateY in px.
+ * @param {!angular.$window} $window
* @param {!angular.JQLite|!Element} el
* @param {string} property
* @return {{x: number, y: number}}
*/
-function getComputedTranslations(el, property) {
+function getComputedTranslations($window, el, property) {
// The transform being returned by `getComputedStyle` is in the format:
// `matrix(a, b, c, d, translateX, translateY)` if defined and `none`
// if the element doesn't have a transform.
- var transform = getComputedStyle(el[0] || el)[property];
+ var transform = $window.getComputedStyle(el[0] || el)[property];
var openIndex = transform.indexOf('(');
var closeIndex = transform.lastIndexOf(')');
var output = { x: 0, y: 0 };
diff --git a/src/components/radioButton/demoBasicUsage/index.html b/src/components/radioButton/demoBasicUsage/index.html
index 7bb088244f..a4c5da5eaa 100644
--- a/src/components/radioButton/demoBasicUsage/index.html
+++ b/src/components/radioButton/demoBasicUsage/index.html
@@ -1,5 +1,5 @@
diff --git a/src/components/select/demoValidations/script.js b/src/components/select/demoValidations/script.js
index 69e208a098..069868c1a1 100755
--- a/src/components/select/demoValidations/script.js
+++ b/src/components/select/demoValidations/script.js
@@ -1,16 +1,21 @@
angular.module('selectDemoValidation', ['ngMaterial', 'ngMessages'])
-.controller('AppCtrl', function($scope) {
+.controller('AppCtrl', function($scope, $mdDialog) {
$scope.clearValue = function() {
$scope.quest = undefined;
$scope.favoriteColor = undefined;
$scope.myForm.$setPristine();
};
- $scope.save = function() {
- if ($scope.myForm.$valid) {
+ $scope.save = function(event) {
+ var valid = $scope.myForm.$valid;
+ if (valid) {
$scope.myForm.$setSubmitted();
- alert('Form was valid.');
- } else {
- alert('Form was invalid!');
}
+
+ $mdDialog.show(
+ $mdDialog
+ .alert()
+ .title('Form submit attempt.')
+ .textContent('Form was ' + valid ? 'valid' : 'invalid!')
+ );
};
});
diff --git a/src/components/select/select.js b/src/components/select/select.js
index d50f4caad4..1cc32d807b 100755
--- a/src/components/select/select.js
+++ b/src/components/select/select.js
@@ -672,7 +672,15 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
}
}
- function SelectMenuController($scope, $attrs, $element) {
+ function SelectMenuController($scope, $attrs, $element, $timeout) {
+ function setTimeout(fn, delay) {
+ return $timeout(fn, delay, false);
+ }
+
+ function clearTimeout(obj) {
+ $timeout.cancel(obj);
+ }
+
var self = this;
self.isMultiple = angular.isDefined($attrs.multiple);
// selected is an object with keys matching all of the selected options' hashed values
@@ -1631,7 +1639,7 @@ function SelectProvider($$interimElementProvider) {
minWidth = Math.min(targetRect.width + centeredRect.paddingLeft + centeredRect.paddingRight, maxWidth);
- fontSize = window.getComputedStyle(targetNode)['font-size'];
+ fontSize = $window.getComputedStyle(targetNode)['font-size'];
}
// Keep left and top within the window
diff --git a/src/components/select/select.spec.js b/src/components/select/select.spec.js
index b0aaa83ffe..6146528df0 100755
--- a/src/components/select/select.spec.js
+++ b/src/components/select/select.spec.js
@@ -1459,7 +1459,9 @@ describe('', function() {
el.triggerHandler('click');
$material.flushInterimElement();
el.triggerHandler('blur');
- } catch (e) { }
+ } catch (e) {
+ // ignore error
+ }
}
function closeSelect() {
diff --git a/src/components/slider/slider.js b/src/components/slider/slider.js
index 1025415e50..443243ee58 100644
--- a/src/components/slider/slider.js
+++ b/src/components/slider/slider.js
@@ -22,7 +22,10 @@
*
*
*/
-function SliderContainerDirective() {
+/**
+ * @ngInject
+ */
+function SliderContainerDirective($window) {
return {
controller: function () {},
compile: function (elem) {
@@ -74,7 +77,7 @@ function SliderContainerDirective() {
var input = element[0].querySelector('md-input-container');
if (input) {
- var computedStyle = getComputedStyle(input);
+ var computedStyle = $window.getComputedStyle(input);
var minWidth = parseInt(computedStyle.minWidth);
var padding = parseInt(computedStyle.padding) * 2;
@@ -160,6 +163,10 @@ function SliderDirective($$rAF, $window, $mdAria, $mdUtil, $mdConstant, $mdThemi
compile: compile
};
+ function setTimeout(fn, delay) {
+ return $timeout(fn, delay, false);
+ }
+
// **********************************************************
// Private Methods
// **********************************************************
diff --git a/src/components/swipe/demoBasicUsage/index.html b/src/components/swipe/demoBasicUsage/index.html
index efe7bf6e95..e8ede2ac3a 100644
--- a/src/components/swipe/demoBasicUsage/index.html
+++ b/src/components/swipe/demoBasicUsage/index.html
@@ -1,23 +1,23 @@
-
+
Swipe me to the left
-
+ class="demo-swipe" md-swipe-up="onSwipe('up', $event)">
Swipe me up
+ class="demo-swipe" md-swipe-down="onSwipe('down', $event)">
Swipe me down
diff --git a/src/components/swipe/demoBasicUsage/script.js b/src/components/swipe/demoBasicUsage/script.js
index 2450b8a260..3e4ca637de 100644
--- a/src/components/swipe/demoBasicUsage/script.js
+++ b/src/components/swipe/demoBasicUsage/script.js
@@ -1,17 +1,12 @@
angular.module('demoSwipe', ['ngMaterial'])
- .controller('demoSwipeCtrl', function($scope) {
- $scope.onSwipeLeft = function(ev) {
- alert('You swiped left!!');
- };
-
- $scope.onSwipeRight = function(ev) {
- alert('You swiped right!!');
- };
- $scope.onSwipeUp = function(ev) {
- alert('You swiped up!!');
- };
-
- $scope.onSwipeDown = function(ev) {
- alert('You swiped down!!');
+ .controller('demoSwipeCtrl', function($scope, $mdDialog) {
+ $scope.onSwipe = function onSwipe(direction, ev) {
+ $mdDialog.show(
+ $mdDialog
+ .alert()
+ .title('Swipe action')
+ .textContent('You swiped ' + direction + '!!')
+ .event(ev)
+ );
};
});
diff --git a/src/components/switch/demoBasicUsage/script.js b/src/components/switch/demoBasicUsage/script.js
index 7991f6422d..f5aed5a171 100644
--- a/src/components/switch/demoBasicUsage/script.js
+++ b/src/components/switch/demoBasicUsage/script.js
@@ -9,6 +9,6 @@ angular.module('switchDemo1', ['ngMaterial'])
$scope.message = 'false';
$scope.onChange = function(cbState) {
- $scope.message = cbState;
+ $scope.message = cbState;
};
});
diff --git a/src/components/tabs/js/tabsController.js b/src/components/tabs/js/tabsController.js
index b12e91901c..7de71d5806 100644
--- a/src/components/tabs/js/tabsController.js
+++ b/src/components/tabs/js/tabsController.js
@@ -683,7 +683,7 @@ function MdTabsController ($scope, $element, $window, $mdConstant, $mdTabInkRipp
index = ctrl[ key ];
for (newIndex = index + inc;
ctrl.tabs[ newIndex ] && ctrl.tabs[ newIndex ].scope.disabled;
- newIndex += inc) {}
+ newIndex += inc) { /* do nothing */ }
newIndex = (index + inc + ctrl.tabs.length) % ctrl.tabs.length;
diff --git a/src/components/tabs/js/tabsDummyWrapperDirective.js b/src/components/tabs/js/tabsDummyWrapperDirective.js
index aaed701e03..59735251bd 100644
--- a/src/components/tabs/js/tabsDummyWrapperDirective.js
+++ b/src/components/tabs/js/tabsDummyWrapperDirective.js
@@ -36,7 +36,7 @@ function MdTabsDummyWrapper ($mdUtil, $window) {
characterData: true
};
- observer = new MutationObserver(mutationCallback);
+ observer = new $window.MutationObserver(mutationCallback);
observer.observe(element[0], config);
disconnect = observer.disconnect.bind(observer);
} else {
diff --git a/src/components/tabs/tabsPaginationService.spec.js b/src/components/tabs/tabsPaginationService.spec.js
index e95f587664..506414049a 100644
--- a/src/components/tabs/tabsPaginationService.spec.js
+++ b/src/components/tabs/tabsPaginationService.spec.js
@@ -1,6 +1,6 @@
describe('MdTabsPaginationService', function() {
- const TAB_WIDTH = 100;
+ var TAB_WIDTH = 100;
var MdTabsPaginationService;
diff --git a/src/components/toast/demoBasicUsage/script.js b/src/components/toast/demoBasicUsage/script.js
index 0f39479932..fb39695df1 100644
--- a/src/components/toast/demoBasicUsage/script.js
+++ b/src/components/toast/demoBasicUsage/script.js
@@ -1,7 +1,7 @@
angular.module('toastDemo1', ['ngMaterial'])
-.controller('AppCtrl', function($scope, $mdToast) {
+.controller('AppCtrl', function($scope, $mdToast, $mdDialog) {
var last = {
bottom: false,
top: true,
@@ -52,7 +52,12 @@ angular.module('toastDemo1', ['ngMaterial'])
$mdToast.show(toast).then(function(response) {
if ( response == 'ok' ) {
- alert('You clicked the \'UNDO\' action.');
+ $mdDialog.show(
+ $mdDialog
+ .alert()
+ .title('Action clicked')
+ .textContent("You clicked the 'UNDO' action.")
+ );
}
});
};
diff --git a/src/components/toast/toast.js b/src/components/toast/toast.js
index a95f365cba..b40fcf65f2 100644
--- a/src/components/toast/toast.js
+++ b/src/components/toast/toast.js
@@ -365,7 +365,7 @@ function MdToastProvider($$interimElementProvider) {
}
/* @ngInject */
- function toastDefaultOptions($animate, $mdToast, $mdUtil, $mdMedia) {
+ function toastDefaultOptions($animate, $mdToast, $mdUtil, $mdMedia, $document) {
var SWIPE_EVENTS = '$md.swipeleft $md.swiperight $md.swipeup $md.swipedown';
return {
onShow: onShow,
@@ -382,7 +382,7 @@ function MdToastProvider($$interimElementProvider) {
// Root element of template will be
. We need to wrap all of its content inside of
// of . All templates provided here should be static, developer-controlled
// content (meaning we're not attempting to guard against XSS).
- var templateRoot = document.createElement('md-template');
+ var templateRoot = $document[0].createElement('md-template');
templateRoot.innerHTML = template;
// Iterate through all root children, to detect possible md-toast directives.
diff --git a/src/components/toolbar/toolbar.spec.js b/src/components/toolbar/toolbar.spec.js
index f4afbafebd..7d0060f542 100644
--- a/src/components/toolbar/toolbar.spec.js
+++ b/src/components/toolbar/toolbar.spec.js
@@ -35,6 +35,7 @@ describe('', function() {
});
var contentCss = {};
spyOn(contentEl, 'css').and.callFake(function(properties, value) {
+ var k;
if (angular.isObject(properties)) {
for (k in properties) {
if (properties.hasOwnProperty(k)) {
diff --git a/src/components/tooltip/tooltip.js b/src/components/tooltip/tooltip.js
index c69201ee5e..b9697a0b94 100644
--- a/src/components/tooltip/tooltip.js
+++ b/src/components/tooltip/tooltip.js
@@ -159,7 +159,7 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $interpolate,
// for it in the form of viable host(parent[0]).
if (parent[0] && 'MutationObserver' in $window) {
// Use a mutationObserver to tackle #2602.
- var attributeObserver = new MutationObserver(function(mutations) {
+ var attributeObserver = new $window.MutationObserver(function(mutations) {
if (isDisabledMutation(mutations)) {
$mdUtil.nextTick(function() {
setVisible(false);
@@ -197,7 +197,7 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $interpolate,
}
function windowBlurEventHandler() {
- elementFocusedOnWindowBlur = document.activeElement === parent[0];
+ elementFocusedOnWindowBlur = $document[0].activeElement === parent[0];
}
function enterEventHandler($event) {
@@ -268,7 +268,7 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $interpolate,
function configureWatchers() {
if (element[0] && 'MutationObserver' in $window) {
- var attributeObserver = new MutationObserver(function(mutations) {
+ var attributeObserver = new $window.MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.attributeName === 'md-visible' &&
!scope.visibleWatcher ) {
@@ -373,7 +373,7 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $interpolate,
}
if (!panelRef) {
- var attachTo = angular.element(document.body);
+ var attachTo = angular.element($document[0].body);
var panelAnimation = $mdPanel.newPanelAnimation()
.openFrom(parent)
.closeTo(parent)
@@ -417,9 +417,9 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $interpolate,
*
* @ngInject
*/
-function MdTooltipRegistry() {
+function MdTooltipRegistry($window) {
var listeners = {};
- var ngWindow = angular.element(window);
+ var ngWindow = angular.element($window);
return {
register: register,
@@ -449,7 +449,7 @@ function MdTooltipRegistry() {
var handlers = listeners[type] = listeners[type] || [];
if (!handlers.length) {
- useCapture ? window.addEventListener(type, globalEventHandler, true) :
+ useCapture ? $window.addEventListener(type, globalEventHandler, true) :
ngWindow.on(type, globalEventHandler);
}
@@ -472,7 +472,7 @@ function MdTooltipRegistry() {
handlers.splice(index, 1);
if (handlers.length === 0) {
- useCapture ? window.removeEventListener(type, globalEventHandler, true) :
+ useCapture ? $window.removeEventListener(type, globalEventHandler, true) :
ngWindow.off(type, globalEventHandler);
}
}
diff --git a/src/components/virtualRepeat/virtual-repeater.js b/src/components/virtualRepeat/virtual-repeater.js
index 6d79d276ce..6cbca1194a 100644
--- a/src/components/virtualRepeat/virtual-repeater.js
+++ b/src/components/virtualRepeat/virtual-repeater.js
@@ -96,11 +96,12 @@ var NUM_EXTRA = 3;
/** @ngInject */
function VirtualRepeatContainerController($$rAF, $mdUtil, $mdConstant, $parse, $rootScope, $window, $scope,
- $element, $attrs) {
+ $element, $attrs, $document) {
this.$rootScope = $rootScope;
this.$scope = $scope;
this.$element = $element;
this.$attrs = $attrs;
+ this.$document = $document;
/** @type {number} The width or height of the container */
this.size = 0;
@@ -254,6 +255,7 @@ VirtualRepeatContainerController.prototype.getDimensionName_ = function() {
VirtualRepeatContainerController.prototype.sizeScroller_ = function(size) {
var dimension = this.getDimensionName_();
var crossDimension = this.isHorizontal() ? 'height' : 'width';
+ var $document = this.$document;
// Clear any existing dimensions.
this.sizer.innerHTML = '';
@@ -271,7 +273,7 @@ VirtualRepeatContainerController.prototype.sizeScroller_ = function(size) {
var numChildren = Math.floor(size / this.maxElementPixels);
// Element template to clone for each max-size piece.
- var sizerChild = document.createElement('div');
+ var sizerChild = $document[0].createElement('div');
sizerChild.style[dimension] = this.maxElementPixels + 'px';
sizerChild.style[crossDimension] = '1px';
@@ -377,6 +379,7 @@ VirtualRepeatContainerController.prototype.resetScroll = function() {
VirtualRepeatContainerController.prototype.handleScroll_ = function() {
+ var document = this.$document[0];
var ltr = document.dir != 'rtl' && document.body.dir != 'rtl';
if(!ltr && !this.maxSize) {
this.scroller.scrollLeft = this.scrollSize;
diff --git a/src/core/services/aria/aria.js b/src/core/services/aria/aria.js
index bc44b83b6e..78dc144169 100644
--- a/src/core/services/aria/aria.js
+++ b/src/core/services/aria/aria.js
@@ -37,8 +37,8 @@ function MdAriaProvider() {
return {
disableWarnings: disableWarnings,
- $get: function($$rAF, $log, $window, $interpolate) {
- return MdAriaService.apply(config, arguments);
+ $get: function($injector) {
+ return $injector.invoke(mdAriaService, undefined, config);
}
};
@@ -55,12 +55,7 @@ function MdAriaProvider() {
/*
* @ngInject
*/
-function MdAriaService($$rAF, $log, $window, $interpolate) {
-
- // Load the showWarnings option from the current context and store it inside of a scope variable,
- // because the context will be probably lost in some function calls.
- var showWarnings = this.showWarnings;
-
+function mdAriaService($$rAF, $log, $window, $interpolate, $document, showWarnings) {
return {
expect: expect,
expectAsync: expectAsync,
@@ -130,7 +125,7 @@ function MdAriaService($$rAF, $log, $window, $interpolate) {
function getText(element) {
element = element[0] || element;
- var walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false);
+ var walker = $document[0].createTreeWalker(element, $window.NodeFilter.SHOW_TEXT, null, false);
var text = '';
var node;
diff --git a/src/core/services/compiler/compiler.js b/src/core/services/compiler/compiler.js
index 825236f0fc..bf582f0578 100644
--- a/src/core/services/compiler/compiler.js
+++ b/src/core/services/compiler/compiler.js
@@ -172,12 +172,14 @@ function MdCompilerProvider($compileProvider) {
return false;
}
- this.$get = ["$q", "$templateRequest", "$injector", "$compile", "$controller",
- function($q, $templateRequest, $injector, $compile, $controller) {
- return new MdCompilerService($q, $templateRequest, $injector, $compile, $controller);
+ this.$get = ["$injector",
+ function($injector) {
+ return $injector.instantiate(MdCompilerService);
}];
-
- function MdCompilerService($q, $templateRequest, $injector, $compile, $controller) {
+ /**
+ * @ngInject
+ */
+ function MdCompilerService($q, $templateRequest, $injector, $compile, $controller, $document) {
/** @private @const {!angular.$q} */
this.$q = $q;
@@ -193,6 +195,9 @@ function MdCompilerProvider($compileProvider) {
/** @private @const {!angular.$controller} */
this.$controller = $controller;
+
+ /** @private @const {!angular.$controller} */
+ this.$document = $document;
}
/**
@@ -395,7 +400,7 @@ function MdCompilerProvider($compileProvider) {
* @returns {{element: !JQLite, restore: !Function}}
*/
MdCompilerService.prototype._fetchContentElement = function(options) {
-
+ var document = this.$document[0];
var contentEl = options.contentElement;
var restoreFn = null;
diff --git a/src/core/services/gesture/gesture.js b/src/core/services/gesture/gesture.js
index 884cd081d1..7108fb591b 100644
--- a/src/core/services/gesture/gesture.js
+++ b/src/core/services/gesture/gesture.js
@@ -66,8 +66,8 @@ MdGestureProvider.prototype = {
* $get is used to build an instance of $mdGesture
* @ngInject
*/
- $get : function($$MdGestureHandler, $$rAF, $timeout) {
- return new MdGesture($$MdGestureHandler, $$rAF, $timeout);
+ $get : function($injector) {
+ return $injector.instantiate(MdGesture);
}
};
@@ -77,7 +77,9 @@ MdGestureProvider.prototype = {
* MdGesture factory construction function
* @ngInject
*/
-function MdGesture($$MdGestureHandler, $$rAF, $timeout) {
+function MdGesture($$MdGestureHandler, $$rAF, $timeout, $window, $document) {
+ var window = $window;
+ var navigator = $window.navigator;
var userAgent = navigator.userAgent || navigator.vendor || window.opera;
var isIos = userAgent.match(/ipad|iphone|ipod/i);
var isAndroid = userAgent.match(/android/i);
@@ -328,7 +330,7 @@ function MdGesture($$MdGestureHandler, $$rAF, $timeout) {
});
function getTouchAction() {
- var testEl = document.createElement('div');
+ var testEl = $document[0].createElement('div');
var vendorPrefixes = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
for (var i = 0; i < vendorPrefixes.length; i++) {
@@ -358,8 +360,11 @@ function GestureHandler (name) {
this.state = {};
}
-function MdGestureHandler() {
- var hasJQuery = (typeof window.jQuery !== 'undefined') && (angular.element === window.jQuery);
+/**
+ * @ngInject
+ */
+function MdGestureHandler($window, $document) {
+ var hasJQuery = (typeof $window.jQuery !== 'undefined') && (angular.element === $window.jQuery);
GestureHandler.prototype = {
options: {},
@@ -481,13 +486,14 @@ function MdGestureHandler() {
* @param eventPointer the pointer object that matches this event.
*/
function nativeDispatchEvent(srcEvent, eventType, eventPointer) {
+ var document = $document[0];
eventPointer = eventPointer || pointer;
var eventObj;
if (eventType === 'click' || eventType == 'mouseup' || eventType == 'mousedown' ) {
eventObj = document.createEvent('MouseEvents');
eventObj.initMouseEvent(
- eventType, true, true, window, srcEvent.detail,
+ eventType, true, true, $window, srcEvent.detail,
eventPointer.x, eventPointer.y, eventPointer.x, eventPointer.y,
srcEvent.ctrlKey, srcEvent.altKey, srcEvent.shiftKey, srcEvent.metaKey,
srcEvent.button, srcEvent.relatedTarget || null
@@ -509,10 +515,11 @@ function MdGestureHandler() {
* Attach Gestures: hook document and check shouldHijack clicks
* @ngInject
*/
-function attachToDocument( $mdGesture, $$MdGestureHandler ) {
+function attachToDocument( $mdGesture, $$MdGestureHandler, $document) {
// Polyfill document.contains for IE11.
- // TODO: move to util
+ // TODO: avoid muating $document!
+ var document = $document[0];
document.contains || (document.contains = function (node) {
return document.body.contains(node);
});
diff --git a/src/core/services/interaction/interaction.js b/src/core/services/interaction/interaction.js
index 845012c9c9..6e2853dd67 100644
--- a/src/core/services/interaction/interaction.js
+++ b/src/core/services/interaction/interaction.js
@@ -33,11 +33,16 @@ angular
*
*
*/
-function MdInteractionService($timeout, $mdUtil) {
+/**
+ * @ngInject
+ */
+function MdInteractionService($timeout, $mdUtil, $document, $window) {
this.$timeout = $timeout;
this.$mdUtil = $mdUtil;
+ this.$window = $window;
+ this.$document = $document;
- this.bodyElement = angular.element(document.body);
+ this.bodyElement = angular.element($document[0].body);
this.isBuffering = false;
this.bufferTimeout = null;
this.lastInteractionType = null;
@@ -72,6 +77,8 @@ function MdInteractionService($timeout, $mdUtil) {
* body element.
*/
MdInteractionService.prototype.initializeEvents = function() {
+ var window = this.$window;
+ var document = this.$document[0];
// IE browsers can also trigger pointer events, which also leads to an interaction.
var pointerEvent = 'MSPointerEvent' in window ? 'MSPointerDown' : 'PointerEvent' in window ? 'pointerdown' : null;
diff --git a/src/core/services/layout/layout.js b/src/core/services/layout/layout.js
index 191c9af4d0..0f04158eb1 100644
--- a/src/core/services/layout/layout.js
+++ b/src/core/services/layout/layout.js
@@ -11,25 +11,6 @@
var ALIGNMENT_MAIN_AXIS= [ "", "start", "center", "end", "stretch", "space-around", "space-between" ];
var ALIGNMENT_CROSS_AXIS= [ "", "start", "center", "end", "stretch" ];
- var config = {
- /**
- * Enable directive attribute-to-class conversions
- * Developers can use `` to quickly
- * disable the Layout directives and prohibit the injection of Layout classNames
- */
- enabled: true,
-
- /**
- * List of mediaQuery breakpoints and associated suffixes
- *
- * [
- * { suffix: "sm", mediaQuery: "screen and (max-width: 599px)" },
- * { suffix: "md", mediaQuery: "screen and (min-width: 600px) and (max-width: 959px)" }
- * ]
- */
- breakpoints: []
- };
-
registerLayoutAPI( angular.module('material.core.layout', ['ng']) );
/**
@@ -73,8 +54,8 @@
* ```
*/
function registerLayoutAPI(module){
- var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
- var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
+ var PREFIX_REGEXP = /^((?:x|data)[:\-_])/i;
+ var SPECIAL_CHARS_REGEXP = /([:\-_]+(.))/g;
// NOTE: these are also defined in constants::MEDIA_PRIORITY and constants::MEDIA
var BREAKPOINTS = [ "", "xs", "gt-xs", "sm", "gt-sm", "md", "gt-md", "lg", "gt-lg", "xl", "print" ];
@@ -102,10 +83,28 @@
// Register other, special directive functions for the Layout features:
module
- .provider('$$mdLayout' , function() {
+ .provider('$$mdLayout', function() {
+ /**
+ * Enable directive attribute-to-class conversions
+ * Developers can use `
` to quickly
+ * disable the Layout directives and prohibit the injection of Layout classNames
+ */
+ var enabled = true;
// Publish internal service for Layouts
return {
- $get : angular.noop,
+ $get : function() {
+ return {
+ enabled: function() {
+ return enabled;
+ },
+ disabled: function() {
+ return !enabled;
+ },
+ disable: function() {
+ enabled = false;
+ }
+ };
+ },
validateAttributeValue : validateAttributeValue,
validateAttributeUsage : validateAttributeUsage,
/**
@@ -113,7 +112,7 @@
* When disabled, this stops all attribute-to-classname generations
*/
disableLayouts : function(isDisabled) {
- config.enabled = (isDisabled !== true);
+ enabled = (isDisabled !== true);
}
};
})
@@ -145,8 +144,7 @@
.directive('showLtMd' , warnAttrNotSupported('show-lt-md'))
.directive('showLtLg' , warnAttrNotSupported('show-lt-lg'))
- // Determine if
- .config( detectDisabledLayouts );
+ .run( detectDisabledLayouts );
/**
* Converts snake_case to camelCase.
@@ -173,9 +171,10 @@
/**
* @ngInject
*/
- function detectDisabledLayouts() {
- var isDisabled = !!document.querySelector('[md-layouts-disabled]');
- config.enabled = !isDisabled;
+ function detectDisabledLayouts($document, $$mdLayout) {
+ if ($document[0].querySelector('[md-layouts-disabled]')) {
+ $$mdLayout.disable();
+ }
}
/**
@@ -198,9 +197,12 @@
* conversions; this would obviate the use of the `md-layout-css` directive
*
*/
- function disableLayoutDirective() {
+ /**
+ * @ngInject
+ */
+ function disableLayoutDirective($$mdLayout) {
// Return a 1x-only, first-match attribute directive
- config.enabled = false;
+ $$mdLayout.disable();
return {
restrict : 'A',
@@ -213,12 +215,12 @@
* finish processing. Eliminates flicker with Material.Layouts
*/
function buildCloakInterceptor(className) {
- return [ '$timeout', function($timeout){
+ return [ '$timeout', '$$mdLayout', function($timeout, $$mdLayout){
return {
restrict : 'A',
priority : -10, // run after normal ng-cloak
compile : function( element ) {
- if (!config.enabled) return angular.noop;
+ if ($$mdLayout.disabled()) return angular.noop;
// Re-add the cloak
element.addClass(className);
@@ -253,7 +255,7 @@
*/
function attributeWithObserve(className) {
- return ['$mdUtil', '$interpolate', "$log", function(_$mdUtil_, _$interpolate_, _$log_) {
+ return ['$mdUtil', '$interpolate', "$log", '$$mdLayout', function(_$mdUtil_, _$interpolate_, _$log_, $$mdLayout) {
$mdUtil = _$mdUtil_;
$interpolate = _$interpolate_;
$log = _$log_;
@@ -262,7 +264,7 @@
restrict: 'A',
compile: function(element, attr) {
var linkFn;
- if (config.enabled) {
+ if ($$mdLayout.enabled()) {
// immediately replace static (non-interpolated) invalid values...
validateAttributeUsage(className, attr, element, $log);
@@ -300,7 +302,7 @@
* any attribute value
*/
function attributeWithoutValue(className) {
- return ['$mdUtil', '$interpolate', "$log", function(_$mdUtil_, _$interpolate_, _$log_) {
+ return ['$mdUtil', '$interpolate', "$log", '$$mdLayout', function(_$mdUtil_, _$interpolate_, _$log_, $$mdLayout) {
$mdUtil = _$mdUtil_;
$interpolate = _$interpolate_;
$log = _$log_;
@@ -309,7 +311,7 @@
restrict: 'A',
compile: function(element, attr) {
var linkFn;
- if (config.enabled) {
+ if ($$mdLayout.enabled()) {
// immediately replace static (non-interpolated) invalid values...
validateAttributeValue( className,
@@ -441,7 +443,6 @@
case 'layout-margin' :
case 'layout-fill' :
case 'layout-wrap' :
- case 'layout-nowrap' :
case 'layout-nowrap' :
value = '';
break;
diff --git a/src/core/services/liveAnnouncer/live-announcer.js b/src/core/services/liveAnnouncer/live-announcer.js
index 45dad2a9fa..2bd22cfc13 100644
--- a/src/core/services/liveAnnouncer/live-announcer.js
+++ b/src/core/services/liveAnnouncer/live-announcer.js
@@ -30,12 +30,12 @@ angular
*
*
*/
-function MdLiveAnnouncer($timeout) {
+function MdLiveAnnouncer($timeout, $document) {
/** @private @const @type {!angular.$timeout} */
this._$timeout = $timeout;
/** @private @const @type {!HTMLElement} */
- this._liveElement = this._createLiveElement();
+ this._liveElement = createLiveElement($document[0]);
/** @private @const @type {!number} */
this._announceTimeout = 100;
@@ -72,9 +72,8 @@ MdLiveAnnouncer.prototype.announce = function(message, politeness) {
* Creates a live announcer element, which listens for DOM changes and announces them
* to the screenreaders.
* @returns {!HTMLElement}
- * @private
*/
-MdLiveAnnouncer.prototype._createLiveElement = function() {
+function createLiveElement(document) {
var liveEl = document.createElement('div');
liveEl.classList.add('md-visually-hidden');
@@ -85,4 +84,4 @@ MdLiveAnnouncer.prototype._createLiveElement = function() {
document.body.appendChild(liveEl);
return liveEl;
-};
+}
diff --git a/src/core/services/meta/meta.js b/src/core/services/meta/meta.js
index 96011155af..3450ba74e2 100644
--- a/src/core/services/meta/meta.js
+++ b/src/core/services/meta/meta.js
@@ -5,16 +5,16 @@
*
* @description
*
- * A provider and a service that simplifies meta tags access
+ * A service that simplifies meta tags access
*
* Note: This is intended only for use with dynamic meta tags such as browser color and title.
* Tags that are only processed when the page is rendered (such as `charset`, and `http-equiv`)
* will not work since `$$mdMeta` adds the tags after the page has already been loaded.
*
* ```js
- * app.config(function($$mdMetaProvider) {
- * var removeMeta = $$mdMetaProvider.setMeta('meta-name', 'content');
- * var metaValue = $$mdMetaProvider.getMeta('meta-name'); // -> 'content'
+ * app.run(function($$mdMeta) {
+ * var removeMeta = $$mdMeta.setMeta('meta-name', 'content');
+ * var metaValue = $$mdMeta.getMeta('meta-name'); // -> 'content'
*
* removeMeta();
* });
@@ -31,8 +31,8 @@
*
*/
angular.module('material.core.meta', [])
- .provider('$$mdMeta', function () {
- var head = angular.element(document.head);
+ .factory('$$mdMeta', ['$document', function ($document) {
+ var head = angular.element($document[0].head);
var metaElements = {};
/**
@@ -46,7 +46,7 @@ angular.module('material.core.meta', [])
return true;
}
- var element = document.getElementsByName(name)[0];
+ var element = $document[0].getElementsByName(name)[0];
if (!element) {
return false;
@@ -107,14 +107,8 @@ angular.module('material.core.meta', [])
return metaElements[name].attr('content');
}
- var module = {
+ return {
setMeta: setMeta,
getMeta: getMeta
};
-
- return angular.extend({}, module, {
- $get: function () {
- return module;
- }
- });
- });
\ No newline at end of file
+ }]);
diff --git a/src/core/services/theming/theming.js b/src/core/services/theming/theming.js
index d8663474ff..8f123ea6b4 100644
--- a/src/core/services/theming/theming.js
+++ b/src/core/services/theming/theming.js
@@ -11,21 +11,8 @@ angular.module('material.core.theming', ['material.core.theming.palette', 'mater
.directive('mdThemable', ThemableDirective)
.directive('mdThemesDisabled', disableThemesDirective )
.provider('$mdTheming', ThemingProvider)
- .config( detectDisabledThemes )
.run(generateAllThemes);
-/**
- * Detect if the HTML or the BODY tags has a [md-themes-disabled] attribute
- * If yes, then immediately disable all theme stylesheet generation and DOM injection
- */
-/**
- * @ngInject
- */
-function detectDisabledThemes($mdThemingProvider) {
- var isDisabled = !!document.querySelector('[md-themes-disabled]');
- $mdThemingProvider.disableTheming(isDisabled);
-}
-
/**
* @ngdoc service
* @name $mdThemingProvider
@@ -252,17 +239,20 @@ var VALID_HUE_VALUES = [
'700', '800', '900', 'A100', 'A200', 'A400', 'A700'
];
-var themeConfig = {
- disableTheming : false, // Generate our themes at run time; also disable stylesheet DOM injection
- generateOnDemand : false, // Whether or not themes are to be generated on-demand (vs. eagerly).
- registeredStyles : [], // Custom styles registered to be used in the theming of custom components.
- nonce : null // Nonce to be added as an attribute to the generated themes style tags.
-};
+function browserColorSetter() {
+ var browserColor = {};
+ return {
+ setBrowserColor: function setBrowserColor(color) {
+ browserColor.color = color;
+ },
+ browserColor: browserColor,
+ }
+}
/**
- *
+ * @ngInject
*/
-function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
+function ThemingProvider($mdColorPalette, $injector) {
PALETTES = { };
var THEMES = { };
@@ -270,6 +260,9 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
var alwaysWatchTheme = false;
var defaultTheme = 'default';
+ var bcs = browserColorSetter();
+ var doBrowserColor = bcs.setBrowserColor;
+ var browserColor = bcs.browserColor;
// Load JS Defined Palettes
angular.extend(PALETTES, $mdColorPalette);
@@ -281,11 +274,11 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
* @param {string} color Hex value of the wanted browser color
* @returns {Function} Remove function of the meta tags
*/
- var setBrowserColor = function (color) {
+ var setBrowserColor = function ($$mdMeta, color) {
// Chrome, Firefox OS and Opera
- var removeChrome = $$mdMetaProvider.setMeta('theme-color', color);
+ var removeChrome = $$mdMeta.setMeta('theme-color', color);
// Windows Phone
- var removeWindows = $$mdMetaProvider.setMeta('msapplication-navbutton-color', color);
+ var removeWindows = $$mdMeta.setMeta('msapplication-navbutton-color', color);
return function () {
removeChrome();
@@ -309,7 +302,7 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
* @param {Object=} options Options object for the browser color
* @returns {Function} remove function of the browser color
*/
- var enableBrowserColor = function (options) {
+ var enableBrowserColor = function ($$mdMeta, options) {
options = angular.isObject(options) ? options : {};
var theme = options.theme || 'default';
@@ -320,7 +313,14 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
var color = angular.isObject(palette[hue]) ? palette[hue].hex : palette[hue];
- return setBrowserColor(color);
+ return setBrowserColor($$mdMeta, color);
+ };
+
+ var themeConfig = {
+ disableTheming : false, // Generate our themes at run time; also disable stylesheet DOM injection
+ generateOnDemand : false, // Whether or not themes are to be generated on-demand (vs. eagerly).
+ registeredStyles : [], // Custom styles registered to be used in the theming of custom components.
+ nonce : null // Nonce to be added as an attribute to the generated themes style tags.
};
return themingProvider = {
@@ -368,9 +368,13 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
alwaysWatchTheme = alwaysWatch;
},
- enableBrowserColor: enableBrowserColor,
+ enableBrowserColor: function(color) {
+ doBrowserColor(color);
+ },
- $get: ThemingService,
+ $get: ['$injector', function($injector) {
+ return $injector.invoke(themingService, undefined, { browserColor: browserColor });
+ }],
_LIGHT_DEFAULT_HUES: LIGHT_DEFAULT_HUES,
_DARK_DEFAULT_HUES: DARK_DEFAULT_HUES,
_PALETTES: PALETTES,
@@ -510,7 +514,8 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
self[colorType + 'Color'] = function() {
var args = Array.prototype.slice.call(arguments);
- console.warn('$mdThemingProviderTheme.' + colorType + 'Color() has been deprecated. ' +
+ var $log = $injector.get('$log');
+ $log.warn('$mdThemingProviderTheme.' + colorType + 'Color() has been deprecated. ' +
'Use $mdThemingProviderTheme.' + colorType + 'Palette() instead.');
return self[colorType + 'Palette'].apply(self, args);
};
@@ -630,7 +635,7 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
*/
/* @ngInject */
- function ThemingService($rootScope, $mdUtil, $q, $log) {
+ function themingService($rootScope, $mdUtil, $q, $log, $document, $$mdMeta, browserColor) {
// Allow us to be invoked via a linking function signature.
var applyTheme = function (scope, el) {
if (el === undefined) { el = scope; scope = undefined; }
@@ -656,7 +661,7 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
applyTheme.inherit = inheritTheme;
applyTheme.registered = registered;
applyTheme.defaultTheme = function() { return defaultTheme; };
- applyTheme.generateTheme = function(name) { generateTheme(THEMES[name], name, themeConfig.nonce); };
+ applyTheme.generateTheme = function(name) { generateTheme($document[0], THEMES[name], name, themeConfig.nonce); };
applyTheme.defineTheme = function(name, options) {
options = options || {};
@@ -682,7 +687,36 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
return $q.resolve(name);
};
- applyTheme.setBrowserColor = enableBrowserColor;
+
+ applyTheme.setBrowserColor = function (color) {
+ return enableBrowserColor($$mdMeta, color);
+ };
+
+ doBrowserColor = function (color) {
+ $log.warn("$mdThemingProvider.enableBrowserColor() is deprecated, use $mdTheming.setBrowserColor(); in run.");
+ applyTheme.setBrowserColor(color);
+ };
+
+ if ('color' in browserColor) {
+ doBrowserColor(browserColor.color);
+ delete browserColor.color;
+ }
+
+ applyTheme.isDisabled = function() {
+ return themeConfig.disableTheming;
+ };
+
+ applyTheme.registeredStyles = function() {
+ return themeConfig.registeredStyles.join('');
+ };
+
+ applyTheme.generateOnDemand = function() {
+ return themeConfig.generateOnDemand;
+ };
+
+ applyTheme.nonce = function() {
+ return themeConfig.nonce;
+ };
return applyTheme;
@@ -863,8 +897,6 @@ function ThemingDirective($mdTheming, $interpolate, $parse, $mdUtil, $q, $log) {
*
*/
function disableThemesDirective() {
- themeConfig.disableTheming = true;
-
// Return a 1x-only, first-match attribute directive
return {
restrict : 'A',
@@ -885,8 +917,8 @@ function parseRules(theme, colorType, rules) {
var themeNameRegex = new RegExp('\\.md-' + theme.name + '-theme', 'g');
// Matches '{{ primary-color }}', etc
- var hueRegex = new RegExp('(\'|")?{{\\s*(' + colorType + ')-(color|contrast)-?(\\d\\.?\\d*)?\\s*}}(\"|\')?','g');
- var simpleVariableRegex = /'?"?\{\{\s*([a-zA-Z]+)-(A?\d+|hue\-[0-3]|shadow|default)-?(\d\.?\d*)?(contrast)?\s*\}\}'?"?/g;
+ var hueRegex = new RegExp('(\'|")?{{\\s*(' + colorType + ')-(color|contrast)-?(\\d\\.?\\d*)?\\s*}}("|\')?','g');
+ var simpleVariableRegex = /'?"?\{\{\s*([a-zA-Z]+)-(A?\d+|hue-[0-3]|shadow|default)-?(\d\.?\d*)?(contrast)?\s*\}\}'?"?/g;
var palette = PALETTES[color.name];
// find and replace simple variables where we use a specific hue, not an entire palette
@@ -938,13 +970,25 @@ function parseRules(theme, colorType, rules) {
var rulesByType = {};
// Generate our themes at run time given the state of THEMES and PALETTES
-function generateAllThemes($injector, $mdTheming) {
- var head = document.head;
+/**
+ * @ngInject
+ */
+function generateAllThemes($injector, $mdTheming, $document) {
+ /**
+ * Detect if the HTML or the BODY tags has a [md-themes-disabled] attribute
+ * If yes, then immediately disable all theme stylesheet generation and DOM injection
+ */
+ var isDisabled = (
+ !$mdTheming.isDisabled || // tests tinker with $mdTheming
+ $mdTheming.isDisabled() ||
+ $document[0].querySelector('[md-themes-disabled]')
+ );
+ var head = $document[0].head;
var firstChild = head ? head.firstElementChild : null;
- var themeCss = !themeConfig.disableTheming && $injector.has('$MD_THEME_CSS') ? $injector.get('$MD_THEME_CSS') : '';
+ var themeCss = !isDisabled && $injector.has('$MD_THEME_CSS') ? $injector.get('$MD_THEME_CSS') : '';
// Append our custom registered styles to the theme stylesheet.
- themeCss += themeConfig.registeredStyles.join('');
+ themeCss += $mdTheming.registeredStyles ? $mdTheming.registeredStyles() : '';
if ( !firstChild ) return;
if (themeCss.length === 0) return; // no rules, so no point in running this expensive task
@@ -993,11 +1037,11 @@ function generateAllThemes($injector, $mdTheming) {
// If themes are being generated on-demand, quit here. The user will later manually
// call generateTheme to do this on a theme-by-theme basis.
- if (themeConfig.generateOnDemand) return;
+ if ($mdTheming.generateOnDemand()) return;
angular.forEach($mdTheming.THEMES, function(theme) {
if (!GENERATED[theme.name] && !($mdTheming.defaultTheme() !== 'default' && theme.name === 'default')) {
- generateTheme(theme, theme.name, themeConfig.nonce);
+ generateTheme($document[0], theme, theme.name, $mdTheming.nonce());
}
});
@@ -1063,7 +1107,7 @@ function generateAllThemes($injector, $mdTheming) {
}
}
-function generateTheme(theme, name, nonce) {
+function generateTheme(document, theme, name, nonce) {
var head = document.head;
var firstChild = head ? head.firstElementChild : null;
@@ -1139,4 +1183,4 @@ function rgba(rgbArray, opacity) {
}
-})(window.angular);
+})(angular);
diff --git a/src/core/services/theming/theming.spec.js b/src/core/services/theming/theming.spec.js
index 047da92a63..173be19687 100644
--- a/src/core/services/theming/theming.spec.js
+++ b/src/core/services/theming/theming.spec.js
@@ -5,6 +5,7 @@ describe('$mdThemingProvider', function() {
var testTheme;
var testPalette;
var startAngular = inject;
+ var postRun;
beforeEach(function() {
@@ -20,7 +21,21 @@ describe('$mdThemingProvider', function() {
});
function setup() {
- module('material.core', function($mdThemingProvider) {
+ var testM = 'material.theming.test';
+ var coreM = 'material.core';
+ var didRun;
+ // eslint-disable-next-line no-undef
+ postRun = new Promise(function (resolve) {
+ didRun = resolve;
+ });
+
+ angular
+ .module(testM, [coreM])
+ .run(function ($mdTheming) {
+ didRun();
+ });
+
+ module(coreM, testM, function($mdThemingProvider) {
themingProvider = $mdThemingProvider;
testPalette = themingProvider._PALETTES.testPalette = themingProvider._PALETTES.otherTestPalette = {
@@ -357,8 +372,10 @@ describe('$mdThemingProvider', function() {
themingProvider.enableBrowserColor();
- expect(document.getElementsByName(name).length).toBe(1);
- expect(angular.element(document.getElementsByName(name)[0]).attr('content')).toBe(content);
+ return postRun.then(function() {
+ expect(document.getElementsByName(name).length).toBe(1);
+ expect(angular.element(document.getElementsByName(name)[0]).attr('content')).toBe(content);
+ });
});
it('should use default primary color with hue `200`', function () {
@@ -372,8 +389,10 @@ describe('$mdThemingProvider', function() {
themingProvider.enableBrowserColor({ hue: hue });
- expect(document.getElementsByName(name).length).toBe(1);
- expect(angular.element(document.getElementsByName(name)[0]).attr('content')).toBe(content);
+ return postRun.then(function() {
+ expect(document.getElementsByName(name).length).toBe(1);
+ expect(angular.element(document.getElementsByName(name)[0]).attr('content')).toBe(content);
+ });
});
it('should use red palette', function () {
@@ -385,8 +404,10 @@ describe('$mdThemingProvider', function() {
themingProvider.enableBrowserColor({ palette: 'red' });
- expect(document.getElementsByName(name).length).toBe(1);
- expect(angular.element(document.getElementsByName(name)[0]).attr('content')).toBe(content);
+ return postRun.then(function() {
+ expect(document.getElementsByName(name).length).toBe(1);
+ expect(angular.element(document.getElementsByName(name)[0]).attr('content')).toBe(content);
+ });
});
it('should use test theme', function () {
@@ -398,10 +419,12 @@ describe('$mdThemingProvider', function() {
themingProvider.enableBrowserColor({ theme: 'test' });
- expect(document.getElementsByName(name).length).toBe(1);
- expect(angular.element(document.getElementsByName(name)[0]).attr('content')).toBe(content);
+ return postRun.then(function() {
+ expect(document.getElementsByName(name).length).toBe(1);
+ expect(angular.element(document.getElementsByName(name)[0]).attr('content')).toBe(content);
+ });
});
- })
+ });
describe('configuration', function () {
beforeEach(function () {
@@ -593,7 +616,7 @@ describe('$mdThemeProvider with disabled themes', function() {
it('should not set any classnames', function() {
inject(function($rootScope, $compile, $mdTheming) {
- el = $compile('Test
')($rootScope);
+ var el = $compile('Test
')($rootScope);
$mdTheming(el);
expect(el.hasClass('md-default-theme')).toBe(false);
});
@@ -601,7 +624,7 @@ describe('$mdThemeProvider with disabled themes', function() {
it('should not inject any styles', function() {
inject(function($rootScope, $compile, $mdTheming) {
- el = $compile('Test
')($rootScope);
+ var el = $compile('Test
')($rootScope);
$mdTheming(el);
var styles = getThemeStyleElements();
diff --git a/src/core/util/animation/animate.js b/src/core/util/animation/animate.js
index 96322a4921..d27bd0344d 100644
--- a/src/core/util/animation/animate.js
+++ b/src/core/util/animation/animate.js
@@ -1,20 +1,23 @@
// Polyfill angular < 1.4 (provide $animateCss)
angular
.module('material.core')
- .factory('$$mdAnimate', function($q, $timeout, $mdConstant, $animateCss){
+ .factory('$$mdAnimate', function($injector){
// Since $$mdAnimate is injected into $mdUtil... use a wrapper function
// to subsequently inject $mdUtil as an argument to the AnimateDomUtils
return function($mdUtil) {
- return AnimateDomUtils( $mdUtil, $q, $timeout, $mdConstant, $animateCss);
+ return $injector.invoke(animateDomUtils, undefined, { $mdUtil: $mdUtil });
};
});
/**
* Factory function that requires special injections
*/
-function AnimateDomUtils($mdUtil, $q, $timeout, $mdConstant, $animateCss) {
+/**
+ * @ngInject
+ */
+function animateDomUtils($mdUtil, $q, $timeout, $mdConstant, $animateCss, $window) {
var self;
return self = {
/**
@@ -92,7 +95,7 @@ function AnimateDomUtils($mdUtil, $q, $timeout, $mdConstant, $animateCss) {
* @returns {boolean} True if there is no transition/duration; false otherwise.
*/
function noTransitionFound(styles) {
- styles = styles || window.getComputedStyle(element[0]);
+ styles = styles || $window.getComputedStyle(element[0]);
return styles.transitionDuration == '0s' || (!styles.transition && !styles.transitionProperty);
}
diff --git a/src/core/util/animation/animateCss.js b/src/core/util/animation/animateCss.js
index 51dc161873..1232fd0955 100644
--- a/src/core/util/animation/animateCss.js
+++ b/src/core/util/animation/animateCss.js
@@ -6,14 +6,6 @@ if (angular.version.minor >= 4) {
var forEach = angular.forEach;
- var WEBKIT = angular.isDefined(document.documentElement.style.WebkitAppearance);
- var TRANSITION_PROP = WEBKIT ? 'WebkitTransition' : 'transition';
- var ANIMATION_PROP = WEBKIT ? 'WebkitAnimation' : 'animation';
- var PREFIX = WEBKIT ? '-webkit-' : '';
-
- var TRANSITION_EVENTS = (WEBKIT ? 'webkitTransitionEnd ' : '') + 'transitionend';
- var ANIMATION_EVENTS = (WEBKIT ? 'webkitAnimationEnd ' : '') + 'animationend';
-
var $$ForceReflowFactory = ['$document', function($document) {
return function() {
return $document[0].body.clientWidth + 1;
@@ -155,8 +147,16 @@ if (angular.version.minor >= 4) {
.factory('$$forceReflow', $$ForceReflowFactory)
.factory('$$AnimateRunner', $$AnimateRunnerFactory)
.factory('$$rAFMutex', $$rAFMutexFactory)
- .factory('$animateCss', ['$window', '$$rAF', '$$AnimateRunner', '$$forceReflow', '$$jqLite', '$timeout', '$animate',
- function($window, $$rAF, $$AnimateRunner, $$forceReflow, $$jqLite, $timeout, $animate) {
+ .factory('$animateCss', ['$window', '$$rAF', '$$AnimateRunner', '$$forceReflow', '$$jqLite', '$timeout', '$animate', '$document',
+ function($window, $$rAF, $$AnimateRunner, $$forceReflow, $$jqLite, $timeout, $animate, $document) {
+
+ var WEBKIT = angular.isDefined($document[0].documentElement.style.WebkitAppearance);
+ var TRANSITION_PROP = WEBKIT ? 'WebkitTransition' : 'transition';
+ var ANIMATION_PROP = WEBKIT ? 'WebkitAnimation' : 'animation';
+ var PREFIX = WEBKIT ? '-webkit-' : '';
+
+ var TRANSITION_EVENTS = (WEBKIT ? 'webkitTransitionEnd ' : '') + 'transitionend';
+ var ANIMATION_EVENTS = (WEBKIT ? 'webkitAnimationEnd ' : '') + 'animationend';
function init(element, options) {
diff --git a/src/core/util/animation/animateCss.spec.js b/src/core/util/animation/animateCss.spec.js
index 5f1bf7dcbb..639e414966 100644
--- a/src/core/util/animation/animateCss.spec.js
+++ b/src/core/util/animation/animateCss.spec.js
@@ -450,14 +450,17 @@ describe('$animateCss', function() {
function assertStyle(element, prop, val, not) {
var node = element[0];
var webKit = '-webkit-';
+ var otherVal;
+ var otherAssertion;
+ var key;
if (typeof prop === 'string') {
var assertion = expect(node.style[camelCase(prop)] || node.style[camelCase(webKit+prop)]);
not ? assertion.not.toBe(val) : assertion.toBe(val);
} else {
- for (var key in prop) {
- var val = prop[key];
- var assertion = expect(node.style[camelCase(key)] || node.style[camelCase(webKit+key)]);
- not ? assertion.not.toBe(val) : assertion.toBe(val);
+ for (key in prop) {
+ otherVal = prop[key];
+ otherAssertion = expect(node.style[camelCase(key)] || node.style[camelCase(webKit+key)]);
+ not ? otherAssertion.not.toBe(otherVal) : otherAssertion.toBe(otherVal);
}
}
}
diff --git a/src/core/util/color.js b/src/core/util/color.js
index b91726bb13..2e9135d6c7 100644
--- a/src/core/util/color.js
+++ b/src/core/util/color.js
@@ -60,7 +60,7 @@ function ColorUtilFactory() {
*/
function rgbaToRgb (color) {
return color
- ? color.replace('rgba', 'rgb').replace(/,[^\),]+\)/, ')')
+ ? color.replace('rgba', 'rgb').replace(/,[^),]+\)/, ')')
: 'rgb(0,0,0)';
}
diff --git a/src/core/util/constant.js b/src/core/util/constant.js
index 62c560a8f8..a081695489 100755
--- a/src/core/util/constant.js
+++ b/src/core/util/constant.js
@@ -5,9 +5,9 @@ angular.module('material.core')
* Factory function that creates the grab-bag $mdConstant service.
* @ngInject
*/
-function MdConstantFactory() {
+function MdConstantFactory($document) {
- var prefixTestEl = document.createElement('div');
+ var prefixTestEl = $document[0].createElement('div');
var vendorPrefix = getVendorPrefix(prefixTestEl);
var isWebkit = /webkit/i.test(vendorPrefix);
var SPECIAL_CHARS_REGEXP = /([:\-_]+(.))/g;
diff --git a/src/core/util/util.js b/src/core/util/util.js
index 0b3b82636e..70f29216d3 100644
--- a/src/core/util/util.js
+++ b/src/core/util/util.js
@@ -59,8 +59,8 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
var $mdUtil = {
dom: {},
- now: window.performance && window.performance.now ?
- angular.bind(window.performance, window.performance.now) : Date.now || function() {
+ now: $window.performance && $window.performance.now ?
+ angular.bind($window.performance, $window.performance.now) : Date.now || function() {
return new Date().getTime();
},
@@ -121,7 +121,7 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
clientRect: function(element, offsetParent, isOffsetRect) {
var node = getNode(element);
- offsetParent = getNode(offsetParent || node.offsetParent || document.body);
+ offsetParent = getNode(offsetParent || node.offsetParent || $document[0].body);
var nodeRect = node.getBoundingClientRect();
// The user can ask for an offsetRect: a rect relative to the offsetParent,
@@ -157,7 +157,7 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
* @returns {number}
*/
getViewportTop: function() {
- return window.scrollY || window.pageYOffset || 0;
+ return $window.scrollY || $window.pageYOffset || 0;
},
/**
@@ -348,7 +348,7 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
forceFocus: function(element) {
var node = element[0] || element;
- document.addEventListener('click', function focusOnClick(ev) {
+ $document[0].addEventListener('click', function focusOnClick(ev) {
if (ev.target === node && ev.$focus) {
node.focus();
ev.stopImmediatePropagation();
@@ -357,8 +357,8 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
}
}, true);
- var newEvent = document.createEvent('MouseEvents');
- newEvent.initMouseEvent('click', false, true, window, {}, 0, 0, 0, 0,
+ var newEvent = $document[0].createEvent('MouseEvents');
+ newEvent.initMouseEvent('click', false, true, $window, {}, 0, 0, 0, 0,
false, false, false, false, 0, null);
newEvent.$material = true;
newEvent.$focus = true;
@@ -380,7 +380,7 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
* be property names, property chains, or array indices.
*/
supplant: function(template, values, pattern) {
- pattern = pattern || /\{([^\{\}]*)\}/g;
+ pattern = pattern || /\{([^{}]*)\}/g;
return template.replace(pattern, function(a, b) {
var p = b.split('.'),
r = values;
@@ -570,7 +570,7 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
* Build polyfill for the Node.contains feature (if needed)
*/
elementContains: function(node, child) {
- var hasContains = (window.Node && window.Node.prototype && Node.prototype.contains);
+ var hasContains = ($window.Node && $window.Node.prototype && $window.Node.prototype.contains);
var findFn = hasContains ? angular.bind(node, node.contains) : angular.bind(node, function(arg) {
// compares the positions of two nodes and returns a bitmask
return (node === child) || !!(this.compareDocumentPosition(arg) & 16)
@@ -600,7 +600,7 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
* Breadth-First tree scan for element with matching `nodeName`
*/
function scanTree(element) {
- return scanLevel(element) || (!!scanDeep ? scanChildren(element) : null);
+ return scanLevel(element) || (scanDeep ? scanChildren(element) : null);
}
/**
@@ -736,7 +736,7 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
getNearestContentElement: function (element) {
var current = element.parent()[0];
// Look for the nearest parent md-content, stopping at the rootElement.
- while (current && current !== $rootElement[0] && current !== document.body && current.nodeName.toUpperCase() !== 'MD-CONTENT') {
+ while (current && current !== $rootElement[0] && current !== $document[0].body && current.nodeName.toUpperCase() !== 'MD-CONTENT') {
current = current.parentNode;
}
return current;