NewsBlur/media/js/newsblur/reader/reader_organizer.js

434 lines
18 KiB
JavaScript

NEWSBLUR.ReaderOrganizer = function(user_id, options) {
var defaults = {
width: 800,
sorting: 'alphabetical',
onOpen: _.bind(function() {
this.resize_modal();
}, this),
hierarchy: "nested",
inverse_sorting: false
};
this.options = $.extend({}, defaults, options);
this.model = NEWSBLUR.assets;
this.init();
};
NEWSBLUR.ReaderOrganizer.prototype = new NEWSBLUR.Modal;
_.extend(NEWSBLUR.ReaderOrganizer.prototype, {
init: function() {
this.reset_feeds();
this.make_modal();
this.open_modal();
this.$modal.bind('click', $.rescope(this.handle_click, this));
this.$modal.bind('change', $.rescope(this.handle_change, this));
},
reset_feeds: function() {
NEWSBLUR.assets.feeds.each(function(feed) {
feed.highlight_in_all_folders(false, true, {silent: true});
});
},
make_modal: function() {
var self = this;
this.$modal = $.make('div', { className: 'NB-modal NB-modal-organizer' }, [
$.make('h2', { className: 'NB-modal-title' }, [
$.make('div', { className: 'NB-modal-loading' }),
$.make('div', { className: 'NB-icon' }),
'Organize sites',
$.make('div', { className: 'NB-icon-dropdown' })
]),
$.make('div', { className: 'NB-organizer-sidebar'}, [
$.make('div', { className: 'NB-organizer-sidebar-hierarchy' }, [
$.make('div', { className: 'NB-organizer-sidebar-title' }, 'Show Folders'),
$.make('div', { className: 'NB-organizer-sidebar-container' }, [
$.make('ul', { className: 'segmented-control' }, [
$.make('li', { className: 'NB-organizer-hierarchy NB-organizer-hierarchy-nested NB-active' }, 'Nested'),
$.make('li', { className: 'NB-organizer-hierarchy NB-organizer-hierarchy-flat' }, 'Flat')
])
])
]),
$.make('div', { className: 'NB-organizer-sidebar-move' }, [
$.make('div', { className: 'NB-organizer-sidebar-title' }, 'Move to folder'),
$.make('div', { className: 'NB-organizer-sidebar-container' }, [
NEWSBLUR.utils.make_folders(),
$.make('div', { className: 'NB-icon-add', title: "Add folder" }),
$.make('div', { className: "NB-add-folder NB-hidden" }, [
$.make('div', { className: 'NB-icon-subfolder' }),
$.make('input', { type: 'text', id: 'NB-add-folder', className: 'NB-input NB-add-folder-input', name: 'new_folder_name', placeholder: "New folder name..." })
]),
$.make('div', { className: 'NB-error-move NB-error' }),
$.make('div', { className: 'NB-modal-submit-button NB-modal-submit-green NB-disabled NB-action-move' }, 'Move'),
$.make('div', { className: 'NB-loading' })
])
]),
$.make('div', { className: 'NB-organizer-sidebar-delete' }, [
$.make('div', { className: 'NB-organizer-sidebar-title' }, 'Delete sites'),
$.make('div', { className: 'NB-organizer-sidebar-container' }, [
$.make('div', { className: 'NB-error-delete NB-error' }),
$.make('div', { className: 'NB-modal-submit-button NB-modal-submit-red NB-disabled NB-action-delete' }, 'Delete'),
$.make('div', { className: 'NB-loading' })
])
]),
$.make('div', { className: 'NB-organizer-sidebar-jump' }, [
$.make('div', { className: 'NB-organizer-sidebar-title' }, 'Jump to Folder'),
$.make('div', { className: 'NB-organizer-sidebar-container' }, [
this.make_folders()
])
])
]),
$.make('div', { className: 'NB-organizer-actionbar' }, [
$.make('div', { className: 'NB-organizer-sorts' }, [
$.make('div', { className: 'NB-organizer-action-title' }, 'Sort '),
$.make('div', { className: 'NB-organizer-action NB-action-alphabetical NB-active' }, 'Name'),
$.make('div', { className: 'NB-organizer-action NB-action-subscribers' }, 'Subscribers'),
$.make('div', { className: 'NB-organizer-action NB-action-frequency' }, 'Frequency'),
$.make('div', { className: 'NB-organizer-action NB-action-recency' }, 'Recency'),
$.make('div', { className: 'NB-organizer-action NB-action-mostused' }, 'Opens')
]),
$.make('div', { className: 'NB-organizer-selects' }, [
$.make('div', { className: 'NB-organizer-action-title' }, 'Select'),
$.make('div', { className: 'NB-organizer-action NB-action-select-all' }, 'All'),
$.make('div', { className: 'NB-organizer-action NB-action-select-none' }, 'None')
])
]),
this.make_feeds()
]);
},
resize_modal: function(previous_height) {
var resize_height = 0;
var $feedlist = $('.NB-feedchooser', this.$modal);
var content_height = $feedlist.height() + 90;
var container_height = this.$modal.parent().height();
if (content_height > container_height && previous_height != content_height) {
var chooser_height = $feedlist.height();
var diff = Math.max(4, content_height - container_height);
resize_height = chooser_height - diff;
$feedlist.css({'max-height': resize_height});
_.defer(_.bind(function() { this.resize_modal(content_height); }, this), 1);
}
if (resize_height) {
this.options.resize = resize_height;
}
},
// =============
// = Feed list =
// =============
make_feeds: function(options) {
var feeds = this.model.feeds;
if (this.options.hierarchy == "flat") {
this.options.folders = new NEWSBLUR.Collections.Folders(NEWSBLUR.assets.feeds.pluck('id'));
} else {
this.options.folders = NEWSBLUR.assets.folders;
}
this.feed_count = _.unique(this.options.folders.feed_ids_in_folder()).length;
NEWSBLUR.Collections.Folders.organizer_sortorder = this.options.sorting;
NEWSBLUR.Collections.Folders.organizer_inversesort = this.options.inverse_sorting;
this.options.folders.sort();
this.feedlist = new NEWSBLUR.Views.FeedList({
feed_chooser: true,
organizer: true,
hierarchy: this.options.hierarchy,
sorting: this.options.sorting,
inverse_sorting: this.options.inverse_sorting
}).make_feeds({folders: this.options.folders});
var $feeds = this.feedlist.$el;
if (this.options.resize) {
$feeds.css({'max-height': this.options.resize});
}
if ($feeds.data('sortable')) $feeds.data('sortable').disable();
// Expand collapsed folders
$('.NB-folder-collapsed', $feeds).css({
'display': 'block',
'opacity': 1
}).removeClass('NB-folder-collapsed');
// Pretend unfetched feeds are fine
$('.NB-feed-unfetched', $feeds).removeClass('NB-feed-unfetched');
// Make sure all folders are visible
$('.NB-folder.NB-hidden', $feeds).removeClass('NB-hidden');
$('.NB-organizer-sorts', this.$modal).toggleClass('NB-sort-inverse', this.options.inverse_sorting);
NEWSBLUR.Collections.Folders.organizer_sortorder = null;
this.options.folders.sort();
NEWSBLUR.assets.feeds.off('change:highlighted')
.on('change:highlighted', _.bind(this.change_selection, this));
return $feeds;
},
make_folders: function() {
var $folders = $.make('div', { className: 'NB-organizer-sidebar-folderjump' }, [
NEWSBLUR.utils.make_folders()
]);
return $folders;
},
replace_folders: function() {
$(".NB-folders", this.$modal).replaceWith(NEWSBLUR.utils.make_folders());
},
// =============
// = Selecting =
// =============
change_select: function(select) {
if (select == "all") {
this.feedlist.folder_view.highlight_feeds({force_highlight: true});
} else if (select == "none") {
this.feedlist.folder_view.highlight_feeds({force_deselect: true});
}
},
change_selection: function() {
var $title = $(".NB-organizer-selects .NB-organizer-action-title", this.$modal);
var $move = $(".NB-action-move", this.$modal);
var $error = $(".NB-error-move", this.$modal);
var $delete = $(".NB-action-delete", this.$modal);
var count = this.feedlist.folder_view.highlighted_count_unique_folders();
console.log(['change_selection', count]);
$title.text(count ? count + " selected" : "Select");
$error.text('');
if (!count) {
$delete.text('Delete').addClass('NB-disabled');
$move.text('Move').addClass('NB-disabled');
} else {
$delete.text('Delete ' + Inflector.pluralize('site', count, true)).removeClass('NB-disabled');
$move.text('Move ' + Inflector.pluralize('site', count, true)).removeClass('NB-disabled');
}
NEWSBLUR.assets.feeds.off('change:highlighted')
.on('change:highlighted', _.bind(this.change_selection, this));
},
// ===========
// = Sorting =
// ===========
change_sort: function(sorting) {
var inverse = this.options.inverse_sorting;
if (this.options.sorting == sorting) {
this.options.inverse_sorting = !inverse;
} else {
this.options.inverse_sorting = false;
}
this.options.sorting = sorting;
var $feedlist = $('.NB-feedchooser', this.$modal);
var old_position = $feedlist.scrollTop();
$(".NB-action-"+sorting, this.$modal).addClass('NB-active').siblings().removeClass('NB-active');
$(".NB-feedlist", this.$modal).replaceWith(this.make_feeds());
var $feedlist = $('.NB-feedchooser', this.$modal);
$feedlist.scrollTop(old_position);
},
// =============
// = Hierarchy =
// =============
toggle_hierarchy: function(hierarchy) {
this.options.hierarchy = hierarchy;
$(".NB-organizer-hierarchy", this.$modal).removeClass('NB-active');
$(".NB-organizer-hierarchy-"+hierarchy, this.$modal).addClass('NB-active');
$(".NB-feedlist", this.$modal).replaceWith(this.make_feeds());
},
// ==========
// = Server =
// ==========
serialize: function() {
var highlighted_feeds = this.feedlist.folder_view.highlighted_feeds({
collection: this.options.folders
});
return highlighted_feeds;
},
move_feeds: function() {
var self = this;
var highlighted_feeds = this.serialize();
var $move = $('.NB-action-move', this.$modal);
var $error = $(".NB-error-move", this.$modal).hide();
var $loading = $('.NB-modal-loading', this.$modal);
var $new_folder = $('.NB-add-folder-input', this.$modal);
var new_folder = $new_folder.val();
var $feedlist = $(".NB-feedlist", this.$modal);
var to_folder = $('.NB-folders').val();
$loading.addClass('NB-active');
$move.addClass('NB-disabled').text('Moving...');
NEWSBLUR.reader.flags['reloading_feeds'] = true;
if (!this._open_folder) new_folder = null;
console.log(["Moving feeds by folder", highlighted_feeds, to_folder, new_folder]);
NEWSBLUR.assets.move_feeds_by_folder(highlighted_feeds, to_folder, new_folder, function() {
NEWSBLUR.reader.flags['reloading_feeds'] = false;
$loading.removeClass('NB-active');
NEWSBLUR.assets.feeds.trigger('reset');
self.reset_feeds();
$feedlist.replaceWith(self.make_feeds());
self.change_selection();
$move.text('Moved!');
if (self._open_folder) self.toggle_folder_add();
self.replace_folders();
$new_folder.val('');
}, function(error) {
NEWSBLUR.reader.flags['reloading_feeds'] = false;
$loading.removeClass('NB-active');
self.change_selection();
$error.show().text("Sorry, there was a problem moving feeds.");
});
},
delete_feeds: function() {
var self = this;
var highlighted_feeds = this.serialize();
var $loading = $('.NB-modal-loading', this.$modal);
var $error = $(".NB-error-delete", this.$modal).hide();
var $delete = $('.NB-action-delete', this.$modal);
var $feedlist = $(".NB-feedlist", this.$modal);
$loading.addClass('NB-active');
$delete.addClass('NB-disabled').text('Deleting...');
NEWSBLUR.reader.flags['reloading_feeds'] = true;
console.log(["Deleting feeds by folder", highlighted_feeds]);
if (this.options.hierarchy == 'flat') {
// Ignore folder when flat, which will delte feed out of all folders
highlighted_feeds = _.map(highlighted_feeds, function(feed_folder) {
return [feed_folder[0], null];
});
}
NEWSBLUR.assets.delete_feeds_by_folder(highlighted_feeds, function() {
NEWSBLUR.reader.flags['reloading_feeds'] = false;
$loading.removeClass('NB-active');
self.reset_feeds();
$feedlist.replaceWith(self.make_feeds());
self.change_selection();
NEWSBLUR.assets.feeds.trigger('reset');
$delete.text('Deleted!');
if (self._open_folder) self.toggle_folder_add();
}, function(error) {
NEWSBLUR.reader.flags['reloading_feeds'] = false;
$loading.removeClass('NB-active');
self.change_selection();
$error.show().text("Sorry, there was a problem deleting feeds.");
});
},
// ===========
// = Actions =
// ===========
handle_click: function(elem, e) {
var self = this;
$.targetIs(e, { tagSelector: '.NB-organizer-action', childOf: '.NB-organizer-sorts' },
_.bind(function($t, $p) {
e.preventDefault();
var sort = $t.attr('class').match(/\bNB-action-(\w+)\b/)[1];
this.change_sort(sort);
}, this));
$.targetIs(e, { tagSelector: '.NB-organizer-action', childOf: '.NB-organizer-selects' },
_.bind(function($t, $p) {
e.preventDefault();
var select = $t.attr('class').match(/\bNB-action-select-(\w+)\b/)[1];
this.change_select(select);
}, this));
$.targetIs(e, { tagSelector: '.NB-organizer-hierarchy' },
_.bind(function($t, $p) {
e.preventDefault();
var hierarchy = $t.hasClass('NB-organizer-hierarchy-nested') ? 'nested' : 'flat';
if (this.options.hierarchy == hierarchy) return;
this.toggle_hierarchy(hierarchy);
}, this));
$.targetIs(e, { tagSelector: '.NB-icon-add' },
_.bind(function($t, $p) {
e.preventDefault();
this.toggle_folder_add();
}, this));
$.targetIs(e, { tagSelector: '.NB-action-move' },
_.bind(function($t, $p) {
e.preventDefault();
if ($t.is('.NB-disabled')) return;
this.move_feeds();
}, this));
$.targetIs(e, { tagSelector: '.NB-action-delete' },
_.bind(function($t, $p) {
e.preventDefault();
if ($t.is('.NB-disabled')) return;
this.delete_feeds();
}, this));
},
handle_change: function(elem, e) {
$.targetIs(e, { tagSelector: '.NB-folders', childOf: '.NB-organizer-sidebar-folderjump' },
_.bind(function($t, $p) {
this.jump_to_folder($t.val());
}, this));
},
toggle_folder_add: function() {
var $folder = $(".NB-add-folder", this.$modal);
var $icon = $(".NB-icon-add", this.$modal);
if (this._open_folder) {
$folder.slideUp(300);
$icon.removeClass('NB-active');
this._open_folder = false;
} else {
this._open_folder = true;
$icon.addClass('NB-active');
$folder.slideDown(300);
}
},
jump_to_folder: function(folder_title) {
if (this.options.hierarchy != 'nested') this.toggle_hierarchy('nested');
var $feedlist = $('.NB-feedchooser', this.$modal);
var $folder_title = $(".folder_title_text", $feedlist).filter(function(i) {
console.log(["folder", this, _.string.trim($(this).text()), folder_title]);
return _.string.trim($(this).text()) == folder_title;
});
if ($folder_title.length) $feedlist.scrollTo($folder_title, {
duration: 850,
axis: 'y',
easing: 'easeInOutCubic',
offset: -4,
queue: false
});
}
});