Skip to content

Instantly share code, notes, and snippets.

@bdryanovski
Created May 16, 2013 20:53
Show Gist options
  • Select an option

  • Save bdryanovski/5595017 to your computer and use it in GitHub Desktop.

Select an option

Save bdryanovski/5595017 to your computer and use it in GitHub Desktop.
Channel selector
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