Skip to content

Commit

Permalink
Merge pull request #1278 from SergioCrisostomo/cssAssets
Browse files Browse the repository at this point in the history
add onLoad callback for cross-origin CSS assets
  • Loading branch information
anutron committed Jul 29, 2014
2 parents 6d07f3a + e5f81bf commit d0d5712
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 34 deletions.
2 changes: 2 additions & 0 deletions Docs/Utilities/Assets.md
Expand Up @@ -52,6 +52,8 @@ Injects a css file in the page.

1. source - (*string*) The path of the CSS file.
2. properties - (*object*) Some additional attributes you might want to add to the link Element; this is the same as the second argument you might pass to including the Element constructor. For instance you might specify a title attribute or perhaps an id.
- onLoad - (*function*) A function that will be invoked when the CSS is loaded.
- timeout - (*number*, defaults to 3000 ms) The maximum amount of milliseconds to wait for onLoad callback to be called.
- document - (*object*, defaults to `document`) The document which the link element should be injected in.


Expand Down
1 change: 1 addition & 0 deletions Gruntfile.js
Expand Up @@ -82,6 +82,7 @@ module.exports = function(grunt) {

options: {
captureTimeout: 60000 * 2,
browserNoActivityTimeout: 20000,
singleRun: true,
frameworks: ['jasmine', 'sinon'],
files: [
Expand Down
40 changes: 29 additions & 11 deletions Source/Utilities/Assets.js
Expand Up @@ -50,22 +50,40 @@ var Asset = {
css: function(source, properties){
if (!properties) properties = {};

var load = properties.onload || properties.onLoad,
doc = properties.document || document,
timeout = properties.timeout || 3000;

['onload', 'onLoad', 'document'].each(function(prop){
delete properties[prop];
});

var link = new Element('link', {
type: 'text/css',
rel: 'stylesheet',
media: 'screen',
type: 'text/css',
href: source
});

var load = properties.onload || properties.onLoad,
doc = properties.document || document;

delete properties.onload;
delete properties.onLoad;
delete properties.document;
}).setProperties(properties).inject(doc.head);

if (load) link.addEvent('load', load);
return link.set(properties).inject(doc.head);
if (load){
// based on article at http://www.yearofmoo.com/2011/03/cross-browser-stylesheet-preloading.html
var loaded = false, retries = 0;
var check = function(){
var stylesheets = document.styleSheets;
for (var i = 0; i < stylesheets.length; i++){
var file = stylesheets[i];
var owner = file.ownerNode ? file.ownerNode : file.owningElement;
if (owner && owner == link){
loaded = true;
return load.call(link);
}
}
retries++;
if (!loaded && retries < timeout / 50) return setTimeout(check, 50);
}
setTimeout(check, 0);
}
return link;
},

image: function(source, properties){
Expand Down
65 changes: 42 additions & 23 deletions Specs/Utilities/Assets.js
Expand Up @@ -20,7 +20,7 @@ describe('Assets', function(){
}
});

waits(500);
waits(800);

runs(function(){
expect(myScript.get('tag')).toEqual('script');
Expand All @@ -31,35 +31,59 @@ describe('Assets', function(){
});

});

});

describe('Assets.css', function(){

it('should load a css file and fire the load event', function(){

var load = jasmine.createSpy('load');
function addCSS(source, load){
new Element('div', {
id: 'moologo'
}).inject($(document.body));

var myCSS = Asset.css('base/Tests/Specs/assets/Assets.css.test.css', {
return myCSS = Asset.css(source, {
id: 'myStyle',
title: 'myStyle',
onload: function(){
onLoad: function(){
load(this);
}
});
}

afterEach(function(){
$('myStyle').destroy();
$('moologo').destroy();
});

waits(500);
it('should load a external css file and run load callback', function(){
var load = jasmine.createSpy('load');
var url = 'https://rawgit.com/mootools/mootools-more/master/Tests/Specs/assets/Assets.css.test.css';
var myCSS = addCSS(url, load);
var myCSS = addCSS(url, load);

waits(3000);
runs(function(){
expect(myCSS.get('tag')).toEqual('link');
expect(myCSS.id).toEqual('myStyle');
// Current implementation of assets uses the load event which only works in IE/Opera
// expect(load).toHaveBeenCalledWith(myCSS);
myCSS.destroy();
expect(load).toHaveBeenCalledWith(myCSS);
load = myCSS = null;
});

});

it('should load a local css file and run load callback', function(){
var load = jasmine.createSpy('load');
var url = 'base/Tests/Specs/assets/Assets.css.test.css';
var myCSS = addCSS(url, load);

waits(2000);
runs(function(){
var border = $('moologo').getStyle('border');
expect(load).toHaveBeenCalledWith(myCSS);
expect(myCSS.get('tag')).toEqual('link');
expect(myCSS.id).toEqual('myStyle');
expect(border.contains('4px solid')).toBeTruthy();
load = myCSS = null;
});
});
});

describe('Assets.image', function(){
Expand All @@ -74,7 +98,7 @@ describe('Assets', function(){
onload: load
});

waits(500);
waits(800);

runs(function(){
expect(myImage.get('tag')).toEqual('img');
Expand All @@ -97,7 +121,7 @@ describe('Assets', function(){
onerror: error
});

waits(500);
waits(800);

runs(function(){
expect(load).not.toHaveBeenCalled();
Expand All @@ -122,7 +146,7 @@ describe('Assets', function(){
onload: loaded
});

waits(500);
waits(800);

runs(function(){
expect(loadedagain).toHaveBeenCalled();
Expand All @@ -141,16 +165,14 @@ describe('Assets', function(){
onerror: error
});

waits(500);
waits(800);

runs(function(){
expect(load).not.toHaveBeenCalled();
expect(error).toHaveBeenCalledWith(myImage);
myImage.destroy();
});

});

});

describe('Assets.images', function(){
Expand All @@ -170,7 +192,7 @@ describe('Assets', function(){
onError: error
});

waits(500);
waits(800);

runs(function(){
expect(complete).toHaveBeenCalled();
Expand All @@ -196,16 +218,13 @@ describe('Assets', function(){
onError: error
});

waits(500);
waits(800);

runs(function(){
expect(complete).toHaveBeenCalled();
expect(progress.callCount).toEqual(1);
expect(error.callCount).toEqual(2);
});

});

});

});

0 comments on commit d0d5712

Please sign in to comment.