Skip to content

Commit

Permalink
Merge pull request #84 from wibblymat/resource-handlers
Browse files Browse the repository at this point in the history
Handle resources other than JavaScript
  • Loading branch information
addyosmani committed Sep 1, 2013
2 parents df4d354 + 39c72e0 commit c7fa593
Show file tree
Hide file tree
Showing 3 changed files with 338 additions and 22 deletions.
7 changes: 5 additions & 2 deletions Gruntfile.js
Expand Up @@ -53,8 +53,10 @@ module.exports = function( grunt ) {
}
},
watch: {
files: '<%= jshint.all %>',
tasks: 'jshint test'
scripts: {
files: '<%= jshint.all %>',
tasks: ['test']
}
},
connect: {
server: {
Expand All @@ -77,6 +79,7 @@ module.exports = function( grunt ) {
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-watch');

// Dev - default
grunt.registerTask('default', ['test']);
Expand Down
95 changes: 75 additions & 20 deletions lib/basket.js
Expand Up @@ -51,52 +51,57 @@
xhr.onreadystatechange = function() {
if ( xhr.readyState === 4 ) {
if( xhr.status === 200 ) {
promise.resolve( xhr.responseText );
promise.resolve( {
content: xhr.responseText,
type: xhr.getResponseHeader('content-type')
});
} else {
promise.reject( new Error( xhr.statusText ) );
}
}
};

// By default XHRs never timeout, and even Chrome doesn't implement the
// spec for xhr.timeout. So we do it ourselves.
setTimeout( function () {
if( xhr.readyState < 4 ) {
xhr.abort();
}
}, basket.timeout );
xhr.send();

return promise;
};

var saveUrl = function( obj ) {
return getUrl( obj.url ).then( function( text ) {
var storeObj = wrapStoreData( obj, text );
return getUrl( obj.url ).then( function( result ) {
var storeObj = wrapStoreData( obj, result );

addLocalStorage( obj.key , storeObj );

return storeObj;
});
};

var injectScript = function( obj ) {
var script = document.createElement('script');
script.defer = true;
// Have to use .text, since we support IE8,
// which won't allow appending to a script
script.text = obj.data;
head.appendChild( script );
};

var wrapStoreData = function( obj, data ) {
var now = +new Date();
obj.data = data;
obj.data = data.content;
obj.originalType = data.type;
obj.type = obj.type || data.type;
obj.stamp = now;
obj.expire = now + ( ( obj.expire || defaultExpiration ) * 60 * 60 * 1000 );

return obj;
};

var isValidItem = function(source, obj) {
return (!source || source.expire - +new Date() < 0 || obj.unique !== source.unique || (basket.isValidItem && !basket.isValidItem(source, obj)));
var isCacheValid = function(source, obj) {
return !source ||
source.expire - +new Date() < 0 ||
obj.unique !== source.unique ||
(basket.isValidItem && !basket.isValidItem(source, obj));
};

var handleStackObject = function( obj ) {
var source, promise;
var source, promise, shouldFetch;

if ( !obj.url ) {
return;
Expand All @@ -107,24 +112,59 @@

obj.execute = obj.execute !== false;

if (isValidItem(source, obj)) {
shouldFetch = isCacheValid(source, obj);

if( obj.live || shouldFetch ) {
if ( obj.unique ) {
// set parameter to prevent browser cache
obj.url += ( ( obj.url.indexOf('?') > 0 ) ? '&' : '?' ) + 'basket-unique=' + obj.unique;
}
promise = saveUrl( obj );

if( obj.live && !shouldFetch ) {
promise = promise
.then( function( result ) {
// If we succeed, just return the value
// RSVP doesn't have a .fail convenience method
return result;
}, function() {
return source;
});
}
} else {
source.type = obj.type || source.originalType;
promise = new RSVP.Promise();
promise.resolve( source );
}

return promise;
};

var injectScript = function( obj ) {
var script = document.createElement('script');
script.defer = true;
// Have to use .text, since we support IE8,
// which won't allow appending to a script
script.text = obj.data;
head.appendChild( script );
};

var handlers = {
'default': injectScript
};

var execute = function( obj ) {
if( obj.type && handlers[ obj.type ] ) {
return handlers[ obj.type ]( obj );
}

return handlers['default']( obj ); // 'default' is a reserved word
};

var performActions = function( resources ) {
resources.map( function( obj ) {
if( obj.execute ) {
injectScript( obj );
execute( obj );
}

return obj;
Expand Down Expand Up @@ -186,7 +226,22 @@
return this;
},

isValidItem: null
isValidItem: null,

timeout: 5000,

addHandler: function( types, handler ) {
if( !Array.isArray( types ) ) {
types = [ types ];
}
types.forEach( function( type ) {
handlers[ type ] = handler;
});
},

removeHandler: function( types ) {
basket.addHandler( types, undefined );
}
};

// delete expired keys
Expand Down

0 comments on commit c7fa593

Please sign in to comment.