angular-material-npfixed
Version:
The Angular Material project is an implementation of Material Design in Angular.js. This project provides a set of reusable, well-tested, and accessible Material Design UI components. Angular Material is supported internally at Google by the Angular.js, M
195 lines (175 loc) • 5.3 kB
JavaScript
angular.module('material.core')
.factory('$mdMedia', mdMediaFactory);
/**
* @ngdoc service
* @name $mdMedia
* @module material.core
*
* @description
* `$mdMedia` is used to evaluate whether a given media query is true or false given the
* current device's screen / window size. The media query will be re-evaluated on resize, allowing
* you to register a watch.
*
* `$mdMedia` also has pre-programmed support for media queries that match the layout breakpoints:
*
* <table class="md-api-table">
* <thead>
* <tr>
* <th>Breakpoint</th>
* <th>mediaQuery</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td>xs</td>
* <td>(max-width: 599px)</td>
* </tr>
* <tr>
* <td>gt-xs</td>
* <td>(min-width: 600px)</td>
* </tr>
* <tr>
* <td>sm</td>
* <td>(min-width: 600px) and (max-width: 959px)</td>
* </tr>
* <tr>
* <td>gt-sm</td>
* <td>(min-width: 960px)</td>
* </tr>
* <tr>
* <td>md</td>
* <td>(min-width: 960px) and (max-width: 1279px)</td>
* </tr>
* <tr>
* <td>gt-md</td>
* <td>(min-width: 1280px)</td>
* </tr>
* <tr>
* <td>lg</td>
* <td>(min-width: 1280px) and (max-width: 1919px)</td>
* </tr>
* <tr>
* <td>gt-lg</td>
* <td>(min-width: 1920px)</td>
* </tr>
* <tr>
* <td>xl</td>
* <td>(min-width: 1920px)</td>
* </tr>
* <tr>
* <td>landscape</td>
* <td>landscape</td>
* </tr>
* <tr>
* <td>portrait</td>
* <td>portrait</td>
* </tr>
* <tr>
* <td>print</td>
* <td>print</td>
* </tr>
* </tbody>
* </table>
*
* See Material Design's <a href="https://material.google.com/layout/responsive-ui.html">Layout - Adaptive UI</a> for more details.
*
* <a href="https://www.google.com/design/spec/layout/adaptive-ui.html">
* <img src="https://material-design.storage.googleapis.com/publish/material_v_4/material_ext_publish/0B8olV15J7abPSGFxemFiQVRtb1k/layout_adaptive_breakpoints_01.png" width="100%" height="100%"></img>
* </a>
*
* @returns {boolean} a boolean representing whether or not the given media query is true or false.
*
* @usage
* <hljs lang="js">
* app.controller('MyController', function($mdMedia, $scope) {
* $scope.$watch(function() { return $mdMedia('lg'); }, function(big) {
* $scope.bigScreen = big;
* });
*
* $scope.screenIsSmall = $mdMedia('sm');
* $scope.customQuery = $mdMedia('(min-width: 1234px)');
* $scope.anotherCustom = $mdMedia('max-width: 300px');
* });
* </hljs>
*/
/* @ngInject */
function mdMediaFactory($mdConstant, $rootScope, $window) {
var queries = {};
var mqls = {};
var results = {};
var normalizeCache = {};
$mdMedia.getResponsiveAttribute = getResponsiveAttribute;
$mdMedia.getQuery = getQuery;
$mdMedia.watchResponsiveAttributes = watchResponsiveAttributes;
return $mdMedia;
function $mdMedia(query) {
var validated = queries[query];
if (angular.isUndefined(validated)) {
validated = queries[query] = validate(query);
}
var result = results[validated];
if (angular.isUndefined(result)) {
result = add(validated);
}
return result;
}
function validate(query) {
return $mdConstant.MEDIA[query] ||
((query.charAt(0) !== '(') ? ('(' + query + ')') : query);
}
function add(query) {
var result = mqls[query];
if ( !result ) {
result = mqls[query] = $window.matchMedia(query);
}
result.addListener(onQueryChange);
return (results[result.media] = !!result.matches);
}
function onQueryChange(query) {
$rootScope.$evalAsync(function() {
results[query.media] = !!query.matches;
});
}
function getQuery(name) {
return mqls[name];
}
function getResponsiveAttribute(attrs, attrName) {
for (var i = 0; i < $mdConstant.MEDIA_PRIORITY.length; i++) {
var mediaName = $mdConstant.MEDIA_PRIORITY[i];
if (!mqls[queries[mediaName]].matches) {
continue;
}
var normalizedName = getNormalizedName(attrs, attrName + '-' + mediaName);
if (attrs[normalizedName]) {
return attrs[normalizedName];
}
}
// fallback on unprefixed
return attrs[getNormalizedName(attrs, attrName)];
}
function watchResponsiveAttributes(attrNames, attrs, watchFn) {
var unwatchFns = [];
attrNames.forEach(function(attrName) {
var normalizedName = getNormalizedName(attrs, attrName);
if (angular.isDefined(attrs[normalizedName])) {
unwatchFns.push(
attrs.$observe(normalizedName, angular.bind(void 0, watchFn, null)));
}
for (var mediaName in $mdConstant.MEDIA) {
normalizedName = getNormalizedName(attrs, attrName + '-' + mediaName);
if (angular.isDefined(attrs[normalizedName])) {
unwatchFns.push(
attrs.$observe(normalizedName, angular.bind(void 0, watchFn, mediaName)));
}
}
});
return function unwatch() {
unwatchFns.forEach(function(fn) { fn(); });
};
}
// Improves performance dramatically
function getNormalizedName(attrs, attrName) {
return normalizeCache[attrName] ||
(normalizeCache[attrName] = attrs.$normalize(attrName));
}
}