From 5a0d0b7fa043678d09409e3b0a7a9d541b65663f Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Mon, 5 Mar 2012 22:44:58 +0100 Subject: Added basic playlist implementation using backbone.js. --- static/backbone-localstorage.js | 84 +++++++++++++++++++++ static/backbone-min.js | 37 +++++++++ .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 260 -> 0 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 251 -> 0 bytes .../ui-bg_diagonals-thick_90_eeeeee_40x40.png | Bin 0 -> 251 bytes static/images/ui-bg_flat_10_000000_40x100.png | Bin 178 -> 0 bytes static/images/ui-bg_flat_15_cd0a0a_40x100.png | Bin 0 -> 181 bytes static/images/ui-bg_glass_100_ebebeb_1x400.png | Bin 0 -> 114 bytes static/images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 104 -> 0 bytes static/images/ui-bg_glass_100_fdf5ce_1x400.png | Bin 125 -> 0 bytes static/images/ui-bg_glass_50_8f8f8f_1x400.png | Bin 0 -> 114 bytes static/images/ui-bg_glass_65_ffffff_1x400.png | Bin 105 -> 0 bytes static/images/ui-bg_glass_80_e6e6e6_1x400.png | Bin 0 -> 113 bytes .../images/ui-bg_gloss-wave_35_f6a828_500x100.png | Bin 3762 -> 0 bytes .../ui-bg_highlight-hard_100_f5f5f5_1x100.png | Bin 0 -> 87 bytes .../ui-bg_highlight-hard_70_000000_1x100.png | Bin 0 -> 118 bytes .../ui-bg_highlight-soft_100_e6e6e6_1x100.png | Bin 0 -> 92 bytes .../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 90 -> 0 bytes .../ui-bg_highlight-soft_25_ffef8f_1x100.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_ffe45c_1x100.png | Bin 129 -> 0 bytes static/images/ui-icons_222222_256x240.png | Bin 4369 -> 0 bytes static/images/ui-icons_228ef1_256x240.png | Bin 4369 -> 0 bytes static/images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes static/images/ui-icons_444_256x240.png | Bin 0 -> 399 bytes static/images/ui-icons_757575_256x240.png | Bin 0 -> 4369 bytes static/images/ui-icons_858585_256x240.png | Bin 0 -> 4369 bytes static/images/ui-icons_9c9c9c_256x240.png | Bin 0 -> 5355 bytes static/images/ui-icons_edef01_256x240.png | Bin 0 -> 4369 bytes static/images/ui-icons_ef8c08_256x240.png | Bin 5355 -> 0 bytes static/images/ui-icons_ffd27a_256x240.png | Bin 4369 -> 0 bytes static/index.html | 23 +++++- static/init.js | 42 +---------- static/jquery-ui-1.8.18.custom.css | 58 +++++++------- static/playlist.js | 57 ++++++++++++++ static/sound.js | 53 +++++++++++++ static/style.css | 16 ++-- static/underscore-min.js | 31 ++++++++ 37 files changed, 322 insertions(+), 79 deletions(-) create mode 100644 static/backbone-localstorage.js create mode 100644 static/backbone-min.js delete mode 100644 static/images/ui-bg_diagonals-thick_18_b81900_40x40.png delete mode 100644 static/images/ui-bg_diagonals-thick_20_666666_40x40.png create mode 100644 static/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png delete mode 100644 static/images/ui-bg_flat_10_000000_40x100.png create mode 100644 static/images/ui-bg_flat_15_cd0a0a_40x100.png create mode 100644 static/images/ui-bg_glass_100_ebebeb_1x400.png delete mode 100644 static/images/ui-bg_glass_100_f6f6f6_1x400.png delete mode 100644 static/images/ui-bg_glass_100_fdf5ce_1x400.png create mode 100644 static/images/ui-bg_glass_50_8f8f8f_1x400.png delete mode 100644 static/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 static/images/ui-bg_glass_80_e6e6e6_1x400.png delete mode 100644 static/images/ui-bg_gloss-wave_35_f6a828_500x100.png create mode 100644 static/images/ui-bg_highlight-hard_100_f5f5f5_1x100.png create mode 100644 static/images/ui-bg_highlight-hard_70_000000_1x100.png create mode 100644 static/images/ui-bg_highlight-soft_100_e6e6e6_1x100.png delete mode 100644 static/images/ui-bg_highlight-soft_100_eeeeee_1x100.png create mode 100644 static/images/ui-bg_highlight-soft_25_ffef8f_1x100.png delete mode 100644 static/images/ui-bg_highlight-soft_75_ffe45c_1x100.png delete mode 100644 static/images/ui-icons_222222_256x240.png delete mode 100644 static/images/ui-icons_228ef1_256x240.png create mode 100644 static/images/ui-icons_2e83ff_256x240.png create mode 100644 static/images/ui-icons_444_256x240.png create mode 100644 static/images/ui-icons_757575_256x240.png create mode 100644 static/images/ui-icons_858585_256x240.png create mode 100644 static/images/ui-icons_9c9c9c_256x240.png create mode 100644 static/images/ui-icons_edef01_256x240.png delete mode 100644 static/images/ui-icons_ef8c08_256x240.png delete mode 100644 static/images/ui-icons_ffd27a_256x240.png create mode 100644 static/playlist.js create mode 100644 static/sound.js create mode 100644 static/underscore-min.js diff --git a/static/backbone-localstorage.js b/static/backbone-localstorage.js new file mode 100644 index 0000000..091d7f3 --- /dev/null +++ b/static/backbone-localstorage.js @@ -0,0 +1,84 @@ +// A simple module to replace `Backbone.sync` with *localStorage*-based +// persistence. Models are given GUIDS, and saved into a JSON object. Simple +// as that. + +// Generate four random hex digits. +function S4() { + return (((1+Math.random())*0x10000)|0).toString(16).substring(1); +}; + +// Generate a pseudo-GUID by concatenating random hexadecimal. +function guid() { + return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()); +}; + +// Our Store is represented by a single JS object in *localStorage*. Create it +// with a meaningful name, like the name you'd give a table. +var Store = function(name) { + this.name = name; + var store = localStorage.getItem(this.name); + this.data = (store && JSON.parse(store)) || {}; +}; + +_.extend(Store.prototype, { + + // Save the current state of the **Store** to *localStorage*. + save: function() { + localStorage.setItem(this.name, JSON.stringify(this.data)); + }, + + // Add a model, giving it a (hopefully)-unique GUID, if it doesn't already + // have an id of it's own. + create: function(model) { + if (!model.id) model.id = model.attributes.id = guid(); + this.data[model.id] = model; + this.save(); + return model; + }, + + // Update a model by replacing its copy in `this.data`. + update: function(model) { + this.data[model.id] = model; + this.save(); + return model; + }, + + // Retrieve a model from `this.data` by id. + find: function(model) { + return this.data[model.id]; + }, + + // Return the array of all models currently in storage. + findAll: function() { + return _.values(this.data); + }, + + // Delete a model from `this.data`, returning it. + destroy: function(model) { + delete this.data[model.id]; + this.save(); + return model; + } + +}); + +// Override `Backbone.sync` to use delegate to the model or collection's +// *localStorage* property, which should be an instance of `Store`. +Backbone.sync = function(method, model, options) { + + var resp; + var store = model.localStorage || model.collection.localStorage; + + switch (method) { + case "read": resp = model.id ? store.find(model) : store.findAll(); break; + case "create": resp = store.create(model); break; + case "update": resp = store.update(model); break; + case "delete": resp = store.destroy(model); break; + } + + if (resp) { + options.success(resp); + } else { + options.error("Record not found"); + } +}; \ No newline at end of file diff --git a/static/backbone-min.js b/static/backbone-min.js new file mode 100644 index 0000000..5846b32 --- /dev/null +++ b/static/backbone-min.js @@ -0,0 +1,37 @@ +// Backbone.js 0.9.1 + +// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Backbone may be freely distributed under the MIT license. +// For all details and documentation: +// http://backbonejs.org +(function(){var i=this,r=i.Backbone,s=Array.prototype.slice,t=Array.prototype.splice,g;g="undefined"!==typeof exports?exports:i.Backbone={};g.VERSION="0.9.1";var f=i._;!f&&"undefined"!==typeof require&&(f=require("underscore"));var h=i.jQuery||i.Zepto||i.ender;g.setDomLibrary=function(a){h=a};g.noConflict=function(){i.Backbone=r;return this};g.emulateHTTP=!1;g.emulateJSON=!1;g.Events={on:function(a,b,c){for(var d,a=a.split(/\s+/),e=this._callbacks||(this._callbacks={});d=a.shift();){d=e[d]||(e[d]= +{});var f=d.tail||(d.tail=d.next={});f.callback=b;f.context=c;d.tail=f.next={}}return this},off:function(a,b,c){var d,e,f;if(a){if(e=this._callbacks)for(a=a.split(/\s+/);d=a.shift();)if(f=e[d],delete e[d],b&&f)for(;(f=f.next)&&f.next;)if(!(f.callback===b&&(!c||f.context===c)))this.on(d,f.callback,f.context)}else delete this._callbacks;return this},trigger:function(a){var b,c,d,e;if(!(d=this._callbacks))return this;e=d.all;for((a=a.split(/\s+/)).push(null);b=a.shift();)e&&a.push({next:e.next,tail:e.tail, +event:b}),(c=d[b])&&a.push({next:c.next,tail:c.tail});for(e=s.call(arguments,1);c=a.pop();){b=c.tail;for(d=c.event?[c.event].concat(e):e;(c=c.next)!==b;)c.callback.apply(c.context||this,d)}return this}};g.Events.bind=g.Events.on;g.Events.unbind=g.Events.off;g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=j(this,"defaults"))a=f.extend({},c,a);b&&b.collection&&(this.collection=b.collection);this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");if(!this.set(a, +{silent:!0}))throw Error("Can't create an invalid model");delete this._changed;this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(g.Model.prototype,g.Events,{idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.attributes[a];return this._escapedAttributes[a]=f.escape(null==b?"":""+b)},has:function(a){return null!= +this.attributes[a]},set:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;d instanceof g.Model&&(d=d.attributes);if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return!1;this.idAttribute in d&&(this.id=d[this.idAttribute]);var b=this.attributes,k=this._escapedAttributes,n=this._previousAttributes||{},h=this._setting;this._changed||(this._changed={});this._setting=!0;for(e in d)if(a=d[e],f.isEqual(b[e],a)||delete k[e],c.unset?delete b[e]:b[e]= +a,this._changing&&!f.isEqual(this._changed[e],a)&&(this.trigger("change:"+e,this,a,c),this._moreChanges=!0),delete this._changed[e],!f.isEqual(n[e],a)||f.has(b,e)!=f.has(n,e))this._changed[e]=a;h||(!c.silent&&this.hasChanged()&&this.change(c),this._setting=!1);return this},unset:function(a,b){(b||(b={})).unset=!0;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=!0;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=a?f.clone(a):{},b=this,c=a.success;a.success=function(d, +e,f){if(!b.set(b.parse(d,f),a))return!1;c&&c(b,d)};a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};c.wait&&(e=f.clone(this.attributes));a=f.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c))return!1;var k=this,h=c.success;c.success=function(a,b,e){b=k.parse(a,e);c.wait&&(b=f.extend(d||{},b));if(!k.set(b,c))return!1;h?h(k,a):k.trigger("sync",k,a,c)};c.error=g.wrapError(c.error, +k,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d();a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=j(this.collection,"url")||j(this,"urlRoot")||o();return this.isNew()? +a:a+("/"==a.charAt(a.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){if(this._changing||!this.hasChanged())return this;this._moreChanges=this._changing=!0;for(var b in this._changed)this.trigger("change:"+b,this,this._changed[b],a);for(;this._moreChanges;)this._moreChanges=!1,this.trigger("change",this,a);this._previousAttributes=f.clone(this.attributes); +delete this._changed;this._changing=!1;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this._changed):this._changed&&f.has(this._changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this._changed):!1;var b,c=!1,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length||!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)}, +isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return!0;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error?b.error(this,c,b):this.trigger("error",this,c,b);return!1}});g.Collection=function(a,b){b||(b={});b.comparator&&(this.comparator=b.comparator);this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:!0,parse:b.parse})};f.extend(g.Collection.prototype,g.Events,{model:g.Model,initialize:function(){}, +toJSON:function(){return this.map(function(a){return a.toJSON()})},add:function(a,b){var c,d,e,g,h,i={},j={};b||(b={});a=f.isArray(a)?a.slice():[a];for(c=0,d=a.length;c=b))this.iframe=h('