From c26418fbae4ebafe120693712ef0cfcb5d04ebb9 Mon Sep 17 00:00:00 2001 From: Denis Filimonov Date: Wed, 4 May 2016 04:15:20 +0400 Subject: [PATCH] Simple search by items title (#506) --- assets/css/app.css | 33 +++++++++++++++++++++++ assets/js/all.min.js | 20 +++++++------- assets/js/event.js | 3 +++ assets/js/nav.js | 6 ++++- controllers/search.php | 34 ++++++++++++++++++++++++ index.php | 2 +- locales/ar_AR/translations.php | 2 ++ locales/cs_CZ/translations.php | 2 ++ locales/de_DE/translations.php | 2 ++ locales/es_ES/translations.php | 2 ++ locales/fr_FR/translations.php | 2 ++ locales/it_IT/translations.php | 2 ++ locales/ja_JP/translations.php | 2 ++ locales/pt_BR/translations.php | 2 ++ locales/ru_RU/translations.php | 2 ++ locales/sr_RS/translations.php | 2 ++ locales/sr_RS@latin/translations.php | 2 ++ locales/tr_TR/translations.php | 2 ++ locales/zh_CN/translations.php | 2 ++ models/item.php | 39 ++++++++++++++++++++++++++++ templates/bookmarks.php | 2 +- templates/history.php | 2 +- templates/paging.php | 28 +++++++++++++++++--- templates/search.php | 26 +++++++++++++++++++ templates/search_form.php | 7 +++++ templates/unread_items.php | 2 +- 26 files changed, 212 insertions(+), 18 deletions(-) create mode 100644 controllers/search.php create mode 100644 templates/search.php create mode 100644 templates/search_form.php diff --git a/assets/css/app.css b/assets/css/app.css index 7bb4a84..ffd7861 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -775,6 +775,30 @@ iframe { max-width: 98%; } +.search { + text-align: right; +} + +#search-opener { + color: #777; + font-size: 87.5%; + cursor: pointer; + text-transform: lowercase; +} + +#search-opener:hover { + color: #333; +} + +#search-form { + border: 0; + padding: 0; +} + +#search-form input { + font-size: 75%; +} + .menu-more li { font-size: 1.1em; padding-top: 10px; @@ -893,6 +917,10 @@ html[dir="rtl"] span.items-count:before { overflow: hidden; white-space: nowrap; } + + .search { + margin-top: -30px; + } } /* mobile design */ @@ -957,6 +985,11 @@ html[dir="rtl"] span.items-count:before { font-size: 0.85em; } + #search-form input { + box-sizing: border-box; + width: 100%; + } + .item-icons { display: block; float: right; diff --git a/assets/js/all.min.js b/assets/js/all.min.js index 8e43310..e4f4e45 100644 --- a/assets/js/all.min.js +++ b/assets/js/all.min.js @@ -5,16 +5,16 @@ document.createEvent("MouseEvents");e.initEvent("mousedown",!0,!0);a.dispatchEve a&&(a.textContent=r||"");document.getElementById("nav-counter").textContent=l||"";var e=document.querySelector("div.page-header h2:first-of-type");if(e)pageHeading=e.firstChild.nodeValue;else if(e=document.querySelector("article.item h1:first-of-type")){document.title=e.textContent;return}switch(document.querySelector("section.page").getAttribute("data-item-page")){case "unread":document.title="Miniflux ("+l+")";break;case "feed-items":document.title="("+r+") "+pageHeading;break;default:document.title= a?pageHeading+" ("+r+")":pageHeading}}function q(a){var e=d(a),b=new XMLHttpRequest;b.onload=function(){v.b()&&(c(a),n())};b.open("POST","?action=mark-item-read&id="+e,!0);b.send()}function p(g){var e=d(g),c=new XMLHttpRequest;c.onload=function(){if(v.b()){if("unread"!==g.getAttribute("data-item-status")){if(g.getAttribute("data-hide"))k(g);else{g.setAttribute("data-item-status","unread");a(g.querySelector(".read-icon"));var c=g.querySelector(".read-icon");c&&c.setAttribute("data-action","mark-read")}l++}n()}}; c.open("POST","?action=mark-item-unread&id="+e,!0);c.send()}var u=[],t=!1,l=function(){var a=document.getElementById("nav-counter");if(a)return counter=parseInt(a.textContent,10)||0}(),r=function(){var a=document.getElementById("page-counter");if(a)return counter=parseInt(a.textContent,10)||0}();return{w:q,B:p,A:function(a){var c=d(a),b=new XMLHttpRequest;b.onload=function(){v.b()&&(k(a),"unread"===a.getAttribute("data-item-status")&&l--,n())};b.open("POST","?action=mark-item-removed&id="+c,!0);b.send()}, -j:function(c){var e=d(c),b="1"===c.getAttribute("data-item-bookmark")?"0":"1",w=new XMLHttpRequest;w.onload=function(){var e=document.querySelector("section.page");v.b()&&"bookmarks"===e.getAttribute("data-item-page")?(k(c),n()):(c.setAttribute("data-item-bookmark",b),a(c.querySelector(".bookmark-icon")))};w.open("POST","?action=bookmark&id="+e+"&value="+b,!0);w.send()},K:function(a){var c=a.getAttribute("data-item-status");"read"===c?p(a):"unread"===c&&q(a)},I:function(a){(a=a.querySelector("a.show"))&& +j:function(c){var e=d(c),b="1"===c.getAttribute("data-item-bookmark")?"0":"1",w=new XMLHttpRequest;w.onload=function(){var e=document.querySelector("section.page");v.b()&&"bookmarks"===e.getAttribute("data-item-page")?(k(c),n()):(c.setAttribute("data-item-bookmark",b),a(c.querySelector(".bookmark-icon")))};w.open("POST","?action=bookmark&id="+e+"&value="+b,!0);w.send()},L:function(a){var c=a.getAttribute("data-item-status");"read"===c?p(a):"unread"===c&&q(a)},I:function(a){(a=a.querySelector("a.show"))&& b(a)},F:function(a){(a=a.querySelector("a.original"))&&b(a)},i:function(a){var c=document.getElementById("download-item");if(c){c.innerHTML=" "+c.getAttribute("data-before-message");c.className="loading-icon";var b=new XMLHttpRequest;b.onload=function(){var a=JSON.parse(b.responseText);c.className="";if(a.result){var d=document.getElementById("item-content");d&&(d.innerHTML=a.content);c.innerHTML=c.getAttribute("data-after-message")}else c.innerHTML=c.getAttribute("data-failure-message")};a=d(a); -b.open("POST","?action=download-item&id="+a,!0);b.send()}},C:function(a){var b=new XMLHttpRequest;b.onload=function(){for(var a=document.getElementsByTagName("article"),b=0,d=a.length;bu[d])u[d]=k.time,"unread"===k.status&&(c=!0)}document.hidden||b.nbUnread===l&&!t?document.hidden&&!a&&c&&(t=!0,document.title="\u21bb "+document.title):(t=!1,l=b.nbUnread,n())};a.open("POST","?action=latest-feeds-items",!0);a.send()}}}}(), +b.open("POST","?action=download-item&id="+a,!0);b.send()}},C:function(a){var b=new XMLHttpRequest;b.onload=function(){for(var a=document.getElementsByTagName("article"),b=0,d=a.length;bu[d])u[d]=k.time,"unread"===k.status&&(c=!0)}document.hidden||b.nbUnread===l&&!t?document.hidden&&!a&&c&&(t=!0,document.title="\u21bb "+document.title):(t=!1,l=b.nbUnread,n())};a.open("POST","?action=latest-feeds-items",!0);a.send()}}}}(), m=function(){function b(a){if(63!==a.keyCode&&63!==a.which&&(a.ctrlKey||a.shiftKey||a.altKey||a.metaKey))return!0;a=a.target||a.srcElement;return"INPUT"===a.tagName||"TEXTAREA"===a.tagName?!0:!1}var d=[];return{c:"",u:function(){document.onclick=function(a){a.target.hasAttribute("data-action")&&"original"!==a.target.className&&a.preventDefault()};document.onmouseup=function(a){if(2!==a.button)if("INPUT"===a.target.nodeName&&"auto-select"===a.target.className)a.target.select();else{var c=a.target.getAttribute("data-action"); if(c){m.c="mouse";var b;a:{for(element=a.target;element&&element.parentNode;)if(element=element.parentNode,element.tagName&&"article"===element.tagName.toLowerCase()){b=element;break a}b=void 0}switch(c){case "refresh-all":h.m(a.target.getAttribute("data-concurrent-requests"));break;case "refresh-feed":b&&h.l(b);break;case "mark-read":b&&f.w(b);break;case "mark-unread":b&&f.B(b);break;case "mark-removed":b&&f.A(b);break;case "bookmark":b&&f.j(b);break;case "download-item":b&&f.i(b);break;case "mark-feed-read":a= -document.getElementById("listing").getAttribute("data-feed-id");f.C(a);break;case "close-help":v.h()}}}}},s:function(){document.onkeypress=function(a){if(!b(a))if(m.c="keyboard",d.push(a.key||a.which),"g"===d[0]||103===d[0])switch(d[1]){case void 0:break;case "u":case 117:window.location.href="?action=unread";d=[];break;case "b":case 98:window.location.href="?action=bookmarks";d=[];break;case "h":case 104:window.location.href="?action=history";d=[];break;case "s":case 115:window.location.href="?action=feeds"; -d=[];break;case "p":case 112:window.location.href="?action=config";d=[];break;default:d=[]}else{d=[];var c=document.getElementById("current-item");switch(a.key||a.which){case "d":case 100:c&&f.i(c);break;case "p":case 112:case "k":case 107:v.g();break;case "n":case 110:case "j":case 106:v.f();break;case "v":case 118:c&&f.F(c);break;case "o":case 111:c&&f.I(c);break;case "m":case 109:c&&f.K(c);break;case "f":case 102:c&&f.j(c);break;case "h":case 104:v.G();break;case "l":case 108:v.D();break;case "r":case 114:h.m(); -break;case "?":case 63:v.J();break;case "Q":case 81:case "q":case 113:v.h();break;case "z":case 122:f.L()}}};document.onkeydown=function(a){if(!b(a))switch(m.c="keyboard",a.key||a.which){case "ArrowLeft":case "Left":case 37:v.g();break;case "ArrowRight":case "Right":case 39:v.f()}}},v:function(){document.addEventListener("visibilitychange",function(){!document.hidden&&f.M()&&f.a()})}}}(),v=function(){function b(a){var b=pageYOffset+document.documentElement.clientHeight;(0>b-(a.offsetTop+a.offsetHeight)|| -b-a.offsetTop>document.documentElement.clientHeight)&&window.scrollTo(0,a.offsetTop-10)}function d(){return document.getElementById("listing")?!0:!1}return{D:function(){var a=document.getElementById("next-page");a&&a.click()},G:function(){var a=document.getElementById("previous-page");a&&a.click()},f:function(){var a=document.getElementById("next-item");if(a)a.click();else if(d())if(a=document.getElementsByTagName("article"),document.getElementById("current-item"))for(var c=0,k=a.length;cb-(a.offsetTop+a.offsetHeight)||b-a.offsetTop>document.documentElement.clientHeight)&&window.scrollTo(0,a.offsetTop-10)}function d(){return document.getElementById("listing")?!0:!1}return{D:function(){var a=document.getElementById("next-page");a&&a.click()},G:function(){var a=document.getElementById("previous-page");a&&a.click()},f:function(){var a=document.getElementById("next-item");if(a)a.click();else if(d())if(a=document.getElementsByTagName("article"),document.getElementById("current-item"))for(var c= +0,k=a.length;c Model\Favicon\get_item_favicons($items), + 'original_marks_read' => Model\Config\get('original_marks_read'), + 'text' => $text, + 'items' => $items, + 'order' => '', + 'direction' => '', + 'display_mode' => Model\Config\get('items_display_mode'), + 'item_title_link' => Model\Config\get('item_title_link'), + 'group_id' => array(), + 'nb_items' => $nb_items, + 'nb_unread_items' => Model\Item\count_by_status('unread'), + 'offset' => $offset, + 'items_per_page' => Model\Config\get('items_per_page'), + 'nothing_to_read' => Request\int_param('nothing_to_read'), + 'menu' => 'search', + 'title' => t('Search').' ('.$nb_items.')' + ))); +}); diff --git a/index.php b/index.php index 1e93611..da30816 100644 --- a/index.php +++ b/index.php @@ -2,7 +2,7 @@ require __DIR__.'/common.php'; -Router\bootstrap(__DIR__.'/controllers', 'common', 'console', 'user', 'config', 'item', 'history', 'bookmark', 'feed'); +Router\bootstrap(__DIR__.'/controllers', 'common', 'console', 'user', 'config', 'item', 'history', 'bookmark', 'feed', 'search'); // Page not found Router\notfound(function() { diff --git a/locales/ar_AR/translations.php b/locales/ar_AR/translations.php index b52f145..db235a7 100644 --- a/locales/ar_AR/translations.php +++ b/locales/ar_AR/translations.php @@ -245,4 +245,6 @@ return array( // 'Item title links to' => '', // 'Original' => '', // 'Last login:' => '', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/cs_CZ/translations.php b/locales/cs_CZ/translations.php index eac43be..df0f09c 100644 --- a/locales/cs_CZ/translations.php +++ b/locales/cs_CZ/translations.php @@ -245,4 +245,6 @@ return array( 'Item title links to' => 'Titulek článku odkazuje na', 'Original' => 'Originál', 'Last login:' => 'Poslední přihlášení:', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/de_DE/translations.php b/locales/de_DE/translations.php index be17992..5aba224 100644 --- a/locales/de_DE/translations.php +++ b/locales/de_DE/translations.php @@ -245,4 +245,6 @@ return array( // 'Item title links to' => '', // 'Original' => '', // 'Last login:' => '', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/es_ES/translations.php b/locales/es_ES/translations.php index 1dec4b2..e709873 100644 --- a/locales/es_ES/translations.php +++ b/locales/es_ES/translations.php @@ -245,4 +245,6 @@ return array( // 'Item title links to' => '', // 'Original' => '', // 'Last login:' => '', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/fr_FR/translations.php b/locales/fr_FR/translations.php index 564409f..03e7e26 100644 --- a/locales/fr_FR/translations.php +++ b/locales/fr_FR/translations.php @@ -245,4 +245,6 @@ return array( 'Item title links to' => 'Le titre des articles redirige vers', 'Original' => 'Original', 'Last login:' => 'Dernière connexion :', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/it_IT/translations.php b/locales/it_IT/translations.php index 72a3bf5..6cd72a7 100644 --- a/locales/it_IT/translations.php +++ b/locales/it_IT/translations.php @@ -245,4 +245,6 @@ return array( // 'Item title links to' => '', // 'Original' => '', // 'Last login:' => '', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/ja_JP/translations.php b/locales/ja_JP/translations.php index 221ff68..a90b283 100644 --- a/locales/ja_JP/translations.php +++ b/locales/ja_JP/translations.php @@ -247,4 +247,6 @@ return array( 'Item title links to' => 'アイテムのタイトルのリンク先', 'Original' => '元のページ', // 'Last login:' => '', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/pt_BR/translations.php b/locales/pt_BR/translations.php index ee7840b..80cd3e0 100644 --- a/locales/pt_BR/translations.php +++ b/locales/pt_BR/translations.php @@ -245,4 +245,6 @@ return array( // 'Item title links to' => '', // 'Original' => '', // 'Last login:' => '', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/ru_RU/translations.php b/locales/ru_RU/translations.php index bb320b2..536c777 100644 --- a/locales/ru_RU/translations.php +++ b/locales/ru_RU/translations.php @@ -245,4 +245,6 @@ return array( 'Item title links to' => 'Заголовок статьи ведет на', 'Original' => 'Оригинал', 'Last login:' => 'Последний вход:', + 'Search' => 'Поиск', + 'There are no results for your search' => 'По вашему запросу ничего не нашлось', ); diff --git a/locales/sr_RS/translations.php b/locales/sr_RS/translations.php index 5d1c38a..0d74004 100644 --- a/locales/sr_RS/translations.php +++ b/locales/sr_RS/translations.php @@ -245,4 +245,6 @@ return array( // 'Item title links to' => '', // 'Original' => '', // 'Last login:' => '', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/sr_RS@latin/translations.php b/locales/sr_RS@latin/translations.php index 172ab78..45ba9c2 100644 --- a/locales/sr_RS@latin/translations.php +++ b/locales/sr_RS@latin/translations.php @@ -245,4 +245,6 @@ return array( // 'Item title links to' => '', // 'Original' => '', // 'Last login:' => '', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/tr_TR/translations.php b/locales/tr_TR/translations.php index c2ed44b..fe7b497 100644 --- a/locales/tr_TR/translations.php +++ b/locales/tr_TR/translations.php @@ -245,4 +245,6 @@ return array( 'Item title links to' => 'Öğe başlığıyla ilişkili bağlantılar', 'Original' => 'Orijinal', 'Last login:' => 'En son sisteme giriş zamanı:', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/locales/zh_CN/translations.php b/locales/zh_CN/translations.php index 5ff2989..cd707d0 100644 --- a/locales/zh_CN/translations.php +++ b/locales/zh_CN/translations.php @@ -245,4 +245,6 @@ return array( // 'Item title links to' => '', // 'Original' => '', // 'Last login:' => '', + // 'Search' => '', + // 'There are no results for your search' => '', ); diff --git a/models/item.php b/models/item.php index 8ba36b6..d07ae8e 100644 --- a/models/item.php +++ b/models/item.php @@ -64,6 +64,45 @@ function get_all_since($timestamp) ->findAll(); } +function search_all($text, $offset = null, $limit = null) +{ + return Database::getInstance('db') + ->table('items') + ->columns( + 'items.id', + 'items.title', + 'items.updated', + 'items.url', + 'items.enclosure', + 'items.enclosure_type', + 'items.bookmark', + 'items.feed_id', + 'items.status', + 'items.content', + 'items.language', + 'items.author', + 'feeds.site_url', + 'feeds.title AS feed_title', + 'feeds.rtl' + ) + ->join('feeds', 'id', 'feed_id') + ->neq('status', 'removed') + ->ilike('items.title', '%' . $text . '%') + ->orderBy('updated', 'desc') + ->offset($offset) + ->limit($limit) + ->findAll(); +} + +function count_by_search($text) +{ + return Database::getInstance('db') + ->table('items') + ->neq('status', 'removed') + ->ilike('title', '%' . $text . '%') + ->count(); +} + function get_latest_feeds_items() { return Database::getInstance('db') diff --git a/templates/bookmarks.php b/templates/bookmarks.php index 43e1bb8..1296a80 100644 --- a/templates/bookmarks.php +++ b/templates/bookmarks.php @@ -1,7 +1,7 @@

- +