From 77547197028f411d93654882f685b49a7847f031 Mon Sep 17 00:00:00 2001 From: maxpozdeev Date: Fri, 21 Feb 2025 12:20:27 +0300 Subject: [PATCH] + Can filter tags in tag cloud (GH-105) --- src/content/mytinytodo.js | 82 +++++++++++++++++++++++------ src/content/theme/style.css | 11 +++- src/includes/api/TagsController.php | 1 + src/includes/lang/en.json | 1 + src/includes/lang/ru.json | 1 + src/includes/theme.php | 5 +- 6 files changed, 82 insertions(+), 19 deletions(-) diff --git a/src/content/mytinytodo.js b/src/content/mytinytodo.js index 50c7b96..ff21b1b 100644 --- a/src/content/mytinytodo.js +++ b/src/content/mytinytodo.js @@ -86,6 +86,7 @@ var mytinytodo = window.mytinytodo = _mtt = { previewtag: 0, ajaxAnimation: 0, newTaskCounter: 0, + searchTags: 0, }, lang: { @@ -292,19 +293,42 @@ var mytinytodo = window.mytinytodo = _mtt = { else { $('#tagcloudAllLists').prop('checked', flag.showTagsFromAllLists).prop('disabled', false); } - if(!_mtt.menus.tagcloud) _mtt.menus.tagcloud = new mttMenu('tagcloud', { + if (!_mtt.menus.tagcloud) _mtt.menus.tagcloud = new mttMenu('tagcloud', { beforeShow: function(){ - if(flag.tagsChanged) { + if (flag.tagsChanged) { $('#tagcloudcontent').html(''); $('#tagcloudload').show(); - loadTags(curList.id, function(){$('#tagcloudload').hide();}); + loadTags(curList.id, function() { + $('#tagcloudload').hide(); + document.getElementById('tagcloudSearch').value = ''; + }); } }, - alignRight:true + alignRight: true, + onClose: function(){ + document.getElementById('tagcloudSearch').value = ''; + searchTags(); + } }); _mtt.menus.tagcloud.show(this); }); + $('#tagcloudSearch').keyup(function(event) { + if (event.keyCode == 27) return; + clearTimeout(_mtt.timers.searchTags); + _mtt.timers.searchTags = setTimeout(function(){searchTags()}, 400); + + }) + .keydown(function(event){ + if (event.keyCode == 27) { // Cancel on Esc + if (this.value === '') return; //allow to close the popup + this.value = ''; + clearTimeout(_mtt.timers.searchTags); + searchTags(); + return false; + } + }) + $('#tagcloudcancel').click(function(){ if(_mtt.menus.tagcloud) _mtt.menus.tagcloud.close(); }); @@ -321,7 +345,10 @@ var mytinytodo = window.mytinytodo = _mtt = { flag.showTagsFromAllLists = this.checked; $('#tagcloudcontent').html(''); $('#tagcloudload').show(); - loadTags(curList.id, function(){$('#tagcloudload').hide();}); + loadTags(curList.id, function(){ + $('#tagcloudload').hide(); + $('#tagcloudSearch').val(''); + }); }); $('#mtt-notes-show').click(function(e){ @@ -1995,23 +2022,28 @@ function loadTags(listId, callback) _mtt.db.request('tagCloud', {list:listId}, function(json){ if (!parseInt(json.total)) tagsList = []; else tagsList = json.items; - let cloud = ''; - tagsList.forEach( item => { - // item.tag is escaped with htmlspecialchars() - cloud += ` ${item.tag}`; - }); - if (cloud == '') { - cloud = _mtt.lang.get('noTags'); - } - else { - cloud = `${_mtt.lang.get('withoutTags')}` + cloud; - } - $('#tagcloudcontent').html(cloud) flag.tagsChanged = false; + setTagcloudContent(tagsList); callback(); }); }; +function setTagcloudContent(tags, isFiltered = false) +{ + let cloud = ''; + tags.forEach( item => { + // item.tag is escaped with htmlspecialchars() + cloud += ` ${item.tag}`; + }); + if (cloud == '') { + cloud = _mtt.lang.get('noTags'); + } + else if (!isFiltered) { + cloud = `${_mtt.lang.get('withoutTags')}` + cloud; + } + $('#tagcloudcontent').html(cloud) +} + function cancelTagFilter(tagId, dontLoadTasks) { if(tagId) _mtt.filter.cancelTag(tagId); @@ -2026,6 +2058,22 @@ function addFilterTag(tag, tagId, exclude) loadTasks(); }; +function searchTags() +{ + const filter = document.getElementById('tagcloudSearch').value.toLocaleLowerCase(); + if (filter === '') { + setTagcloudContent(tagsList); + return; + } + const filtered = []; + tagsList.forEach( item => { + if (item.tagText.toLocaleLowerCase().search(filter) === -1) + return; + filtered.push(item); + }); + setTagcloudContent(filtered, true); +} + function liveSearchToggle(toSearch, dontLoad) { if(toSearch) diff --git a/src/content/theme/style.css b/src/content/theme/style.css index 56f5663..6e352b9 100644 --- a/src/content/theme/style.css +++ b/src/content/theme/style.css @@ -975,6 +975,9 @@ textarea.form-input.inmax { #tagcloudAllLists:disabled + label { opacity: 0.6; } +#tagcloudSearch { + margin-left: 0.5rem; +} #tagcloudcancel span { mask: var(--svg-closetag) no-repeat; -webkit-mask: var(--svg-closetag) no-repeat; background-color: var(--color-btn-reduced); @@ -1358,7 +1361,9 @@ li.mtt-item-hidden { display:none; } textarea.form-input.inmax { font-size: 14px; } } -/* narrow screens */ + + +/* ========== narrow screens =========*/ @media only screen and (max-width: 600px) { #mtt { padding: 15px 8px 0px; } @@ -1400,6 +1405,10 @@ li.mtt-item-hidden { display:none; } #toolbar.mtt-insearch .searchbox-c { width:100%; max-width:100%; } #search { padding:5px 20px; border-radius:15px; } + #tagcloudSearch { + margin-top: 0.5rem; + } + .task-date { white-space: nowrap; overflow: hidden; diff --git a/src/includes/api/TagsController.php b/src/includes/api/TagsController.php index 8158ea8..cbf9f6f 100644 --- a/src/includes/api/TagsController.php +++ b/src/includes/api/TagsController.php @@ -52,6 +52,7 @@ class TagsController extends ApiController { { $t['items'][] = array( 'tag' => htmlspecialchars($tag['name']), + 'tagText' => (string)$tag['name'], 'id' => (int)$tag['id'], 'count' => $ac[$i], 'w' => $this->tagWeight($qmin, $ac[$i], $step) diff --git a/src/includes/lang/en.json b/src/includes/lang/en.json index 57c1435..059126a 100644 --- a/src/includes/lang/en.json +++ b/src/includes/lang/en.json @@ -42,6 +42,7 @@ "public_tasks": "Public Tasks", "tagcloud": "Tags", "tagfilter_cancel": "cancel filter", + "filterTags": "Filter tags", "showTagsFromAllLists": "Show tags from all lists", "sortByHand": "Sort by hand", "sortByTitle": "Sort by title", diff --git a/src/includes/lang/ru.json b/src/includes/lang/ru.json index 17eaa28..2233c1e 100644 --- a/src/includes/lang/ru.json +++ b/src/includes/lang/ru.json @@ -42,6 +42,7 @@ "public_tasks": "Опубликованные задачи", "tagcloud": "Теги", "tagfilter_cancel": "отменить фильтр по тегу", + "filterTags": "Фильтр тегов", "showTagsFromAllLists": "Показать теги из всех списков", "sortByHand": "Сортировка вручную", "sortByTitle": "Сортировка по алфавиту", diff --git a/src/includes/theme.php b/src/includes/theme.php index 20fa116..104df83 100644 --- a/src/includes/theme.php +++ b/src/includes/theme.php @@ -253,7 +253,10 @@ $().ready(function(){