UNPKG

angular-media-queries

Version:

Angular service to test if a given @media statment is true.

193 lines (155 loc) 6.95 kB
# Angular matchMedia Module Provides an Angular service that returns true if the current screen width matches or false if not. Uses the screen widths predefined in Twitter Bootstrap 3 or a customized size you define. There is a staic method `is` which checks for a match on page load and a dynamic method `on` which checks for a match and updates the value on window resize. ## Installation Download the component via bower: ```bash bower install --save angular-media-queries ``` Include AngularJS on the page and then include this script. If possible, include these scripts in the footer of your site before the closing `</body>` tag. ```html <script type='text/javascript' src='/static/path/to/angular.min.js'></script> <script type='text/javascript' src='/static/path/to/angular-media-queries/match-media.js'></script> ``` ## Usage Require the `matchMedia` module as a dependency in your app: ```javascript angular.module('myApp', ['matchMedia']) ``` ### In a Controller #### Is Use the service's `is` method to determine if the screensize matches the given string/array. ```javascript angular.module('myApp', ['matchMedia']) .controller('mainController', ['screenSize', function (screenSize) { var data = complicatedChartData; //Determine to either perform cpu/network-intensive actions(desktop) or retrieve a small static image(mobile). if (screenSize.is('xs, sm')) { // it's a mobile device so fetch a small image $http.post('/imageGenerator', data) .success(function (response) { document.querySelector('.chart').src = response.chartUrl; }); } else { // it's a desktop size so do the complicated calculations and render that document.querySelector('.chart') .appendCanvas() .parseData() .renderCrazyChart(); } }]); ``` #### On The callback fed to `.on` will execute on every window resize and takes the truthiness of the media query as its first argument. Be careful using this method as `resize` events fire often and can bog down your application if not handled properly. - Executes the callback function on window resize with the match truthiness as the first argument. - Returns the current match truthiness. - Passing $scope as a third parameter is optional, when not passed it will use $rootScope ```javascript angular.module('myApp', ['matchMedia']) .controller('mainController', ['screenSize', function (screenSize) { $scope.isMobile = screenSize.on('xs, sm', function(isMatch){ $scope.isMobile = isMatch; }); }]); ``` #### When If you only want the callback to fire while in the correct screensize, use the `when` method. Be careful using this method as `resize` events fire often and can bog down your application if not handled properly. ```javascript angular.module('myApp', ['matchMedia']) .controller('mainController', ['screenSize', function (screenSize) { // Will fire as long as the screen is size between 768px and 991px screenSize.when('sm', function() { console.log('Your screen size at the moment is between 768px and 991px.'); }); }]); ``` #### OnChange The callback fed to `.onChange` will execute on every window resize and takes the truthiness of the media query as its first argument. Be careful using this method as `resize` events fire often and can bog down your application if not handled properly. - Executes the callback function ONLY when the match differs from previous match. - Returns the current match truthiness. - The 'scope' parameter is required for cleanup reasons (destroy event). ```javascript angular.module('myApp', ['matchMedia']) .controller('mainController', ['screenSize', function (screenSize) { $scope.isMobile = screenSize.onChange('xs, sm', function(isMatch){ $scope.isMobile = isMatch; }); }]); ``` #### isRetina This will return a boolean to indicate if the current screen is hi-def/retina. ```javascript angular.module('myApp', ['matchMedia']) .controller('mainController', ['screenSize', function (screenSize) { $scope.isRetina = screenSize.isRetina; }]); ``` ### Filter Operate on string values with the filter: Have the placeholder sign % replaced by the actual media query rule name. #### Example: ```html <div> {{'Your screen size is: ' | media }} "</div> ``` #### Example with replace: ```html <div ng-include="'/views/_partials/_team_%.html' | media:{ replace: '%' }"></div> ``` #### Extended example: ```html <div ng-include="'/views/_partials/_team_%.html' | media:{ replace: '%', groups: { mobile:['ti','xs','sm'], desktop:['md','lg'] } }"></div> ``` ### ngIf Example In your controller you can create variables that correspond to screen sizes. For example add the following to your controller: ```javascript // Using static method `is` angular.module('myApp', ['matchMedia']) .controller('mainController', ['screenSize', function (screenSize) { $scope.desktop = screenSize.is('md, lg'); $scope.mobile = screenSize.is('xs, sm'); }]); // Using dynamic method `on`, which will set the variables initially and then update the variable on window resize $scope.desktop = screenSize.on('md, lg', function(match){ $scope.desktop = match; }); $scope.mobile = screenSize.on('xs, sm', function(match){ $scope.mobile = match; }); ``` Then in your HTML you can show or hide content using ngIf or similar directives that take an Angular expression: ```javascript <img ng-if='desktop' ng-src='http://example.com/path/to/giant/image.jpg'> ``` This particular example is great for only loading large, unnecessary images on desktop computers. Note: It's important if you plan on using screensize.is() in directives to assign its return value to a scoped variable. If you don't, it will only be evaluated once and will not update if the window is resized or if a mobile device is turned sideways. ### Custom Screen Sizes or Media Queries You can access and therefore customize the media queries or create your own: ```javascript angular.module('myApp', ['matchMedia']) .controller('mainController', ['screenSize', function (screenSize) { screenSize.rules = { retina: 'only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx)', superJumbo: '(min-width: 2000px)', }; if (screenSize.is('retina')) { // switch out regular images for hi-dpi ones } if (screenSize.is('superJumbo')) { // do something for enormous screens } }]); ``` ## License This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/deed.en_US. ## Contributors * Module roughly based on https://github.com/chrismatheson/ngMediaFilter * Polyfill from https://github.com/paulirish/matchMedia.js/ * @jacopotarantino * @thatmarvin * Matthias Max @bitflowertweets ## Todo * Write tests. * Add a simple directive wrapper for ng-if. * Add Grunt tasks.