From 2407e33ea283ded80ebdaa6aa42febb540fce341 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 14 Jun 2013 16:18:37 -0700 Subject: [PATCH] almost all js files are loaded using require.js --- .../RootFolders/RootFolderCollection.js | 4 +- UI/Calendar/CalendarView.js | 2 +- UI/Cells/EpisodeStatusCell.js | 2 +- UI/Cells/FileSizeCell.js | 2 +- UI/Cells/IndexerCell.js | 2 +- UI/Cells/NzbDroneCell.js | 2 +- UI/History/Collection.js | 6 +- UI/History/Row.js | 21 +- UI/Index.html | 23 -- UI/JsLibraries/backbone.deep.model.js | 288 ++++++------------ .../backbone.mutators.deep.model.js | 211 ------------- UI/Logs/Collection.js | 24 +- UI/Missing/Collection.js | 26 +- UI/Missing/Row.js | 25 +- UI/Mixins/SaveIfChangedModel.js | 14 +- UI/Mixins/backbone.ajax.js | 4 +- UI/Mixins/backbone.marionette.templates.js | 34 ++- UI/Mixins/backbone.signalr.mixin.js | 69 ++--- UI/Mixins/underscore.mixin.deepExtend.js | 109 +++++++ UI/Quality/qualityProfileModel.js | 4 +- UI/Release/Collection.js | 4 +- UI/Release/DownloadReportCell.js | 40 +-- UI/Series/Details/SeriesDetailsLayout.js | 2 +- UI/Series/Index/Table/Row.js | 33 +- UI/Series/Index/Table/SeriesStatusCell.js | 36 ++- UI/Series/SeasonCollection.js | 4 +- UI/Series/SeriesModel.js | 4 +- .../DownloadClient/DownloadClientView.js | 2 +- UI/Settings/Indexers/Model.js | 5 +- UI/Settings/Notifications/Model.js | 4 +- UI/Settings/Quality/Size/QualitySizeView.js | 3 +- UI/Shared/Grid/HeaderCell.js | 176 ++++++----- UI/Shared/Grid/Pager.js | 18 +- UI/Shared/Modal/Region.js | 3 +- UI/app.js | 101 ++++-- 35 files changed, 580 insertions(+), 727 deletions(-) delete mode 100644 UI/JsLibraries/backbone.mutators.deep.model.js create mode 100644 UI/Mixins/underscore.mixin.deepExtend.js diff --git a/UI/AddSeries/RootFolders/RootFolderCollection.js b/UI/AddSeries/RootFolders/RootFolderCollection.js index e7c0caa9e..d6d20c471 100644 --- a/UI/AddSeries/RootFolders/RootFolderCollection.js +++ b/UI/AddSeries/RootFolders/RootFolderCollection.js @@ -1,5 +1,5 @@ "use strict"; -define(['app', 'AddSeries/RootFolders/RootFolderModel'], function () { +define(['app', 'AddSeries/RootFolders/RootFolderModel','mixins/backbone.signalr.mixin'], function () { var rootFolderCollection = Backbone.Collection.extend({ url : NzbDrone.Constants.ApiRoot + '/rootfolder', @@ -7,4 +7,4 @@ define(['app', 'AddSeries/RootFolders/RootFolderModel'], function () { }); return new rootFolderCollection().BindSignalR(); -}); \ No newline at end of file +}); diff --git a/UI/Calendar/CalendarView.js b/UI/Calendar/CalendarView.js index 950b0b939..03b517965 100644 --- a/UI/Calendar/CalendarView.js +++ b/UI/Calendar/CalendarView.js @@ -1,6 +1,6 @@ 'use strict'; -define(['app', 'Calendar/Collection'], function () { +define(['app', 'Calendar/Collection','fullcalendar'], function () { NzbDrone.Calendar.CalendarView = Backbone.Marionette.ItemView.extend({ initialize : function () { this.collection = new NzbDrone.Calendar.Collection(); diff --git a/UI/Cells/EpisodeStatusCell.js b/UI/Cells/EpisodeStatusCell.js index 4401eeb4c..fee91b83c 100644 --- a/UI/Cells/EpisodeStatusCell.js +++ b/UI/Cells/EpisodeStatusCell.js @@ -1,6 +1,6 @@ "use strict"; -define(['app' ], function () { +define(['app','backgrid' ], function () { NzbDrone.Cells.EpisodeStatusCell = Backgrid.Cell.extend({ className: 'episode-status-cell', diff --git a/UI/Cells/FileSizeCell.js b/UI/Cells/FileSizeCell.js index b80ec579d..4ae55c65d 100644 --- a/UI/Cells/FileSizeCell.js +++ b/UI/Cells/FileSizeCell.js @@ -1,6 +1,6 @@ "use strict"; -define(['app', 'Shared/FormatHelpers'], function () { +define(['app', 'Shared/FormatHelpers','backgrid'], function () { NzbDrone.Cells.FileSizeCell = Backgrid.Cell.extend({ className: "file-size-cell", diff --git a/UI/Cells/IndexerCell.js b/UI/Cells/IndexerCell.js index 485e32fd3..59b5d4ff3 100644 --- a/UI/Cells/IndexerCell.js +++ b/UI/Cells/IndexerCell.js @@ -1,5 +1,5 @@ "use strict"; -define(['app'], function () { +define(['app','backgrid'], function () { NzbDrone.Cells.IndexerCell = Backgrid.Cell.extend({ class : 'indexer-cell', diff --git a/UI/Cells/NzbDroneCell.js b/UI/Cells/NzbDroneCell.js index 580ba0273..3bb5dfe79 100644 --- a/UI/Cells/NzbDroneCell.js +++ b/UI/Cells/NzbDroneCell.js @@ -1,6 +1,6 @@ "use strict"; -define(['app'], function () { +define(['app','backgrid'], function () { NzbDrone.Cells.NzbDroneCell = Backgrid.Cell.extend({ _originalInit: Backgrid.Cell.prototype.initialize, diff --git a/UI/History/Collection.js b/UI/History/Collection.js index 5b2a9be88..d9fb1b740 100644 --- a/UI/History/Collection.js +++ b/UI/History/Collection.js @@ -1,6 +1,6 @@ "use strict"; -define(['app', 'History/Model'], function () { - NzbDrone.History.Collection = Backbone.PageableCollection.extend({ +define(['app', 'History/Model', 'backbone.pageable'], function (App, HistoryModel, PageableCollection) { + NzbDrone.History.Collection = PageableCollection.extend({ url : NzbDrone.Constants.ApiRoot + '/history', model : NzbDrone.History.Model, @@ -34,4 +34,4 @@ define(['app', 'History/Model'], function () { return resp; } }); -}); \ No newline at end of file +}); diff --git a/UI/History/Row.js b/UI/History/Row.js index 76003b0f2..e6aae27c1 100644 --- a/UI/History/Row.js +++ b/UI/History/Row.js @@ -1,9 +1,14 @@ -NzbDrone.Missing.Row = Backgrid.Row.extend({ - events: { - 'click .x-search' : 'search' - }, +"use strict"; +define(['app','backgrid'], function () { + NzbDrone.Missing.Row = Backgrid.Row.extend({ + events: { + 'click .x-search': 'search' + }, - search: function () { - window.alert('Episode Search'); - } -}); \ No newline at end of file + search: function () { + window.alert('Episode Search'); + } + }); + + return NzbDrone.Missing.Row; +}); diff --git a/UI/Index.html b/UI/Index.html index 9b736d495..548798ea5 100644 --- a/UI/Index.html +++ b/UI/Index.html @@ -78,35 +78,12 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/UI/JsLibraries/backbone.deep.model.js b/UI/JsLibraries/backbone.deep.model.js index 5307ffcf3..cbea78c52 100644 --- a/UI/JsLibraries/backbone.deep.model.js +++ b/UI/JsLibraries/backbone.deep.model.js @@ -1,124 +1,3 @@ -/*jshint expr:true eqnull:true */ -/** - * - * Backbone.DeepModel v0.10.4 - * - * Copyright (c) 2013 Charles Davison, Pow Media Ltd - * - * https://github.com/powmedia/backbone-deep-model - * Licensed under the MIT License - */ - -/** - * Underscore mixins for deep objects - * - * Based on https://gist.github.com/echong/3861963 - */ -(function() { - var arrays, basicObjects, deepClone, deepExtend, deepExtendCouple, isBasicObject, - __slice = [].slice; - - deepClone = function(obj) { - var func, isArr; - if (!_.isObject(obj) || _.isFunction(obj)) { - return obj; - } - if (obj instanceof Backbone.Collection || obj instanceof Backbone.Model) { - return obj; - } - if (_.isDate(obj)) { - return new Date(obj.getTime()); - } - if (_.isRegExp(obj)) { - return new RegExp(obj.source, obj.toString().replace(/.*\//, "")); - } - isArr = _.isArray(obj || _.isArguments(obj)); - func = function(memo, value, key) { - if (isArr) { - memo.push(deepClone(value)); - } else { - memo[key] = deepClone(value); - } - return memo; - }; - return _.reduce(obj, func, isArr ? [] : {}); - }; - - isBasicObject = function(object) { - if (object == null) return false; - return (object.prototype === {}.prototype || object.prototype === Object.prototype) && _.isObject(object) && !_.isArray(object) && !_.isFunction(object) && !_.isDate(object) && !_.isRegExp(object) && !_.isArguments(object); - }; - - basicObjects = function(object) { - return _.filter(_.keys(object), function(key) { - return isBasicObject(object[key]); - }); - }; - - arrays = function(object) { - return _.filter(_.keys(object), function(key) { - return _.isArray(object[key]); - }); - }; - - deepExtendCouple = function(destination, source, maxDepth) { - var combine, recurse, sharedArrayKey, sharedArrayKeys, sharedObjectKey, sharedObjectKeys, _i, _j, _len, _len1; - if (maxDepth == null) { - maxDepth = 20; - } - if (maxDepth <= 0) { - console.warn('_.deepExtend(): Maximum depth of recursion hit.'); - return _.extend(destination, source); - } - sharedObjectKeys = _.intersection(basicObjects(destination), basicObjects(source)); - recurse = function(key) { - return source[key] = deepExtendCouple(destination[key], source[key], maxDepth - 1); - }; - for (_i = 0, _len = sharedObjectKeys.length; _i < _len; _i++) { - sharedObjectKey = sharedObjectKeys[_i]; - recurse(sharedObjectKey); - } - sharedArrayKeys = _.intersection(arrays(destination), arrays(source)); - combine = function(key) { - return source[key] = _.union(destination[key], source[key]); - }; - for (_j = 0, _len1 = sharedArrayKeys.length; _j < _len1; _j++) { - sharedArrayKey = sharedArrayKeys[_j]; - combine(sharedArrayKey); - } - return _.extend(destination, source); - }; - - deepExtend = function() { - var finalObj, maxDepth, objects, _i; - objects = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), maxDepth = arguments[_i++]; - if (!_.isNumber(maxDepth)) { - objects.push(maxDepth); - maxDepth = 20; - } - if (objects.length <= 1) { - return objects[0]; - } - if (maxDepth <= 0) { - return _.extend.apply(this, objects); - } - finalObj = objects.shift(); - while (objects.length > 0) { - finalObj = deepExtendCouple(finalObj, deepClone(objects.shift()), maxDepth); - } - return finalObj; - }; - - _.mixin({ - deepClone: deepClone, - isBasicObject: isBasicObject, - basicObjects: basicObjects, - arrays: arrays, - deepExtend: deepExtend - }); - -}).call(this); - /** * Main source */ @@ -132,7 +11,7 @@ factory(_, Backbone); } }(function(_, Backbone) { - + /** * Takes a nested object and returns a shallow object keyed with the path names * e.g. { "level1.level2": "value" } @@ -184,7 +63,7 @@ if (result == null && i < n - 1) { result = {}; } - + if (typeof result === 'undefined') { if (return_exists) { @@ -233,7 +112,7 @@ } function deleteNested(obj, path) { - setNested(obj, path, null, { unset: true }); + setNested(obj, path, null, { unset: true }); } var DeepModel = Backbone.Model.extend({ @@ -260,7 +139,7 @@ // Return a copy of the model's `attributes` object. toJSON: function(options) { - return _.deepClone(this.attributes); + return _.deepClone(this.attributes); }, // Override get @@ -274,17 +153,17 @@ set: function(key, val, options) { var attr, attrs, unset, changes, silent, changing, prev, current; if (key == null) return this; - + // Handle both `"key", value` and `{key: value}` -style arguments. if (typeof key === 'object') { - attrs = key; - options = val || {}; + attrs = key; + options = val || {}; } else { - (attrs = {})[key] = val; + (attrs = {})[key] = val; } options || (options = {}); - + // Run validation. if (!this._validate(attrs, options)) return false; @@ -296,8 +175,8 @@ this._changing = true; if (!changing) { - this._previousAttributes = _.deepClone(this.attributes); //: Replaced _.clone with _.deepClone - this.changed = {}; + this._previousAttributes = _.deepClone(this.attributes); //: Replaced _.clone with _.deepClone + this.changed = {}; } current = this.attributes, prev = this._previousAttributes; @@ -310,50 +189,64 @@ // For each `set` attribute, update or delete the current value. for (attr in attrs) { - val = attrs[attr]; - - //: Using getNested, setNested and deleteNested - if (!_.isEqual(getNested(current, attr), val)) changes.push(attr); - if (!_.isEqual(getNested(prev, attr), val)) { - setNested(this.changed, attr, val); - } else { - deleteNested(this.changed, attr); - } - unset ? deleteNested(current, attr) : setNested(current, attr, val); - // + val = attrs[attr]; + + //: Using getNested, setNested and deleteNested + if (!_.isEqual(getNested(current, attr), val)) changes.push(attr); + if (!_.isEqual(getNested(prev, attr), val)) { + setNested(this.changed, attr, val); + } else { + deleteNested(this.changed, attr); + } + unset ? deleteNested(current, attr) : setNested(current, attr, val); + // } // Trigger all relevant attribute changes. if (!silent) { - if (changes.length) this._pending = true; - - // - var separator = DeepModel.keyPathSeparator; - - for (var i = 0, l = changes.length; i < l; i++) { - var key = changes[i]; - - this.trigger('change:' + key, this, getNested(current, key), options); + if (changes.length) this._pending = true; - var fields = key.split(separator); - - //Trigger change events for parent keys with wildcard (*) notation - for(var n = fields.length - 1; n > 0; n--) { - var parentKey = _.first(fields, n).join(separator), - wildcardKey = parentKey + separator + '*'; - - this.trigger('change:' + wildcardKey, this, getNested(current, parentKey), options); + // + var separator = DeepModel.keyPathSeparator; + var alreadyTriggered = {}; // * @restorer + + for (var i = 0, l = changes.length; i < l; i++) { + var key = changes[i]; + + if (!alreadyTriggered.hasOwnProperty(key) || !alreadyTriggered[key]) { // * @restorer + alreadyTriggered[key] = true; // * @restorer + this.trigger('change:' + key, this, getNested(current, key), options); + } // * @restorer + + var fields = key.split(separator); + + //Trigger change events for parent keys with wildcard (*) notation + for(var n = fields.length - 1; n > 0; n--) { + var parentKey = _.first(fields, n).join(separator), + wildcardKey = parentKey + separator + '*'; + + if (!alreadyTriggered.hasOwnProperty(wildcardKey) || !alreadyTriggered[wildcardKey]) { // * @restorer + alreadyTriggered[wildcardKey] = true; // * @restorer + this.trigger('change:' + wildcardKey, this, getNested(current, parentKey), options); + } // * @restorer + + // + @restorer + if (!alreadyTriggered.hasOwnProperty(parentKey) || !alreadyTriggered[parentKey]) { + alreadyTriggered[parentKey] = true; + this.trigger('change:' + parentKey, this, getNested(current, parentKey), options); + } + // - @restorer + } + // } - // - } } if (changing) return this; if (!silent) { - while (this._pending) { - this._pending = false; - this.trigger('change', this, options); - } + while (this._pending) { + this._pending = false; + this.trigger('change', this, options); + } } this._pending = false; this._changing = false; @@ -363,17 +256,17 @@ // Clear all attributes on the model, firing `"change"` unless you choose // to silence it. clear: function(options) { - var attrs = {}; - var shallowAttributes = objToPaths(this.attributes); - for (var key in shallowAttributes) attrs[key] = void 0; - return this.set(attrs, _.extend({}, options, {unset: true})); + var attrs = {}; + var shallowAttributes = objToPaths(this.attributes); + for (var key in shallowAttributes) attrs[key] = void 0; + return this.set(attrs, _.extend({}, options, {unset: true})); }, // Determine if the model has changed since the last `"change"` event. // If you specify an attribute name, determine if that attribute has changed. hasChanged: function(attr) { - if (attr == null) return !_.isEmpty(this.changed); - return getNested(this.changed, attr) !== undefined; + if (attr == null) return !_.isEmpty(this.changed); + return getNested(this.changed, attr) !== undefined; }, // Return an object containing all the attributes that have changed, or @@ -383,41 +276,41 @@ // You can also pass an attributes object to diff against the model, // determining if there *would be* a change. changedAttributes: function(diff) { - //: objToPaths - if (!diff) return this.hasChanged() ? objToPaths(this.changed) : false; - // - - var old = this._changing ? this._previousAttributes : this.attributes; - - // - diff = objToPaths(diff); - old = objToPaths(old); - // - - var val, changed = false; - for (var attr in diff) { - if (_.isEqual(old[attr], (val = diff[attr]))) continue; - (changed || (changed = {}))[attr] = val; - } - return changed; + //: objToPaths + if (!diff) return this.hasChanged() ? objToPaths(this.changed) : false; + // + + var old = this._changing ? this._previousAttributes : this.attributes; + + // + diff = objToPaths(diff); + old = objToPaths(old); + // + + var val, changed = false; + for (var attr in diff) { + if (_.isEqual(old[attr], (val = diff[attr]))) continue; + (changed || (changed = {}))[attr] = val; + } + return changed; }, // Get the previous value of an attribute, recorded at the time the last // `"change"` event was fired. previous: function(attr) { - if (attr == null || !this._previousAttributes) return null; + if (attr == null || !this._previousAttributes) return null; - // - return getNested(this._previousAttributes, attr); - // + // + return getNested(this._previousAttributes, attr); + // }, // Get all of the attributes of the model at the time of the previous // `"change"` event. previousAttributes: function() { - // - return _.deepClone(this._previousAttributes); - // + // + return _.deepClone(this._previousAttributes); + // } }); @@ -431,8 +324,7 @@ //For use in NodeJS if (typeof module != 'undefined') module.exports = DeepModel; - + return Backbone; })); - diff --git a/UI/JsLibraries/backbone.mutators.deep.model.js b/UI/JsLibraries/backbone.mutators.deep.model.js deleted file mode 100644 index 8bbebc069..000000000 --- a/UI/JsLibraries/backbone.mutators.deep.model.js +++ /dev/null @@ -1,211 +0,0 @@ -/*! Backbone.Mutators - v0.4.0 ------------------------------- -Build @ 2013-05-01 -Documentation and Full License Available at: -http://asciidisco.github.com/Backbone.Mutators/index.html -git://github.com/asciidisco/Backbone.Mutators.git -Copyright (c) 2013 Sebastian Golasch - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the - -Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE.*/ -(function (root, factory, undef) { - 'use strict'; - - if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like enviroments that support module.exports, - // like Node. - module.exports = factory(require('underscore'), require('Backbone')); - } else if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['underscore', 'backbone'], function (_, Backbone) { - // Check if we use the AMD branch of Back - _ = _ === undef ? root._ : _; - Backbone = Backbone === undef ? root.Backbone : Backbone; - return (root.returnExportsGlobal = factory(_, Backbone, root)); - }); - } else { - // Browser globals - root.returnExportsGlobal = factory(root._, root.Backbone); - } - -// Usage: -// -// Note: This plugin is UMD compatible, you can use it in node, amd and vanilla js envs -// -// Vanilla JS: -// -// -// -// -// Node: -// var _ = require('underscore'); -// var Backbone = require('backbone'); -// var Mutators = require('backbone.mutators'); -// -// -// AMD: -// define(['underscore', 'backbone', 'backbone.mutators'], function (_, Backbone, Mutators) { -// // insert sample from below -// return User; -// }); -// -// var User = Backbone.Model.extend({ -// mutators: { -// fullname: function () { -// return this.firstname + ' ' + this.lastname; -// } -// }, -// -// defaults: { -// firstname: 'Sebastian', -// lastname: 'Golasch' -// } -// }); -// -// var user = new User(); -// user.get('fullname') // returns 'Sebastian Golasch' -// user.toJSON() // return '{firstname: 'Sebastian', lastname: 'Golasch', fullname: 'Sebastian Golasch'}' - -}(this, function (_, Backbone, root, undef) { - 'use strict'; - - // check if we use the amd branch of backbone and underscore - Backbone = Backbone === undef ? root.Backbone : Backbone; - _ = _ === undef ? root._ : _; - - // extend backbones model prototype with the mutator functionality - var Mutator = function () {}, - oldGet = Backbone.DeepModel.prototype.get, - oldSet = Backbone.DeepModel.prototype.set, - oldToJson = Backbone.DeepModel.prototype.toJSON; - - // This is necessary to ensure that Models declared without the mutators object do not throw and error - Mutator.prototype.mutators = {}; - - // override get functionality to fetch the mutator props - Mutator.prototype.get = function (attr) { - var isMutator = this.mutators !== undef; - - // check if we have a getter mutation - if (isMutator === true && _.isFunction(this.mutators[attr]) === true) { - return this.mutators[attr].call(this); - } - - // check if we have a deeper nested getter mutation - if (isMutator === true && _.isObject(this.mutators[attr]) === true && _.isFunction(this.mutators[attr].get) === true) { - return this.mutators[attr].get.call(this); - } - - return oldGet.call(this, attr); - }; - - // override set functionality to set the mutator props - Mutator.prototype.set = function (key, value, options) { - var isMutator = this.mutators !== undef, - ret = null, - attrs = null; - - // seamleassly stolen from backbone core - // check if the setter action is triggered - // using key <-> value or object - if (_.isObject(key) || key === null) { - attrs = key; - options = value; - } else { - attrs = {}; - attrs[key] = value; - } - - // check if we have a deeper nested setter mutation - if (isMutator === true && _.isObject(this.mutators[key]) === true) { - - // check if we need to set a single value - if (_.isFunction(this.mutators[key].set) === true) { - ret = this.mutators[key].set.call(this, key, attrs[key], options, _.bind(oldSet, this)); - } else if(_.isFunction(this.mutators[key])){ - ret = this.mutators[key].call(this, key, attrs[key], options, _.bind(oldSet, this)); - } - } - - if (_.isObject(attrs)) { - _.each(attrs, _.bind(function (attr, attrKey) { - var cur_ret = null; - if (isMutator === true && _.isObject(this.mutators[attrKey]) === true) { - // check if we need to set a single value - - var meth = this.mutators[attrKey]; - if(_.isFunction(meth.set)){ - meth = meth.set; - } - - if(_.isFunction(meth)){ - if (options === undef || (_.isObject(options) === true && options.silent !== true && (options.mutators !== undef && options.mutators.silent !== true))) { - this.trigger('mutators:set:' + attrKey); - } - cur_ret = meth.call(this, attrKey, attr, options, _.bind(oldSet, this)); - } - - } - if (cur_ret === null) { - cur_ret = _.bind(oldSet, this)(attrKey, attr, options); - } - - if (ret !== false) { ret = cur_ret; } - - }, this)); - } - - //validation purposes - if (ret !== null) { - return ret; - } - - return oldSet.call(this, key, value, options); - }; - - // override toJSON functionality to serialize mutator properties - Mutator.prototype.toJSON = function () { - // fetch ye olde values - var attr = oldToJson.call(this); - // iterate over all mutators (if there are some) - _.each(this.mutators, _.bind(function (mutator, name) { - // check if we have some getter mutations - if (_.isObject(this.mutators[name]) === true && _.isFunction(this.mutators[name].get)) { - attr[name] = _.bind(this.mutators[name].get, this)(); - } else { - attr[name] = _.bind(this.mutators[name], this)(); - } - }, this)); - - return attr; - }; - - // override get functionality to get HTML-escaped the mutator props - Mutator.prototype.escape = function (attr){ - var val = this.get(attr); - return _.escape(val == null ? '' : '' + val); - }; - - // extend the models prototype - _.extend(Backbone.DeepModel.prototype, Mutator.prototype); - - // make mutators globally available under the Backbone namespace - Backbone.Mutators = Mutator; - return Mutator; -})); diff --git a/UI/Logs/Collection.js b/UI/Logs/Collection.js index b7d949f2c..cfc645874 100644 --- a/UI/Logs/Collection.js +++ b/UI/Logs/Collection.js @@ -1,24 +1,24 @@ "use strict"; -define(['app', 'Logs/Model'], function () { - NzbDrone.Logs.Collection = Backbone.PageableCollection.extend({ - url : NzbDrone.Constants.ApiRoot + '/log', - model : NzbDrone.Logs.Model, +define(['app', 'Logs/Model', 'backbone.pageable'], function (app, SeriesModel, PagableCollection) { + NzbDrone.Logs.Collection = PagableCollection.extend({ + url : NzbDrone.Constants.ApiRoot + '/log', + model: NzbDrone.Logs.Model, state: { pageSize: 50, - sortKey: "time", - order: 1 + sortKey : "time", + order : 1 }, queryParams: { - totalPages: null, + totalPages : null, totalRecords: null, - pageSize: 'pageSize', - sortKey: "sortKey", - order: "sortDir", - directions: { + pageSize : 'pageSize', + sortKey : "sortKey", + order : "sortDir", + directions : { "-1": "asc", - "1": "desc" + "1" : "desc" } }, diff --git a/UI/Missing/Collection.js b/UI/Missing/Collection.js index 812246373..4fc370aa6 100644 --- a/UI/Missing/Collection.js +++ b/UI/Missing/Collection.js @@ -1,24 +1,24 @@ "use strict"; -define(['app', 'Series/EpisodeModel'], function () { - NzbDrone.Missing.Collection = Backbone.PageableCollection.extend({ - url : NzbDrone.Constants.ApiRoot + '/missing', - model : NzbDrone.Series.EpisodeModel, +define(['app', 'Series/EpisodeModel', 'backbone.pageable'], function (app, EpisodeModel, PagableCollection) { + NzbDrone.Missing.Collection = PagableCollection.extend({ + url : NzbDrone.Constants.ApiRoot + '/missing', + model: NzbDrone.Series.EpisodeModel, state: { pageSize: 15, - sortKey: "airDate", - order: 1 + sortKey : "airDate", + order : 1 }, queryParams: { - totalPages: null, + totalPages : null, totalRecords: null, - pageSize: 'pageSize', - sortKey: "sortKey", - order: "sortDir", - directions: { + pageSize : 'pageSize', + sortKey : "sortKey", + order : "sortDir", + directions : { "-1": "asc", - "1": "desc" + "1" : "desc" } }, @@ -34,4 +34,4 @@ define(['app', 'Series/EpisodeModel'], function () { return resp; } }); -}); \ No newline at end of file +}); diff --git a/UI/Missing/Row.js b/UI/Missing/Row.js index 76003b0f2..dc3d998b5 100644 --- a/UI/Missing/Row.js +++ b/UI/Missing/Row.js @@ -1,9 +1,16 @@ -NzbDrone.Missing.Row = Backgrid.Row.extend({ - events: { - 'click .x-search' : 'search' - }, - - search: function () { - window.alert('Episode Search'); - } -}); \ No newline at end of file +"use strict"; +define(['app','backgrid'], function () { + + NzbDrone.Missing.Row = Backgrid.Row.extend({ + events: { + 'click .x-search': 'search' + }, + + search: function () { + window.alert('Episode Search'); + } + }); + return NzbDrone.Mixins.Row; + +}); + diff --git a/UI/Mixins/SaveIfChangedModel.js b/UI/Mixins/SaveIfChangedModel.js index af9012d1a..bebff25bd 100644 --- a/UI/Mixins/SaveIfChangedModel.js +++ b/UI/Mixins/SaveIfChangedModel.js @@ -1,8 +1,8 @@ "use strict"; -(function () { +define(['app'], function () { NzbDrone.Mixins.SaveIfChangedModel = { -// originalInitialize: this.initialize, + // originalInitialize: this.initialize, initialize: function () { this.isSaved = true; @@ -15,9 +15,9 @@ this.isSaved = true; }, this); -// if (originalInitialize) { -// originalInitialize.call(this); -// } + // if (originalInitialize) { + // originalInitialize.call(this); + // } }, saveIfChanged: function (options) { @@ -26,4 +26,6 @@ } } }; -}()); \ No newline at end of file + + return NzbDrone.Missing.SaveIfChangedModel; +}); diff --git a/UI/Mixins/backbone.ajax.js b/UI/Mixins/backbone.ajax.js index cda69416f..139b4c0c4 100644 --- a/UI/Mixins/backbone.ajax.js +++ b/UI/Mixins/backbone.ajax.js @@ -1,6 +1,6 @@ //try to add ajax data as query string to DELETE calls. "use strict"; -(function () { +define(['jquery'], function () { var original = Backbone.ajax; @@ -20,4 +20,4 @@ return original.apply(this, arguments); }; -}()); +}); diff --git a/UI/Mixins/backbone.marionette.templates.js b/UI/Mixins/backbone.marionette.templates.js index 542c257b2..d14fc8f47 100644 --- a/UI/Mixins/backbone.marionette.templates.js +++ b/UI/Mixins/backbone.marionette.templates.js @@ -1,24 +1,26 @@ "use strict"; -Marionette.TemplateCache.get = function (templateId) { +define(['app', 'marionette'], function (App, Marionette) { + Marionette.TemplateCache.get = function (templateId) { - var templateKey = templateId.toLowerCase(); + var templateKey = templateId.toLowerCase(); - var templateFunction = window.Templates[templateKey]; + var templateFunction = window.Templates[templateKey]; - if (!templateFunction) { - throw 'couldn\'t find pre-compiled template ' + templateKey; - } + if (!templateFunction) { + throw 'couldn\'t find pre-compiled template ' + templateKey; + } - return function (data) { + return function (data) { - try { - return templateFunction(data); - } - catch (error) { - console.error('template render failed for ' + templateKey + ' ' + error); - console.error(data); - throw error; - } + try { + return templateFunction(data); + } + catch (error) { + console.error('template render failed for ' + templateKey + ' ' + error); + console.error(data); + throw error; + } + }; }; -}; +}); diff --git a/UI/Mixins/backbone.signalr.mixin.js b/UI/Mixins/backbone.signalr.mixin.js index ef0c0bcde..313f39dbf 100644 --- a/UI/Mixins/backbone.signalr.mixin.js +++ b/UI/Mixins/backbone.signalr.mixin.js @@ -1,48 +1,49 @@ "use strict"; +define(['app', 'signalR'], function () { -_.extend(Backbone.Collection.prototype, {BindSignalR: function (options) { + _.extend(Backbone.Collection.prototype, {BindSignalR: function (options) { - if (!options || !options.url) { - console.assert(this.url, 'url must be provided or collection must have url'); - options = { - url: this.url.replace('api', 'signalr') - }; - } - - var self = this; - - var _getStatus = function (status) { - switch (status) { - case 0: - return 'connecting'; - case 1: - return 'connected'; - case 2: - return 'reconnecting'; - case 4: - return 'disconnected'; - default: - throw 'invalid status ' + status; + if (!options || !options.url) { + console.assert(this.url, 'url must be provided or collection must have url'); + options = { + url: this.url.replace('api', 'signalr') + }; } - }; + var self = this; + + var _getStatus = function (status) { + switch (status) { + case 0: + return 'connecting'; + case 1: + return 'connected'; + case 2: + return 'reconnecting'; + case 4: + return 'disconnected'; + default: + throw 'invalid status ' + status; + } + }; - var connection = $.connection(options.url); - connection.stateChanged(function (change) { - console.debug('{0} [{1}]'.format(options.url, _getStatus(change.newState))); - }); + var connection = $.connection(options.url); - connection.received(function (model) { - console.debug(model); - self.fetch(); - }); + connection.stateChanged(function (change) { + console.debug('{0} [{1}]'.format(options.url, _getStatus(change.newState))); + }); - connection.start({ transport: ['longPolling'] }); + connection.received(function (model) { + console.debug(model); + self.fetch(); + }); - return this; -}}); + connection.start({ transport: ['longPolling'] }); + return this; + }}); +}); diff --git a/UI/Mixins/underscore.mixin.deepExtend.js b/UI/Mixins/underscore.mixin.deepExtend.js new file mode 100644 index 000000000..5b6a20f25 --- /dev/null +++ b/UI/Mixins/underscore.mixin.deepExtend.js @@ -0,0 +1,109 @@ +/** + * Underscore mixins for deep objects + * + * Based on https://gist.github.com/echong/3861963 + */ +(function() { + var arrays, basicObjects, deepClone, deepExtend, deepExtendCouple, isBasicObject, + __slice = [].slice; + + deepClone = function(obj) { + var func, isArr; + if (!_.isObject(obj) || _.isFunction(obj)) { + return obj; + } + if (obj instanceof Backbone.Collection || obj instanceof Backbone.Model) { + return obj; + } + if (_.isDate(obj)) { + return new Date(obj.getTime()); + } + if (_.isRegExp(obj)) { + return new RegExp(obj.source, obj.toString().replace(/.*\//, "")); + } + isArr = _.isArray(obj || _.isArguments(obj)); + func = function(memo, value, key) { + if (isArr) { + memo.push(deepClone(value)); + } else { + memo[key] = deepClone(value); + } + return memo; + }; + return _.reduce(obj, func, isArr ? [] : {}); + }; + + isBasicObject = function(object) { + if (object == null) return false; + return (object.prototype === {}.prototype || object.prototype === Object.prototype) && _.isObject(object) && !_.isArray(object) && !_.isFunction(object) && !_.isDate(object) && !_.isRegExp(object) && !_.isArguments(object); + }; + + basicObjects = function(object) { + return _.filter(_.keys(object), function(key) { + return isBasicObject(object[key]); + }); + }; + + arrays = function(object) { + return _.filter(_.keys(object), function(key) { + return _.isArray(object[key]); + }); + }; + + deepExtendCouple = function(destination, source, maxDepth) { + var combine, recurse, sharedArrayKey, sharedArrayKeys, sharedObjectKey, sharedObjectKeys, _i, _j, _len, _len1; + if (maxDepth == null) { + maxDepth = 20; + } + if (maxDepth <= 0) { + console.warn('_.deepExtend(): Maximum depth of recursion hit.'); + return _.extend(destination, source); + } + sharedObjectKeys = _.intersection(basicObjects(destination), basicObjects(source)); + recurse = function(key) { + return source[key] = deepExtendCouple(destination[key], source[key], maxDepth - 1); + }; + for (_i = 0, _len = sharedObjectKeys.length; _i < _len; _i++) { + sharedObjectKey = sharedObjectKeys[_i]; + recurse(sharedObjectKey); + } + sharedArrayKeys = _.intersection(arrays(destination), arrays(source)); + combine = function(key) { + return source[key] = _.union(destination[key], source[key]); + }; + for (_j = 0, _len1 = sharedArrayKeys.length; _j < _len1; _j++) { + sharedArrayKey = sharedArrayKeys[_j]; + combine(sharedArrayKey); + } + return _.extend(destination, source); + }; + + deepExtend = function() { + var finalObj, maxDepth, objects, _i; + objects = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), maxDepth = arguments[_i++]; + if (!_.isNumber(maxDepth)) { + objects.push(maxDepth); + maxDepth = 20; + } + if (objects.length <= 1) { + return objects[0]; + } + if (maxDepth <= 0) { + return _.extend.apply(this, objects); + } + finalObj = objects.shift(); + while (objects.length > 0) { + finalObj = deepExtendCouple(finalObj, deepClone(objects.shift()), maxDepth); + } + return finalObj; + }; + + _.mixin({ + deepClone: deepClone, + isBasicObject: isBasicObject, + basicObjects: basicObjects, + arrays: arrays, + deepExtend: deepExtend + }); + +}).call(this); diff --git a/UI/Quality/qualityProfileModel.js b/UI/Quality/qualityProfileModel.js index 50cf01cf1..53662a9cf 100644 --- a/UI/Quality/qualityProfileModel.js +++ b/UI/Quality/qualityProfileModel.js @@ -1,6 +1,6 @@ "use strict"; -define(['app'], function () { - NzbDrone.Quality.QualityProfileModel = Backbone.DeepModel.extend({ +define(['app', 'backbone.deepmodel'], function (App, DeepModel) { + NzbDrone.Quality.QualityProfileModel = DeepModel.DeepModel.extend({ defaults: { id : null, diff --git a/UI/Release/Collection.js b/UI/Release/Collection.js index ec094a0e8..a8333963a 100644 --- a/UI/Release/Collection.js +++ b/UI/Release/Collection.js @@ -1,6 +1,6 @@ "use strict"; -define(['app', 'Release/Model'], function () { - NzbDrone.Release.Collection = Backbone.PageableCollection.extend({ +define(['app', 'Release/Model', 'backbone.pageable'], function (app, SeriesModel, PagableCollection) { + NzbDrone.Release.Collection = PagableCollection.extend({ url : NzbDrone.Constants.ApiRoot + '/release', model: NzbDrone.Release.Model, diff --git a/UI/Release/DownloadReportCell.js b/UI/Release/DownloadReportCell.js index da996bbb0..3bf832a14 100644 --- a/UI/Release/DownloadReportCell.js +++ b/UI/Release/DownloadReportCell.js @@ -1,27 +1,33 @@ "use strict"; -NzbDrone.Release.DownloadReportCell = Backgrid.Cell.extend({ - className: "download-report-cell", +define(['app'], function () { + NzbDrone.Release.DownloadReportCell = Backgrid.Cell.extend({ - events: { - 'click': '_onClick' - }, + className: "download-report-cell", - _onClick: function () { + events: { + 'click': '_onClick' + }, - var self = this; + _onClick: function () { - this.$el.html(''); - this.model.save() - .always(function () { - self.$el.html(''); - }); - }, + var self = this; - render: function () { + this.$el.html(''); + this.model.save() + .always(function () { + self.$el.html(''); + }); + }, - this.$el.html(''); - return this; + render: function () { - } + this.$el.html(''); + return this; + + } + }); + + + return NzbDrone.Release.DownloadReportCell; }); diff --git a/UI/Series/Details/SeriesDetailsLayout.js b/UI/Series/Details/SeriesDetailsLayout.js index f42745a04..4cb037fd4 100644 --- a/UI/Series/Details/SeriesDetailsLayout.js +++ b/UI/Series/Details/SeriesDetailsLayout.js @@ -1,5 +1,5 @@ "use strict"; -define(['app', 'Series/Details/SeasonCollectionView', 'Shared/LoadingView'], function () { +define(['app', 'Series/Details/SeasonCollectionView', 'Shared/LoadingView','backstrech'], function () { NzbDrone.Series.Details.SeriesDetailsLayout = Backbone.Marionette.Layout.extend({ itemViewContainer: '.x-series-seasons', diff --git a/UI/Series/Index/Table/Row.js b/UI/Series/Index/Table/Row.js index 455e98a99..cd0b43c85 100644 --- a/UI/Series/Index/Table/Row.js +++ b/UI/Series/Index/Table/Row.js @@ -1,17 +1,22 @@ "use strict"; -NzbDrone.Series.Index.Table.Row = Backgrid.Row.extend({ - events: { - 'click .x-edit' : 'editSeries', - 'click .x-remove': 'removeSeries' - }, +define(['app','backgrid'], function () { + NzbDrone.Series.Index.Table.Row = Backgrid.Row.extend({ + events: { + 'click .x-edit' : 'editSeries', + 'click .x-remove': 'removeSeries' + }, - editSeries: function () { - var view = new NzbDrone.Series.Edit.EditSeriesView({ model: this.model}); - NzbDrone.modalRegion.show(view); - }, + editSeries: function () { + var view = new NzbDrone.Series.Edit.EditSeriesView({ model: this.model}); + NzbDrone.modalRegion.show(view); + }, + + removeSeries: function () { + var view = new NzbDrone.Series.Delete.DeleteSeriesView({ model: this.model }); + NzbDrone.modalRegion.show(view); + } + }); + + return NzbDrone.Series.Table.Row; +}); - removeSeries: function () { - var view = new NzbDrone.Series.Delete.DeleteSeriesView({ model: this.model }); - NzbDrone.modalRegion.show(view); - } -}); \ No newline at end of file diff --git a/UI/Series/Index/Table/SeriesStatusCell.js b/UI/Series/Index/Table/SeriesStatusCell.js index 1dd569d4c..b2a26ea8a 100644 --- a/UI/Series/Index/Table/SeriesStatusCell.js +++ b/UI/Series/Index/Table/SeriesStatusCell.js @@ -1,23 +1,27 @@ "use strict"; -Backgrid.SeriesStatusCell = Backgrid.Cell.extend({ - className: "series-status-cell", +define(['app','backgrid'], function () { + Backgrid.SeriesStatusCell = Backgrid.Cell.extend({ + className: "series-status-cell", - render: function () { - this.$el.empty(); - var monitored = this.model.get('monitored'); - var status = this.model.get('status'); + render: function () { + this.$el.empty(); + var monitored = this.model.get('monitored'); + var status = this.model.get('status'); - if (!monitored) { - this.$el.html(''); - } - else if (status === 'continuing') { - this.$el.html(''); - } + if (!monitored) { + this.$el.html(''); + } + else if (status === 'continuing') { + this.$el.html(''); + } + + else { + this.$el.html(''); + } - else { - this.$el.html(''); + return this; } + }); - return this; - } + return Backgrid.SeriesStatusCell; }); diff --git a/UI/Series/SeasonCollection.js b/UI/Series/SeasonCollection.js index 8202f34f3..12dea609c 100644 --- a/UI/Series/SeasonCollection.js +++ b/UI/Series/SeasonCollection.js @@ -1,6 +1,6 @@ "use strict"; -define(['app', 'Series/SeasonModel'], function () { - NzbDrone.Series.SeasonCollection = Backbone.PageableCollection.extend({ +define(['app', 'Series/SeasonModel', 'backbone.pageable'], function (App, SeasonModel, PageAbleCollection) { + NzbDrone.Series.SeasonCollection = PageAbleCollection.extend({ url : NzbDrone.Constants.ApiRoot + '/season', model: NzbDrone.Series.SeasonModel, diff --git a/UI/Series/SeriesModel.js b/UI/Series/SeriesModel.js index 9ba22f360..659be3eaf 100644 --- a/UI/Series/SeriesModel.js +++ b/UI/Series/SeriesModel.js @@ -66,7 +66,7 @@ define(['app', 'Quality/QualityProfileCollection'], function (app, qualityProfil var profile = qualityProfiles.get(this.get('qualityProfileId')); - if(profile){ + if (profile) { return profile.toJSON(); } @@ -82,4 +82,6 @@ define(['app', 'Quality/QualityProfileCollection'], function (app, qualityProfil } }); + return NzbDrone.Series.SeriesModel; + }); diff --git a/UI/Settings/DownloadClient/DownloadClientView.js b/UI/Settings/DownloadClient/DownloadClientView.js index 4feec45bf..09bf825a6 100644 --- a/UI/Settings/DownloadClient/DownloadClientView.js +++ b/UI/Settings/DownloadClient/DownloadClientView.js @@ -1,7 +1,7 @@ 'use strict'; define([ - 'app', 'Settings/SettingsModel' + 'app', 'Settings/SettingsModel','bootstrap' ], function () { diff --git a/UI/Settings/Indexers/Model.js b/UI/Settings/Indexers/Model.js index acde63869..1d80214fa 100644 --- a/UI/Settings/Indexers/Model.js +++ b/UI/Settings/Indexers/Model.js @@ -1,7 +1,8 @@ "use strict"; define(['app', - 'Mixins/SaveIfChangedModel'], function () { - NzbDrone.Settings.Indexers.Model = Backbone.DeepModel.extend({ + 'Mixins/SaveIfChangedModel', + 'backbone.deepmodel'], function (App, SaveIfChangedModel, DeepModel) { + NzbDrone.Settings.Indexers.Model = DeepModel.DeepModel.extend({ }); _.extend(NzbDrone.Settings.Indexers.Model.prototype, NzbDrone.Mixins.SaveIfChangedModel); diff --git a/UI/Settings/Notifications/Model.js b/UI/Settings/Notifications/Model.js index bee0e1da4..0055d733e 100644 --- a/UI/Settings/Notifications/Model.js +++ b/UI/Settings/Notifications/Model.js @@ -1,5 +1,5 @@ "use strict"; -define(['app'], function () { - NzbDrone.Settings.Notifications.Model = Backbone.DeepModel.extend({ +define(['app', 'backbone.deepmodel'], function (App, DeepModel) { + NzbDrone.Settings.Notifications.Model = DeepModel.DeepModel.extend({ }); }); diff --git a/UI/Settings/Quality/Size/QualitySizeView.js b/UI/Settings/Quality/Size/QualitySizeView.js index ccce82543..084f8ce2a 100644 --- a/UI/Settings/Quality/Size/QualitySizeView.js +++ b/UI/Settings/Quality/Size/QualitySizeView.js @@ -2,7 +2,8 @@ define([ 'app', - 'Quality/QualitySizeCollection' + 'Quality/QualitySizeCollection', + 'bootstrap.slider' ], function () { diff --git a/UI/Shared/Grid/HeaderCell.js b/UI/Shared/Grid/HeaderCell.js index 27e9b88f5..00242b9fc 100644 --- a/UI/Shared/Grid/HeaderCell.js +++ b/UI/Shared/Grid/HeaderCell.js @@ -1,106 +1,100 @@ "use strict"; -Backgrid.Column.prototype.defaults = { - name : undefined, - label : undefined, - sortable : true, - editable : false, - renderable: true, - formatter : undefined, - cell : undefined, - headerCell: 'nzbDrone' -}; - - -Backgrid.NzbDroneHeaderCell = Backgrid.HeaderCell.extend({ - events: { - 'click': 'onClick' - }, - - render: function () { - this.$el.empty(); - this.$el.append(this.column.get("label")); - - if (this.column.get('sortable')) { - this.$el.addClass('clickable'); - this.$el.append(" "); - - if (this.collection.state) { - var sortKey = this.collection.state.sortKey; - var sortDir = this._convertIntToDirection(this.collection.state.order); - - if (sortKey === this.column.get('name')) { - this.$el.children('i').addClass(this._convertDirectionToIcon(sortDir)); - this._direction = sortDir; - } - } - } - this.delegateEvents(); - return this; - }, - - direction: function (dir) { - if (arguments.length) { - if (this._direction) { - this.$el.children('i').removeClass(this._convertDirectionToIcon(this._direction)); - } - if (dir) { - this.$el.children('i').addClass(this._convertDirectionToIcon(dir)); - } - this._direction = dir; - } +define(['app','backgrid'], function () { - return this._direction; - }, - onClick: function (e) { - e.preventDefault(); + Backgrid.NzbDroneHeaderCell = Backgrid.HeaderCell.extend({ + events: { + 'click': 'onClick' + }, - var columnName = this.column.get("name"); + render: function () { + this.$el.empty(); + this.$el.append(this.column.get("label")); - if (this.column.get("sortable")) { - if (this.direction() === "ascending") { - this.sort(columnName, "descending", function (left, right) { - var leftVal = left.get(columnName); - var rightVal = right.get(columnName); - if (leftVal === rightVal) { - return 0; - } - else if (leftVal > rightVal) { - return -1; + if (this.column.get('sortable')) { + this.$el.addClass('clickable'); + this.$el.append(" "); + + if (this.collection.state) { + var sortKey = this.collection.state.sortKey; + var sortDir = this._convertIntToDirection(this.collection.state.order); + + if (sortKey === this.column.get('name')) { + this.$el.children('i').addClass(this._convertDirectionToIcon(sortDir)); + this._direction = sortDir; } - return 1; - }); + } } - else { - this.sort(columnName, "ascending", function (left, right) { - var leftVal = left.get(columnName); - var rightVal = right.get(columnName); - if (leftVal === rightVal) { - return 0; - } - else if (leftVal < rightVal) { - return -1; - } - return 1; - }); + this.delegateEvents(); + return this; + }, + + direction: function (dir) { + if (arguments.length) { + if (this._direction) { + this.$el.children('i').removeClass(this._convertDirectionToIcon(this._direction)); + } + if (dir) { + this.$el.children('i').addClass(this._convertDirectionToIcon(dir)); + } + this._direction = dir; } - } - }, - _convertDirectionToIcon: function (dir) { - if (dir === 'ascending') { - return 'icon-sort-up'; - } + return this._direction; + }, + + onClick: function (e) { + e.preventDefault(); + + var columnName = this.column.get("name"); + + if (this.column.get("sortable")) { + if (this.direction() === "ascending") { + this.sort(columnName, "descending", function (left, right) { + var leftVal = left.get(columnName); + var rightVal = right.get(columnName); + if (leftVal === rightVal) { + return 0; + } + else if (leftVal > rightVal) { + return -1; + } + return 1; + }); + } + else { + this.sort(columnName, "ascending", function (left, right) { + var leftVal = left.get(columnName); + var rightVal = right.get(columnName); + if (leftVal === rightVal) { + return 0; + } + else if (leftVal < rightVal) { + return -1; + } + return 1; + }); + } + } + }, + + _convertDirectionToIcon: function (dir) { + if (dir === 'ascending') { + return 'icon-sort-up'; + } - return 'icon-sort-down'; - }, + return 'icon-sort-down'; + }, + + _convertIntToDirection: function (dir) { + if (dir === '-1') { + return 'ascending'; + } - _convertIntToDirection: function (dir) { - if (dir === '-1') { - return 'ascending'; + return 'descending'; } + }); - return 'descending'; - } + return Backgrid.NzbDroneHeaderCell; }); diff --git a/UI/Shared/Grid/Pager.js b/UI/Shared/Grid/Pager.js index 357703a43..6a8ca69ce 100644 --- a/UI/Shared/Grid/Pager.js +++ b/UI/Shared/Grid/Pager.js @@ -1,20 +1,8 @@ "use strict"; - -Backgrid.Column.prototype.defaults = { - name : undefined, - label : undefined, - sortable : true, - editable : false, - renderable: true, - formatter : undefined, - cell : undefined, - headerCell: 'nzbDrone' -}; - - define([ 'app', - 'JsLibraries/backbone.backgrid.paginator' + 'backgrid', + 'backgrid.paginator' ], function () { NzbDrone.Shared.Grid.Pager = Backgrid.Extension.Paginator.extend({ @@ -153,4 +141,6 @@ define([ return this; } }); + + return NzbDrone.Shared.Grid.Pager; }); diff --git a/UI/Shared/Modal/Region.js b/UI/Shared/Modal/Region.js index 69cf4373d..b8cd75e7c 100644 --- a/UI/Shared/Modal/Region.js +++ b/UI/Shared/Modal/Region.js @@ -1,6 +1,5 @@ "use strict"; -define(function () { - +define(['marionette'], function () { return Backbone.Marionette.Region.extend({ el: "#modal-region", diff --git a/UI/app.js b/UI/app.js index a50b06210..780593f5a 100644 --- a/UI/app.js +++ b/UI/app.js @@ -2,43 +2,110 @@ require.config({ paths: { - 'backbone' : 'JsLibraries/backbone', - '$' : 'JsLibraries/jquery', - 'underscore': 'JsLibraries/underscore', - 'marionette': 'JsLibraries/backbone.marionette', - 'handlebars': 'JsLibraries/handlebars', - 'libs' : 'JsLibraries/' + 'backbone' : 'JsLibraries/backbone', + 'bootstrap' : 'JsLibraries/bootstrap', + 'bootstrap.slider' : 'JsLibraries/bootstrap.slider', + 'backbone.mutators' : 'JsLibraries/backbone.mutators', + 'backbone.deepmodel': 'JsLibraries/backbone.deep.model', + 'backbone.pageable' : 'JsLibraries/backbone.pageable', + 'backgrid' : 'JsLibraries/backbone.backgrid', + 'backgrid.paginator': 'JsLibraries/backbone.backgrid.paginator', + 'fullcalendar' : 'JsLibraries/fullcalendar', + 'backstrech' : 'JsLibraries/jquery.backstretch', + '$' : 'JsLibraries/jquery', + 'underscore' : 'JsLibraries/underscore', + 'marionette' : 'JsLibraries/backbone.marionette', + 'handlebars' : 'JsLibraries/handlebars', + 'signalR' : 'JsLibraries/jquery.signalR', + 'libs' : 'JsLibraries/' }, shim: { - underscore: { - exports: '_' + + $: { + exports: '$' + }, + + bootstrap: { + deps: ['$'] + }, + + 'bootstrap.slider': { + deps: ['$'] + }, + + backstrech: { + deps: ['$'] }, - backbone : { + + 'underscore': { + dep : ['$'], + exports: '_', + init : function () { + require(['mixins/underscore.mixin.deepExtend']); + } + }, + + backbone: { deps : ['underscore', '$'], - exports: 'Backbone' + exports: 'Backbone', + init : function () { + require(['libs/backbone.mutators']); + } }, + marionette: { deps : ['backbone'], - exports: 'Marionette' + exports: 'Marionette', + init : function () { + require(['mixins/backbone.marionette.templates']); + } }, + handlebars: { exports: 'Handlebars' }, - backbone_backgrid :{ - exports: 'backgrid' + signalR: { + dep: ['$'] }, - backgrid : { - deps: ['backbone', 'libs/backbone.backgrid', 'libs/backbone.backgrid.paginator'] + 'backbone.pageable': { + dep : ['backbone'], + init: function () { + console.log(this); + } + }, + + backgrid : { + deps: ['backbone'], + init: function () { + Backgrid.Column.prototype.defaults = { + name : undefined, + label : undefined, + sortable : true, + editable : false, + renderable: true, + formatter : undefined, + cell : undefined, + headerCell: 'nzbDrone' + }; + } + }, + 'backgrid.paginator': { + deps: ['backgrid'] } } }); -define(['backbone','backgrid'], function (ModalRegion) { +define([ + 'marionette', + 'shared/modal/region', + 'Instrumentation/StringFormat', + 'Instrumentation/ErrorHandler' +], function (Marionette, ModalRegion) { - window.NzbDrone = new Backbone.Marionette.Application(); + window.NzbDrone = new Marionette.Application(); window.NzbDrone.Config = {}; window.NzbDrone.Form = {};