Created
May 16, 2013 20:53
-
-
Save bdryanovski/5595017 to your computer and use it in GitHub Desktop.
Channel selector
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| define('app/channel_selector/channel_selector', function () { | |
| var controller = Spine.Controller.create({ | |
| proxied: ["searchItems", "seeMore", "handleOutsideClick"], | |
| events: { | |
| //"keyup .search_walls_stats": "searchItemsThrottled", | |
| "click table.cs_channels thead tr": "selectItemHeader", | |
| "click table.cs_channels tbody": "selectItem", | |
| "click div.thead.cs_channels": "sortItemsThrottled", | |
| "click .channel_selector_header": "toggleSelector", | |
| "click div.see_more": "seeMore", | |
| "click table.cs_aggregate tr": "selectAggregateItem" | |
| }, | |
| default_see_more_limits: { | |
| agency: 10, | |
| client: 10, | |
| campaign: 10, | |
| channels: 25 | |
| }, | |
| initSeeMoreLimits: function(){ | |
| this.see_more_limits = {}; | |
| //counters for user clicks on More/See more | |
| this.see_more_limits_increased_count = {}; | |
| for(i in this.default_see_more_limits){ | |
| this.see_more_limits_increased_count[i] = 0; | |
| this.see_more_limits[i] = this.default_see_more_limits[i]; | |
| } | |
| }, | |
| configure: function (options) { | |
| this.opt = options; | |
| }, | |
| /* | |
| Contains all non-model related properties we need to initialize: | |
| */ | |
| initVariables: function(){ | |
| var self = this; | |
| this.displayed_items = 0; | |
| this.sort_column = 'name'; | |
| this.sort_order = 'asc'; | |
| this.wall_corner = ''; | |
| // The selection - normal items | |
| this.Selection = new function() { | |
| this.list = []; | |
| this.find = function (id, type) { | |
| return _(this.list).find( function (el) { return el.type == type && el.id == id; } ); | |
| } | |
| this.load = function (list, is_flat) { | |
| var self = this; | |
| _(list).each( function (item) { | |
| var tmp; | |
| if (is_flat) { | |
| tmp = item.split("_"); | |
| self.add(tmp[1], tmp[0]); | |
| } else { | |
| self.add(item.id, item.type); | |
| } | |
| }); | |
| return this; | |
| } | |
| this.add = function (id, type) { | |
| if (!this.find(id, type)) { | |
| this.list.push({id: id, type: type}); | |
| } | |
| return this; | |
| } | |
| this.toggle = function (id, type) { | |
| if (!this.find(id, type)) { | |
| this.list.push({id: id, type: type}); | |
| } else { | |
| this.remove(id, type); | |
| } | |
| return this; | |
| } | |
| this.remove = function (id, type) { | |
| this.list = _(this.list).reject( function (el) { return el.type == type && el.id == id; } ); | |
| return this; | |
| } | |
| this.empty = function () { | |
| this.list = []; | |
| return this; | |
| } | |
| this.isEmpty = function () { | |
| return this.list.length ? false : true; | |
| } | |
| this.getList = function (flat) { | |
| if (flat) { | |
| return _(this.list).map( function (el) { return el.type + "_" + el.id; } ); | |
| } else { | |
| return this.list; | |
| } | |
| } | |
| this.filterList = function (type) { | |
| return _(this.list).chain().filter( function (el) { return el.type == type; } ).pluck('id').value(); | |
| } | |
| }; | |
| // The special selection - agency, client, campaign, all | |
| this.SelectionSpecial = new function() { | |
| this.agency_id = null; | |
| this.client_id = null; | |
| this.campaign_id = null; | |
| this.all_channels = false; | |
| this.reset = function () { | |
| this.agency_id = null; | |
| this.client_id = null; | |
| this.campaign_id = null; | |
| this.all_channels = false; | |
| } | |
| this.setAgency = function (id) { | |
| this.agency_id = id; | |
| this.client_id = null; | |
| this.campaign_id = null; | |
| this.all_channels = false; | |
| } | |
| this.getAgency = function(){ | |
| return this.agency_id; | |
| } | |
| this.setClient = function (id) { | |
| this.agency_id = null; | |
| this.client_id = id; | |
| this.campaign_id = null; | |
| this.all_channels = false; | |
| } | |
| this.getClient = function(){ | |
| return this.client_id; | |
| } | |
| this.setCampaign = function (id) { | |
| this.agency_id = null; | |
| this.client_id = null; | |
| this.campaign_id = id; | |
| this.all_channels = false; | |
| } | |
| this.getCampaign = function(){ | |
| return this.campaign_id; | |
| } | |
| this.setAllSources = function () { | |
| this.agency_id = null; | |
| this.client_id = null; | |
| this.campaign_id = null; | |
| this.all_channels = true; | |
| } | |
| this.getAllSources = function(){ | |
| return this.all_channels; | |
| } | |
| this.getSelectedItem = function(){ | |
| if(this.agency_id) | |
| { | |
| return {id:this.agency_id, type:'agency'}; | |
| }else if(this.client_id) | |
| { | |
| return {id:this.client_id, type:'client'}; | |
| }else if(this.campaign_id) | |
| { | |
| return {id:this.campaign_id, type:'campaign'}; | |
| }else if( self.getSelectedItems().length == 1) | |
| { | |
| var _id, item, source_type; | |
| if( item = self.getSelectedItems()[0] ) | |
| { | |
| //currently we return only fb single selected page. | |
| if( _id = item['fb_page_id'] ) | |
| { | |
| source_type = 'fb'; | |
| return { id: _id, source_type:source_type, type:'channel' }; | |
| } | |
| } | |
| } | |
| //all other cases ( i.e. twitter accounts, multiple selection) | |
| //they are not handled yet. | |
| return {id:null, type:null}; | |
| } | |
| this.get = function () { | |
| return { | |
| agency_id: this.agency_id, | |
| client_id: this.client_id, | |
| campaign_id: this.campaign_id, | |
| all_channels: this.all_channels | |
| } | |
| } | |
| this.load = function (data) { | |
| this.agency_id = data.agency_id; | |
| this.client_id = data.client_id; | |
| this.campaign_id = data.campaign_id; | |
| this.all_channels = data.all_channels; | |
| } | |
| this.agencySelected = function () { | |
| return this.agency_id; | |
| } | |
| this.clientSelected = function () { | |
| return this.client_id; | |
| } | |
| this.campaignSelected = function () { | |
| return this.campaign_id; | |
| } | |
| this.allChannelsSelected = function () { | |
| if (ui_helpers.has_user_role(['master']) || (ui_helpers.has_user_role(['agency_admin']) && logged_user.roles[0].agency_id == 20)) { | |
| return false; | |
| } | |
| return this.all_channels; | |
| } | |
| }; | |
| if( this.hasCache()) | |
| { | |
| self.SelectionSpecial.load(kizzy(self.opt.cache_key).get('special_selection'), true); | |
| self.Selection.load( kizzy(self.opt.cache_key).get('source_list'), true ); | |
| } | |
| }, | |
| hasCache: function(){ | |
| return ( | |
| typeof kizzy( this.opt.cache_key ).get('source_list') == "object" && | |
| typeof kizzy( this.opt.cache_key ).get('special_selection') == "object" | |
| ); | |
| }, | |
| load: function (next) { | |
| this.initVariables(); | |
| var self = this; | |
| async.parallel([ | |
| function (next2) { | |
| app.getTemplates(['channel_selector/channel_selector'], function () { | |
| next2(); | |
| }); | |
| }, | |
| function (next2) { | |
| if (!self.opt.source.model_preloaded) { | |
| if (typeof self.opt.source.model_query !== "undefined") { | |
| self.opt.source.model.query = $.extend(self.opt.source.model.query, self.opt.source.model_query); | |
| } | |
| self.opt.source.model.fetch({ondone: next2}); | |
| } else { | |
| next2(); | |
| } | |
| }, | |
| function (next2) { | |
| if( !( app.models.agency.all().length > 0 && | |
| app.models.client.all().length > 0 && | |
| app.models.campaign.all().length > 0 | |
| ) | |
| ) | |
| { | |
| self.first_load = false; | |
| var resources = [ | |
| { | |
| model: app.models.agency, | |
| pre_call: function() { app.models.agency.query = { fields: 'name' };}, | |
| callback: function() { app.models.agency.query = {};} | |
| }, | |
| { | |
| model: app.models.client, | |
| pre_call: function() { app.models.client.query = { fields: 'agency_id, name' };}, | |
| callback: function() { app.models.client.query = {};} | |
| }, | |
| { | |
| model: app.models.campaign, | |
| pre_call: function() { app.models.campaign.query = { fields: 'client_id, name' };}, | |
| callback: function() { app.models.campaign.query = {};} | |
| } | |
| ]; | |
| app.batchFetch(resources, next2); | |
| }else{ | |
| next2(); | |
| } | |
| } | |
| ], function (err) { | |
| var agency_id, client_id, campaign_id, selected, | |
| all_items = _(self.opt.source.model.all()).map( function (item) { | |
| var type = self.opt.source.getType(item); | |
| var id = self.opt.source.getSourceId(item); | |
| return type + "_" + id; | |
| }); | |
| // Initialize the special selection from kizzy | |
| if (typeof kizzy(self.opt.cache_key).get('special_selection') === 'object') { | |
| self.SelectionSpecial.load(kizzy(self.opt.cache_key).get('special_selection'), true); | |
| } | |
| agency_id = self.SelectionSpecial.agencySelected(); | |
| client_id = self.SelectionSpecial.clientSelected(); | |
| campaign_id = self.SelectionSpecial.campaignSelected(); | |
| // Validate the special selection, if any | |
| // Agency selected | |
| if (false && agency_id) { | |
| if (app.models.agency.find( agency_id )) { | |
| selected = _(self.opt.source.model.all()).chain().filter(function (item) { | |
| return (item.agency_id == agency_id) && self.opt.source.isActive(item) ? true : false; | |
| }).map(function (item) { | |
| return {type: self.opt.source.getType(item), id: self.opt.source.getSourceId(item)}; | |
| }).value(); | |
| self.Selection.empty().load(selected); | |
| } else { | |
| self.SelectionSpecial.setAllSources(); | |
| self.Selection.empty(); | |
| } | |
| // Client selected | |
| } else if ( false && client_id ) { | |
| if (app.models.client.find( client_id )) { | |
| selected = _(self.opt.source.model.all()).chain().filter(function (item) { | |
| return (item.client_id == client_id) && self.opt.source.isActive(item) ? true : false; | |
| }).map(function (item) { | |
| return {type: self.opt.source.getType(item), id: self.opt.source.getSourceId(item)}; | |
| }).value(); | |
| self.Selection.empty().load(selected); | |
| } else { | |
| self.SelectionSpecial.setAllSources(); | |
| self.Selection.empty(); | |
| } | |
| // Campaign selected | |
| } else if ( false && campaign_id ) { | |
| if (app.models.campaign.find( campaign_id )) { | |
| selected = _(self.opt.source.model.all()).chain().filter(function (item) { | |
| return (item.campaign_id == campaign_id) && self.opt.source.isActive(item) ? true : false; | |
| }).map(function (item) { | |
| return {type: self.opt.source.getType(item), id: self.opt.source.getSourceId(item)}; | |
| }).value(); | |
| self.Selection.empty().load(selected); | |
| } else { | |
| self.SelectionSpecial.setAllSources(); | |
| self.Selection.empty(); | |
| } | |
| // All channels selected | |
| } else if (self.SelectionSpecial.allChannelsSelected()) { | |
| self.Selection.empty(); | |
| // Individual channels selected | |
| } else { | |
| if (typeof kizzy(self.opt.cache_key).get('source_list') !== 'object') { | |
| selection = []; | |
| } else { | |
| selection = _.intersection(kizzy(self.opt.cache_key).get('source_list'), all_items); | |
| } | |
| if (selection.length === 0) { | |
| self.SelectionSpecial.setAllSources(); | |
| self.Selection.empty(); | |
| } else { | |
| self.Selection.load(selection, true); | |
| } | |
| } | |
| // Save the selection in the cache | |
| kizzy(self.opt.cache_key).set('source_list', self.Selection.getList(true)); | |
| kizzy(self.opt.cache_key).set('special_selection', self.SelectionSpecial.get()); | |
| next(err); | |
| }); | |
| }, | |
| first_load: true, | |
| startup: function () { | |
| var self = this; | |
| /* new properties / new params */ | |
| this.is_first_load = true; | |
| this.show_popup = false; | |
| this.initSeeMoreLimits(); | |
| this.search_string = ''; | |
| this.limit_search = true; | |
| this.use_default_sorting = true; | |
| this.last_scroll_ratio = 0;//in pixels , set in searchItems | |
| this.selection_updated = false; | |
| this.is_typing = false; | |
| //needed because we call render() everytime a sort / occured | |
| /* end of new properties */ | |
| $(document).bind('click', this.handleOutsideClick); | |
| this.bind('destroy', function () { | |
| $(document).unbind('click', this.handleOutsideClick); | |
| }); | |
| //displayed items are moved to render: | |
| this.el = $('#channel_selector'); | |
| var multiplier = 2; | |
| if(this.opt.source.model.count() > 1000) | |
| { | |
| multiplier = 3; | |
| }else if(this.opt.source.model.count() > 500) | |
| { | |
| multiplier = 2; | |
| } | |
| this.searchItemsThrottled = _.throttle(this.searchItems, 100*multiplier ); | |
| this.sortItemsThrottled = _.throttle(this.sortItems, 100*multiplier ); | |
| this.delegateEvents(); | |
| this.render(); | |
| //this.updateScrollbar('relative'); | |
| }, | |
| render: function ( params ) { | |
| var self = this, stats_totals, items_list, hide_dialog;//hide_dialog if we are in startup flow. | |
| var focus_search = false;//whether to focus on the search box or not. | |
| if(!params) //startup flow | |
| { | |
| params = { | |
| agency_items: app.models.agency.all(), | |
| client_items: app.models.client.all(), | |
| campaign_items: app.models.campaign.all(), | |
| items: this.opt.source.model.all(), | |
| search_string : '' | |
| }; | |
| hide_dialog = true; | |
| }else{ //search flow - we have searched for sth | |
| if($(".search_walls_stats").length){ | |
| //render for second time | |
| params.search_string = $(".search_walls_stats").val(); | |
| } | |
| hide_dialog = false; | |
| focus_search = true; | |
| } | |
| stats_totals = {}; | |
| if(this.use_default_sorting) | |
| { | |
| items_list = _.sortBy( params.items , function (item) { | |
| var type = self.opt.source.getType(item); | |
| for (i=0; i < self.opt.header.stats.length; i++) { | |
| if (self.opt.header.stats[i].aggregation === "sum") { | |
| if (typeof stats_totals[i] === "undefined") { | |
| stats_totals[i] = parseFloat(self.opt.source.getStat(item, i)); | |
| } else { | |
| stats_totals[i] += parseFloat(self.opt.source.getStat(item, i)); | |
| } | |
| } | |
| } | |
| return item.name.toLowerCase(); | |
| }); | |
| }else{ | |
| items_list = params.items; | |
| } | |
| // Auto select the first if necessary | |
| if (!this.opt.can_select_all && this.Selection.isEmpty()) { | |
| if (items_list.length > 0) { | |
| item_type = self.opt.source.getType(items_list[0]); | |
| item_id = self.opt.source.getSourceId(items_list[0]); | |
| this.Selection.add(item_id, item_type); | |
| kizzy(self.opt.cache_key).set('source_list', this.Selection.getList(true)); | |
| } | |
| } | |
| var channel_selector_html = app.templates.built['channel_selector/channel_selector']( { | |
| agency_items: params.agency_items, | |
| client_items: params.client_items, | |
| campaign_items: params.campaign_items, | |
| opt: this.opt, | |
| items_list: items_list, | |
| stats_totals: stats_totals, | |
| Selection: this.Selection, | |
| SelectionSpecial: this.SelectionSpecial, | |
| all_items: this.opt.source.model.all(), | |
| see_more_limits: this.see_more_limits, | |
| search_string: params.search_string, | |
| load_everything: this.is_first_load | |
| }); | |
| if(this.is_first_load) | |
| { | |
| this.html(channel_selector_html.replace(new RegExp("/\\s+", "gi"), " ")); | |
| //bind the typing event !!very important | |
| $('.search_walls_stats').typing({ | |
| start: _.throttle( function(){ self.is_typing = true; ui_helpers.loader.show('.wall_list','.channel_selector_body'); }, 500 ), | |
| stop: self.searchItemsThrottled, | |
| delay:500 | |
| }); | |
| $('.search_walls_stats').keyup( | |
| function(event) | |
| { | |
| var keyCodes = [86, 88]; | |
| //intercept ctrl+v: 86-v, 88-x | |
| if( keyCodes.indexOf(event.keyCode) > -1 ) | |
| { | |
| ui_helpers.loader.show('.wall_list','.channel_selector_body'); | |
| _.throttle( self.searchItems, 500)(); | |
| } | |
| //leave ctrl+a unchanged | |
| } | |
| ); | |
| }else{ | |
| //partial render to avoid problems with focus on search. | |
| this.el.find('.wall_list').html( channel_selector_html.replace(new RegExp("\\s+", "gi"), " ") ); | |
| } | |
| this.displayed_items = 0; | |
| this.displayed_items += _.min([ params.agency_items.length , this.see_more_limits.agency]); | |
| this.displayed_items += _.min([ params.client_items.length , this.see_more_limits.client]); | |
| this.displayed_items += _.min([ params.campaign_items.length , this.see_more_limits.campaign]); | |
| this.displayed_items += _.min([ items_list.length, this.see_more_limits.channels ]); | |
| if( this.opt.trigger_callback_on_first_load && this.is_first_load ) { | |
| this.trigger('selectionUpdated', this.Selection); | |
| this.is_first_load = false; | |
| } | |
| if(self.show_popup) | |
| { | |
| hide_dialog = false; | |
| } | |
| if(focus_search) | |
| { | |
| var html_search = $(".search_walls_stats")[0]; | |
| html_search.selectionStart = html_search.selectionEnd = $(".search_walls_stats").val().length; | |
| } | |
| this.pseudo_render(hide_dialog); | |
| }, | |
| // pseudo-render | |
| pseudo_render: function (hide_popup) { | |
| var self = this; | |
| if(this.show_popup) | |
| { | |
| hide_popup = false; | |
| this.show_popup = false; //reset it. | |
| } | |
| // hide the selector popup | |
| if (hide_popup) { | |
| this.el.find('.channel_selector_body').hide(); | |
| }else{ | |
| this.el.find('.channel_selector_body').show(); | |
| } | |
| // update selection info | |
| this.updateSelectionInfo(); | |
| // mark all selected walls in the UI | |
| if (this.Selection.isEmpty()) { | |
| // $('#wall_stat_total').addClass('active'); | |
| } else { | |
| $('#wall_stat_' + this.Selection.getList(true).join(',#wall_stat_')).addClass('active'); | |
| } | |
| // mark the selected agencies, etc... | |
| if (this.SelectionSpecial.agencySelected()) { | |
| $('#cs_agency_' + this.SelectionSpecial.agencySelected()).addClass('active'); | |
| } | |
| if (this.SelectionSpecial.clientSelected()) { | |
| $('#cs_client_' + this.SelectionSpecial.clientSelected()).addClass('active'); | |
| } | |
| if (this.SelectionSpecial.campaignSelected()) { | |
| $('#cs_campaign_' + this.SelectionSpecial.campaignSelected()).addClass('active'); | |
| } | |
| if (this.SelectionSpecial.allChannelsSelected()) { | |
| $('#wall_stat_total').addClass('active'); | |
| } | |
| this.arrangeOrderIcons(); | |
| this.updateScrollbar('relative'); | |
| return this; | |
| }, | |
| // updater for the info about the selected pages | |
| updateSelectionInfo: function () { | |
| var self = this, img, txt; | |
| //debugger; | |
| if (this.SelectionSpecial.allChannelsSelected()) { | |
| img = this.opt.source.getAggregateImage(this.Selection, this.SelectionSpecial, this.opt.source.model.all()); | |
| txt = 'All ' + this.opt.source.noun + ' (' + (parseInt(this.opt.source.model.count(), 10)) + ')'; | |
| } else if (this.SelectionSpecial.agencySelected()) { | |
| img = 'images/cs/default_agency_image.png'; | |
| txt = app.models.agency.find( this.SelectionSpecial.agencySelected() ).name + " (" + this.Selection.getList().length + ")"; | |
| } else if (this.SelectionSpecial.clientSelected()) { | |
| img = 'images/cs/default_client_image.png'; | |
| txt = app.models.client.find( this.SelectionSpecial.clientSelected() ).name + " (" + this.Selection.getList().length + ")"; | |
| } else if (this.SelectionSpecial.campaignSelected()) { | |
| img = 'images/cs/default_campaign_image.png'; | |
| txt = app.models.campaign.find( this.SelectionSpecial.campaignSelected() ).name + " (" + this.Selection.getList().length + ")"; | |
| } else if (this.Selection.isEmpty()) { | |
| img = this.opt.source.getAggregateImage(this.Selection, this.SelectionSpecial, this.opt.source.model.all()); | |
| txt = 'No channels' | |
| } else if (this.Selection.getList().length === 1) { | |
| var temp = this.Selection.getList()[0]; | |
| var item = this.opt.source.model.findByAttribute(this.opt.source.types[temp.type], temp.id); | |
| var img = this.opt.source.getImage(item); | |
| var txt = this.opt.source.getName(item); | |
| if (this.opt.source.getSecondaryName(item)) { | |
| txt += " - " + this.opt.source.getSecondaryName(item); | |
| } | |
| } else { | |
| img = this.opt.source.getAggregateImage(this.Selection, this.SelectionSpecial, this.opt.source.model); | |
| txt = 'Multiple ' + this.opt.source.noun + ' (' + this.Selection.getList().length + ')'; | |
| } | |
| this.el.find('.channel_selector_header').find('img').attr('src', img).end().find('.title').html(txt); | |
| }, | |
| // toggle selector popup | |
| toggleSelector: function () { | |
| var sizes, $stats = this.el.find('.channel_selector_body'), | |
| self = this, | |
| wdt = 0; | |
| if ($stats.is(':visible')) { | |
| $stats.hide(); | |
| } else { | |
| $stats.show(); | |
| self.arrangeOrderIcons(); | |
| this.updateScrollbar('relative'); | |
| } | |
| }, | |
| arrangeOrderIcons: function(){ | |
| var sizes, $stats = this.el.find('.channel_selector_body'), | |
| self = this, | |
| wdt = 0; | |
| this.difference = 0; | |
| sizes = $stats.find('table.cs_channels thead th,table.cs_channels thead td').map(function () { | |
| var min_size = 24; | |
| if ($(this).width() <= min_size) { | |
| self.difference += min_size - $(this).width(); | |
| return min_size; // min-width per cell | |
| } else { | |
| return $(this).width(); | |
| } | |
| }); | |
| $stats.find('.thead.cs_channels .th,.thead.cs_channels .td').each(function (i) { $(this).css('width', sizes[i] + 'px'); }); | |
| wdt = $stats.find('.thead.cs_channels .th[data-sortby="name"]').css('width'); | |
| $stats.find('.thead.cs_channels .th[data-sortby="name"]').css('width', parseInt(wdt, 10) - this.difference - 2); | |
| }, | |
| // update the custom scrollbar | |
| updateScrollbar: function (update_type) { | |
| if (this.displayed_items > 10) { | |
| // activate the scroller | |
| this.el.find('.viewport').css({height: '400px'}).find('.scrollbar').css({display: 'block'}); | |
| this.el.find('.overview').css({position: 'absolute'}); | |
| /*!Important - removed .not('.tinyscrollbar')*/ | |
| this.el.find('.channel_selector_body').addClass('tinyscrollbar').tinyscrollbar({axis: 'y', wheel: 75, scroll: true, size: 400-10, sizethumb: 100}); | |
| /*if(this.last_scroll_ratio > 0) | |
| { | |
| update_type = _.min([this.last_scroll_ratio * this.el.find('.scrollbar').height() , this.el.find('.scrollbar').height() - 100 ]); //the same as size_thumb | |
| }*/ | |
| if (typeof update_type !== "undefined") { | |
| this.el.find('.channel_selector_body').tinyscrollbar_update(update_type); | |
| } else { | |
| this.el.find('.channel_selector_body').tinyscrollbar_update(); | |
| } | |
| } else { | |
| this.el.find('.viewport').css({height: 'auto'}).find('.scrollbar').css({display: 'none'}); | |
| this.el.find('.overview').css({position: 'relative', top: '0px'}); | |
| } | |
| }, | |
| selectItemHeader: function (event) { | |
| var self = this, | |
| row = $(event.target).closest('tr'), | |
| source_id = row.data('id'), | |
| source_type = row.data('type'); | |
| // update the active state of the channels table | |
| row.closest('table.cs_channels').find('tr').removeClass('active'); | |
| row.addClass('active'); | |
| // update the active state of special tables | |
| this.el.find('table.cs_agency').find('tr.active').removeClass('active'); | |
| this.el.find('table.cs_client').find('tr.active').removeClass('active'); | |
| this.el.find('table.cs_campaign').find('tr.active').removeClass('active'); | |
| // Select All (all types, all ids) | |
| if (!source_id && !source_type) { | |
| self.Selection.empty(); | |
| self.SelectionSpecial.setAllSources(); | |
| } | |
| kizzy(self.opt.cache_key).set('source_list', this.Selection.getList(true)); | |
| kizzy(self.opt.cache_key).set('special_selection', this.SelectionSpecial.get()); | |
| this.trigger('selectionUpdated', this.Selection); | |
| this.pseudo_render(true); | |
| }, | |
| // handle selection of wall in the popup | |
| selectItem: function (event) { | |
| var self = this, | |
| row = $(event.target).closest('tr'), | |
| source_id = row.data('id'), | |
| source_type = row.data('type'), | |
| item = self.opt.source.model.findByAttribute(this.opt.source.types[source_type], source_id), | |
| item_id = self.opt.source.getSourceId(item), | |
| item_type = self.opt.source.getType(item); | |
| var item = self.opt.source.model.findByAttribute(this.opt.source.types[source_type], source_id); | |
| // Activate item | |
| if (item && !self.opt.source.isActive(item)) { | |
| self.opt.source.activateCb(item); | |
| return; | |
| } | |
| if (source_id === '' || !item) { | |
| // update wall list | |
| self.Selection.empty(); | |
| this.wall_corner = ''; | |
| } else if (self.opt.can_select_multiple && event.ctrlKey === true) { | |
| if (self.opt.can_mix || this.Selection.isEmpty() || this.Selection.getList()[0].type == item_type) { | |
| this.Selection.toggle(item_id, item_type); | |
| } | |
| this.wall_corner = parseInt(item_id, 10); | |
| } else if (self.opt.can_select_multiple && event.shiftKey === true) { | |
| var corners = [parseInt(item_id, 10)], corners_found = 1; | |
| if (this.wall_corner !== '') { | |
| corners.push(this.wall_corner); | |
| corners_found = 0; | |
| } | |
| self.Selection.empty(); | |
| row.closest('table.cs_channels').find('tbody tr').not('.wall_invalid,:hidden').each(function (i, elem) { | |
| var elem_id = parseInt($(elem).data('id'), 10), | |
| elem_type = $(elem).data('type'), | |
| element = self.opt.source.model.findByAttribute(self.opt.source.types[elem_type], elem_id); | |
| if (corners.indexOf(elem_id) > -1) { | |
| if (self.opt.can_mix || self.Selection.isEmpty() || self.Selection.getList()[0].type == elem_type) { | |
| self.Selection.add(elem_id, elem_type); | |
| } | |
| corners_found += 1; | |
| } else if (corners_found === 1 && isNaN(elem_id) === false) { | |
| if (self.opt.can_mix || self.Selection.isEmpty() || self.Selection.getList()[0].type == elem_type) { | |
| self.Selection.add(elem_id, elem_type); | |
| } | |
| } | |
| }); | |
| if (self.Selection.isEmpty()) { | |
| this.wall_corner = ''; | |
| } | |
| } else { | |
| self.Selection.empty().add(item_id, item_type); | |
| this.wall_corner = parseInt(item_id, 10); | |
| } | |
| if (this.Selection.isEmpty()) | |
| { | |
| this.SelectionSpecial.setAllSources(); | |
| } else { | |
| this.SelectionSpecial.reset(); | |
| } | |
| // update the active state of special tables | |
| this.el.find('table.cs_agency').find('tr.active').removeClass('active'); | |
| this.el.find('table.cs_client').find('tr.active').removeClass('active'); | |
| this.el.find('table.cs_campaign').find('tr.active').removeClass('active'); | |
| // update active state of table rows | |
| row.closest('table.cs_channels').find('tr').removeClass('active'); | |
| _.each(self.Selection.getList(), function (sel) { | |
| try { | |
| var item = self.opt.source.model.findByAttribute(self.opt.source.types[sel.type], sel.id); | |
| if (self.opt.source.isActive(item)) { | |
| $('#wall_stat_' + sel.type + "_" + sel.id).addClass('active'); | |
| } | |
| } catch (no_wall) {} | |
| }); | |
| kizzy(self.opt.cache_key).set('source_list', this.Selection.getList(true)); | |
| kizzy(self.opt.cache_key).set('special_selection', this.SelectionSpecial.get()); | |
| this.trigger('selectionUpdated', this.Selection); | |
| this.pseudo_render(!self.opt.can_select_multiple || !(event.ctrlKey || event.shiftKey || event.altKey)); | |
| }, | |
| // search for walls | |
| //reinitializes this.search_string. from the value in html. | |
| searchItems: function (event) { | |
| ui_helpers.loader.hide('.channel_selector_body'); | |
| var self = this, is_expanded, matched = {}, | |
| search_string = $.trim($(".search_walls_stats").val()), | |
| search_texts = search_string.split(' '), | |
| sorted_items = []; | |
| this.is_typing = false; | |
| //set the last scroll position to use after render | |
| if( this.el.find('.scrollbar .thumb').length > 0 ) | |
| { | |
| var pos = this.el.find('.scrollbar .thumb').position().top , | |
| total_height = _.max([ this.el.find('.scrollbar').height() - this.el.find('.scrollbar .thumb').height() , pos ]); | |
| this.last_scroll_ratio = Math.round( (pos/total_height)*100 )/100; | |
| } | |
| if( this.limit_search && search_string.length <= 2 && search_string === this.search_string ) | |
| { | |
| return; | |
| } | |
| if( $(".search_walls_stats").val() != self.search_string ) | |
| { // a new search was made for a first time- | |
| //reset the limits. | |
| this.search_string = $(".search_walls_stats").val(); | |
| this.initSeeMoreLimits(); | |
| this.use_default_sorting = true; //return the default sorting back. | |
| } | |
| search_texts = _(search_texts).chain().filter(function (item) { return item !== '' ? true : false; }).map(function (elem) { return new RegExp(elem, 'gi'); }).value(); | |
| // Filter the list of agencies, clients and campaigns based on the state of see more | |
| _(['agency', 'client', 'campaign']).each(function (t) { | |
| is_expanded = self.el.find('table.cs_' + t).hasClass("expanded"); | |
| // Show the tread by default | |
| $('table.cs_' + t ).show() | |
| matched[ t+'_items' ] = (search_texts.length === 0) ? app.models[t].all() : _(app.models[t].all()).filter(function (item) { | |
| var j, show_row = 0; | |
| for (j = 0; j < search_texts.length; j++) { | |
| if (item.name.match(search_texts[j])) { | |
| show_row += 1; | |
| } | |
| } | |
| return (show_row === search_texts.length) ? true : false; | |
| }); | |
| self.el.find(".channel_selector_body table.cs_" + t + " tbody tr").hide(); | |
| if (!is_expanded) { | |
| if (matched[t+'_items'].length <= self.see_more_limits[t]) { | |
| self.el.find(".channel_selector_body div.see_more.cs_" + t).hide(); | |
| } else { | |
| self.el.find(".channel_selector_body div.see_more.cs_" + t).show(); | |
| self.el.find(".channel_selector_body div.see_more.cs_" + t).find('span').html(matched[t+'_items'].length - self.see_more_limits[t]); | |
| //matched = _(matched).first(self.see_more_limits[t]); | |
| } | |
| } | |
| /* | |
| if (matched.length > 0) { | |
| $('#cs_' + t + '_' + _(matched).pluck('id').join(',#cs_' + t + '_')).css({display: 'block'}); | |
| } else { | |
| // Hide thead title if there are no matches. | |
| $('.cs_' + t ).hide() | |
| } | |
| */ | |
| }); | |
| // Filter the channels | |
| is_expanded = self.el.find('table.cs_channels').hasClass("expanded"); | |
| matched.items = (search_texts.length === 0) ? self.opt.source.model.all() : _(self.opt.source.model.all()).filter(function (item) { | |
| var j, show_row = 0, | |
| item_id = self.opt.source.getSourceId(item), | |
| item_type = self.opt.source.getType(item), | |
| item_name = self.opt.source.getName(item), | |
| item_secondary_name = self.opt.source.getSecondaryName(item); | |
| for (j = 0; j < search_texts.length; j++) { | |
| if (item_name.match(search_texts[j]) || item_secondary_name && item_secondary_name.match(search_texts[j])) { | |
| show_row += 1; | |
| } | |
| } | |
| return (show_row === search_texts.length) ? true : false; | |
| }); | |
| if(!this.use_default_sorting) | |
| { | |
| //sort matched.items | |
| sorted_items = _.sortBy( matched.items , function (item) { | |
| var sort_val; | |
| if (self.sort_column !== 'name') { | |
| sort_val = self.opt.source.getStat(item, self.sort_column); | |
| return sort_val === null ? -1 : parseFloat(sort_val); | |
| } else { | |
| sort_val = self.opt.source.getName(item).toLowerCase(); | |
| return sort_val; // alphabetical sort | |
| } | |
| }); | |
| if (this.sort_order === 'desc') { | |
| sorted_items.reverse(); | |
| } | |
| matched.items = sorted_items; | |
| } | |
| self.el.find(".channel_selector_body table.cs_channels tbody tr").hide(); | |
| if (!is_expanded) { | |
| if (matched.items.length <= self.see_more_limits.channels) { | |
| self.el.find(".channel_selector_body div.see_more.cs_channels").hide(); | |
| } else { | |
| self.el.find(".channel_selector_body div.see_more.cs_channels").show(); | |
| //self.el.find(".channel_selector_body div.see_more.cs_channels").find('span').html(matched.length - self.see_more_limits.channels); | |
| //matched.items = _(matched).first(self.see_more_limits.channels); | |
| //this is handled by the render function | |
| } | |
| } | |
| //we call render just to show the items. | |
| this.is_first_load = false; | |
| this.render(matched); | |
| //this.updateScrollbar('relative'); | |
| }, | |
| /* return the selected items - if we can*/ | |
| getCacheSourceList: function() | |
| { | |
| if (typeof kizzy(this.opt.cache_key).get('source_list') === 'object') | |
| { | |
| return kizzy(this.opt.cache_key).get('source_list'); | |
| } | |
| return null; | |
| }, | |
| sortItems: function (event) { | |
| var self = this, sorted_items, $sort_col = $(event.target).closest('.td,.th'), | |
| sort_col = $sort_col.data('sortby'), $items_list = this.el.find('table.cs_channels tbody'); | |
| this.use_default_sorting = false; | |
| if (sort_col !== this.sort_column) { | |
| this.sort_column = sort_col; | |
| this.sort_order = 'desc'; | |
| } else { | |
| this.sort_order = (this.sort_order === 'asc') ? 'desc' : 'asc'; | |
| } | |
| //we need - sort.column. sort_order. then call searchItems. | |
| /* //Moved to searchItems. | |
| sorted_items = _.sortBy(self.opt.source.model.all(), function (item) { | |
| var sort_val; | |
| if (self.sort_column !== 'name') { | |
| sort_val = self.opt.source.getStat(item, self.sort_column); | |
| return sort_val === null ? -1 : parseFloat(sort_val); | |
| } else { | |
| sort_val = self.opt.source.getName(item).toLowerCase(); | |
| return sort_val; // alphabetical sort | |
| } | |
| }); | |
| if (this.sort_order === 'desc') { | |
| sorted_items.reverse(); | |
| }*/ | |
| var is_expanded = this.el.find('table.cs_channels').hasClass("expanded"); | |
| this.limit_search = false; | |
| this.searchItems();//we've ordered the items. | |
| this.el.find('.thead.cs_channels i').removeClass('sort sort_asc sort_desc'); | |
| $sort_col.find('i').addClass('sort sort_' + this.sort_order); | |
| this.el.find('.channel_selector_body').tinyscrollbar_update('relative'); | |
| }, | |
| handleOutsideClick: function (event) { | |
| if( $(event.target).closest('.see_more', '#channel_selector').length > 0 ) | |
| { | |
| return; | |
| }else if( $(event.target).closest('.cs_channels', '#channel_selector').length > 0) | |
| { | |
| return; | |
| } | |
| if( $(event.target).hasClass('see_more_text') || $(event.target).hasClass('see_more_arrow') ) | |
| { | |
| //a very nasty IE9 fix. | |
| return; | |
| } | |
| if ($(event.target).closest('#channel_selector').length === 0) { | |
| this.el.find('.channel_selector_body').hide(); | |
| } | |
| }, | |
| getSelectedItems: function () { | |
| var self = this; | |
| return _(this.opt.source.model.all()).filter(function (item) { | |
| var item_type = self.opt.source.getType(item), | |
| item_id = self.opt.source.getSourceId(item); | |
| return _(self.Selection.getList()).find(function (sel) { | |
| return (sel.id == item_id && sel.type == item_type) ? true : false; | |
| }) ? true : false; | |
| }); | |
| }, | |
| getAllItems: function (type) { | |
| var self = this; | |
| if (typeof type === "undefined") { | |
| return this.opt.source.model.all(); | |
| } | |
| return _(this.opt.source.model.all()).filter(function (item) { | |
| var item_type = self.opt.source.getType(item); | |
| return item_type == type ? true : false; | |
| }); | |
| }, | |
| sourceUpdated: function (updated_items) { | |
| var self = this; | |
| // Update the stats for all updated items | |
| _(updated_items).each(function (item) { | |
| var item_type = self.opt.source.getType(item), | |
| item_id = self.opt.source.getSourceId(item), | |
| stat_value; | |
| _(self.opt.header.stats).each(function (stat, i) { | |
| stat_value = self.opt.source.getStat(item, i); | |
| self.el.find('#wall_stat_' + item_type + "_" + item_id).find("." + stat.name).text(stat_value); | |
| }); | |
| }); | |
| // Calculate the totals (for all items, no matter if updated or not) | |
| stats_totals = {}; | |
| _.each(this.opt.source.model.all(), function (item) { | |
| var type = self.opt.source.getType(item); | |
| for (i = 0; i < self.opt.header.stats.length; i += 1) { | |
| if (self.opt.header.stats[i].aggregation === "sum") { | |
| if (typeof stats_totals[i] === "undefined") { | |
| stats_totals[i] = parseFloat(self.opt.source.getStat(item, i)); | |
| } else { | |
| stats_totals[i] += parseFloat(self.opt.source.getStat(item, i)); | |
| } | |
| } | |
| } | |
| }); | |
| // Update the totals | |
| _(self.opt.header.stats).each(function (stat, i) { | |
| self.el.find('#wall_stat_total').find("." + stat.name).text(stats_totals[i]); | |
| }); | |
| }, | |
| itemActivated: function (id, type) { | |
| }, | |
| seeMore: function (event) { | |
| var see_more = $(event.target).closest("div.see_more"); | |
| for( i in this.see_more_limits ) | |
| { | |
| if( see_more.hasClass('cs_'+i) ) | |
| { | |
| if(this.see_more_limits_increased_count[i] >= 1) | |
| { | |
| this.see_more_limits[i] += 50;//default increase size | |
| }else{ | |
| this.see_more_limits[i] += this.default_see_more_limits[i]; | |
| } | |
| this.see_more_limits_increased_count[i]++; | |
| } | |
| } | |
| // Hide the See more button | |
| see_more.hide(); | |
| // Add the expanded class to the table to show that the See more button has been clicked | |
| see_more.prev().addClass("expanded"); | |
| // Call the search function which will show/hide the good elements depending on the filter and will update the scrollbar in the end | |
| //this.searchItems(); | |
| //keep the search string. | |
| this.show_popup = true; | |
| if(this.limit_search) | |
| { | |
| this.limit_search = false; | |
| this.searchItems(); | |
| this.limit_search = true; | |
| }else{ | |
| this.searchItems(); | |
| } | |
| }, | |
| selectAggregateItem: function (event) { | |
| var self = this, agency_id, client_id, campaign_id, selected; | |
| if ($(event.target).closest("tr").hasClass("see_more")) { | |
| return; | |
| } | |
| agency_id = $(event.target).closest("tr").data("agency_id"); | |
| client_id = $(event.target).closest("tr").data("client_id"); | |
| campaign_id = $(event.target).closest("tr").data("campaign_id"); | |
| if (agency_id) { | |
| selected = _(this.opt.source.model.all()).chain().filter(function (item) { | |
| return (item.agency_id == agency_id) && self.opt.source.isActive(item) ? true : false; | |
| }).map(function (item) { | |
| return {type: self.opt.source.getType(item), id: self.opt.source.getSourceId(item)}; | |
| }).value(); | |
| this.SelectionSpecial.setAgency(agency_id); | |
| } | |
| if (client_id) { | |
| selected = _(this.opt.source.model.all()).chain().filter(function (item) { | |
| return (item.client_id == client_id) && self.opt.source.isActive(item) ? true : false; | |
| }).map(function (item) { | |
| return {type: self.opt.source.getType(item), id: self.opt.source.getSourceId(item)}; | |
| }).value(); | |
| this.SelectionSpecial.setClient(client_id); | |
| } | |
| if (campaign_id) { | |
| selected = _(this.opt.source.model.all()).chain().filter(function (item) { | |
| return (item.campaign_id == campaign_id) && self.opt.source.isActive(item) ? true : false; | |
| }).map(function (item) { | |
| return {type: self.opt.source.getType(item), id: self.opt.source.getSourceId(item)}; | |
| }).value(); | |
| this.SelectionSpecial.setCampaign(campaign_id); | |
| } | |
| this.Selection.empty().load(selected); | |
| // update active state of table rows | |
| this.el.find('table.cs_channels').find('tr').removeClass('active'); | |
| _.each(self.Selection.getList(), function (sel) { | |
| try { | |
| var item = self.opt.source.model.findByAttribute(self.opt.source.types[sel.type], sel.id); | |
| if (self.opt.source.isActive(item)) { | |
| $('#wall_stat_' + sel.type + "_" + sel.id).addClass('active'); | |
| } | |
| } catch (no_wall) {} | |
| }); | |
| // update the active state of special tables | |
| this.el.find('table.cs_agency').find('tr.active').removeClass('active'); | |
| this.el.find('table.cs_client').find('tr.active').removeClass('active'); | |
| this.el.find('table.cs_campaign').find('tr.active').removeClass('active'); | |
| $(event.target).closest("tr").addClass('active'); | |
| kizzy(self.opt.cache_key).set('source_list', this.Selection.getList(true)); | |
| kizzy(self.opt.cache_key).set('special_selection', this.SelectionSpecial.get()); | |
| this.trigger('selectionUpdated', this.Selection); | |
| this.pseudo_render(true); | |
| }, | |
| // returns true if single channel is selected, false otherwise. | |
| // (checks that selected item is actually a channel, agency/client/campaign that contains one channel will return false) | |
| singleChannelSelected: function () { | |
| return (this.SelectionSpecial.agency_id === null && this.SelectionSpecial.client_id === null && this.SelectionSpecial.agency_id === null) | |
| && (this.Selection.getList().length === 1); | |
| }, | |
| destroy: function () { | |
| this.trigger('destroy'); | |
| } | |
| }); | |
| return function () { return controller; }; | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment