From c515b65acc66d8adfdfcfa52cb253d835277562f Mon Sep 17 00:00:00 2001 From: Adrian Pardini Date: Thu, 6 Feb 2014 00:09:53 -0300 Subject: [PATCH] make MediaListView inherit from MasterView --- public/js/views/medialist.js | 503 ++++++++++++++++++----------------- 1 file changed, 262 insertions(+), 241 deletions(-) diff --git a/public/js/views/medialist.js b/public/js/views/medialist.js index 9ed9a90..d3e36b4 100644 --- a/public/js/views/medialist.js +++ b/public/js/views/medialist.js @@ -1,289 +1,310 @@ -window.MediaListView = function(options){ - var self = this; - _.extend(self, Backbone.Events); +window.MediaListView = MasterView.extend({ + el: "#content", + initialize: function(options){ + MasterView.prototype.initialize.apply(this, arguments); + var self = this; - options = options || {}; + options = options || {}; + self.options = options; - var model = options['model']; + var model = options['model']; - var el = options['el'] || $('#content'); - this.el = el; + var el = options['el'] || $('#content'); + this.el = el; - this._hasChanges = false; - var allow_drop = false; + var type = 'type' in options ? options['type'] : 'medialist-searchable-fixed'; - var default_pagination = 'endless'; - var pagination = 'pagination' in options ? options['pagination'] : default_pagination; + var collection; + if (type.match(/playlist/)) { + // In case of playlist, fetch related + if (!model.isNew()) { + model.fetchRelated("pieces"); + model.fetchRelated("occurrences"); + model.fetch(); + } + collection = model.get('pieces'); + } else { + if (model !== undefined) { + // Use provided model + collection = model; + } else { + // Or use default collection type + collection = new Media.CollectionPageable(); + model = collection; + } + collection.fetch(); + } - var config = 0; - var default_facets = appCollection.at(config).get('Search').Medias.facets; - var fulltext_fields = appCollection.at(config).get('Search').Medias.fulltext; - var facets = 'facets' in options ? options['facets'] : default_facets; + this.model = model; + this.collection = collection; - var default_search_type = 'server'; - var search_type = 'search_type' in options ? options['search_type'] : default_search_type; - var type = 'type' in options ? options['type'] : 'medialist-searchable-fixed'; + this.render(); + }, - var collection; - if (type.match(/playlist/)) { - // In case of playlist, fetch related - if (!model.isNew()) { - model.fetchRelated("pieces"); - model.fetchRelated("occurrences"); - model.fetch(); - } - collection = model.get('pieces'); - } else { - if (model !== undefined) { - // Use provided model - collection = model; - } else { - // Or use default collection type - collection = new Media.CollectionPageable(); - model = collection; - } - collection.fetch(); - } + render: function (options) { + var self = this; + var options = options || this.options; - this.model = model; + var allow_drop = false; + var type = options.type; + var el = this.el; - if (type.match(/sortable/)){ - allow_drop = true; - search_type = 'client'; - } + var collection = this.collection; + var model = this.model; - el.html(template.medialist({type: type})); + var default_pagination = 'endless'; + var pagination = 'pagination' in options ? options['pagination'] : default_pagination; - $("#media-view", el).on("dragstart", function() { - self.trigger('dragstart') - }); + var config = 0; + var default_facets = appCollection.at(config).get('Search').Medias.facets; + var fulltext_fields = appCollection.at(config).get('Search').Medias.fulltext; + var facets = 'facets' in options ? options['facets'] : default_facets; - $("#media-view", el).on("dragstop", function() { - self.trigger('dragstop') - }); + var default_search_type = 'server'; + var search_type = 'search_type' in options ? options['search_type'] : default_search_type; + var type = 'type' in options ? options['type'] : 'medialist-searchable-fixed'; - var MediaListViewModel = kb.ViewModel.extend({ - constructor: function(model) { - kb.ViewModel.prototype.constructor.apply(this, arguments); - var self = this; + if (type.match(/sortable/)){ + allow_drop = true; + search_type = 'client'; + } - _.bindAll(this, "afterMove", "dragHandler"); - _.extend(self, Backbone.Events); + el.html(template.medialist({type: type})); - this.editingName = ko.observable(false); - this.nameClick = function () { - this.editingName(true); - } + $("#media-view", el).on("dragstart", function() { + self.trigger('dragstart') + }); - this.changeFocus = function () { - if(self.name().length<=0) - return false; - self.editingName(false); - } + $("#media-view", el).on("dragstop", function() { + self.trigger('dragstop') + }); - this.removeItem = function (item) { - var filters = self.filter(); - self.filter(null); - self.collection.remove(item); - self.filter(filters); - } + var MediaListViewModel = kb.ViewModel.extend({ + constructor: function(model) { + kb.ViewModel.prototype.constructor.apply(this, arguments); + var self = this; + _.bindAll(this, "afterMove", "dragHandler"); + _.extend(self, Backbone.Events); - this.__filters = ko.observable(); - this.filter = ko.computed({ - read: function() { - return self.__filters(); - }, - write: function(query) { - filters = []; - if (!query) { - self.collection.filters(filters); - self.__filters(filters); - return; - } - var deep_get = function(model, prop) { - var value = ''; - attrs = prop.split("."); - value = model.get(attrs.shift()); - while (attrs.length) { - value = value[attrs.shift()]; - } - return value; - } - _.each(query, function(target, prop) { - var flt = function(model) { - var re = new RegExp(target, "i"); - if (prop != "text") { - value = deep_get(model, prop); - // returning true here tells KO to skip that model from the display list. - return String(value).search(re) < 0; - } else { - var fields = _.clone(fulltext_fields); - var results = []; - while (fields.length) { - value = deep_get(model, fields.shift()); - results.push( String(value).search(re) < 0 ); - } - return _.every(results); - } - } - filters.push(flt); - }); - self.__filters(query); - self.collection.filters(filters); - }, - }); - this.collection = kb.collectionObservable(collection, { - view_model: kb.ViewModel, - }); - collection.bind('filter', self.filter); - - this.playlist_or_notempty = ko.computed({ - read: function () { - return (!self.collection.length || type.match(/playlist/)); + this.editingName = ko.observable(false); + this.nameClick = function () { + this.editingName(true); } - }); - - this.duration = kb.observable(model, 'duration'); - - this.total_time = ko.computed(function(){ -//XXX: keep this, it tells KO to update total_time when something happens to the model. -// For Media.Playlist we look for changes in the duration field, as the pieces may arrive with incomplete -// information when we do a fetchRelated(). We take care of that inside the model and update duration when -// everything is ready. -// If we are rendering a Media.Collection we don't have a duration attribute and so we add a dependency to -// the collection itself. - var x = self.duration(); - if (x === null) { - x = self.collection(); + + this.changeFocus = function () { + if(self.name().length<=0) + return false; + self.editingName(false); } - return model.pretty_duration(); - }, model); - }, - - allowDrop: ko.observable(allow_drop), - - dragHandler: function(item, event, ui){ - // Instantiate drag element as Media.Piece - var attrs = _.clone(item.model().attributes); - var piece = new Media.Piece(attrs); - piece.set('checksum', attrs['_id']); - piece.unset('_id'); - return kb.viewModel(piece) - }, - - afterMove: function(arg, event, ui) { - var pieces = this.model().get("pieces"); - var model = arg.item.model(); - if (model.isNew()) { - pieces.add(model, {at: arg.targetIndex}); - } - }, - }); - this.search_view = new SearchView({ - el: $('#media-search',el), - collection: collection, - type: search_type, - pagination: pagination, - facets: facets - }); - this.clearSearch = this.search_view.clearSearch; + this.removeItem = function (item) { + var filters = self.filter(); + self.filter(null); + self.collection.remove(item); + self.filter(filters); + } - this.view_model = new MediaListViewModel(model); + this.__filters = ko.observable(); + this.filter = ko.computed({ + read: function() { + return self.__filters(); + }, + write: function(query) { + filters = []; + if (!query) { + self.collection.filters(filters); + self.__filters(filters); + return; + } + var deep_get = function(model, prop) { + var value = ''; + attrs = prop.split("."); + value = model.get(attrs.shift()); + while (attrs.length) { + value = value[attrs.shift()]; + } + return value; + } + _.each(query, function(target, prop) { + var flt = function(model) { + var re = new RegExp(target, "i"); + if (prop != "text") { + value = deep_get(model, prop); + // returning true here tells KO to skip that model from the display list. + return String(value).search(re) < 0; + } else { + var fields = _.clone(fulltext_fields); + var results = []; + while (fields.length) { + value = deep_get(model, fields.shift()); + results.push( String(value).search(re) < 0 ); + } + return _.every(results); + } + } + filters.push(flt); + }); + self.__filters(query); + self.collection.filters(filters); + }, + }); + this.collection = kb.collectionObservable(collection, { + view_model: kb.ViewModel, + }); + collection.bind('filter', self.filter); + + this.playlist_or_notempty = ko.computed({ + read: function () { + return (!self.collection.length || type.match(/playlist/)); + } + }); + + this.duration = kb.observable(model, 'duration'); + + this.total_time = ko.computed(function(){ + //XXX: keep this, it tells KO to update total_time when something happens to the model. + // For Media.Playlist we look for changes in the duration field, as the pieces may arrive with incomplete + // information when we do a fetchRelated(). We take care of that inside the model and update duration when + // everything is ready. + // If we are rendering a Media.Collection we don't have a duration attribute and so we add a dependency to + // the collection itself. + var x = self.duration(); + if (x === null) { + x = self.collection(); + } + return model.pretty_duration(); + }, model); + }, + + allowDrop: ko.observable(allow_drop), + + dragHandler: function(item, event, ui){ + // Instantiate drag element as Media.Piece + var attrs = _.clone(item.model().attributes); + var piece = new Media.Piece(attrs); + piece.set('checksum', attrs['_id']); + piece.unset('_id'); + return kb.viewModel(piece) + }, + + afterMove: function(arg, event, ui) { + var pieces = this.model().get("pieces"); + var model = arg.item.model(); + if (model.isNew()) { + pieces.add(model, {at: arg.targetIndex}); + } + }, + }); - this.searchFilter = this.view_model.filter; + this.search_view = new SearchView({ + el: $('#media-search',el), + collection: collection, + type: search_type, + pagination: pagination, + facets: facets + }); - this.editListName = function () { - this.view_model.editingName(true); - }; + this.view_model = new MediaListViewModel(model); - this.releaseView = function() { - // Release resources - collection.off("filter"); - this.model.off("change"); - this.search_view.destroy(); - kb.release(this.view_model); - }; - this.removeView = function() { - // Clear element - ko.cleanNode(this.el[0]); - this.el.html(''); - }; + this.searchFilter = this.view_model.filter; - this.destroyView = function() { - this.releaseView(); - this.removeView(); - }; + this.editListName = function () { + this.view_model.editingName(true); + }; - this.deleteModel = function () { - this.destroyView(); - var pieces = this.model.get('pieces'); - for( i=pieces.length-1; i>=0; i--) { - pieces.at(i).destroy(); - } - this.model.destroy(); - }; + this.deleteModel = function () { + this.destroyView(); + var pieces = this.model.get('pieces'); + for( i=pieces.length-1; i>=0; i--) { + pieces.at(i).destroy(); + } + this.model.destroy(); + }; - this.save = function (newmodel) { - if (newmodel) { - this.view_model.model(newmodel); - this.model = newmodel; - newmodel.bind('change', this._model_change_cb); - } - this.model.save(); - this._hasChanges = false; - }; + this.addDummyRow = function () { + var container = $("#media-view", this.el); + if ($(".dummy-row", container).length) { + return; + } + container.append(''); + }; + + this.removeDummyRow = function () { + var container = $("#media-view", this.el); + var dummy = $(".dummy-row", container); + dummy.remove() + }; + + this.onCollectionChange = function (value) { + if (0 == value.length){ + this.addDummyRow(); + } else { + this.removeDummyRow(); + } + }; - this.addDummyRow = function () { - var container = $("#media-view", this.el); - if ($(".dummy-row", container).length) { - return; - } - container.append(''); - }; + this._model_change_cb = function () { + this._hasChanges = true; + }; + + _.bindAll(this, 'onCollectionChange', 'addDummyRow', 'removeDummyRow', 'destroyView', 'deleteModel', 'save', 'editListName', '_model_change_cb', 'clearChanges', 'hasChanges'); + this.view_model.collection.subscribe(this.onCollectionChange); + model.bind('change', this._model_change_cb); - this.removeDummyRow = function () { - var container = $("#media-view", this.el); - var dummy = $(".dummy-row", container); - dummy.remove() - }; + ko.applyBindings(this.view_model, el[0]); - this.onCollectionChange = function (value) { - if (0 == value.length){ + if (0 == collection.length){ this.addDummyRow(); - } else { - this.removeDummyRow(); } - }; - this._model_change_cb = function () { - this._hasChanges = true; - }; + }, + + clearSearch: function () { + this.search_view.clearSearch(); + }, - this.clearChanges = function () { + clearChanges: function () { this._hasChanges = false; - }; + }, - this.hasChanges = function () { + hasChanges: function () { return this.model.isNew() || this._hasChanges - }; + }, - _.bindAll(this, 'onCollectionChange', 'addDummyRow', 'removeDummyRow', 'destroyView', 'deleteModel', 'save', 'editListName', '_model_change_cb', 'clearChanges', 'hasChanges'); - this.view_model.collection.subscribe(this.onCollectionChange); - model.bind('change', this._model_change_cb); + save: function (newmodel) { + if (newmodel) { + this.view_model.model(newmodel); + this.model = newmodel; + newmodel.bind('change', this._model_change_cb); + } + this.model.save(); + this._hasChanges = false; + }, + + releaseView: function() { + // Release resources + this.collection.off("filter"); + this.model.off("change"); + this.search_view.destroy(); + kb.release(this.view_model); + }, - ko.applyBindings(this.view_model, el[0]); + removeView: function() { + // Clear element + ko.cleanNode(this.el[0]); + this.el.html(''); + }, - if (0 == collection.length){ - this.addDummyRow(); - } + destroyView: function() { + this.releaseView(); + this.removeView(); + }, - this.canNavigateAway = function(options) { + canNavigateAway: function(options) { this.destroyView(); options["ok"](); - }; -} - + }, +});