Replaces yepnope.js with lazyload.js

Solves the caching and multi-load of the same file problems - adds a bit
of promise-based loading logic ontop of ll.js to ensure order and count
This commit is contained in:
per ploug
2014-04-29 11:38:13 +02:00
parent e964d52548
commit 90bf600378
9 changed files with 148 additions and 135 deletions

View File

@@ -0,0 +1,4 @@
LazyLoad=function(x,h){function r(b,a){var c=h.createElement(b),d;for(d in a)a.hasOwnProperty(d)&&c.setAttribute(d,a[d]);return c}function k(b){var a=i[b],c,d;if(a){c=a.callback;d=a.urls;d.shift();l=0;if(!d.length){c&&c.call(a.context,a.obj);i[b]=null;j[b].length&&m(b)}}}function w(){if(!e){var b=navigator.userAgent;e={async:h.createElement("script").async===true};(e.webkit=/AppleWebKit\//.test(b))||(e.ie=/MSIE/.test(b))||(e.opera=/Opera/.test(b))||(e.gecko=/Gecko\//.test(b))||(e.unknown=true)}}function m(b,
a,c,d,s){var n=function(){k(b)},o=b==="css",f,g,p;w();if(a){a=typeof a==="string"?[a]:a.concat();if(o||e.async||e.gecko||e.opera)j[b].push({urls:a,callback:c,obj:d,context:s});else{f=0;for(g=a.length;f<g;++f)j[b].push({urls:[a[f]],callback:f===g-1?c:null,obj:d,context:s})}}if(!(i[b]||!(p=i[b]=j[b].shift()))){q||(q=h.head||h.getElementsByTagName("head")[0]);a=p.urls;f=0;for(g=a.length;f<g;++f){c=a[f];if(o)c=r("link",{charset:"utf-8","class":"lazyload",href:c,rel:"stylesheet",type:"text/css"});else{c=
r("script",{charset:"utf-8","class":"lazyload",src:c});c.async=false}if(e.ie)c.onreadystatechange=function(){var t=this.readyState;if(t==="loaded"||t==="complete"){this.onreadystatechange=null;n()}};else if(o&&(e.gecko||e.webkit))if(e.webkit){p.urls[f]=c.href;u()}else setTimeout(n,50*g);else c.onload=c.onerror=n;q.appendChild(c)}}}function u(){var b=i.css,a;if(b){for(a=v.length;a&&--a;)if(v[a].href===b.urls[0]){k("css");break}l+=1;if(b)l<200?setTimeout(u,50):k("css")}}var e,q,i={},l=0,j={css:[],js:[]},
v=h.styleSheets;return{css:function(b,a,c,d){m("css",b,a,c,d)},js:function(b,a,c,d){m("js",b,a,c,d)}}}(this,this.document);

View File

@@ -50,14 +50,24 @@ angular.module('umbraco.services')
return url;
}
var rnd = Umbraco.Sys.ServerVariables.isDebuggingEnabled ? (new Date()).getTime() : Umbraco.Sys.ServerVariables.application.version +"."+Umbraco.Sys.ServerVariables.application.cdf;
var rnd = Umbraco.Sys.ServerVariables.application.version +"."+Umbraco.Sys.ServerVariables.application.cdf;
var _op = (url.indexOf("?")>0) ? "&" : "?";
url = url + _op + "umb__rnd=" + rnd;
return url;
};
return {
var service = {
loadedAssets:{},
_getAssetPromise : function(path){
if(this.loadedAssets[path]){
return this.loadedAssets[path];
}else{
var deferred = $q.defer();
this.loadedAssets[path] = {deferred: deferred, state: "new", path: path};
return this.loadedAssets[path];
}
},
/**
Internal method. This is called when the application is loading and the user is already authenticated, or once the user is authenticated.
There's a few assets the need to be loaded for the application to function but these assets require authentication to load.
@@ -97,21 +107,27 @@ angular.module('umbraco.services')
* @returns {Promise} Promise object which resolves when the file has loaded
*/
loadCss : function(path, scope, attributes, timeout){
var deferred = $q.defer();
var asset = this._getAssetPromise(path); // $q.defer();
var t = timeout || 5000;
var a = attributes || undefined;
yepnope.injectCss(appendRnd(path), function () {
if (!scope) {
deferred.resolve(true);
}else{
angularHelper.safeApply(scope, function () {
deferred.resolve(true);
});
}
},a,t);
return deferred.promise;
if(asset.state === "new"){
asset.state = "loading";
LazyLoad.css(appendRnd(path), function () {
if (!scope) {
asset.state = "loaded";
asset.deferred.resolve(true);
}else{
asset.state = "loaded";
angularHelper.safeApply(scope, function () {
asset.deferred.resolve(true);
});
}
});
}else if(asset.state === "loaded"){
asset.deferred.resolve(true);
}
return asset.deferred.promise;
},
/**
@@ -129,22 +145,31 @@ angular.module('umbraco.services')
* @returns {Promise} Promise object which resolves when the file has loaded
*/
loadJs : function(path, scope, attributes, timeout){
var deferred = $q.defer();
var asset = this._getAssetPromise(path); // $q.defer();
var t = timeout || 5000;
var a = attributes || undefined;
yepnope.injectJs(appendRnd(path), function () {
if (!scope) {
deferred.resolve(true);
}else{
angularHelper.safeApply(scope, function () {
deferred.resolve(true);
});
}
},a,t);
if(asset.state === "new"){
asset.state = "loading";
LazyLoad.js(appendRnd(path), function () {
if (!scope) {
asset.state = "loaded";
asset.deferred.resolve(true);
}else{
asset.state = "loaded";
angularHelper.safeApply(scope, function () {
asset.deferred.resolve(true);
});
}
});
return deferred.promise;
}else if(asset.state === "loaded"){
asset.deferred.resolve(true);
}
return asset.deferred.promise;
},
/**
@@ -162,8 +187,7 @@ angular.module('umbraco.services')
* @returns {Promise} Promise object which resolves when all the files has loaded
*/
load: function (pathArray, scope) {
var deferred = $q.defer();
var promise;
var nonEmpty = _.reject(pathArray, function(item) {
return item === undefined || item === "";
});
@@ -171,36 +195,55 @@ angular.module('umbraco.services')
//don't load anything if there's nothing to load
if (nonEmpty.length > 0) {
yepnope({
load: pathArray,
complete: function() {
var promises = [];
var assets = [];
//if a scope is supplied then we need to make a digest here because
// deferred only executes in a digest. This might be required if we
// are doing a load script after an http request or some other async call.
if (!scope) {
deferred.resolve(true);
}
else {
angularHelper.safeApply(scope, function () {
deferred.resolve(true);
});
//compile a list of promises
//blocking
_.each(nonEmpty, function(path){
var asset = service._getAssetPromise(path);
//if not previously loaded, add to list of promises
if(asset.state !== "loaded")
{
if(asset.state === "new"){
asset.state = "loading";
assets.push(asset);
}
//we need to always push to the promises collection to monitor correct
//execution
promises.push(asset.deferred.promise);
}
});
}
else {
if (!scope) {
deferred.resolve(true);
}
else {
angularHelper.safeApply(scope, function () {
deferred.resolve(true);
});
}
//gives a central monitoring of all assets to load
promise = $q.all(promises);
_.each(assets, function(asset){
LazyLoad.js(appendRnd(asset.path), function () {
if (!scope) {
asset.state = "loaded";
asset.deferred.resolve(true);
}else{
asset.state = "loaded";
angularHelper.safeApply(scope, function () {
asset.deferred.resolve(true);
});
}
});
});
}else{
//return and resolve
var deferred = $q.defer();
promise = deferred.promise;
deferred.resolve(true);
}
return deferred.promise;
return promise;
}
};
return service;
});

View File

@@ -22,7 +22,7 @@
<umb-notifications></umb-notifications>
<script src="lib/yepnope/yepnope.min.js"></script>
<script src="lib/lazyload/lazyload.min.js"></script>
<script src="js/loader.js"></script>
</body>
</html>

View File

@@ -1,61 +1,47 @@
//global no-cache filter, this is enabled when we're in debug mode
//in live mode we use client dependency and don't turn this thing on
yepnope.addFilter(function (resourceObj) {
var url = resourceObj.url;
if(url.indexOf("lib/") === 0 || url.indexOf("js/umbraco.") === 0){
return resourceObj;
}
LazyLoad.js(
[
'lib/jquery/jquery-2.0.3.min.js',
resourceObj.url = resourceObj.url + "?umb__rnd=" + (new Date).getTime();
return resourceObj;
});
/* the jquery ui elements we need */
'lib/jquery/jquery-ui-1.10.3.custom.min.js',
/* 1.1.5 */
'lib/angular/1.1.5/angular.min.js',
'lib/angular/1.1.5/angular-cookies.min.js',
'lib/angular/1.1.5/angular-mobile.min.js',
'lib/angular/1.1.5/angular-mocks.js',
'lib/angular/1.1.5/angular-sanitize.min.js',
'lib/angular/angular-ui-sortable.js',
yepnope({
/* App-wide file-upload helper */
'lib/jquery/jquery.upload/js/jquery.fileupload.js',
'lib/jquery/jquery.upload/js/jquery.fileupload-process.js',
'lib/jquery/jquery.upload/js/jquery.fileupload-angular.js',
'lib/bootstrap/js/bootstrap.2.3.2.min.js',
'lib/underscore/underscore.js',
'lib/umbraco/Extensions.js',
'lib/umbraco/NamespaceManager.js',
load: [
'lib/jquery/jquery-2.0.3.min.js',
'js/umbraco.servervariables.js',
'js/app.dev.js',
'js/umbraco.httpbackend.js',
'js/umbraco.testing.js',
/* the jquery ui elements we need */
'lib/jquery/jquery-ui-1.10.3.custom.min.js',
/* 1.1.5 */
'lib/angular/1.1.5/angular.min.js',
'lib/angular/1.1.5/angular-cookies.min.js',
'lib/angular/1.1.5/angular-mobile.min.js',
'lib/angular/1.1.5/angular-mocks.js',
'lib/angular/1.1.5/angular-sanitize.min.js',
'lib/angular/angular-ui-sortable.js',
/* App-wide file-upload helper */
'lib/jquery/jquery.upload/js/jquery.fileupload.js',
'lib/jquery/jquery.upload/js/jquery.fileupload-process.js',
'lib/jquery/jquery.upload/js/jquery.fileupload-angular.js',
'lib/bootstrap/js/bootstrap.2.3.2.min.js',
'lib/underscore/underscore.js',
'lib/umbraco/Extensions.js',
'lib/umbraco/NamespaceManager.js',
'js/umbraco.servervariables.js',
'js/app.dev.js',
'js/umbraco.httpbackend.js',
'js/umbraco.testing.js',
'js/umbraco.directives.js',
'js/umbraco.filters.js',
'js/umbraco.resources.js',
'js/umbraco.services.js',
'js/umbraco.security.js',
'js/umbraco.controllers.js',
'js/routes.js',
'js/init.js'
'js/umbraco.directives.js',
'js/umbraco.filters.js',
'js/umbraco.resources.js',
'js/umbraco.services.js',
'js/umbraco.security.js',
'js/umbraco.controllers.js',
'js/routes.js',
'js/init.js'
],
complete: function () {
function () {
jQuery(document).ready(function () {
angular.bootstrap(document, ['umbraco']);
});
});
}
});
);