updated backbone, marionette, sugar, underscore, modelbinder, bootstrap.switch

pull/2/head
Keivan Beigi 12 years ago
parent 99cd327002
commit 549b497770

@ -6,14 +6,14 @@ module.exports = function(grunt) {
curl: {
'UI/JsLibraries/backbone.collectionbinder.js': 'http://raw.github.com/theironcook/Backbone.ModelBinder/master/Backbone.CollectionBinder.js',
'UI/JsLibraries/backbone.js': 'http://raw.github.com/documentcloud/backbone/master/backbone.js',
'UI/JsLibraries/backbone.marionette.js': 'http://raw.github.com/marionettejs/backbone.marionette/master/lib/backbone.marionette.js',
'UI/JsLibraries/backbone.js': 'http://backbonejs.org/backbone.js',
'UI/JsLibraries/backbone.marionette.js': 'http://marionettejs.com/downloads/backbone.marionette.js',
'UI/JsLibraries/backbone.modelbinder.js': 'http://raw.github.com/theironcook/Backbone.ModelBinder/master/Backbone.ModelBinder.js',
'UI/JsLibraries/backbone.mutators.js': 'http://raw.github.com/asciidisco/Backbone.Mutators/master/backbone.mutators.js',
'UI/JsLibraries/backbone.shortcuts.js': 'http://raw.github.com/bry4n/backbone-shortcuts/master/backbone.shortcuts.js',
//'UI/JsLibraries/bootstrap.js':
//'UI/JsLibraries/bootstrap.slider.js':
'UI/JsLibraries/bootstrap.swtitch.js': 'http://raw.github.com/nostalgiaz/bootstrap-switch/master/static/js/bootstrapSwitch.js',
'UI/JsLibraries/bootstrap.switch.js': 'http://raw.github.com/nostalgiaz/bootstrap-switch/master/static/js/bootstrapSwitch.js',
'UI/JsLibraries/handlebars.runtime.js': 'http://raw.github.com/wycats/handlebars.js/master/dist/handlebars.runtime.js',
'UI/JsLibraries/jquery.cookie.js': 'http://raw.github.com/carhartl/jquery-cookie/master/jquery.cookie.js',
'UI/JsLibraries/jquery.js': 'http://code.jquery.com/jquery.js',
@ -21,7 +21,7 @@ module.exports = function(grunt) {
//'NzbDrone.Backbone/JsLibraries/jquery.tablesorter.js':
'UI/JsLibraries/require.js': 'http://raw.github.com/jrburke/requirejs/master/require.js',
'UI/JsLibraries/sugar.js': 'http://raw.github.com/andrewplummer/Sugar/master/release/sugar-full.development.js',
'UI/JsLibraries/underscore.js': 'http://raw.github.com/documentcloud/underscore/master/underscore.js'
'UI/JsLibraries/underscore.js': 'http://underscorejs.org/underscore.js'
},
uglify: {
@ -43,6 +43,7 @@ module.exports = function(grunt) {
handlebars: {
options: {
namespace: "Templates",
wrapped: true,
processName: function(fileName){
return fileName
.replace('UI/','')
@ -123,5 +124,6 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-curl');
// Default task(s).
grunt.registerTask('default', ['copy','less:bootstrap','handlebars', 'watch']);
grunt.registerTask('update', ['curl']);
};

@ -57,13 +57,9 @@ define([
},
initialize: function (context, action, query) {
if (action) {
this.action = action.toLowerCase();
}
if (query) {
this.query = query.toLowerCase();
initialize: function (options) {
if (options.action) {
this.action = options.action.toLowerCase();
}
},

@ -10,8 +10,8 @@ define(['app', 'Calendar/CalendarItemView'], function () {
calendar: '#calendar'
},
initialize : function (context, action, query, collection) {
this.collection = collection;
initialize : function () {
//should use this.collection?
this.calendar = new NzbDrone.Calendar.CalendarCollection();
},
onCompositeCollectionRendered: function () {

@ -9,69 +9,69 @@ define(['app', 'Shared/ModalRegion', 'AddSeries/AddSeriesLayout',
var controller = Backbone.Marionette.Controller.extend({
addSeries: function (action, query) {
this.setTitle('Add Series');
NzbDrone.mainRegion.show(new NzbDrone.AddSeries.AddSeriesLayout(this, action, query));
},
series: function () {
this.setTitle('NzbDrone');
this._setTitle('NzbDrone');
NzbDrone.mainRegion.show(new NzbDrone.Series.Index.SeriesIndexCollectionView());
},
upcoming: function (action, query) {
this.setTitle('Upcoming');
NzbDrone.mainRegion.show(new NzbDrone.Upcoming.UpcomingCollectionView(this, action, query));
},
calendar: function (action, query) {
this.setTitle('Calendar');
var calendarCollection = new NzbDrone.Calendar.CalendarCollection();
calendarCollection.fetch();
NzbDrone.mainRegion.show(new NzbDrone.Calendar.CalendarCollectionView(this, action, query, calendarCollection));
},
seriesDetails: function (query) {
var self = this;
this.setTitle('Loading Series');
this._setTitle('Loading Series');
var series = new NzbDrone.Series.SeriesModel({ id: query });
series.fetch({
success: function (seriesModel) {
self.setTitle(seriesModel.get('title'));
self._setTitle(seriesModel.get('title'));
NzbDrone.mainRegion.show(new NzbDrone.Series.Details.SeriesDetailsView({ model: seriesModel }));
}
});
},
settings: function (action, query) {
this.setTitle('Settings');
addSeries: function (action) {
this._setTitle('Add Series');
NzbDrone.mainRegion.show(new NzbDrone.AddSeries.AddSeriesLayout({action: action}));
},
upcoming: function () {
this._setTitle('Upcoming');
NzbDrone.mainRegion.show(new NzbDrone.Upcoming.UpcomingCollectionView());
},
calendar: function () {
this._setTitle('Calendar');
var calendarCollection = new NzbDrone.Calendar.CalendarCollection();
calendarCollection.fetch();
NzbDrone.mainRegion.show(new NzbDrone.Calendar.CalendarCollectionView({collection: calendarCollection}));
},
settings: function (action) {
this._setTitle('Settings');
var settingsModel = new NzbDrone.Settings.SettingsModel();
settingsModel.fetch({
success: function (settings) {
NzbDrone.mainRegion.show(new NzbDrone.Settings.SettingsLayout(this, action, query, settings));
NzbDrone.mainRegion.show(new NzbDrone.Settings.SettingsLayout({settings: settings, action: action}));
}
});
},
missing: function (action, query) {
this.setTitle('Missing');
missing: function () {
this._setTitle('Missing');
var missingCollection = new NzbDrone.Missing.MissingCollection();
missingCollection.fetch({
success: function (missing) {
NzbDrone.mainRegion.show(new NzbDrone.Missing.MissingCollectionView(this, action, query, missing));
success: function () {
NzbDrone.mainRegion.show(new NzbDrone.Missing.MissingCollectionView({collection: missingCollection}));
}
});
},
notFound: function () {
this.setTitle('Not Found');
this._setTitle('Not Found');
NzbDrone.mainRegion.show(new NzbDrone.Shared.NotFoundView(this));
},
setTitle: function (title) {
_setTitle: function (title) {
$('#title-region').html(title);
if (title.toLocaleLowerCase() === 'nzbdrone') {

@ -92,7 +92,7 @@
<script src="/JsLibraries/jquery.js"></script>
<script src="/JsLibraries/bootstrap.js"></script>
<script src="/JsLibraries/bootstrap.slider.js"></script>
<script src="/JsLibraries/bootstrapSwitch.js"></script>
<script src="/JsLibraries/bootstrap.switch.js"></script>
<script src="/JsLibraries/underscore.js"></script>
<script src="/JsLibraries/handlebars.runtime.js"></script>
<script src="/JsLibraries/backbone.js"></script>

@ -1,23 +1,23 @@
// Backbone.CollectionBinder v0.1.1
// (c) 2012 Bart Wood
// Backbone.CollectionBinder v1.0.0
// (c) 2013 Bart Wood
// Distributed Under MIT License
(function () {
(function(){
if (!Backbone) {
if(!Backbone){
throw 'Please include Backbone.js before Backbone.ModelBinder.js';
}
if (!Backbone.ModelBinder) {
if(!Backbone.ModelBinder){
throw 'Please include Backbone.ModelBinder.js before Backbone.CollectionBinder.js';
}
Backbone.CollectionBinder = function (elManagerFactory, options) {
Backbone.CollectionBinder = function(elManagerFactory, options){
_.bindAll(this);
this._elManagers = {};
this._elManagerFactory = elManagerFactory;
if (!this._elManagerFactory) throw 'elManagerFactory must be defined.';
if(!this._elManagerFactory) throw 'elManagerFactory must be defined.';
// Let the factory just use the trigger function on the view binder
this._elManagerFactory.trigger = this.trigger;
@ -25,14 +25,14 @@
this._options = options || {};
};
Backbone.CollectionBinder.VERSION = '0.1.1';
Backbone.CollectionBinder.VERSION = '1.0.0';
_.extend(Backbone.CollectionBinder.prototype, Backbone.Events, {
bind: function (collection, parentEl) {
bind: function(collection, parentEl){
this.unbind();
if (!collection) throw 'collection must be defined';
if (!parentEl) throw 'parentEl must be defined';
if(!collection) throw 'collection must be defined';
if(!parentEl) throw 'parentEl must be defined';
this._collection = collection;
this._elManagerFactory.setParentEl(parentEl);
@ -45,8 +45,8 @@
},
unbind: function () {
if (this._collection !== undefined) {
unbind: function(){
if(this._collection !== undefined){
this._collection.off('add', this._onCollectionAdd);
this._collection.off('remove', this._onCollectionRemove);
this._collection.off('reset', this._onCollectionReset);
@ -55,13 +55,13 @@
this._removeAllElManagers();
},
getManagerForEl: function (el) {
getManagerForEl: function(el){
var i, elManager, elManagers = _.values(this._elManagers);
for (i = 0; i < elManagers.length; i++) {
for(i = 0; i < elManagers.length; i++){
elManager = elManagers[i];
if (elManager.isElContained(el)) {
if(elManager.isElContained(el)){
return elManager;
}
}
@ -69,13 +69,13 @@
return undefined;
},
getManagerForModel: function (model) {
getManagerForModel: function(model){
var i, elManager, elManagers = _.values(this._elManagers);
for (i = 0; i < elManagers.length; i++) {
for(i = 0; i < elManagers.length; i++){
elManager = elManagers[i];
if (elManager.getModel() === model) {
if(elManager.getModel() === model){
return elManager;
}
}
@ -83,31 +83,31 @@
return undefined;
},
_onCollectionAdd: function (model) {
_onCollectionAdd: function(model){
this._elManagers[model.cid] = this._elManagerFactory.makeElManager(model);
this._elManagers[model.cid].createEl();
if (this._options['autoSort']) {
if(this._options['autoSort']){
this.sortRootEls();
}
},
_onCollectionRemove: function (model) {
_onCollectionRemove: function(model){
this._removeElManager(model);
},
_onCollectionReset: function () {
_onCollectionReset: function(){
this._removeAllElManagers();
this._collection.each(function (model) {
this._collection.each(function(model){
this._onCollectionAdd(model);
}, this);
this.trigger('elsReset', this._collection);
},
_removeAllElManagers: function () {
_.each(this._elManagers, function (elManager) {
_removeAllElManagers: function(){
_.each(this._elManagers, function(elManager){
elManager.removeEl();
delete this._elManagers[elManager._model.cid];
}, this);
@ -116,21 +116,21 @@
this._elManagers = {};
},
_removeElManager: function (model) {
if (this._elManagers[model.cid] !== undefined) {
_removeElManager: function(model){
if(this._elManagers[model.cid] !== undefined){
this._elManagers[model.cid].removeEl();
delete this._elManagers[model.cid];
}
},
sortRootEls: function () {
this._collection.each(function (model, modelIndex) {
sortRootEls: function(){
this._collection.each(function(model, modelIndex){
var modelElManager = this.getManagerForModel(model);
if (modelElManager) {
if(modelElManager){
var modelEl = modelElManager.getEl();
var currentRootEls = this._elManagerFactory.getParentEl().children();
var currentRootEls = $(this._elManagerFactory.getParentEl()).children();
if (currentRootEls[modelIndex] !== modelEl[0]) {
if(currentRootEls[modelIndex] !== modelEl[0]){
modelEl.detach();
modelEl.insertBefore(currentRootEls[modelIndex]);
}
@ -142,40 +142,40 @@
// The ElManagerFactory is used for els that are just html templates
// elHtml - how the model's html will be rendered. Must have a single root element (div,span).
// bindings (optional) - either a string which is the binding attribute (name, id, data-name, etc.) or a normal bindings hash
Backbone.CollectionBinder.ElManagerFactory = function (elHtml, bindings) {
Backbone.CollectionBinder.ElManagerFactory = function(elHtml, bindings){
_.bindAll(this);
this._elHtml = elHtml;
this._bindings = bindings;
if (!_.isString(this._elHtml)) throw 'elHtml must be a valid html string';
if(! _.isString(this._elHtml)) throw 'elHtml must be a valid html string';
};
_.extend(Backbone.CollectionBinder.ElManagerFactory.prototype, {
setParentEl: function (parentEl) {
setParentEl: function(parentEl){
this._parentEl = parentEl;
},
getParentEl: function () {
getParentEl: function(){
return this._parentEl;
},
makeElManager: function (model) {
makeElManager: function(model){
var elManager = {
_model: model,
createEl: function () {
createEl: function(){
this._el = $(this._elHtml);
this._el = $(this._elHtml);
$(this._parentEl).append(this._el);
if (this._bindings) {
if (_.isString(this._bindings)) {
if(this._bindings){
if(_.isString(this._bindings)){
this._modelBinder = new Backbone.ModelBinder();
this._modelBinder.bind(this._model, this._el, Backbone.ModelBinder.createDefaultBindings(this._el, this._bindings));
}
else if (_.isObject(this._bindings)) {
else if(_.isObject(this._bindings)){
this._modelBinder = new Backbone.ModelBinder();
this._modelBinder.bind(this._model, this._el, this._bindings);
}
@ -187,8 +187,8 @@
this.trigger('elCreated', this._model, this._el);
},
removeEl: function () {
if (this._modelBinder !== undefined) {
removeEl: function(){
if(this._modelBinder !== undefined){
this._modelBinder.unbind();
}
@ -196,15 +196,15 @@
this.trigger('elRemoved', this._model, this._el);
},
isElContained: function (findEl) {
isElContained: function(findEl){
return this._el === findEl || $(this._el).has(findEl).length > 0;
},
getModel: function () {
getModel: function(){
return this._model;
},
getEl: function () {
getEl: function(){
return this._el;
}
};
@ -218,36 +218,36 @@
// The ViewManagerFactory is used for els that are created and owned by backbone views.
// There is no bindings option because the view made by the viewCreator should take care of any binding
// viewCreator - a callback that will create backbone view instances for a model passed to the callback
Backbone.CollectionBinder.ViewManagerFactory = function (viewCreator) {
Backbone.CollectionBinder.ViewManagerFactory = function(viewCreator){
_.bindAll(this);
this._viewCreator = viewCreator;
if (!_.isFunction(this._viewCreator)) throw 'viewCreator must be a valid function that accepts a model and returns a backbone view';
if(!_.isFunction(this._viewCreator)) throw 'viewCreator must be a valid function that accepts a model and returns a backbone view';
};
_.extend(Backbone.CollectionBinder.ViewManagerFactory.prototype, {
setParentEl: function (parentEl) {
setParentEl: function(parentEl){
this._parentEl = parentEl;
},
getParentEl: function () {
getParentEl: function(){
return this._parentEl;
},
makeElManager: function (model) {
makeElManager: function(model){
var elManager = {
_model: model,
createEl: function () {
createEl: function(){
this._view = this._viewCreator(model);
$(this._parentEl).append(this._view.render(this._model).el);
this.trigger('elCreated', this._model, this._view);
},
removeEl: function () {
if (this._view.close !== undefined) {
removeEl: function(){
if(this._view.close !== undefined){
this._view.close();
}
else {
@ -258,19 +258,19 @@
this.trigger('elRemoved', this._model, this._view);
},
isElContained: function (findEl) {
isElContained: function(findEl){
return this._view.el === findEl || this._view.$el.has(findEl).length > 0;
},
getModel: function () {
getModel: function(){
return this._model;
},
getView: function () {
getView: function(){
return this._view;
},
getEl: function () {
getEl: function(){
return this._view.$el;
}
};
@ -281,4 +281,4 @@
}
});
}).call(this);
}).call(this);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
// Backbone.ModelBinder v0.1.6
// (c) 2012 Bart Wood
// Backbone.ModelBinder v1.0.1
// (c) 2013 Bart Wood
// Distributed Under MIT License
(function (factory) {
@ -10,36 +10,40 @@
// Browser globals
factory(_, $, Backbone);
}
}(function (_, $, Backbone) {
}(function(_, $, Backbone){
if (!Backbone) {
if(!Backbone){
throw 'Please include Backbone.js before Backbone.ModelBinder.js';
}
Backbone.ModelBinder = function (modelSetOptions) {
Backbone.ModelBinder = function(){
_.bindAll(this);
this._modelSetOptions = modelSetOptions || {};
};
// Static setter for class level options
Backbone.ModelBinder.SetOptions = function(options){
Backbone.ModelBinder.options = options;
};
// Current version of the library.
Backbone.ModelBinder.VERSION = '0.1.6';
Backbone.ModelBinder.VERSION = '1.0.1';
Backbone.ModelBinder.Constants = {};
Backbone.ModelBinder.Constants.ModelToView = 'ModelToView';
Backbone.ModelBinder.Constants.ViewToModel = 'ViewToModel';
_.extend(Backbone.ModelBinder.prototype, {
bind: function (model, rootEl, attributeBindings, modelSetOptions) {
bind:function (model, rootEl, attributeBindings, options) {
this.unbind();
this._model = model;
this._rootEl = rootEl;
this._modelSetOptions = _.extend({}, this._modelSetOptions, modelSetOptions);
this._setOptions(options);
if (!this._model) throw 'model must be specified';
if (!this._rootEl) throw 'rootEl must be specified';
if (!this._model) this._throwException('model must be specified');
if (!this._rootEl) this._throwException('rootEl must be specified');
if (attributeBindings) {
if(attributeBindings){
// Create a deep clone of the attribute bindings
this._attributeBindings = $.extend(true, {}, attributeBindings);
@ -54,43 +58,61 @@
this._bindViewToModel();
},
bindCustomTriggers: function (model, rootEl, triggers, attributeBindings, modelSetOptions) {
this._triggers = triggers;
this.bind(model, rootEl, attributeBindings, modelSetOptions)
},
bindCustomTriggers: function (model, rootEl, triggers, attributeBindings, modelSetOptions) {
this._triggers = triggers;
this.bind(model, rootEl, attributeBindings, modelSetOptions)
},
unbind: function () {
unbind:function () {
this._unbindModelToView();
this._unbindViewToModel();
if (this._attributeBindings) {
if(this._attributeBindings){
delete this._attributeBindings;
this._attributeBindings = undefined;
}
},
_setOptions: function(options){
this._options = _.extend({}, Backbone.ModelBinder.options, options);
// initialize default options
if(!this._options['modelSetOptions']){
this._options['modelSetOptions'] = {};
}
this._options['modelSetOptions'].changeSource = 'ModelBinder';
if(!this._options['changeTriggers']){
this._options['changeTriggers'] = {'': 'change', '[contenteditable]': 'blur'};
}
if(!this._options['initialCopyDirection']){
this._options['initialCopyDirection'] = Backbone.ModelBinder.Constants.ModelToView;
}
},
// Converts the input bindings, which might just be empty or strings, to binding objects
_initializeAttributeBindings: function () {
_initializeAttributeBindings:function () {
var attributeBindingKey, inputBinding, attributeBinding, elementBindingCount, elementBinding;
for (attributeBindingKey in this._attributeBindings) {
inputBinding = this._attributeBindings[attributeBindingKey];
if (_.isString(inputBinding)) {
attributeBinding = { elementBindings: [{ selector: inputBinding }] };
attributeBinding = {elementBindings: [{selector: inputBinding}]};
}
else if (_.isArray(inputBinding)) {
attributeBinding = { elementBindings: inputBinding };
attributeBinding = {elementBindings: inputBinding};
}
else if (_.isObject(inputBinding)) {
attributeBinding = { elementBindings: [inputBinding] };
else if(_.isObject(inputBinding)){
attributeBinding = {elementBindings: [inputBinding]};
}
else {
throw 'Unsupported type passed to Model Binder ' + attributeBinding;
this._throwException('Unsupported type passed to Model Binder ' + attributeBinding);
}
// Add a linkage from the element binding back to the attribute binding
for (elementBindingCount = 0; elementBindingCount < attributeBinding.elementBindings.length; elementBindingCount++) {
for(elementBindingCount = 0; elementBindingCount < attributeBinding.elementBindings.length; elementBindingCount++){
elementBinding = attributeBinding.elementBindings[elementBindingCount];
elementBinding.attributeBinding = attributeBinding;
}
@ -101,28 +123,28 @@
},
// If the bindings are not specified, the default binding is performed on the name attribute
_initializeDefaultBindings: function () {
_initializeDefaultBindings: function(){
var elCount, namedEls, namedEl, name, attributeBinding;
this._attributeBindings = {};
namedEls = $('[name]', this._rootEl);
for (elCount = 0; elCount < namedEls.length; elCount++) {
for(elCount = 0; elCount < namedEls.length; elCount++){
namedEl = namedEls[elCount];
name = $(namedEl).attr('name');
// For elements like radio buttons we only want a single attribute binding with possibly multiple element bindings
if (!this._attributeBindings[name]) {
attributeBinding = { attributeName: name };
attributeBinding.elementBindings = [{ attributeBinding: attributeBinding, boundEls: [namedEl] }];
if(!this._attributeBindings[name]){
attributeBinding = {attributeName: name};
attributeBinding.elementBindings = [{attributeBinding: attributeBinding, boundEls: [namedEl]}];
this._attributeBindings[name] = attributeBinding;
}
else {
this._attributeBindings[name].elementBindings.push({ attributeBinding: this._attributeBindings[name], boundEls: [namedEl] });
else{
this._attributeBindings[name].elementBindings.push({attributeBinding: this._attributeBindings[name], boundEls: [namedEl]});
}
}
},
_initializeElBindings: function () {
_initializeElBindings:function () {
var bindingKey, attributeBinding, bindingCount, elementBinding, foundEls, elCount, el;
for (bindingKey in this._attributeBindings) {
attributeBinding = this._attributeBindings[bindingKey];
@ -137,7 +159,7 @@
}
if (foundEls.length === 0) {
throw 'Bad binding found. No elements returned for binding selector ' + elementBinding.selector;
this._throwException('Bad binding found. No elements returned for binding selector ' + elementBinding.selector);
}
else {
elementBinding.boundEls = [];
@ -153,40 +175,67 @@
_bindModelToView: function () {
this._model.on('change', this._onModelChange, this);
this.copyModelAttributesToView();
if(this._options['initialCopyDirection'] === Backbone.ModelBinder.Constants.ModelToView){
this.copyModelAttributesToView();
}
},
// attributesToCopy is an optional parameter - if empty, all attributes
// that are bound will be copied. Otherwise, only attributeBindings specified
// in the attributesToCopy are copied.
copyModelAttributesToView: function (attributesToCopy) {
copyModelAttributesToView: function(attributesToCopy){
var attributeName, attributeBinding;
for (attributeName in this._attributeBindings) {
if (attributesToCopy === undefined || _.indexOf(attributesToCopy, attributeName) !== -1) {
if(attributesToCopy === undefined || _.indexOf(attributesToCopy, attributeName) !== -1){
attributeBinding = this._attributeBindings[attributeName];
this._copyModelToView(attributeBinding);
}
}
},
_unbindModelToView: function () {
if (this._model) {
copyViewValuesToModel: function(){
var bindingKey, attributeBinding, bindingCount, elementBinding, elCount, el;
for (bindingKey in this._attributeBindings) {
attributeBinding = this._attributeBindings[bindingKey];
for (bindingCount = 0; bindingCount < attributeBinding.elementBindings.length; bindingCount++) {
elementBinding = attributeBinding.elementBindings[bindingCount];
if(this._isBindingUserEditable(elementBinding)){
if(this._isBindingRadioGroup(elementBinding)){
el = this._getRadioButtonGroupCheckedEl(elementBinding);
if(el){
this._copyViewToModel(elementBinding, el);
}
}
else {
for(elCount = 0; elCount < elementBinding.boundEls.length; elCount++){
el = $(elementBinding.boundEls[elCount]);
if(this._isElUserEditable(el)){
this._copyViewToModel(elementBinding, el);
}
}
}
}
}
}
},
_unbindModelToView: function(){
if(this._model){
this._model.off('change', this._onModelChange);
this._model = undefined;
}
},
_bindViewToModel: function () {
if (this._triggers) {
_.each(this._triggers, function (event, selector) {
$(this._rootEl).delegate(selector, event, this._onElChanged);
}, this);
}
else {
$(this._rootEl).delegate('', 'change', this._onElChanged);
// The change event doesn't work properly for contenteditable elements - but blur does
$(this._rootEl).delegate('[contenteditable]', 'blur', this._onElChanged);
_.each(this._options['changeTriggers'], function (event, selector) {
$(this._rootEl).delegate(selector, event, this._onElChanged);
}, this);
if(this._options['initialCopyDirection'] === Backbone.ModelBinder.Constants.ViewToModel){
this.copyViewValuesToModel();
}
},
@ -204,13 +253,13 @@
}
},
_onElChanged: function (event) {
_onElChanged:function (event) {
var el, elBindings, elBindingCount, elBinding;
el = $(event.target)[0];
elBindings = this._getElBindings(el);
for (elBindingCount = 0; elBindingCount < elBindings.length; elBindingCount++) {
for(elBindingCount = 0; elBindingCount < elBindings.length; elBindingCount++){
elBinding = elBindings[elBindingCount];
if (this._isBindingUserEditable(elBinding)) {
this._copyViewToModel(elBinding, el);
@ -218,13 +267,44 @@
}
},
_isBindingUserEditable: function (elBinding) {
_isBindingUserEditable: function(elBinding){
return elBinding.elAttribute === undefined ||
elBinding.elAttribute === 'text' ||
elBinding.elAttribute === 'html';
},
_getElBindings: function (findEl) {
_isElUserEditable: function(el){
var isContentEditable = el.attr('contenteditable');
return isContentEditable || el.is('input') || el.is('select') || el.is('textarea');
},
_isBindingRadioGroup: function(elBinding){
var elCount, el;
var isAllRadioButtons = elBinding.boundEls.length > 0;
for(elCount = 0; elCount < elBinding.boundEls.length; elCount++){
el = $(elBinding.boundEls[elCount]);
if(el.attr('type') !== 'radio'){
isAllRadioButtons = false;
break;
}
}
return isAllRadioButtons;
},
_getRadioButtonGroupCheckedEl: function(elBinding){
var elCount, el;
for(elCount = 0; elCount < elBinding.boundEls.length; elCount++){
el = $(elBinding.boundEls[elCount]);
if(el.attr('type') === 'radio' && el.attr('checked')){
return el;
}
}
return undefined;
},
_getElBindings:function (findEl) {
var attributeName, attributeBinding, elementBindingCount, elementBinding, boundElCount, boundEl;
var elBindings = [];
@ -247,7 +327,7 @@
return elBindings;
},
_onModelChange: function () {
_onModelChange:function () {
var changedAttribute, attributeBinding;
for (changedAttribute in this._model.changedAttributes()) {
@ -259,7 +339,7 @@
}
},
_copyModelToView: function (attributeBinding) {
_copyModelToView:function (attributeBinding) {
var elementBindingCount, elementBinding, boundElCount, boundEl, value, convertedValue;
value = this._model.get(attributeBinding.attributeName);
@ -270,7 +350,7 @@
for (boundElCount = 0; boundElCount < elementBinding.boundEls.length; boundElCount++) {
boundEl = elementBinding.boundEls[boundElCount];
if (!boundEl._isSetting) {
if(!boundEl._isSetting){
convertedValue = this._getConvertedValue(Backbone.ModelBinder.Constants.ModelToView, elementBinding, value);
this._setEl($(boundEl), elementBinding, convertedValue);
}
@ -287,7 +367,7 @@
}
},
_setElAttribute: function (el, elementBinding, convertedValue) {
_setElAttribute:function (el, elementBinding, convertedValue) {
switch (elementBinding.elAttribute) {
case 'html':
el.html(convertedValue);
@ -309,12 +389,12 @@
break;
case 'class':
var previousValue = this._model.previous(elementBinding.attributeBinding.attributeName);
if (!_.isUndefined(previousValue)) {
if(!_.isUndefined(previousValue)){
previousValue = this._getConvertedValue(Backbone.ModelBinder.Constants.ModelToView, elementBinding, previousValue);
el.removeClass(previousValue);
}
if (convertedValue) {
if(convertedValue){
el.addClass(convertedValue);
}
break;
@ -323,13 +403,16 @@
}
},
_setElValue: function (el, convertedValue) {
if (el.attr('type')) {
_setElValue:function (el, convertedValue) {
if(el.attr('type')){
switch (el.attr('type')) {
case 'radio':
if (el.val() === convertedValue) {
el.attr('checked', 'checked');
}
else {
el.removeAttr('checked');
}
break;
case 'checkbox':
if (convertedValue) {
@ -339,28 +422,30 @@
el.removeAttr('checked');
}
break;
case 'file':
break;
default:
el.val(convertedValue);
}
}
else if (el.is('input') || el.is('select') || el.is('textarea')) {
el.val(convertedValue);
else if(el.is('input') || el.is('select') || el.is('textarea')){
el.val(convertedValue || (convertedValue === 0 ? '0' : ''));
}
else {
el.text(convertedValue);
el.text(convertedValue || (convertedValue === 0 ? '0' : ''));
}
},
_copyViewToModel: function (elementBinding, el) {
var value, convertedValue;
var result, value, convertedValue;
if (!el._isSetting) {
el._isSetting = true;
this._setModel(elementBinding, $(el));
result = this._setModel(elementBinding, $(el));
el._isSetting = false;
if (elementBinding.converter) {
if(result && elementBinding.converter){
value = this._model.get(elementBinding.attributeBinding.attributeName);
convertedValue = this._getConvertedValue(Backbone.ModelBinder.Constants.ModelToView, elementBinding, value);
this._setEl($(el), elementBinding, convertedValue);
@ -368,12 +453,12 @@
}
},
_getElValue: function (elementBinding, el) {
_getElValue: function(elementBinding, el){
switch (el.attr('type')) {
case 'checkbox':
return el.prop('checked') ? true : false;
default:
if (el.attr('contenteditable') !== undefined) {
if(el.attr('contenteditable') !== undefined){
return el.html();
}
else {
@ -387,30 +472,40 @@
var elVal = this._getElValue(elementBinding, el);
elVal = this._getConvertedValue(Backbone.ModelBinder.Constants.ViewToModel, elementBinding, elVal);
data[elementBinding.attributeBinding.attributeName] = elVal;
var opts = _.extend({}, this._modelSetOptions, { changeSource: 'ModelBinder' });
this._model.set(data, opts);
return this._model.set(data, this._options['modelSetOptions']);
},
_getConvertedValue: function (direction, elementBinding, value) {
if (elementBinding.converter) {
value = elementBinding.converter(direction, value, elementBinding.attributeBinding.attributeName, this._model);
value = elementBinding.converter(direction, value, elementBinding.attributeBinding.attributeName, this._model, elementBinding.boundEls);
}
return value;
},
_throwException: function(message){
if(this._options.suppressThrows){
if(console && console.error){
console.error(message);
}
}
else {
throw message;
}
}
});
Backbone.ModelBinder.CollectionConverter = function (collection) {
Backbone.ModelBinder.CollectionConverter = function(collection){
this._collection = collection;
if (!this._collection) {
if(!this._collection){
throw 'Collection must be defined';
}
_.bindAll(this, 'convert');
};
_.extend(Backbone.ModelBinder.CollectionConverter.prototype, {
convert: function (direction, value) {
convert: function(direction, value){
if (direction === Backbone.ModelBinder.Constants.ModelToView) {
return value ? value.id : undefined;
}
@ -425,25 +520,25 @@
// attributeType - probably 'name' or 'id' in most cases
// converter(optional) - the default converter you want applied to all your bindings
// elAttribute(optional) - the default elAttribute you want applied to all your bindings
Backbone.ModelBinder.createDefaultBindings = function (rootEl, attributeType, converter, elAttribute) {
Backbone.ModelBinder.createDefaultBindings = function(rootEl, attributeType, converter, elAttribute){
var foundEls, elCount, foundEl, attributeName;
var bindings = {};
foundEls = $('[' + attributeType + ']', rootEl);
for (elCount = 0; elCount < foundEls.length; elCount++) {
for(elCount = 0; elCount < foundEls.length; elCount++){
foundEl = foundEls[elCount];
attributeName = $(foundEl).attr(attributeType);
if (!bindings[attributeName]) {
var attributeBinding = { selector: '[' + attributeType + '="' + attributeName + '"]' };
if(!bindings[attributeName]){
var attributeBinding = {selector: '[' + attributeType + '="' + attributeName + '"]'};
bindings[attributeName] = attributeBinding;
if (converter) {
if(converter){
bindings[attributeName].converter = converter;
}
if (elAttribute) {
if(elAttribute){
bindings[attributeName].elAttribute = elAttribute;
}
}
@ -453,19 +548,19 @@
};
// Helps you to combine 2 sets of bindings
Backbone.ModelBinder.combineBindings = function (destination, source) {
_.each(source, function (value, key) {
var elementBinding = { selector: value.selector };
Backbone.ModelBinder.combineBindings = function(destination, source){
_.each(source, function(value, key){
var elementBinding = {selector: value.selector};
if (value.converter) {
if(value.converter){
elementBinding.converter = value.converter;
}
if (value.elAttribute) {
if(value.elAttribute){
elementBinding.elAttribute = value.elAttribute;
}
if (!destination[key]) {
if(!destination[key]){
destination[key] = elementBinding;
}
else {
@ -479,4 +574,4 @@
return Backbone.ModelBinder;
}));
}));

@ -1,5 +1,5 @@
/* ============================================================
* bootstrapSwitch v1.2 by Larentis Mattia @spiritualGuru
* bootstrapSwitch v1.3 by Larentis Mattia @spiritualGuru
* http://www.larentis.eu/switch/
* ============================================================
* Licensed under the Apache License, Version 2.0
@ -23,7 +23,8 @@
, color
, moving
, onLabel = "ON"
, offLabel = "OFF";
, offLabel = "OFF"
, icon = false;
$.each(['switch-mini', 'switch-small', 'switch-large'], function (i, el) {
if (classes.indexOf(el) >= 0)
@ -41,6 +42,9 @@
if ($element.data('off-label') !== undefined)
offLabel = $element.data('off-label');
if ($element.data('icon') !== undefined)
icon = $element.data('icon');
$switchLeft = $('<span>')
.addClass("switch-left")
.addClass(myClasses)
@ -62,6 +66,10 @@
.addClass(myClasses)
.attr('for', $element.find('input').attr('id'));
if (icon) {
$label.html('<i class="icon icon-' + icon + '"></i>');
}
$div = $element.find(':checkbox').wrap($('<div>')).parent().data('animated', false);
if ($element.data('animated') !== false)
@ -100,21 +108,26 @@
});
$element.find('input').on('change', function (e) {
var $element = $(this).parent();
var $this = $(this)
, $element = $this.parent()
, thisState = $this.is(':checked')
, state = $element.is('.switch-off');
e.preventDefault();
e.stopImmediatePropagation();
$element.css('left', '');
if ($(this).is(':checked'))
$element.removeClass('switch-off').addClass('switch-on');
else $element.removeClass('switch-on').addClass('switch-off');
if (state === thisState) {
if ($element.data('animated') !== false)
$element.addClass("switch-animate");
if (thisState)
$element.removeClass('switch-off').addClass('switch-on');
else $element.removeClass('switch-on').addClass('switch-off');
$element.parent().trigger('switch-change', {'el': $(this), 'value': $(this).is(':checked')})
if ($element.data('animated') !== false)
$element.addClass("switch-animate");
$element.parent().trigger('switch-change', {'el': $this, 'value': thisState})
}
});
$element.find('label').on('mousedown touchstart', function (e) {

@ -123,7 +123,7 @@
function batchMethodExecute(klass, args, fn) {
var all = args.length === 0, methods = multiArgs(args), changed = false;
iterateOverObject(klass['SugarMethods'], function(name, m) {
if(all || methods.indexOf(name) > -1) {
if(all || methods.indexOf(name) !== -1) {
changed = true;
fn(m.instance ? klass.prototype : klass, name, m);
}
@ -211,6 +211,12 @@
}
}
function simpleRepeat(n, fn) {
for(var i = 0; i < n; i++) {
fn(i);
}
}
function simpleMerge(target, source) {
iterateOverObject(source, function(key) {
target[key] = source[key];
@ -228,16 +234,6 @@
// Number helpers
function getRange(start, stop, fn, step) {
var arr = [], i = parseInt(start), down = step < 0;
while((!down && i <= stop) || (down && i >= stop)) {
arr.push(i);
if(fn) fn.call(this, i);
i += step || 1;
}
return arr;
}
function round(val, precision, method) {
var fn = math[method || 'round'];
var multiplier = math.pow(10, math.abs(precision || 0));
@ -253,6 +249,8 @@
return round(val, precision, 'floor');
}
// Used by Number and Date
function padNumber(num, place, sign, base) {
var str = math.abs(num).toString(base || 10);
str = repeatString(place - str.replace(/\.\d+/, '').length, '0') + str;
@ -304,6 +302,31 @@
}
// Date helpers
function callDateGet(d, method) {
return d['get' + (d._utc ? 'UTC' : '') + method]();
}
function callDateSet(d, method, value) {
return d['set' + (d._utc && method != 'ISOWeek' ? 'UTC' : '') + method](value);
}
function extractDurationFromString(str) {
var match, val, unit;
match = str.toLowerCase().match(/^(\d+)?\s?(\w+?)s?$/i);
val = parseInt(match[1]) || 1;
unit = match[2].slice(0,1).toUpperCase() + match[2].slice(1);
if(unit.match(/hour|minute|second/i)) {
unit += 's';
} else if(unit === 'Year') {
unit = 'FullYear';
} else if(unit === 'Day') {
unit = 'Date';
}
return [val, unit];
}
// Specialized helpers
@ -798,7 +821,7 @@
*
***/
'bind': function(scope) {
var fn = this, args = multiArgs(arguments).slice(1), nop, bound;
var fn = this, args = multiArgs(arguments).slice(1), bound;
if(!isFunction(this)) {
throw new TypeError('Function.prototype.bind called on a non-function');
}
@ -1651,11 +1674,11 @@
var arr = this;
var result = [];
var divisor = ceil(this.length / num);
getRange(0, num - 1, function(i) {
simpleRepeat(num, function(i) {
var index = i * divisor;
var group = arr.slice(index, index + divisor);
if(pad && group.length < divisor) {
getRange(1, divisor - group.length, function() {
simpleRepeat(divisor - group.length, function() {
group = group.add(padding);
});
}
@ -1680,7 +1703,7 @@
if(len === 0 || num === 0) return arr;
if(isUndefined(num)) num = 1;
if(isUndefined(padding)) padding = null;
getRange(0, ceil(len / num) - 1, function(i) {
simpleRepeat(ceil(len / num), function(i) {
group = arr.slice(num * i, num * i + num);
while(group.length < num) {
group.push(padding);
@ -2224,6 +2247,7 @@
},
{
unit: 'month',
error: 0.919, // Feb 1-28 over 1 month
method: 'Month',
ambiguous: true,
multiplier: function(d, ms) {
@ -2235,8 +2259,7 @@
}
}
return days * 24 * 60 * 60 * 1000;
},
error: 0.919
}
},
{
unit: 'week',
@ -2247,6 +2270,7 @@
},
{
unit: 'day',
error: 0.958, // DST traversal over 1 day
method: 'Date',
ambiguous: true,
multiplier: function() {
@ -2542,7 +2566,7 @@
if(loc['monthSuffix']) {
loc['month'] = getDigit(1,2);
loc['months'] = getRange(1, 12).map(function(n) { return n + loc['monthSuffix']; });
loc['months'] = '1,2,3,4,5,6,7,8,9,10,11,12'.split(',').map(function(n) { return n + loc['monthSuffix']; });
}
loc['full_month'] = getDigit(1,2) + '|' + arrayToAlternates(loc['months']);
@ -2919,9 +2943,9 @@
return [value, unit, ms];
}
function getAdjustedUnitWithMonthFallback(date) {
function getRelativeWithMonthFallback(date) {
var adu = getAdjustedUnit(date.millisecondsFromNow());
if(adu[1] === 6) {
if(allowMonthFallback(date, adu)) {
// If the adjusted unit is in months, then better to use
// the "monthsfromNow" which applies a special error margin
// for edge cases such as Jan-09 - Mar-09 being less than
@ -2929,10 +2953,18 @@
// The third "ms" element in the array will handle the sign
// (past or future), so simply take the absolute value here.
adu[0] = math.abs(date.monthsFromNow());
adu[1] = 6;
}
return adu;
}
function allowMonthFallback(date, adu) {
// Allow falling back to monthsFromNow if the unit is in months...
return adu[1] === 6 ||
// ...or if it's === 4 weeks and there are more days than in the given month
(adu[1] === 5 && adu[0] === 4 && date.daysFromNow() >= new Date().daysInMonth());
}
// Date formatting helpers
@ -2943,11 +2975,11 @@
} else if(Date[format]) {
format = Date[format];
} else if(isFunction(format)) {
adu = getAdjustedUnitWithMonthFallback(date);
adu = getRelativeWithMonthFallback(date);
format = format.apply(date, adu.concat(loc));
}
if(!format && relative) {
adu = adu || getAdjustedUnitWithMonthFallback(date);
adu = adu || getRelativeWithMonthFallback(date);
// Adjust up if time is in ms, as this doesn't
// look very good for a standard relative date.
if(adu[1] === 0) {
@ -3132,14 +3164,6 @@
return d;
}
function callDateGet(d, method) {
return d['get' + (d._utc ? 'UTC' : '') + method]();
}
function callDateSet(d, method, value) {
return d['set' + (d._utc && method != 'ISOWeek' ? 'UTC' : '') + method](value);
}
// The ISO format allows times strung together without a demarcating ":", so make sure
// that these markers are now optional.
function prepareTime(format, loc, iso) {
@ -3418,7 +3442,7 @@
if(fraction && math.abs(fraction % 1) > error) {
num = round(num);
}
return parseInt(num);
return num < 0 ? ceil(num) : floor(num);
}
since = function(f, localeCode) {
return applyErrorMargin(this.getTime() - date.create(f, localeCode).getTime());
@ -4374,77 +4398,132 @@
setDateProperties();
/***
* @package DateRange
* @dependency date
* @description Date Ranges define a range of time. They can enumerate over specific points within that range, and be manipulated and compared.
* @package Range
* @dependency core
* @description Ranges allow creating spans of numbers, strings, or dates. They can enumerate over specific points within that range, and be manipulated and compared.
*
***/
var DateRange = function(start, end) {
this.start = date.create(start);
this.end = date.create(end);
function Range(start, end) {
this.start = cloneRangeMember(start);
this.end = cloneRangeMember(end);
};
// 'toString' doesn't appear in a for..in loop in IE even though
function getRangeMemberNumericValue(m) {
return isString(m) ? m.charCodeAt(0) : m;
}
function getRangeMemberPrimitiveValue(m) {
if(m == null) return m;
return isDate(m) ? m.getTime() : m.valueOf();
}
function cloneRangeMember(m) {
if(isDate(m)) {
return new date(m.getTime());
} else {
return getRangeMemberPrimitiveValue(m);
}
}
function isValidRangeMember(m) {
var val = getRangeMemberPrimitiveValue(m);
return !!val || val === 0;
}
function incrementRangeMember(obj, increment) {
if(isDate(obj)) {
return advanceDate(obj, increment);
} else if(isString(obj)) {
return string.fromCharCode(m.charCodeAt(0) + increment);
} else if(isNumber(obj)) {
return obj + increment;
}
}
function advanceDate(current, increment) {
var unit, amt = increment, tmp, val, d;
if(isString(increment)) {
tmp = extractDurationFromString(increment);
amt = tmp[0];
unit = tmp[1];
val = callDateGet(current, unit);
d = new date(current.getTime());
callDateSet(d, unit, val + amt);
return d;
} else {
return new date(current.getTime() + increment);
}
}
/***
* @method toString()
* @returns String
* @short Returns a string representation of the range.
* @example
*
* Number.range(1, 5).toString() -> 1..5
* Date.range(new Date(2003, 0), new Date(2005, 0)).toString() -> January 1, 2003..January 1, 2005
*
***/
// Note: 'toString' doesn't appear in a for..in loop in IE even though
// hasOwnProperty reports true, so extend() can't be used here.
// Also tried simply setting the prototype = {} up front for all
// methods but GCC very oddly started dropping properties in the
// object randomly (maybe because of the global scope?) hence
// the need for the split logic here.
DateRange.prototype.toString = function() {
/***
* @method toString()
* @returns String
* @short Returns a string representation of the DateRange.
* @example
*
* Date.range('2003', '2005').toString() -> January 1, 2003..January 1, 2005
*
***/
return this.isValid() ? this.start.full() + '..' + this.end.full() : 'Invalid DateRange';
Range.prototype.toString = function() {
return this.isValid() ? this.start + ".." + this.end : 'Invalid Range';
};
extend(DateRange, true, false, {
extend(Range, true, false, {
/***
* @method isValid()
* @returns Boolean
* @short Returns true if the DateRange is valid, false otherwise.
* @short Returns true if the range is valid, false otherwise.
* @example
*
* Date.range('2003', '2005').isValid() -> true
* Date.range('2005', '2003').isValid() -> false
* Date.range(new Date(2003, 0), new Date(2005, 0)).isValid() -> true
* Number.range(NaN, NaN).isValid() -> false
*
***/
'isValid': function() {
return this.start < this.end;
return isValidRangeMember(this.start) && isValidRangeMember(this.end) && typeof this.start === typeof this.end;
},
/***
* @method duration()
* @method span()
* @returns Number
* @short Return the duration of the DateRange in milliseconds.
* @short Return the span of the range. If the range is a date range, the value is in milliseconds.
* @extra The span includes both the start and the end.
* @example
*
* Date.range('2003', '2005').duration() -> 94694400000
* Number.range(5, 10).span() -> 6
* Date.range(new Date(2003, 0), new Date(2005, 0)).span() -> 94694400000
*
***/
'duration': function() {
return this.isValid() ? this.end.getTime() - this.start.getTime() : NaN;
'span': function() {
return this.isValid() ? getRangeMemberNumericValue(this.end) - getRangeMemberNumericValue(this.start) + 1 : NaN;
},
/***
* @method contains(<d>)
* @method contains(<obj>)
* @returns Boolean
* @short Returns true if <d> is contained inside the DateRange. <d> may be a date or another DateRange.
* @short Returns true if <obj> is contained inside the range. <obj> may be a value or another range.
* @example
*
* Date.range('2003', '2005').contains(Date.create('2004')) -> true
* Number.range(5, 10).contains(7) -> true
* Date.range(new Date(2003, 0), new Date(2005, 0)).contains(new Date(2004, 0)) -> true
*
***/
'contains': function(obj) {
var self = this, arr = obj.start && obj.end ? [obj.start, obj.end] : [obj];
var self = this, arr;
if(obj == null) return false;
arr = obj.start && obj.end ? [obj.start, obj.end] : [obj];
return arr.every(function(d) {
return d >= self.start && d <= self.end;
});
@ -4453,37 +4532,36 @@
/***
* @method every(<increment>, [fn])
* @returns Array
* @short Iterates through the DateRange for every <increment>, calling [fn] if it is passed. Returns an array of each increment visited.
* @extra When <increment> is a number, increments will be to the exact millisecond. <increment> can also be a string in the format %{number} {unit}s%, in which case it will increment in the unit specified. Note that a discrepancy exists in the case of months, as %(2).months()% is an approximation. Stepping through the actual months by passing %"2 months"% is usually preferable in this case.
* @short Iterates through the range for every <increment>, calling [fn] if it is passed. Returns an array of each increment visited.
* @extra When <increment> is a number, increments will be to the exact millisecond. In the case of date ranges, <increment> can also be a string in the format %{number} {unit}s%, in which case it will increment in the unit specified. Note that a discrepancy exists in the case of months, as %(2).months()% is an approximation. Stepping through the actual months by passing %"2 months"% is usually preferable in this case.
* @example
*
* Date.range('2003-01', '2003-03').every("2 months") -> [...]
* Number.range(2, 8).every(2) -> [2,4,6,8]
* Date.range(new Date(2003, 1), new Date(2003,3)).every("2 months") -> [...]
*
***/
'every': function(increment, fn) {
var current = this.start.clone(), result = [], index = 0, params, isDay;
if(isString(increment)) {
current.advance(getDateParamsFromString(increment, 0), true);
params = getDateParamsFromString(increment);
isDay = increment.toLowerCase() === 'day';
} else {
params = { 'milliseconds': increment };
}
while(current <= this.end) {
var start = this.start,
end = this.end,
inverse = end < start,
current = start,
index = 0,
result = [];
if(isFunction(increment)) {
fn = increment;
increment = null;
}
increment = increment || 1;
// Avoiding infinite loops
if(inverse && increment > 0) {
increment *= -1;
}
while(inverse ? current >= end : current <= end) {
result.push(current);
if(fn) fn(current, index);
if(isDay && callDateGet(current, 'Hours') === 23) {
// When DST traversal happens at 00:00 hours, the time is effectively
// pushed back to 23:00, meaning 1) 00:00 for that day does not exist,
// and 2) there is no difference between 23:00 and 00:00, as you are
// "jumping" around in time. Hours here will be reset before the date
// is advanced and the date will never in fact advance, so set the hours
// directly ahead to the next day to avoid this problem.
current = current.clone();
callDateSet(current, 'Hours', 48);
} else {
current = current.clone().advance(params, true);
if(fn) {
fn(current, index);
}
current = incrementRangeMember(current, increment);
index++;
}
return result;
@ -4491,15 +4569,16 @@
/***
* @method union(<range>)
* @returns DateRange
* @short Returns a new DateRange with the earliest starting point as its start, and the latest ending point as its end. If the two ranges do not intersect this will effectively remove the "gap" between them.
* @returns Range
* @short Returns a new range with the earliest starting point as its start, and the latest ending point as its end. If the two ranges do not intersect this will effectively remove the "gap" between them.
* @example
*
* Date.range('2003=01', '2005-01').union(Date.range('2004-01', '2006-01')) -> Jan 1, 2003..Jan 1, 2006
* Number.range(1, 3).union(Number.range(2, 5) -> 1..5
* Date.range(new Date(2003, 1), new Date(2005, 1)).union(Date.range(new Date(2004, 1), new Date(2006, 1))) -> Jan 1, 2003..Jan 1, 2006
*
***/
'union': function(range) {
return new DateRange(
return new Range(
this.start < range.start ? this.start : range.start,
this.end > range.end ? this.end : range.end
);
@ -4507,15 +4586,19 @@
/***
* @method intersect(<range>)
* @returns DateRange
* @short Returns a new DateRange with the latest starting point as its start, and the earliest ending point as its end. If the two ranges do not intersect this will effectively produce an invalid range.
* @returns Range
* @short Returns a new range with the latest starting point as its start, and the earliest ending point as its end. If the two ranges do not intersect this will effectively produce an invalid range.
* @example
*
* Date.range('2003-01', '2005-01').intersect(Date.range('2004-01', '2006-01')) -> Jan 1, 2004..Jan 1, 2005
* Number.range(1, 5).intersect(Number.range(4, 8) -> 4..5
* Date.range(new Date(2003, 1), new Date(2005, 1)).intersect(Date.range(new Date(2004, 1), new Date(2006, 1))) -> Jan 1, 2004..Jan 1, 2005
*
***/
'intersect': function(range) {
return new DateRange(
if(range.start > this.end || range.end < this.start) {
return new Range(NaN, NaN);
}
return new Range(
this.start > range.start ? this.start : range.start,
this.end < range.end ? this.end : range.end
);
@ -4523,60 +4606,161 @@
/***
* @method clone()
* @returns DateRange
* @short Clones the DateRange.
* @returns Range
* @short Clones the range.
* @extra Members of the range will also be cloned.
* @example
*
* Date.range('2003-01', '2005-01').intersect(Date.range('2004-01', '2006-01')) -> Jan 1, 2004..Jan 1, 2005
* Number.range(1, 5).clone() -> Returns a copy of the range.
*
***/
'clone': function(range) {
return new DateRange(this.start, this.end);
return new Range(this.start, this.end);
},
/***
* @method clamp(<obj>)
* @returns Mixed
* @short Clamps <obj> to be within the range if it falls outside.
* @example
*
* Number.range(1, 5).clamp(8) -> 5
* Date.range(new Date(2010, 0), new Date(2012, 0)).clamp(new Date(2013, 0)) -> 2012-01
*
***/
'clamp': function(obj) {
var clamped,
start = this.start,
end = this.end,
min = end < start ? end : start,
max = start > end ? start : end;
if(obj < min) {
clamped = min;
} else if(obj > max) {
clamped = max;
} else {
clamped = obj;
}
return cloneRangeMember(clamped);
}
});
extend(Range, true, false, {
/***
* @method step()
* @returns Array
* @short Alias for %every%.
*
* @example
*
+ range.step(fn); -> iterates over every step
+ range.step(2, fn); -> iterates over every 2 steps
*
***/
'step': Range.prototype.every
});
/***
* @method each[Unit]([fn])
* @returns Date
* @short Increments through the date range for each [unit], calling [fn] if it is passed. Returns an array of each increment visited.
*
* @set
* eachMillisecond
* eachSecond
* eachMinute
* eachHour
* eachDay
* eachWeek
* eachMonth
* eachYear
*
* @example
*
* Date.range('2003-01', '2003-02').eachMonth() -> [...]
* Date.range('2003-01-15', '2003-01-16').eachDay() -> [...]
*
* Date module
***/
extendSimilar(DateRange, true, false, 'Millisecond,Second,Minute,Hour,Day,Week,Month,Year', function(methods, name) {
methods['each' + name] = function(fn) { return this.every(name, fn); }
});
[number, string, date].forEach(function(klass) {
extend(klass, false, false, {
/***
* @method Number.range([start], [end])
* @returns Range
* @short Creates a new range between [start] and [end].
*
***
* @method String.range([start], [end])
* @returns Range
* @short Creates a new range between [start] and [end].
*
***
* @method Date.range([start], [end])
* @returns Range
* @short Creates a new range between [start] and [end].
* @extra If either [start] or [end] are null, they will default to the current date.
*
***/
'range': function(start, end) {
if(klass.create) {
start = klass.create(start);
end = klass.create(end);
}
return new Range(start, end);
}
});
});
/***
* Date module
* Number module
*
***/
extend(date, false, false, {
var numberRangeStep = function(num, fn, step) {
return number.range(this, num).step(step, fn);
};
number.extend({
/***
* @method upto(<num>, [fn], [step] = 1)
* @returns Array
* @short Returns an array containing numbers from the number up to <num>.
* @extra Optionally calls [fn] callback for each number in that array. [step] allows multiples greater than 1.
* @example
*
* (2).upto(6) -> [2, 3, 4, 5, 6]
* (2).upto(6, function(n) {
* // This function is called 5 times receiving n as the value.
* });
* (2).upto(8, null, 2) -> [2, 4, 6, 8]
*
***/
'upto': numberRangeStep,
/***
* @method downto(<num>, [fn], [step] = 1)
* @returns Array
* @short Returns an array containing numbers from the number down to <num>.
* @extra Optionally calls [fn] callback for each number in that array. [step] allows multiples greater than 1.
* @example
*
* (8).downto(3) -> [8, 7, 6, 5, 4, 3]
* (8).downto(3, function(n) {
* // This function is called 6 times receiving n as the value.
* });
* (8).downto(2, null, 2) -> [8, 6, 4, 2]
*
***/
'downto': numberRangeStep,
/***
* @method Date.range([start], [end])
* @returns DateRange
* @short Creates a new date range.
* @extra If either [start] or [end] are null, they will default to the current date.
* @method clamp([start], [end])
* @returns Number
* @short Constrains the number so that it is between [start] and [end].
* @extra This alias will build a range object that can be accessed directly using %Number.range% and has an equivalent %clamp% method.
*
***/
'range': function(start, end) {
return new DateRange(start, end);
'clamp': function(start, end) {
return new Range(start, end).clamp(this);
}
});
extend(array, false, function(a) { return a instanceof Range; }, {
'create': function(range) {
return range.step();
}
});
@ -5044,42 +5228,6 @@
return this.pad(pad || 1, false, 16);
},
/***
* @method upto(<num>, [fn], [step] = 1)
* @returns Array
* @short Returns an array containing numbers from the number up to <num>.
* @extra Optionally calls [fn] callback for each number in that array. [step] allows multiples greater than 1.
* @example
*
* (2).upto(6) -> [2, 3, 4, 5, 6]
* (2).upto(6, function(n) {
* // This function is called 5 times receiving n as the value.
* });
* (2).upto(8, null, 2) -> [2, 4, 6, 8]
*
***/
'upto': function(num, fn, step) {
return getRange(this, num, fn, step || 1);
},
/***
* @method downto(<num>, [fn], [step] = 1)
* @returns Array
* @short Returns an array containing numbers from the number down to <num>.
* @extra Optionally calls [fn] callback for each number in that array. [step] allows multiples greater than 1.
* @example
*
* (8).downto(3) -> [8, 7, 6, 5, 4, 3]
* (8).downto(3, function(n) {
* // This function is called 6 times receiving n as the value.
* });
* (8).downto(2, null, 2) -> [8, 6, 4, 2]
*
***/
'downto': function(num, fn, step) {
return getRange(this, num, fn, -(step || 1));
},
/***
* @method times(<fn>)
* @returns Number
@ -5599,7 +5747,7 @@
},
/***
* @method Object.toQueryString(<obj>, [namespace] = true)
* @method Object.toQueryString(<obj>, [namespace] = null)
* @returns Object
* @short Converts the object into a query string.
* @extra Accepts deep nested objects and arrays. If [namespace] is passed, it will be prefixed to all param names.
@ -6019,7 +6167,7 @@
* @method encodeBase64()
* @returns String
* @short Encodes the string into base64 encoding.
* @extra This method wraps the browser native %btoa% when available, and uses a custom implementation when not available.
* @extra This method wraps the browser native %btoa% when available, and uses a custom implementation when not available. It can also handle Unicode string encodings.
* @example
*
* 'gonna get encoded!'.encodeBase64() -> 'Z29ubmEgZ2V0IGVuY29kZWQh'
@ -6027,14 +6175,14 @@
*
***/
'encodeBase64': function() {
return btoa(this);
return btoa(unescape(encodeURIComponent(this)));
},
/***
* @method decodeBase64()
* @returns String
* @short Decodes the string from base64 encoding.
* @extra This method wraps the browser native %atob% when available, and uses a custom implementation when not available.
* @extra This method wraps the browser native %atob% when available, and uses a custom implementation when not available. It can also handle Unicode string encodings.
* @example
*
* 'aHR0cDovL3R3aXR0ZXIuY29tLw=='.decodeBase64() -> 'http://twitter.com/'
@ -6042,7 +6190,7 @@
*
***/
'decodeBase64': function() {
return atob(this);
return decodeURIComponent(escape(atob(this)));
},
/***
@ -7220,7 +7368,8 @@
'hankaku': {}
};
widthConversionRanges.forEach(function(r) {
getRange(r.start, r.end, function(n) {
simpleRepeat(r.end - r.start + 1, function(n) {
n += r.start;
setWidthConversion(r.type, chr(n), chr(n + r.shift));
});
});

@ -1,12 +1,13 @@
// Underscore.js 1.4.4
// http://underscorejs.org
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore may be freely distributed under the MIT license.
// Underscore.js 1.4.4
// ===================
(function() {
// > http://underscorejs.org
// > (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
// > Underscore may be freely distributed under the MIT license.
// Baseline setup
// --------------
// Baseline setup
// --------------
(function() {
// Establish the root object, `window` in the browser, or `global` on the server.
var root = this;

@ -10,9 +10,6 @@ define(['app', 'Missing/MissingItemView'], function () {
pager: '.x-missing-table-pager'
},
initialize : function (context, action, query, collection) {
this.collection = collection;
},
onCompositeCollectionRendered: function () {
this.ui.table.trigger('update');

@ -17,7 +17,7 @@ Marionette.TemplateCache.get = function (templateId) {
return templateFunction(data);
}
catch (error) {
console.error('template render failed for ' + templateKey + ' ' + error.message);
console.error('template render failed for ' + templateKey + ' ' + error);
console.error(data);
}
};

@ -1,10 +1,7 @@
'use strict';
define([
'app', 'Settings/SettingsModel'
], function () {
NzbDrone.Settings.Quality.QualityView = Backbone.Marionette.ItemView.extend({
template : 'Settings/Quality/QualityTemplate',
className: 'form-horizontal',
@ -12,6 +9,6 @@ define([
initialize: function (options) {
this.qualityProfileCollection = options.qualityProfiles;
this.model.set({ qualityProfiles: this.qualityProfileCollection });
},
}
});
});

@ -1,4 +1,5 @@
define([
"use strict";
define([
'app',
'Settings/Naming/NamingView',
'Settings/Quality/QualityLayout',
@ -8,7 +9,7 @@
'Settings/System/SystemView',
'Settings/Misc/MiscView'
],
function (app) {
function () {
NzbDrone.Settings.SettingsLayout = Backbone.Marionette.Layout.extend({
template: 'Settings/SettingsLayoutTemplate',
@ -106,15 +107,10 @@
NzbDrone.Router.navigate('settings/misc');
},
initialize: function (context, action, query, settings) {
this.settings = settings;
if (action) {
this.action = action.toLowerCase();
}
if (query) {
this.query = query.toLowerCase();
initialize: function (options) {
this.settings = options.settings;
if (options.action) {
this.action = options.action.toLowerCase();
}
},

Loading…
Cancel
Save