diff --git a/assets/js/application.js b/assets/js/application.js index 36ed350..6ec5b3b 100644 --- a/assets/js/application.js +++ b/assets/js/application.js @@ -1,39 +1,12 @@ -var QueueSong = can.Model({ - findAll: 'GET /api/queue' -}, {}); - -var queueSongs = new can.List(); - -// Update the queue display when the queueSongs list changes -queueSongs.bind('change', function(event) { - $('#queue').html(can.view('queueTemplate', - { songs: this })); -}); - -// Get the songs currently in the queue -QueueSong.findAll({}, function(songs) { - queueSongs.replace(songs); -}, function(xhr) { - console.log("An error occured with the request."); -}); - -var updatePlaying = function(queue, index) { - queue.forEach(function(element) { - element.attr('playing', false); - }); - item = queue.attr(index); - item.attr('playing', true); -} - // Set up necessary events and startup stuff $(document).ready(function() { - // Bind transport click events. - $('#transport').on('click', '#controls button', function(e) { - e.preventDefault(); - var action = $(e.currentTarget).data('action'); - can.ajax({ url: '/api/control/'+action, type: 'PUT' }); + + $.when(QueueSong.findAll(), Status.findOne()).then(function(queueSongs, status) { + new Transport('#transport'); + new Queue('#queue', { + queueSongs: queueSongs, + status: status + }); }); - // Render transport - $('#transport').html(can.view('transportTemplate')); }); diff --git a/assets/js/controls/queue.js b/assets/js/controls/queue.js new file mode 100644 index 0000000..32d7a99 --- /dev/null +++ b/assets/js/controls/queue.js @@ -0,0 +1,10 @@ +var Queue = can.Control.extend({ + + init: function(element, options) { + element.html(can.view('views/queue.ejs', { + queueSongs: options.queueSongs, + status: options.status + })); + } + +}); diff --git a/assets/js/controls/transport.js b/assets/js/controls/transport.js new file mode 100644 index 0000000..8f16adf --- /dev/null +++ b/assets/js/controls/transport.js @@ -0,0 +1,16 @@ +var Transport = can.Control.extend({ + + init: function(element) { + element.html(can.view('views/transport.ejs')); + }, + + sendCommand: function(command) { + can.ajax({ url: '/api/control/'+command, type: 'PUT' }); + }, + + 'button click': function(element, event) { + var command = $(element).data('command'); + this.sendCommand(command); + } + +}); diff --git a/assets/js/libs/can.ejs.js b/assets/js/libs/can.ejs.js new file mode 100755 index 0000000..ba25d30 --- /dev/null +++ b/assets/js/libs/can.ejs.js @@ -0,0 +1,174 @@ +/*! + * CanJS - 2.0.3 + * http://canjs.us/ + * Copyright (c) 2013 Bitovi + * Tue, 26 Nov 2013 18:21:40 GMT + * Licensed MIT + * Includes: can/view/ejs + * Download from: http://canjs.com + */ +(function(can) { + // ## ejs.js + // `can.EJS` + // _Embedded JavaScript Templates._ + + // Helper methods. + var extend = can.extend, + EJS = function(options) { + // Supports calling EJS without the constructor + // This returns a function that renders the template. + if (this.constructor != EJS) { + var ejs = new EJS(options); + return function(data, helpers) { + return ejs.render(data, helpers); + }; + } + // If we get a `function` directly, it probably is coming from + // a `steal`-packaged view. + if (typeof options == "function") { + this.template = { + fn: options + }; + return; + } + // Set options on self. + extend(this, options); + this.template = this.scanner.scan(this.text, this.name); + }; + + can.EJS = EJS; + + + EJS.prototype. + + render = function(object, extraHelpers) { + object = object || {}; + return this.template.fn.call(object, object, new EJS.Helpers(object, extraHelpers || {})); + }; + + extend(EJS.prototype, { + + scanner: new can.view.Scanner({ + text: { + outStart: 'with(_VIEW) { with (_CONTEXT) {', + outEnd: "}}", + argNames: '_CONTEXT,_VIEW' + }, + + tokens: [ + ["templateLeft", "<%%"], // Template + ["templateRight", "%>"], // Right Template + ["returnLeft", "<%=="], // Return Unescaped + ["escapeLeft", "<%="], // Return Escaped + ["commentLeft", "<%#"], // Comment + ["left", "<%"], // Run --- this is hack for now + ["right", "%>"], // Right -> All have same FOR Mustache ... + ["returnRight", "%>"] + ], + helpers: [ + + { + name: /\s*\(([\$\w]+)\)\s*->([^\n]*)/, + fn: function(content) { + var quickFunc = /\s*\(([\$\w]+)\)\s*->([^\n]*)/, + parts = content.match(quickFunc); + + return "can.proxy(function(__){var " + parts[1] + "=can.$(__);" + parts[2] + "}, this);"; + } + } + ], + + transform: function(source) { + return source.replace(/<%([\s\S]+?)%>/gm, function(whole, part) { + var brackets = [], + foundBracketPair, + i; + + // Look for brackets (for removing self-contained blocks) + part.replace(/[{}]/gm, function(bracket, offset) { + brackets.push([bracket, offset]); + }); + + // Remove bracket pairs from the list of replacements + do { + foundBracketPair = false; + for (i = brackets.length - 2; i >= 0; i--) { + if (brackets[i][0] == '{' && brackets[i + 1][0] == '}') { + brackets.splice(i, 2); + foundBracketPair = true; + break; + } + } + } while (foundBracketPair); + + // Unmatched brackets found, inject EJS tags + if (brackets.length >= 2) { + var result = ['<%'], + bracket, + last = 0; + for (i = 0; bracket = brackets[i]; i++) { + result.push(part.substring(last, last = bracket[1])); + if ((bracket[0] == '{' && i < brackets.length - 1) || (bracket[0] == '}' && i > 0)) { + result.push(bracket[0] == '{' ? '{ %><% ' : ' %><% }'); + } else { + result.push(bracket[0]); + } + ++last; + } + result.push(part.substring(last), '%>'); + return result.join(''); + } + // Otherwise return the original + else { + return '<%' + part + '%>'; + } + }); + } + }) + }); + + EJS.Helpers = function(data, extras) { + this._data = data; + this._extras = extras; + extend(this, extras); + }; + + + EJS.Helpers.prototype = { + // TODO Deprecated!! + list: function(list, cb) { + + can.each(list, function(item, i) { + cb(item, i, list) + }) + }, + each: function(list, cb) { + // Normal arrays don't get live updated + if (can.isArray(list)) { + this.list(list, cb); + } else { + can.view.lists(list, cb); + } + } + }; + + // Options for `steal`'s build. + can.view.register({ + suffix: "ejs", + // returns a `function` that renders the view. + script: function(id, src) { + return "can.EJS(function(_CONTEXT,_VIEW) { " + new EJS({ + text: src, + name: id + }).template.out + " })"; + }, + renderer: function(id, text) { + return EJS({ + text: text, + name: id + }); + } + }); + + return can; +})(can); \ No newline at end of file diff --git a/assets/js/models/queueSongs.js b/assets/js/models/queueSongs.js new file mode 100644 index 0000000..f0ab7b2 --- /dev/null +++ b/assets/js/models/queueSongs.js @@ -0,0 +1,5 @@ +var QueueSong = can.Model.extend({ + + findAll: 'GET /api/queue' + +}, {}); diff --git a/assets/js/models/status.js b/assets/js/models/status.js new file mode 100644 index 0000000..7aa5504 --- /dev/null +++ b/assets/js/models/status.js @@ -0,0 +1,5 @@ +var Status = can.Model.extend({ + + findOne: 'GET /api/status' + +}, {}); diff --git a/assets/js/mpd-client.js b/assets/js/mpd-client.js index 0a030af..086f396 100644 --- a/assets/js/mpd-client.js +++ b/assets/js/mpd-client.js @@ -1,6 +1,8 @@ //= require ./libs/jquery-1.10.2.min -//= require ./libs/handlebars-1.0.0 //= require ./libs/can.jquery.min.js +//= require ./libs/can.ejs.js -//= require ./application.js +//= require_tree ./models/ +//= require_tree ./controls/ //= require ./router.js +//= require ./application.js diff --git a/public/views/queue.ejs b/public/views/queue.ejs new file mode 100644 index 0000000..89fb89b --- /dev/null +++ b/public/views/queue.ejs @@ -0,0 +1,8 @@ +