diff --git a/README.md b/README.md
index 3edf08b..913e1d5 100644
--- a/README.md
+++ b/README.md
@@ -222,20 +222,58 @@ AngularCSS supports "smart media queries". This means that stylesheets with medi
This will significantly optimize the load time of your apps.
```js
-css: [
- {
- href: 'my-page/my-page.mobile.css',
- media: 'screen and (max-width: 480px)'
- }, {
- href: 'my-page/my-page.tablet.css',
- media: 'screen and (min-width: 768px) and (max-width: 1024px)'
- }, {
- href: 'my-page/my-page.desktop.css',
- media: 'screen and (min-width: 1224px)'
- }
-]
+$routeProvider
+ .when('/my-page', {
+ templateUrl: 'my-page/my-page.html',
+ css: [
+ {
+ href: 'my-page/my-page.mobile.css',
+ media: '(max-width: 480px)'
+ }, {
+ href: 'my-page/my-page.tablet.css',
+ media: '(min-width: 768px) and (max-width: 1024px)'
+ }, {
+ href: 'my-page/my-page.desktop.css',
+ media: '(min-width: 1224px)'
+ }
+ ]
+ });
```
+Even though you can use the `media` property to specify media queries, the best way to manage your breakpoins is by settings them in the provider's defaults. For example:
+
+```js
+myApp.config(function($routeProvider, $cssProvider) {
+
+ angular.extend($cssProvider.defaults, {
+ breakpoints: {
+ mobile: '(max-width: 480px)',
+ tablet: '(min-width: 768px) and (max-width: 1024px)',
+ desktop: '(min-width: 1224px)'
+ }
+ });
+
+ $routeProvider
+ .when('/my-page', {
+ templateUrl: 'my-page/my-page.html',
+ css: [
+ {
+ href: 'my-page/my-page.mobile.css',
+ breakpoint: 'mobile'
+ }, {
+ href: 'my-page/my-page.tablet.css',
+ breakpoint: 'tablet'
+ }, {
+ href: 'my-page/my-page.desktop.css',
+ breakpoint: 'desktop'
+ }
+ ]
+ });
+
+});
+```
+
+
### Config
You can configure AngularCSS at the global level or at the stylesheet level.
diff --git a/angular-css.js b/angular-css.js
index 4969756..26f4f61 100644
--- a/angular-css.js
+++ b/angular-css.js
@@ -1,6 +1,6 @@
/**
* AngularCSS - CSS on-demand for AngularJS
- * @version v1.0.6
+ * @version v1.0.7
* @author DOOR3, Alex Castillo
* @link http://door3.github.io/angular-css
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -35,8 +35,8 @@
weight: 0
};
- this.$get = ['$rootScope','$injector','$window','$timeout','$compile','$http','$filter','$log',
- function $get($rootScope, $injector, $window, $timeout, $compile, $http, $filter, $log) {
+ this.$get = ['$rootScope','$injector','$q','$window','$timeout','$compile','$http','$filter','$log',
+ function $get($rootScope, $injector, $q, $window, $timeout, $compile, $http, $filter, $log) {
var $css = {};
@@ -44,7 +44,8 @@
// Variables - default options that can be overridden from application config
var mediaQuery = {}, mediaQueryListener = {}, mediaQueriesToIgnore = ['print'], options = angular.extend({}, defaults),
- container = angular.element(document.querySelector ? document.querySelector(options.container) : document.getElementsByTagName(options.container)[0]);
+ container = angular.element(document.querySelector ? document.querySelector(options.container) : document.getElementsByTagName(options.container)[0]),
+ dynamicPaths = [];
// Parse all directives
angular.forEach($directives, function (directive, key) {
@@ -69,7 +70,9 @@
function $routeEventListener(event, current, prev) {
// Removes previously added css rules
if (prev) {
- $css.remove($css.getFromRoute(prev));
+ $css.remove($css.getFromRoute(prev).concat(dynamicPaths));
+ // Reset dynamic paths array
+ dynamicPaths.length = 0;
}
// Adds current css rules
if (current) {
@@ -83,7 +86,9 @@
function $stateEventListener(event, current, params, prev) {
// Removes previously added css rules
if (prev) {
- $css.remove($css.getFromState(prev));
+ $css.remove($css.getFromState(prev).concat(dynamicPaths));
+ // Reset dynamic paths array
+ dynamicPaths.length = 0;
}
// Adds current css rules
if (current) {
@@ -91,6 +96,18 @@
}
}
+ /**
+ * Map breakpoitns defined in defaults to stylesheet media attribute
+ **/
+ function mapBreakpointToMedia(stylesheet) {
+ if (angular.isDefined(options.breakpoints)) {
+ if (stylesheet.breakpoint in options.breakpoints) {
+ stylesheet.media = options.breakpoints[stylesheet.breakpoint];
+ }
+ delete stylesheet.breakpoints;
+ }
+ }
+
/**
* Parse: returns array with full all object based on defaults
**/
@@ -98,6 +115,10 @@
if (!obj) {
return;
}
+ // Function syntax
+ if (angular.isFunction(obj)) {
+ obj = angular.copy($injector.invoke(obj));
+ }
// String syntax
if (angular.isString(obj)) {
obj = angular.extend({
@@ -122,6 +143,8 @@
obj = angular.extend(item, options);
});
}
+ // Map breakpoint to media attribute
+ mapBreakpointToMedia(obj);
return obj;
}
@@ -135,10 +158,10 @@
$rootScope.$on('$directiveAdd', $directiveAddEventListener);
// Routes event listener ($route required)
- $rootScope.$on('$routeChangeStart', $routeEventListener);
+ $rootScope.$on('$routeChangeSuccess', $routeEventListener);
// States event listener ($state required)
- $rootScope.$on('$stateChangeStart', $stateEventListener);
+ $rootScope.$on('$stateChangeSuccess', $stateEventListener);
/**
* Bust Cache
@@ -249,10 +272,16 @@
if (css) {
if (angular.isArray(css)) {
angular.forEach(css, function (cssItem) {
+ if (angular.isFunction(cssItem)) {
+ dynamicPaths.push(parse(cssItem));
+ }
result.push(parse(cssItem));
});
} else {
- result.push(parse(css));
+ if (angular.isFunction(css)) {
+ dynamicPaths.push(parse(css));
+ }
+ result.push(parse(css));
}
}
return result;
@@ -288,6 +317,9 @@
if (angular.isDefined(state.views)) {
angular.forEach(state.views, function (item) {
if (item.css) {
+ if (angular.isFunction(item.css)) {
+ dynamicPaths.push(parse(item.css));
+ }
result.push(parse(item.css));
}
});
@@ -296,11 +328,17 @@
if (angular.isDefined(state.children)) {
angular.forEach(state.children, function (child) {
if (child.css) {
+ if (angular.isFunction(child.css)) {
+ dynamicPaths.push(parse(child.css));
+ }
result.push(parse(child.css));
}
if (angular.isDefined(child.children)) {
angular.forEach(child.children, function (childChild) {
if (childChild.css) {
+ if (angular.isFunction(childChild.css)) {
+ dynamicPaths.push(parse(childChild.css));
+ }
result.push(parse(childChild.css));
}
});
@@ -312,10 +350,16 @@
// For multiple stylesheets
if (angular.isArray(state.css)) {
angular.forEach(state.css, function (itemCss) {
+ if (angular.isFunction(itemCss)) {
+ dynamicPaths.push(parse(itemCss));
+ }
result.push(parse(itemCss));
});
// For single stylesheets
} else {
+ if (angular.isFunction(state.css)) {
+ dynamicPaths.push(parse(state.css));
+ }
result.push(parse(state.css));
}
}
@@ -363,21 +407,26 @@
if ($injector.has('$state')) {
Array.prototype.push.apply(stylesheets, $css.getFromStates($injector.get('$state').get()));
}
+ stylesheets = filterBy(stylesheets, 'preload');
}
- stylesheets = filterBy(stylesheets, 'preload');
- angular.forEach(stylesheets, function(stylesheet, index) {
- // Preload via ajax request
- $http.get(stylesheet.href)
- .success(function (response) {
- $log.debug('preload response: ' + response);
- if (stylesheets.length === (index + 1) && angular.isFunction(callback)) {
- callback(stylesheets);
- }
+ if (!angular.isArray(stylesheets)) {
+ stylesheets = [stylesheets];
+ }
+ var stylesheetLoadPromises = [];
+ angular.forEach(stylesheets, function(stylesheet, key) {
+ stylesheet = stylesheets[key] = parse(stylesheet);
+ stylesheetLoadPromises.push(
+ // Preload via ajax request
+ $http.get(stylesheet.href).error(function (response) {
+ $log.error('AngularCSS: Incorrect path for ' + stylesheet.href);
})
- .error(function (response) {
- $log.error('Incorrect path for ' + stylesheet.href);
- });
+ );
});
+ if (angular.isFunction(callback)) {
+ $q.all(stylesheetLoadPromises).then(function () {
+ callback(stylesheets);
+ });
+ }
};
/**
diff --git a/angular-css.min.js b/angular-css.min.js
index 9d4bb90..07f2f84 100644
--- a/angular-css.min.js
+++ b/angular-css.min.js
@@ -1 +1 @@
-"use strict";!function(e){var r=e.module("door3.css",[]);r.config(["$logProvider",function(e){e.debugEnabled(!1)}]),r.provider("$css",[function(){var r=this.defaults={element:"link",rel:"stylesheet",type:"text/css",container:"head",method:"append",weight:0};this.$get=["$rootScope","$injector","$window","$timeout","$compile","$http","$filter","$log",function(s,n,o,i,c,u,a,f){function h(e,r,t){t&&r.hasOwnProperty("css")&&b.bind([p(r.css)],t)}function d(e,r,t){t&&b.remove(b.getFromRoute(t)),r&&b.add(b.getFromRoute(r))}function l(e,r,t,s){s&&b.remove(b.getFromState(s)),r&&b.add(b.getFromState(r))}function p(r){return r?(e.isString(r)&&(r=e.extend({href:r},N)),e.isArray(r)&&e.isString(r[0])&&e.forEach(r,function(t){r=e.extend({href:t},N)}),e.isObject(r)&&!e.isArray(r)&&(r=e.extend(r,N)),e.isArray(r)&&e.isObject(r[0])&&e.forEach(r,function(t){r=e.extend(t,N)}),r):void 0}function y(e){if(!e)return f.error("No stylesheets provided");var r="?cache=";-1===e.href.indexOf(r)&&(e.href=e.href+(e.bustCache?r+(new Date).getTime():""))}function m(e,r){return e&&r?a("filter")(e,function(e){return e[r]}):f.error("filterBy: missing array or property")}function v(e){return e?(F[e.href]=o.matchMedia(e.media),A[e.href]=function(r){i(function(){if(r.matches)s.stylesheets.push(e);else{var t=s.stylesheets.indexOf(a("filter")(s.stylesheets,{href:e.href})[0]);-1!==t&&s.stylesheets.splice(t,1)}})},F[e.href].addListener(A[e.href]),void A[e.href](F[e.href])):f.error("No stylesheet provided")}function g(r){return r?void(s&&e.isDefined(F)&&F[r.href]&&e.isDefined(A)&&F[r.href].removeListener(A[r.href])):f.error("No stylesheet provided")}function $(e){return e?!(!e.media||-1!==S.indexOf(e.media)||!o.matchMedia):f.error("No stylesheet provided")}var b={},E='',F={},A={},S=["print"],N=e.extend({},r),w=e.element(document.querySelector?document.querySelector(N.container):document.getElementsByTagName(N.container)[0]);return e.forEach(t,function(e,r){e.hasOwnProperty("css")&&(t[r]=p(e.css))}),s.stylesheets=[],w[N.method](c(E)(s)),s.$on("$directiveAdd",h),s.$on("$routeChangeStart",d),s.$on("$stateChangeStart",l),b.getFromRoute=function(r){if(!r)return f.error("Get From Route: No route provided");var t=null,s=[];return r.$$route&&r.$$route.css?t=r.$$route.css:r.css&&(t=r.css),t&&(e.isArray(t)?e.forEach(t,function(e){s.push(p(e))}):s.push(p(t))),s},b.getFromRoutes=function(r){if(!r)return f.error("Get From Routes: No routes provided");var t=[];return e.forEach(r,function(e){var r=b.getFromRoute(e);r.length&&t.push(r[0])}),t},b.getFromState=function(r){if(!r)return f.error("Get From State: No state provided");var t=[];return e.isDefined(r.views)&&e.forEach(r.views,function(e){e.css&&t.push(p(e.css))}),e.isDefined(r.children)&&e.forEach(r.children,function(r){r.css&&t.push(p(r.css)),e.isDefined(r.children)&&e.forEach(r.children,function(e){e.css&&t.push(p(e.css))})}),e.isDefined(r.css)&&(e.isArray(r.css)?e.forEach(r.css,function(e){t.push(p(e))}):t.push(p(r.css))),t},b.getFromStates=function(r){if(!r)return f.error("Get From States: No states provided");var t=[];return e.forEach(r,function(r){var s=b.getFromState(r);e.isArray(s)?e.forEach(s,function(e){t.push(e)}):t.push(s)}),t},b.preload=function(r,s){r||(r=[],t.length&&Array.prototype.push.apply(r,t),n.has("$route")&&Array.prototype.push.apply(r,b.getFromRoutes(n.get("$route").routes)),n.has("$state")&&Array.prototype.push.apply(r,b.getFromStates(n.get("$state").get()))),r=m(r,"preload"),e.forEach(r,function(t,n){u.get(t.href).success(function(t){f.debug("preload response: "+t),r.length===n+1&&e.isFunction(s)&&s(r)}).error(function(){f.error("Incorrect path for "+t.href)})})},b.bind=function(r,t){if(!r||!t)return f.error("No scope or stylesheets provided");var s=[];e.isArray(r)?e.forEach(r,function(e){s.push(p(e))}):s.push(p(r)),b.add(s),f.debug("$css.bind(): Added",s),t.$on("$destroy",function(){b.remove(s),f.debug("$css.bind(): Removed",s)})},b.add=function(r){return r?(e.isArray(r)||(r=[r]),e.forEach(r,function(e){e=p(e),e.href&&!a("filter")(s.stylesheets,{href:e.href}).length&&(y(e),$(e)?v(e):s.stylesheets.push(e),f.debug("$css.add(): "+e.href))}),void s.$broadcast("$cssAdd",r,s.stylesheets)):f.error("No stylesheets provided")},b.remove=function(r){return r?(r=a("filter")(r,function(e){return!e.persist}),e.forEach(r,function(e){var r=s.stylesheets.indexOf(a("filter")(s.stylesheets,{href:e.href})[0]);-1!==r&&s.stylesheets.splice(r,1),g(e),f.debug("$css.remove(): "+e.href)}),void s.$broadcast("$cssRemove",r,s.stylesheets)):f.error("No stylesheets provided")},b.removeAll=function(){s&&s.hasOwnProperty("stylesheets")&&(s.stylesheets.length=0),f.debug("all stylesheets removed")},b.preload(),b}]}]),r.filter("$cssLinks",function(){return function(r){if(!r||!e.isArray(r))return r;var t="";return e.forEach(r,function(e){t+='\n\n"}),t}}),r.run(["$css",function(){}]);var t=[],s=e.module;e.module=function(){var r=s.apply(this,arguments),n=r.directive;return r.directive=function(r,s){var o=e.isFunction(s)?s:s[s.length-1];try{var i=e.copy(o)();i.directiveName=r,i.hasOwnProperty("css")&&t.push(i)}catch(c){}return n.apply(this,arguments)},r.config(["$provide","$injector",function(r,s){e.forEach(t,function(e){var t=e.directiveName+"Directive";s.has(t)&&r.decorator(t,["$delegate","$rootScope","$timeout",function(r,t,s){var n=r[0],o=n.compile;return n.css&&(e.css=n.css),n.compile=function(){var e=o?o.apply(this,arguments):!1;return function(r){var o=arguments;s(function(){e&&e.apply(this,o)}),t.$broadcast("$directiveAdd",n,r)}},r}])})}]),r}}(angular);
\ No newline at end of file
+/*! angular-css 1.0.7 | Copyright (c) 2015 DOOR3, Alex Castillo | MIT License */"use strict";!function(a){var b=a.module("door3.css",[]);b.config(["$logProvider",function(a){a.debugEnabled(!1)}]),b.provider("$css",[function(){var b=this.defaults={element:"link",rel:"stylesheet",type:"text/css",container:"head",method:"append",weight:0};this.$get=["$rootScope","$injector","$q","$window","$timeout","$compile","$http","$filter","$log",function(d,e,f,g,h,i,j,k,l){function m(a,b,c){c&&b.hasOwnProperty("css")&&w.bind([q(b.css)],c)}function n(a,b,c){c&&(w.remove(w.getFromRoute(c).concat(D)),D.length=0),b&&w.add(w.getFromRoute(b))}function o(a,b,c,d){d&&(w.remove(w.getFromState(d).concat(D)),D.length=0),b&&w.add(w.getFromState(b))}function p(b){a.isDefined(B.breakpoints)&&(b.breakpoint in B.breakpoints&&(b.media=B.breakpoints[b.breakpoint]),delete b.breakpoints)}function q(b){return b?(a.isFunction(b)&&(b=a.copy(e.invoke(b))),a.isString(b)&&(b=a.extend({href:b},B)),a.isArray(b)&&a.isString(b[0])&&a.forEach(b,function(c){b=a.extend({href:c},B)}),a.isObject(b)&&!a.isArray(b)&&(b=a.extend(b,B)),a.isArray(b)&&a.isObject(b[0])&&a.forEach(b,function(c){b=a.extend(c,B)}),p(b),b):void 0}function r(a){if(!a)return l.error("No stylesheets provided");var b="?cache=";-1===a.href.indexOf(b)&&(a.href=a.href+(a.bustCache?b+(new Date).getTime():""))}function s(a,b){return a&&b?k("filter")(a,function(a){return a[b]}):l.error("filterBy: missing array or property")}function t(a){return a?(y[a.href]=g.matchMedia(a.media),z[a.href]=function(b){h(function(){if(b.matches)d.stylesheets.push(a);else{var c=d.stylesheets.indexOf(k("filter")(d.stylesheets,{href:a.href})[0]);-1!==c&&d.stylesheets.splice(c,1)}})},y[a.href].addListener(z[a.href]),void z[a.href](y[a.href])):l.error("No stylesheet provided")}function u(b){return b?void(d&&a.isDefined(y)&&y[b.href]&&a.isDefined(z)&&y[b.href].removeListener(z[b.href])):l.error("No stylesheet provided")}function v(a){return a?!(!a.media||-1!==A.indexOf(a.media)||!g.matchMedia):l.error("No stylesheet provided")}var w={},x='',y={},z={},A=["print"],B=a.extend({},b),C=a.element(document.querySelector?document.querySelector(B.container):document.getElementsByTagName(B.container)[0]),D=[];return a.forEach(c,function(a,b){a.hasOwnProperty("css")&&(c[b]=q(a.css))}),d.stylesheets=[],C[B.method](i(x)(d)),d.$on("$directiveAdd",m),d.$on("$routeChangeSuccess",n),d.$on("$stateChangeSuccess",o),w.getFromRoute=function(b){if(!b)return l.error("Get From Route: No route provided");var c=null,d=[];return b.$$route&&b.$$route.css?c=b.$$route.css:b.css&&(c=b.css),c&&(a.isArray(c)?a.forEach(c,function(b){a.isFunction(b)&&D.push(q(b)),d.push(q(b))}):(a.isFunction(c)&&D.push(q(c)),d.push(q(c)))),d},w.getFromRoutes=function(b){if(!b)return l.error("Get From Routes: No routes provided");var c=[];return a.forEach(b,function(a){var b=w.getFromRoute(a);b.length&&c.push(b[0])}),c},w.getFromState=function(b){if(!b)return l.error("Get From State: No state provided");var c=[];return a.isDefined(b.views)&&a.forEach(b.views,function(b){b.css&&(a.isFunction(b.css)&&D.push(q(b.css)),c.push(q(b.css)))}),a.isDefined(b.children)&&a.forEach(b.children,function(b){b.css&&(a.isFunction(b.css)&&D.push(q(b.css)),c.push(q(b.css))),a.isDefined(b.children)&&a.forEach(b.children,function(b){b.css&&(a.isFunction(b.css)&&D.push(q(b.css)),c.push(q(b.css)))})}),a.isDefined(b.css)&&(a.isArray(b.css)?a.forEach(b.css,function(b){a.isFunction(b)&&D.push(q(b)),c.push(q(b))}):(a.isFunction(b.css)&&D.push(q(b.css)),c.push(q(b.css)))),c},w.getFromStates=function(b){if(!b)return l.error("Get From States: No states provided");var c=[];return a.forEach(b,function(b){var d=w.getFromState(b);a.isArray(d)?a.forEach(d,function(a){c.push(a)}):c.push(d)}),c},w.preload=function(b,d){b||(b=[],c.length&&Array.prototype.push.apply(b,c),e.has("$route")&&Array.prototype.push.apply(b,w.getFromRoutes(e.get("$route").routes)),e.has("$state")&&Array.prototype.push.apply(b,w.getFromStates(e.get("$state").get())),b=s(b,"preload")),a.isArray(b)||(b=[b]);var g=[];a.forEach(b,function(a,c){a=b[c]=q(a),g.push(j.get(a.href).error(function(){l.error("AngularCSS: Incorrect path for "+a.href)}))}),a.isFunction(d)&&f.all(g).then(function(){d(b)})},w.bind=function(b,c){if(!b||!c)return l.error("No scope or stylesheets provided");var d=[];a.isArray(b)?a.forEach(b,function(a){d.push(q(a))}):d.push(q(b)),w.add(d),l.debug("$css.bind(): Added",d),c.$on("$destroy",function(){w.remove(d),l.debug("$css.bind(): Removed",d)})},w.add=function(b){return b?(a.isArray(b)||(b=[b]),a.forEach(b,function(a){a=q(a),a.href&&!k("filter")(d.stylesheets,{href:a.href}).length&&(r(a),v(a)?t(a):d.stylesheets.push(a),l.debug("$css.add(): "+a.href))}),void d.$broadcast("$cssAdd",b,d.stylesheets)):l.error("No stylesheets provided")},w.remove=function(b){return b?(a.isArray(b)||(b=[b]),b=k("filter")(b,function(a){return!a.persist}),a.forEach(b,function(a){a=q(a);var b=d.stylesheets.indexOf(k("filter")(d.stylesheets,{href:a.href})[0]);-1!==b&&d.stylesheets.splice(b,1),u(a),l.debug("$css.remove(): "+a.href)}),void d.$broadcast("$cssRemove",b,d.stylesheets)):l.error("No stylesheets provided")},w.removeAll=function(){d&&d.hasOwnProperty("stylesheets")&&(d.stylesheets.length=0),l.debug("all stylesheets removed")},w.preload(),w}]}]),b.filter("$cssLinks",function(){return function(b){if(!b||!a.isArray(b))return b;var c="";return a.forEach(b,function(a){c+='\n\n"}),c}}),b.run(["$css",function(){}]);var c=[],d=a.module;a.module=function(){var b=d.apply(this,arguments),e=b.directive;return b.directive=function(b,d){var f=a.isFunction(d)?d:d[d.length-1];try{var g=a.copy(f)();g.directiveName=b,g.hasOwnProperty("css")&&c.push(g)}catch(h){}return e.apply(this,arguments)},b.config(["$provide","$injector",function(b,d){a.forEach(c,function(a){var c=a.directiveName+"Directive";d.has(c)&&b.decorator(c,["$delegate","$rootScope","$timeout",function(b,c,d){var e=b[0],f=e.compile;return e.css&&(a.css=e.css),e.compile=function(){var a=f?f.apply(this,arguments):!1;return function(b){var f=arguments;d(function(){a&&a.apply(this,f)}),c.$broadcast("$directiveAdd",e,b)}},b}])})}]),b}}(angular);
\ No newline at end of file
diff --git a/bower.json b/bower.json
index 107268b..0bb696a 100644
--- a/bower.json
+++ b/bower.json
@@ -1,7 +1,7 @@
{
"name": "angular-css",
"main": "./angular-css.js",
- "version": "1.0.6",
+ "version": "1.0.7",
"homepage": "http://door3.github.io/angular-css",
"authors": [
"Alex Castillo "
diff --git a/package.json b/package.json
index 62bb600..d91c523 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "angular-css",
"filename": "angular-css.js",
"description": "CSS on-demand for AngularJS",
- "version": "1.0.6",
+ "version": "1.0.7",
"homepage": "http://door3.github.io/angular-css",
"repository": {
"type": "git",