mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-05 16:58:59 +00:00
434 lines
18 KiB
JavaScript
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
|
|
});
|
|
}
|
|
|
|
});
|