From 67d92aad3abf7f1df124925090e83110f30a3f89 Mon Sep 17 00:00:00 2001 From: Martin Kadlec Date: Tue, 5 Aug 2014 18:11:51 +0200 Subject: [PATCH] searches wp1 --- scripts/app/staticdb/actions.js | 46 ++++++++++++--- scripts/app/templates/search.html | 3 + scripts/app/views/SearchView.js | 41 +++++++++++++ scripts/app/views/articleList.js | 13 ++--- scripts/app/views/feedList.js | 70 +++++++++++++++++------ scripts/bgprocess/bg.js | 5 +- scripts/bgprocess/collections/Searches.js | 25 ++++++++ scripts/bgprocess/models/Search.js | 26 +++++++++ 8 files changed, 196 insertions(+), 33 deletions(-) create mode 100644 scripts/app/templates/search.html create mode 100644 scripts/app/views/SearchView.js create mode 100644 scripts/bgprocess/collections/Searches.js create mode 100644 scripts/bgprocess/models/Search.js diff --git a/scripts/app/staticdb/actions.js b/scripts/app/staticdb/actions.js index 5f2080f1..35aec1cb 100644 --- a/scripts/app/staticdb/actions.js +++ b/scripts/app/staticdb/actions.js @@ -244,15 +244,30 @@ return { var feedList = require('views/feedList'); var feeds = feedList.getSelectedFeeds(); var ids = _.pluck(feeds, 'id'); + var special = $('.special.selected').get(0); if (special) special = special.view.model; + if (!special && !ids.length) { + special = require('instances/specials').allFeeds; + } + + var searches = $('.search-item.selected'); + if (searches.length) { + searches = searches.toArray().map(function(el) { + return el.view.model.get('name'); + }); + } else { + searches = []; + } + app.trigger('select:' + feedList.el.id, { action: 'new-select', feeds: ids, // _.extend is important, because otherwise it would be sent by reference filter: special ? _.extend({}, special.get('filter')) : null, name: special ? special.get('name') : null, + searches: searches, unreadOnly: !!e.altKey || t.className == 'source-counter' }); @@ -344,21 +359,38 @@ return { e = e || { currentTarget: $('input[type=search]').get(0) }; var str = e.currentTarget.value || ''; var list = require('views/articleList'); - if (str == '') { + + // hide date groups + if (str == '' && !list.currentData.searches.length) { $('.date-group').css('display', 'block'); } else { $('.date-group').css('display', 'none'); } - var searchInContent = false; - if (str[0] && str[0] == ':') { - str = str.replace(/^:/, '', str); - searchInContent = true; + function makeSearchList(val) { + var o = { + searchInContent: val.length && val[0] == ':', + str: val.replace(/^:/, '', str) + }; + o.rg = new RegExp(RegExp.escape(o.str), 'i'); + return o; } - var rg = new RegExp(RegExp.escape(str), 'i'); + + var searchList = list.currentData.searches.map(makeSearchList); + + searchList.push(makeSearchList(str)); + list.views.some(function(view) { if (!view.model) return true; - if (rg.test(view.model.get('title')) || rg.test(view.model.get('author')) || (searchInContent && rg.test(view.model.get('content')) )) { + var allMatch = true; + for (var i=0; i +
<%- name %>
+
+
\ No newline at end of file diff --git a/scripts/app/views/SearchView.js b/scripts/app/views/SearchView.js new file mode 100644 index 00000000..4429f6f9 --- /dev/null +++ b/scripts/app/views/SearchView.js @@ -0,0 +1,41 @@ +define([ + 'jquery', 'underscore', 'views/TopView', 'text!templates/search.html' +], +function($, _, TopView, tplSearch) { + + var SearchView = TopView.extend({ + + className: 'list-item search-item', + template: _.template(tplSearch), + + showContextMenu: function(e) { + if (!this.contextMenu) return; + + if (!this.$el.hasClass('selected')) { + app.feeds.feedList.select(this, e); + } + this.contextMenu.currentSource = this.model; + this.contextMenu.show(e.clientX, e.clientY); + }, + initialize: function() { + this.el.view = this; + + bg.sources.on('clear-events', this.handleClearEvents, this); + }, + handleClearEvents: function(id) { + if (window == null || id == tabID) { + this.clearEvents(); + } + }, + clearEvents: function() { + bg.sources.off('clear-events', this.handleClearEvents, this); + }, + render: function() { + var data = this.model.toJSON(); + this.$el.html(this.template(data)); + return this; + } + }); + + return SearchView; +}); \ No newline at end of file diff --git a/scripts/app/views/articleList.js b/scripts/app/views/articleList.js index 20d87e46..b31a939e 100644 --- a/scripts/app/views/articleList.js +++ b/scripts/app/views/articleList.js @@ -92,6 +92,7 @@ function (BB, _, $, Groups, Group, GroupView, ItemView, selectable, Locale) { */ currentData: { feeds: [], + searches: [], name: 'all-feeds', filter: { trashed: false }, unreadOnly: false @@ -273,7 +274,7 @@ function (BB, _, $, Groups, Group, GroupView, ItemView, selectable, Locale) { */ handleRenderScreen: function() { this.redraw(); - if ($('input[type=search]').val()) { + if ($('input[type=search]').val() || this.currentData.searches.length) { app.actions.execute('articles:search'); } }, @@ -563,7 +564,7 @@ function (BB, _, $, Groups, Group, GroupView, ItemView, selectable, Locale) { this.redraw(); - if ($('input[type=search]').val()) { + if ($('input[type=search]').val() || this.currentData.searches.length) { app.actions.execute('articles:search'); } @@ -579,17 +580,15 @@ function (BB, _, $, Groups, Group, GroupView, ItemView, selectable, Locale) { // Smart RSS used to reset search on feed select change. It instead keeps the fitler now. //$('input[type=search]').val(''); - // if prev selected was trash, hide undelete buttons + // if trash was previously selected, hide undelete buttons if (this.currentData.name == 'trash') { - /*$('[data-action="articles:update"]').css('display', 'block'); - $('[data-action="articles:undelete"]').css('display', 'none');*/ - app.articles.toolbar.showItems('articles:update'); - app.articles.toolbar.hideItems('articles:undelete'); + app.articles.toolbar.showItems('articles:update').hideItems('articles:undelete'); $('#context-undelete').css('display', 'none'); } this.currentData = { feeds: [], + searches: [], name: 'all-feeds', filter: { trashed: false }, unreadOnly: false diff --git a/scripts/app/views/feedList.js b/scripts/app/views/feedList.js index 9233f82d..7f946c60 100644 --- a/scripts/app/views/feedList.js +++ b/scripts/app/views/feedList.js @@ -4,9 +4,9 @@ */ define([ 'backbone', 'jquery', 'underscore', 'views/SourceView', 'views/FolderView', 'views/SpecialView', 'models/Special', - 'instances/contextMenus', 'mixins/selectable', 'instances/specials' + 'instances/contextMenus', 'mixins/selectable', 'instances/specials', 'views/SearchView' ], -function (BB, $, _, SourceView, FolderView, SpecialView, Special, contextMenus, selectable, specials) { +function (BB, $, _, SourceView, FolderView, SpecialView, Special, contextMenus, selectable, specials, SearchView) { /** * List of feeds (in left column) @@ -66,12 +66,32 @@ function (BB, $, _, SourceView, FolderView, SpecialView, Special, contextMenus, bg.sources.on('add', this.addSource, this); bg.sources.on('change:folderID', this.handleChangeFolder, this); bg.folders.on('add', this.addFolder, this); + bg.searches.on('add', this.addSearch, this); + bg.sources.on('clear-events', this.handleClearEvents, this); this.on('pick', this.handlePick); }, + /** + * Unbinds all listeners to bg process + * @method handleClearEvents + * @triggered when tab is closed/refershed + * @param id {Integer} id of the closed tab + */ + handleClearEvents: function(id) { + if (window == null || id == tabID) { + bg.sources.off('reset', this.addSources, this); + bg.sources.off('add', this.addSource, this); + bg.sources.off('change:folderID', this.handleChangeFolder, this); + bg.folders.off('add', this.addFolder, this); + bg.searches.off('add', this.addSearch, this); + + bg.sources.off('clear-events', this.handleClearEvents, this); + } + }, + /** * Sets comm event listeners and inserts feeds * @method handleAttached @@ -114,6 +134,8 @@ function (BB, $, _, SourceView, FolderView, SpecialView, Special, contextMenus, this.addSources(bg.sources); + this.addSearches(bg.searches); + return this; }, @@ -252,21 +274,6 @@ function (BB, $, _, SourceView, FolderView, SpecialView, Special, contextMenus, this.placeSource(source.view); }, - /** - * Unbinds all listeners to bg process - * @method handleClearEvents - * @triggered when tab is closed/refershed - * @param id {Integer} id of the closed tab - */ - handleClearEvents: function(id) { - if (window == null || id == tabID) { - bg.sources.off('reset', this.addSources, this); - bg.sources.off('add', this.addSource, this); - bg.sources.off('change:folderID', this.handleChangeFolder, this); - bg.folders.off('add', this.addFolder, this); - bg.sources.off('clear-events', this.handleClearEvents, this); - } - }, /** * Adds one special (all feeds, pinned, trash) @@ -329,6 +336,19 @@ function (BB, $, _, SourceView, FolderView, SpecialView, Special, contextMenus, this.placeSource(view, noManualSort === true ? true : false); }, + /** + * Adds one search + * @method addSearch + * @param search {models/Search} Search model to add + * @param noManualSort {Boolean} When false, the rigt place is computed + */ + addSearch: function(search, noManualSort) { + var view = new SearchView({ model: search }, this); + // this will be still needed to add new searches to right place by title + // this.placeSource(view, noManualSort === true ? true : false); + this.$el.append(view.render().$el); + }, + /** * Places source to its right place * @method placeSource @@ -422,6 +442,22 @@ function (BB, $, _, SourceView, FolderView, SpecialView, Special, contextMenus, }, this); }, + /** + * Add more searches at once + * @method addSearches + * @param searches {Array} Array of search models to add + */ + addSearches: function(searches) { + var that = this; + $('.search-item').each(function(i, search) { + if (!search.view || !(search instanceof SearchView)) return; + that.destroySource(search.view); + }); + searches.forEach(function(source) { + this.addSearch(source, true); + }, this); + }, + /** * Destroy feed * @method removeSource diff --git a/scripts/bgprocess/bg.js b/scripts/bgprocess/bg.js index a8bdc92a..5832e2c8 100644 --- a/scripts/bgprocess/bg.js +++ b/scripts/bgprocess/bg.js @@ -5,9 +5,9 @@ define([ 'jquery', 'modules/Animation', 'models/Settings', 'models/Info', 'models/Source', 'collections/Sources', 'collections/Items', 'collections/Folders', 'models/Loader', 'collections/Logs', - 'models/Folder', 'models/Item', 'collections/Toolbars' + 'models/Folder', 'models/Item', 'collections/Toolbars', 'collections/Searches' ], -function ($, animation, Settings, Info, Source, Sources, Items, Folders, Loader, Logs, Folder, Item, Toolbars) { +function ($, animation, Settings, Info, Source, Sources, Items, Folders, Loader, Logs, Folder, Item, Toolbars, Searches) { /** * Update animations @@ -38,6 +38,7 @@ function ($, animation, Settings, Info, Source, Sources, Items, Folders, Loader, window.sources = new Sources(); window.items = new Items(); window.folders = new Folders(); + window.searches = new Searches(); /** * This is used for when new feed is subsribed and smart rss tab is opened to focus the newly added feed diff --git a/scripts/bgprocess/collections/Searches.js b/scripts/bgprocess/collections/Searches.js new file mode 100644 index 00000000..c3072a66 --- /dev/null +++ b/scripts/bgprocess/collections/Searches.js @@ -0,0 +1,25 @@ +/** + * @module BgProcess + * @submodule collections/Searches + */ +define(['backbone', 'models/Search', 'preps/indexeddb'], function (BB, Search) { + + /** + * Collection of feed modules + * @class Searches + * @constructor + * @extends Backbone.Collection + */ + var Searches = BB.Collection.extend({ + model: Search, + /*localStorage: new Backbone.LocalStorage('sources-backbone'),*/ + comparator: function(a, b) { + var t1 = (a.get('title') || '').trim().toLowerCase(); + var t2 = (b.get('title') || '').trim().toLowerCase(); + return t1 < t2 ? -1 : 1; + } + }); + + return Searches; + +}); \ No newline at end of file diff --git a/scripts/bgprocess/models/Search.js b/scripts/bgprocess/models/Search.js new file mode 100644 index 00000000..4ac6939d --- /dev/null +++ b/scripts/bgprocess/models/Search.js @@ -0,0 +1,26 @@ +/** + * @module App + * @submodule models/Search + */ +define(['backbone'], function(BB) { + /** + * Model for search items in feed list. + * @class Search + * @constructor + * @extends Backbone.Model + */ + var Search = BB.Model.extend({ + defaults: { + + /** + * Name adn title of the search and the value to search by. + * @attribute name + * @type String + * @default '' + */ + name: '' + } + }); + + return Search; +}); \ No newline at end of file