From 521f98d0e7c4c3b8ff820351c700c81e43c3ec4b Mon Sep 17 00:00:00 2001 From: Clayton Carney Date: Thu, 1 Dec 2022 13:05:01 -0700 Subject: [PATCH] Clipboard Mode --- bundle.js | 431 ++++++++++++++++++---------- css/kja.css | 25 ++ help/about.html | 2 +- help/bookmark.html | 2 +- help/clipboard-mode.html | 9 + js/Model/HelpModel.js | 4 +- js/Model/SearchModel.js | 2 +- js/View/BookmarkExportView.js | 6 +- js/View/BookmarkFolderAddView.js | 6 +- js/View/BookmarkFolderDeleteView.js | 6 +- js/View/BookmarkFolderRenameView.js | 6 +- js/View/BookmarkFolderView.js | 26 +- js/View/BookmarkImportView.js | 6 +- js/View/BookmarkListView.js | 107 ++++++- js/View/BookmarkMoveCopyView.js | 14 +- js/View/HelpReadView.js | 8 +- js/View/HelpTopicView.js | 17 +- js/View/NavigatorBookView.js | 16 +- js/View/NavigatorChapterView.js | 16 +- js/View/ReadView.js | 73 +++-- js/View/SearchFilterView.js | 22 +- js/View/SearchHistoryView.js | 20 +- js/View/SearchLookupView.js | 8 +- js/View/SearchResultView.js | 53 +++- js/View/SettingView.js | 6 +- js/template.js | 9 + sw.js | 7 +- 27 files changed, 614 insertions(+), 293 deletions(-) create mode 100644 help/clipboard-mode.html diff --git a/bundle.js b/bundle.js index c13a422..c9a6803 100644 --- a/bundle.js +++ b/bundle.js @@ -415,6 +415,12 @@ return actionMenu; }; + const templateBtnBanner = (cssModifier, ariaLabel) => { + let btnIcon = templateElement( + 'button', 'btn-banner', cssModifier, ariaLabel); + return btnIcon; + }; + const templateBtnIcon = (svgId, cssModifier, ariaLabel) => { let svgTag = document.createElementNS(svgNS, 'svg'); svgTag.classList.add('icon-svg'); @@ -521,6 +527,9 @@ if (tool.type === 'btn') { element = templateBtnIcon(tool.icon, tool.icon, tool.ariaLabel); toolbarUpper.appendChild(element); + } else if (tool.type === 'btn-banner') { + element = templateBtnBanner(tool.cssModifier, tool.ariaLabel); + toolbarUpper.appendChild(element); } else if (tool.type === 'banner') { element = templateElement( 'div', 'banner', tool.cssModifier, null, tool.text); @@ -564,7 +573,7 @@ const upperToolSet$h = [ { type: 'btn', icon: 'prev', ariaLabel: 'Previous Chapter' }, - { type: 'banner', cssModifier: 'read', text: null }, + { type: 'btn-banner', cssModifier: 'read', text: 'Toogle Clipboard' }, { type: 'btn', icon: 'next', ariaLabel: 'Next Chapter' }, ]; @@ -683,7 +692,7 @@ this.body = document.querySelector('body'); this.btnPrev = this.toolbarUpper.querySelector('.btn-icon--prev'); - this.banner = this.toolbarUpper.querySelector('.banner--read'); + this.btnBanner = this.toolbarUpper.querySelector('.btn-banner--read'); this.btnNext = this.toolbarUpper.querySelector('.btn-icon--next'); this.btnNavigator = this.toolbarLower.querySelector('.btn-icon--navigator'); @@ -719,6 +728,7 @@ this.subscribe(); this.lastFont = null; this.lastFontSize = null; + this.clipboardMode = false; } listClick(event) { @@ -726,7 +736,12 @@ if (!document.getSelection().toString()) { let verse = event.target.closest('div.verse'); if (verse) { - this.verseClick(verse); + if (this.clipboardMode) { + let text = `${this.btnBanner.textContent}:${verse.textContent}`; + navigator.clipboard.writeText(text); + } else { + this.verseClick(verse); + } } } } @@ -888,24 +903,39 @@ }); } + themeUpdate(theme) { + this.theme = theme; + this.changeTheme(); + this.lastTheme = this.theme; + } + + toogleClipboardMode() { + if (this.clipboardMode) { + this.btnBanner.classList.remove('btn-banner--active'); + } else { + this.btnBanner.classList.add('btn-banner--active'); + } + this.clipboardMode = !this.clipboardMode; + } + toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnColumnMode || - !target.classList.contains('btn-icon--active') + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnColumnMode || + !btn.classList.contains('btn-icon--active') ) { - if (target === this.btnNavigator) { + if (btn === this.btnNavigator) { queue.publish('sidebar.select', 'navigator'); - } else if (target === this.btnBookmark) { + } else if (btn === this.btnBookmark) { queue.publish('sidebar.select', 'bookmark'); - } else if (target === this.btnSearch) { + } else if (btn === this.btnSearch) { queue.publish('sidebar.select', 'search'); - } else if (target === this.btnSetting) { + } else if (btn === this.btnSetting) { queue.publish('sidebar.select', 'setting'); - } else if (target === this.btnHelp) { + } else if (btn === this.btnHelp) { queue.publish('sidebar.select', 'help'); - } else if (target === this.btnColumnMode) { + } else if (btn === this.btnColumnMode) { queue.publish('read.column-mode.click', null); } } @@ -914,24 +944,32 @@ toolbarUpperClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnPrev) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnPrev) { queue.publish('read.prev.chapter', 1); - } else if (target === this.btnNext) { + } else if (btn === this.btnNext) { queue.publish('read.next.chapter', 2); } } } - themeUpdate(theme) { - this.theme = theme; - this.changeTheme(); - this.lastTheme = this.theme; + toolbarUpperClick(event) { + event.preventDefault(); + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBanner) { + this.toogleClipboardMode(); + } else if (btn === this.btnPrev) { + queue.publish('read.prev.chapter', 1); + } else if (btn === this.btnNext) { + queue.publish('read.next.chapter', 2); + } + } } updateBanner() { - this.banner.textContent = tomeChapters[this.chapterIdx][chapterName]; + this.btnBanner.textContent = tomeChapters[this.chapterIdx][chapterName]; } updateColumnMode() { @@ -1405,10 +1443,10 @@ listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-book')) { - this.contentClick(target); + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-book')) { + this.contentClick(btn); } } } @@ -1432,11 +1470,11 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('navigator.back', null); - } else if (target === this.btnChapter) { + } else if (btn === this.btnChapter) { queue.publish('navigator-chapter', null); } } @@ -1544,10 +1582,10 @@ listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-chapter')) { - this.contentClick(target); + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-chapter')) { + this.contentClick(btn); } } } @@ -1579,11 +1617,11 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('navigator.back', null); - } else if (target === this.btnBook) { + } else if (btn === this.btnBook) { queue.publish('navigator-book', null); } } @@ -2302,7 +2340,7 @@ ]; const upperToolSet$e = [ - { type: 'banner', cssModifier: 'bookmark-list', text: null }, + { type: 'btn-banner', cssModifier: 'bookmark-list', ariaLbael: 'Toogle Clipboard' }, ]; class BookmarkListView { @@ -2342,6 +2380,9 @@ this.toolbarLower.addEventListener('click', (event) => { this.toolbarLowerClick(event); }); + this.toolbarUpper.addEventListener('click', (event) => { + this.toolbarUpperClick(event); + }); } buildEntry(verseIdx) { @@ -2433,16 +2474,33 @@ this.expandMode = expandMode; if (this.expandMode) { this.btnExpandMode.classList.add('btn-icon--active'); + this.list.classList.add(this.font.fontClass); + this.list.classList.add(this.fontSize); } else { this.btnExpandMode.classList.remove('btn-icon--active'); + this.list.classList.remove(this.font.fontClass); + this.list.classList.remove(this.fontSize); } this.updateBookmarks(); } + fontSizeUpdate(fontSize) { + this.fontSize = fontSize; + this.updateFontSize(); + this.lastFontSize = this.fontSize; + } + + fontUpdate(font) { + this.font = font; + this.updateFont(); + this.lastFont = this.font; + this.lastFontSize = null; + } + getElements() { this.btnFolderAdd = this.toolbarUpper.querySelector( '.btn-icon--folder-add'); - this.banner = this.toolbarUpper.querySelector('.banner--bookmark-list'); + this.btnBanner = this.toolbarUpper.querySelector('.btn-banner--bookmark-list'); this.btnUp = this.actionMenu.querySelector('.btn-icon--up'); this.btnDown = this.actionMenu.querySelector('.btn-icon--down'); @@ -2471,15 +2529,17 @@ this.getElements(); this.addListeners(); this.subscribe(); + this.lastFont = null; + this.clipboardMode = false; } listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); + let btn = event.target.closest('button'); if (this.expandMode) { - this.verseClick(target); + this.verseClick(btn); } else { - this.entryClick(target); + this.entryClick(btn); } } @@ -2520,32 +2580,62 @@ queue.subscribe('bookmark.expand-mode.update', (expandMode) => { this.expandModeUpdate(expandMode); }); + + queue.subscribe('font.update', (font) => { + this.fontUpdate(font); + }); + + queue.subscribe('font-size.update', (fontSize) => { + this.fontSizeUpdate(fontSize); + }); + } + + toogleClipboardMode() { + if (this.clipboardMode) { + this.btnBanner.classList.remove('btn-banner--active'); + } else { + this.btnBanner.classList.add('btn-banner--active'); + } + this.clipboardMode = !this.clipboardMode; } toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('bookmark.back', null); - } else if (target === this.btnSortAscend) { + } else if (btn === this.btnSortAscend) { queue.publish('bookmark-list.sort-ascend', null); - } else if (target === this.btnSortInvert) { + } else if (btn === this.btnSortInvert) { queue.publish('bookmark-list.sort-invert', null); - } else if (target === this.btnBookmarkFolder) { + } else if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); - } else if (target === this.btnExpandMode) { + } else if (btn === this.btnExpandMode) { queue.publish('bookmark-list.expand-mode.click', null); } } } + toolbarUpperClick(event) { + event.preventDefault(); + if (!this.expandMode) { + return; + } + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBanner) { + this.toogleClipboardMode(); + } + } + } + up(verseIdx) { queue.publish('bookmark-list.up', verseIdx); } updateBanner() { - this.banner.innerHTML = `${this.activeFolder.name}`; + this.btnBanner.innerHTML = `${this.activeFolder.name}`; } updateActiveFolder(activeFolder) { @@ -2578,11 +2668,36 @@ this.scroll.scrollTop = scrollSave; } + updateFontSize() { + if (!this.expandMode) { + return; + } + if (this.lastFontSize) { + this.list.classList.remove(this.lastFontSize); + } + this.list.classList.add(this.fontSize); + } + + updateFont() { + if (!this.expandMode) { + return; + } + if (this.lastFont) { + this.list.classList.remove(this.lastFont.fontClass); + } + this.list.classList.add(this.font.fontClass); + } + verseClick(target) { if (target) { if (target.classList.contains('btn-result')) { - let verseIdx = parseInt(target.dataset.verseIdx); - queue.publish('bookmark-list.select', verseIdx); + if (this.clipboardMode) { + let text = target.textContent; + navigator.clipboard.writeText(text); + } else { + let verseIdx = parseInt(target.dataset.verseIdx); + queue.publish('bookmark-list.select', verseIdx); + } } } } @@ -2717,10 +2832,10 @@ listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-icon--h-menu')) { - let entry = target.previousSibling; + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-icon--h-menu')) { + let entry = btn.previousSibling; this.menuClick(entry); } } @@ -2784,9 +2899,9 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } @@ -2954,13 +3069,13 @@ listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-entry')) { - let folderName = target.textContent; + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-entry')) { + let folderName = btn.textContent; queue.publish('bookmark-folder.select', folderName); - } else if (target.classList.contains('btn-icon--h-menu')) { - let entry = target.previousSibling; + } else if (btn.classList.contains('btn-icon--h-menu')) { + let entry = btn.previousSibling; this.menuClick(entry); } } @@ -3000,17 +3115,17 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('bookmark.back', null); - } else if (target === this.btnBookmarkList) { + } else if (btn === this.btnBookmarkList) { queue.publish('bookmark-list', null); - } else if (target === this.btnBookmarkFolderAdd) { + } else if (btn === this.btnBookmarkFolderAdd) { queue.publish('bookmark-folder-add', null); - } else if (target === this.btnExport) { + } else if (btn === this.btnExport) { queue.publish('bookmark-export', null); - } else if (target === this.btnImport) { + } else if (btn === this.btnImport) { queue.publish('bookmark-import', null); } } @@ -3158,9 +3273,9 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } @@ -3273,9 +3388,9 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } @@ -3424,9 +3539,9 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } @@ -3529,9 +3644,9 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } @@ -3655,9 +3770,9 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } @@ -4286,7 +4401,7 @@ 'search-result', 'search-lookup', 'search-filter', 'search-history', ]; - const DEFAULT_QUERY = 'day of the lord'; + const DEFAULT_QUERY = 'lord of israel'; class SearchModel { @@ -4533,7 +4648,7 @@ ]; const upperToolSet$6 = [ - { type: 'banner', cssModifier: 'search-result', text: null }, + { type: 'btn-banner', cssModifier: 'search-result', text: 'Toogle Clipboard' }, ]; const binIdx = 0; @@ -4555,6 +4670,9 @@ this.toolbarLower.addEventListener('click', (event) => { this.toolbarLowerClick(event); }); + this.toolbarUpper.addEventListener('click', (event) => { + this.toolbarUpperClick(event); + }); } applyFilter() { @@ -4686,7 +4804,7 @@ } getElements() { - this.banner = this.toolbarUpper.querySelector('.banner--search-result'); + this.btnBanner = this.toolbarUpper.querySelector('.btn-banner--search-result'); this.btnBack = this.toolbarLower.querySelector('.btn-icon--back'); this.btnFilter = this.toolbarLower.querySelector( @@ -4708,14 +4826,19 @@ this.subscribe(); this.lastFont = null; this.lastFontSize = null; + this.clipboardMode = false; } listClick(event) { event.preventDefault(); - let target = event.target; - let btn = target.closest('button'); - let verseIdx = parseInt(btn.dataset.verseIdx); - queue.publish('search-result.read-select', verseIdx); + let btn = event.target.closest('button'); + if (this.clipboardMode) { + let text = btn.textContent; + navigator.clipboard.writeText(text); + } else { + let verseIdx = parseInt(btn.dataset.verseIdx); + queue.publish('search-result.read-select', verseIdx); + } } loadMoreClick(event) { @@ -4793,24 +4916,43 @@ }); } + toogleClipboardMode() { + if (this.clipboardMode) { + this.btnBanner.classList.remove('btn-banner--active'); + } else { + this.btnBanner.classList.add('btn-banner--active'); + } + this.clipboardMode = !this.clipboardMode; + } + toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('search.back', null); - } else if (target === this.btnFilter) { + } else if (btn === this.btnFilter) { queue.publish('search-filter', null); - } else if (target === this.btnHistory) { + } else if (btn === this.btnHistory) { queue.publish('search-history', null); - } else if (target === this.btnSearchLookup) { + } else if (btn === this.btnSearchLookup) { queue.publish('search-lookup', null); } } } + toolbarUpperClick(event) { + event.preventDefault(); + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBanner) { + this.toogleClipboardMode(); + } + } + } + updateBanner() { - this.banner.innerHTML = `${this.citation} ` + + this.btnBanner.innerHTML = `${this.citation} ` + `(${this.wordCount}/${this.verseCount})
` + `${this.rig.query}`; } @@ -4997,14 +5139,14 @@ listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-filter')) { - this.filterClick(target); - } else if (target.classList.contains('btn-icon--filter-down')) { - this.foldClick(target); - } else if (target.classList.contains('btn-icon--filter-next')) { - this.unfoldClick(target); + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-filter')) { + this.filterClick(btn); + } else if (btn.classList.contains('btn-icon--filter-down')) { + this.foldClick(btn); + } else if (btn.classList.contains('btn-icon--filter-next')) { + this.unfoldClick(btn); } } } @@ -5042,9 +5184,9 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnSearchResult) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnSearchResult) { queue.publish('search-result', null); } } @@ -5186,13 +5328,13 @@ listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-entry--history')) { - let query = target.textContent; + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-entry--history')) { + let query = btn.textContent; queue.publish('search-history.select', query); - } else if (target.classList.contains('btn-icon--delete')) { - let entry = target.previousSibling; + } else if (btn.classList.contains('btn-icon--delete')) { + let entry = btn.previousSibling; let query = entry.textContent; queue.publish('search-history.delete', query); } @@ -5218,11 +5360,11 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnResult) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnResult) { queue.publish('search-result', null); - } else if (target === this.btnHistoryClear) { + } else if (btn === this.btnHistoryClear) { queue.publish('search-history.clear', null); } } @@ -5371,11 +5513,11 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('search.back', null); - } else if (target === this.btnResult) { + } else if (btn === this.btnResult) { queue.publish('search-result', null); } } @@ -6132,9 +6274,9 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('setting.back', null); } } @@ -6378,8 +6520,8 @@ 'help-read', 'help-topic', ]; const validTopics = [ - 'about', 'bookmark', 'help', 'navigator', 'overview', 'read', 'search', - 'setting', 'thats-my-king', + 'about', 'bookmark', 'clipboard-mode', 'help', 'navigator', 'overview', + 'read', 'search', 'setting', 'thats-my-king', ]; class HelpModel { @@ -6480,6 +6622,7 @@ { topic: 'about', name: 'About' }, { topic: 'overview', name: 'Overview' }, { topic: 'read', name: 'Read' }, + { topic: 'clipboard-mode', name: 'Clipboard Mode' }, { topic: 'navigator', name: 'Navigator' }, { topic: 'bookmark', name: 'Bookmark' }, { topic: 'search', name: 'Search' }, @@ -6557,10 +6700,10 @@ scrollClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-topic')) { - let helpTopic = target.dataset.topic; + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-topic')) { + let helpTopic = btn.dataset.topic; queue.publish('help-topic.select', helpTopic); } } @@ -6581,11 +6724,11 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('help.back', null); - } else if (target === this.btnHelpRead) { + } else if (btn === this.btnHelpRead) { queue.publish('help-read', null); } } @@ -6667,11 +6810,11 @@ toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('help.back', null); - } else if (target === this.btnHelpTopic) { + } else if (btn === this.btnHelpTopic) { queue.publish('help-topic', null); } } diff --git a/css/kja.css b/css/kja.css index 2b2f1a6..7306b87 100644 --- a/css/kja.css +++ b/css/kja.css @@ -116,6 +116,31 @@ textarea { margin: 0.25rem; } +.btn-banner { + align-self: center; + background-color: transparent; + flex: 1 1 auto; + height: 100%; + overflow: hidden; + padding: 0 0.5rem; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; +} + +.btn-banner--active { + background-color: var(--ui-hint-bg); + color: var(--ui-hint-fg); +} + +.btn-banner--bookmark-list { + width: 100%; +} + +.btn-banner--search-result { + width: 100%; +} + .btn-book { flex: 0 0 100%; height: var(--target-size); diff --git a/help/about.html b/help/about.html index e144e9b..e22521f 100644 --- a/help/about.html +++ b/help/about.html @@ -8,7 +8,7 @@

KJA

Heaven and earth shall pass away, but my words shall not pass away.

Version

-

2022.11.14

+

2022.12.01

Contact

github.1john419@gmail.com

Source Code

diff --git a/help/bookmark.html b/help/bookmark.html index cd01c16..9a83f4e 100644 --- a/help/bookmark.html +++ b/help/bookmark.html @@ -43,7 +43,7 @@

Expand Mode


-

When Expand Mode is on, verse text for each bookmark is displayed

+

When Expand Mode is active, verse text for each bookmark is displayed

Folder Pane

The Folder pane displays the bookmark folder list.

Tap a folder name to set the Active Folder and open the List pane.

diff --git a/help/clipboard-mode.html b/help/clipboard-mode.html new file mode 100644 index 0000000..7395428 --- /dev/null +++ b/help/clipboard-mode.html @@ -0,0 +1,9 @@ +
+

Clipboard Mode

+

The Clipboard Mode can be activated in the Read, Bookmark List, and Search Result panes.

+

When Clipboard Mode is active, tapping a verse in the associated pane will copy the verse text to the system clipboard.

+

To activate Clipboard Mode, tap the pane banner in the upper toolbar. The banner is highlighted, indicating Clipboard Mode is active.

+

To deactivate Clipboard Mode, tap the banner in the upper toolbar again. The banner is dehighlighted, indicating Clipboard Mode is inactive.

+

Note: In the Bookmark List pane, Clipboard Mode is available only when the Expand Mode is active (see Bookmark help topic).

+
+ \ No newline at end of file diff --git a/js/Model/HelpModel.js b/js/Model/HelpModel.js index 35b4a05..fe72d7b 100644 --- a/js/Model/HelpModel.js +++ b/js/Model/HelpModel.js @@ -8,8 +8,8 @@ const validTasks = [ 'help-read', 'help-topic', ]; const validTopics = [ - 'about', 'bookmark', 'help', 'navigator', 'overview', 'read', 'search', - 'setting', 'thats-my-king', + 'about', 'bookmark', 'clipboard-mode', 'help', 'navigator', 'overview', + 'read', 'search', 'setting', 'thats-my-king', ]; class HelpModel { diff --git a/js/Model/SearchModel.js b/js/Model/SearchModel.js index ff67beb..dfad4e8 100644 --- a/js/Model/SearchModel.js +++ b/js/Model/SearchModel.js @@ -20,7 +20,7 @@ const validTasks = [ 'search-result', 'search-lookup', 'search-filter', 'search-history', ]; -const DEFAULT_QUERY = 'day of the lord'; +const DEFAULT_QUERY = 'lord of israel'; class SearchModel { diff --git a/js/View/BookmarkExportView.js b/js/View/BookmarkExportView.js index 1070914..accb2cf 100644 --- a/js/View/BookmarkExportView.js +++ b/js/View/BookmarkExportView.js @@ -109,9 +109,9 @@ class BookmarkExportview { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } diff --git a/js/View/BookmarkFolderAddView.js b/js/View/BookmarkFolderAddView.js index 6ab0681..cfdee7f 100644 --- a/js/View/BookmarkFolderAddView.js +++ b/js/View/BookmarkFolderAddView.js @@ -136,9 +136,9 @@ class BookmarkFolderAddView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } diff --git a/js/View/BookmarkFolderDeleteView.js b/js/View/BookmarkFolderDeleteView.js index 7db8889..f2dd072 100644 --- a/js/View/BookmarkFolderDeleteView.js +++ b/js/View/BookmarkFolderDeleteView.js @@ -116,9 +116,9 @@ class BookmarkFolderDeleteView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } diff --git a/js/View/BookmarkFolderRenameView.js b/js/View/BookmarkFolderRenameView.js index 697a69f..2f92cc5 100644 --- a/js/View/BookmarkFolderRenameView.js +++ b/js/View/BookmarkFolderRenameView.js @@ -149,9 +149,9 @@ class BookmarkFolderRenameView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } diff --git a/js/View/BookmarkFolderView.js b/js/View/BookmarkFolderView.js index b239b3e..1b45df8 100644 --- a/js/View/BookmarkFolderView.js +++ b/js/View/BookmarkFolderView.js @@ -154,13 +154,13 @@ class BookmarkFolderView { listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-entry')) { - let folderName = target.textContent; + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-entry')) { + let folderName = btn.textContent; queue.publish('bookmark-folder.select', folderName); - } else if (target.classList.contains('btn-icon--h-menu')) { - let entry = target.previousSibling; + } else if (btn.classList.contains('btn-icon--h-menu')) { + let entry = btn.previousSibling; this.menuClick(entry); } } @@ -200,17 +200,17 @@ class BookmarkFolderView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('bookmark.back', null); - } else if (target === this.btnBookmarkList) { + } else if (btn === this.btnBookmarkList) { queue.publish('bookmark-list', null); - } else if (target === this.btnBookmarkFolderAdd) { + } else if (btn === this.btnBookmarkFolderAdd) { queue.publish('bookmark-folder-add', null); - } else if (target === this.btnExport) { + } else if (btn === this.btnExport) { queue.publish('bookmark-export', null); - } else if (target === this.btnImport) { + } else if (btn === this.btnImport) { queue.publish('bookmark-import', null); } } diff --git a/js/View/BookmarkImportView.js b/js/View/BookmarkImportView.js index f9ffbb9..a995968 100644 --- a/js/View/BookmarkImportView.js +++ b/js/View/BookmarkImportView.js @@ -128,9 +128,9 @@ class BookmarkImportView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } diff --git a/js/View/BookmarkListView.js b/js/View/BookmarkListView.js index a9d33b7..b8620aa 100644 --- a/js/View/BookmarkListView.js +++ b/js/View/BookmarkListView.js @@ -41,7 +41,7 @@ const lowerToolSet = [ ]; const upperToolSet = [ - { type: 'banner', cssModifier: 'bookmark-list', text: null }, + { type: 'btn-banner', cssModifier: 'bookmark-list', ariaLbael: 'Toogle Clipboard' }, ]; class BookmarkListView { @@ -81,6 +81,9 @@ class BookmarkListView { this.toolbarLower.addEventListener('click', (event) => { this.toolbarLowerClick(event); }); + this.toolbarUpper.addEventListener('click', (event) => { + this.toolbarUpperClick(event); + }); } buildEntry(verseIdx) { @@ -172,16 +175,33 @@ class BookmarkListView { this.expandMode = expandMode; if (this.expandMode) { this.btnExpandMode.classList.add('btn-icon--active'); + this.list.classList.add(this.font.fontClass); + this.list.classList.add(this.fontSize); } else { this.btnExpandMode.classList.remove('btn-icon--active'); + this.list.classList.remove(this.font.fontClass); + this.list.classList.remove(this.fontSize); } this.updateBookmarks() } + fontSizeUpdate(fontSize) { + this.fontSize = fontSize; + this.updateFontSize(); + this.lastFontSize = this.fontSize; + } + + fontUpdate(font) { + this.font = font; + this.updateFont(); + this.lastFont = this.font; + this.lastFontSize = null; + } + getElements() { this.btnFolderAdd = this.toolbarUpper.querySelector( '.btn-icon--folder-add'); - this.banner = this.toolbarUpper.querySelector('.banner--bookmark-list'); + this.btnBanner = this.toolbarUpper.querySelector('.btn-banner--bookmark-list'); this.btnUp = this.actionMenu.querySelector('.btn-icon--up'); this.btnDown = this.actionMenu.querySelector('.btn-icon--down'); @@ -210,15 +230,17 @@ class BookmarkListView { this.getElements(); this.addListeners(); this.subscribe(); + this.lastFont = null; + this.clipboardMode = false; } listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); + let btn = event.target.closest('button'); if (this.expandMode) { - this.verseClick(target); + this.verseClick(btn); } else { - this.entryClick(target); + this.entryClick(btn); } } @@ -259,32 +281,62 @@ class BookmarkListView { queue.subscribe('bookmark.expand-mode.update', (expandMode) => { this.expandModeUpdate(expandMode); }); + + queue.subscribe('font.update', (font) => { + this.fontUpdate(font); + }); + + queue.subscribe('font-size.update', (fontSize) => { + this.fontSizeUpdate(fontSize); + }); + } + + toogleClipboardMode() { + if (this.clipboardMode) { + this.btnBanner.classList.remove('btn-banner--active'); + } else { + this.btnBanner.classList.add('btn-banner--active'); + } + this.clipboardMode = !this.clipboardMode; } toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('bookmark.back', null); - } else if (target === this.btnSortAscend) { + } else if (btn === this.btnSortAscend) { queue.publish('bookmark-list.sort-ascend', null); - } else if (target === this.btnSortInvert) { + } else if (btn === this.btnSortInvert) { queue.publish('bookmark-list.sort-invert', null); - } else if (target === this.btnBookmarkFolder) { + } else if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); - } else if (target === this.btnExpandMode) { + } else if (btn === this.btnExpandMode) { queue.publish('bookmark-list.expand-mode.click', null); } } } + toolbarUpperClick(event) { + event.preventDefault(); + if (!this.expandMode) { + return; + } + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBanner) { + this.toogleClipboardMode(); + } + } + } + up(verseIdx) { queue.publish('bookmark-list.up', verseIdx); } updateBanner() { - this.banner.innerHTML = `${this.activeFolder.name}`; + this.btnBanner.innerHTML = `${this.activeFolder.name}`; } updateActiveFolder(activeFolder) { @@ -317,11 +369,36 @@ class BookmarkListView { this.scroll.scrollTop = scrollSave; } + updateFontSize() { + if (!this.expandMode) { + return; + } + if (this.lastFontSize) { + this.list.classList.remove(this.lastFontSize); + } + this.list.classList.add(this.fontSize); + } + + updateFont() { + if (!this.expandMode) { + return; + } + if (this.lastFont) { + this.list.classList.remove(this.lastFont.fontClass); + } + this.list.classList.add(this.font.fontClass); + } + verseClick(target) { if (target) { if (target.classList.contains('btn-result')) { - let verseIdx = parseInt(target.dataset.verseIdx); - queue.publish('bookmark-list.select', verseIdx); + if (this.clipboardMode) { + let text = target.textContent; + navigator.clipboard.writeText(text); + } else { + let verseIdx = parseInt(target.dataset.verseIdx); + queue.publish('bookmark-list.select', verseIdx); + } } } } diff --git a/js/View/BookmarkMoveCopyView.js b/js/View/BookmarkMoveCopyView.js index 10dfb89..772f530 100644 --- a/js/View/BookmarkMoveCopyView.js +++ b/js/View/BookmarkMoveCopyView.js @@ -147,10 +147,10 @@ class BookmarkMoveCopyView { listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-icon--h-menu')) { - let entry = target.previousSibling; + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-icon--h-menu')) { + let entry = btn.previousSibling; this.menuClick(entry); } } @@ -214,9 +214,9 @@ class BookmarkMoveCopyView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBookmarkFolder) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBookmarkFolder) { queue.publish('bookmark-folder', null); } } diff --git a/js/View/HelpReadView.js b/js/View/HelpReadView.js index fda6912..91f6d63 100644 --- a/js/View/HelpReadView.js +++ b/js/View/HelpReadView.js @@ -87,11 +87,11 @@ class HelpReadView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('help.back', null); - } else if (target === this.btnHelpTopic) { + } else if (btn === this.btnHelpTopic) { queue.publish('help-topic', null); } } diff --git a/js/View/HelpTopicView.js b/js/View/HelpTopicView.js index 41e503b..ae9fa71 100644 --- a/js/View/HelpTopicView.js +++ b/js/View/HelpTopicView.js @@ -24,6 +24,7 @@ export const helpTopicList = [ { topic: 'about', name: 'About' }, { topic: 'overview', name: 'Overview' }, { topic: 'read', name: 'Read' }, + { topic: 'clipboard-mode', name: 'Clipboard Mode' }, { topic: 'navigator', name: 'Navigator' }, { topic: 'bookmark', name: 'Bookmark' }, { topic: 'search', name: 'Search' }, @@ -101,10 +102,10 @@ class HelpTopicView { scrollClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-topic')) { - let helpTopic = target.dataset.topic; + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-topic')) { + let helpTopic = btn.dataset.topic; queue.publish('help-topic.select', helpTopic); } } @@ -125,11 +126,11 @@ class HelpTopicView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('help.back', null); - } else if (target === this.btnHelpRead) { + } else if (btn === this.btnHelpRead) { queue.publish('help-read', null); } } diff --git a/js/View/NavigatorBookView.js b/js/View/NavigatorBookView.js index 6570be2..c75580c 100644 --- a/js/View/NavigatorBookView.js +++ b/js/View/NavigatorBookView.js @@ -119,10 +119,10 @@ class NavigatorBookView { listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-book')) { - this.contentClick(target); + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-book')) { + this.contentClick(btn); } } } @@ -146,11 +146,11 @@ class NavigatorBookView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('navigator.back', null); - } else if (target === this.btnChapter) { + } else if (btn === this.btnChapter) { queue.publish('navigator-chapter', null); } } diff --git a/js/View/NavigatorChapterView.js b/js/View/NavigatorChapterView.js index 45593f9..d821218 100644 --- a/js/View/NavigatorChapterView.js +++ b/js/View/NavigatorChapterView.js @@ -127,10 +127,10 @@ class NavigatorChapterView { listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-chapter')) { - this.contentClick(target); + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-chapter')) { + this.contentClick(btn); } } } @@ -162,11 +162,11 @@ class NavigatorChapterView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('navigator.back', null); - } else if (target === this.btnBook) { + } else if (btn === this.btnBook) { queue.publish('navigator-book', null); } } diff --git a/js/View/ReadView.js b/js/View/ReadView.js index 50e061d..4fb8f58 100644 --- a/js/View/ReadView.js +++ b/js/View/ReadView.js @@ -36,7 +36,7 @@ const lowerToolSet = [ const upperToolSet = [ { type: 'btn', icon: 'prev', ariaLabel: 'Previous Chapter' }, - { type: 'banner', cssModifier: 'read', text: null }, + { type: 'btn-banner', cssModifier: 'read', text: 'Toogle Clipboard' }, { type: 'btn', icon: 'next', ariaLabel: 'Next Chapter' }, ]; @@ -157,7 +157,7 @@ class ReadView { this.body = document.querySelector('body'); this.btnPrev = this.toolbarUpper.querySelector('.btn-icon--prev'); - this.banner = this.toolbarUpper.querySelector('.banner--read'); + this.btnBanner = this.toolbarUpper.querySelector('.btn-banner--read'); this.btnNext = this.toolbarUpper.querySelector('.btn-icon--next'); this.btnNavigator = this.toolbarLower.querySelector('.btn-icon--navigator'); @@ -193,6 +193,7 @@ class ReadView { this.subscribe(); this.lastFont = null; this.lastFontSize = null; + this.clipboardMode = false; } listClick(event) { @@ -200,7 +201,12 @@ class ReadView { if (!document.getSelection().toString()) { let verse = event.target.closest('div.verse'); if (verse) { - this.verseClick(verse); + if (this.clipboardMode) { + let text = `${this.btnBanner.textContent}:${verse.textContent}`; + navigator.clipboard.writeText(text); + } else { + this.verseClick(verse); + } } } } @@ -362,24 +368,39 @@ class ReadView { }); } + themeUpdate(theme) { + this.theme = theme; + this.changeTheme(); + this.lastTheme = this.theme; + } + + toogleClipboardMode() { + if (this.clipboardMode) { + this.btnBanner.classList.remove('btn-banner--active'); + } else { + this.btnBanner.classList.add('btn-banner--active'); + } + this.clipboardMode = !this.clipboardMode; + } + toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnColumnMode || - !target.classList.contains('btn-icon--active') + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnColumnMode || + !btn.classList.contains('btn-icon--active') ) { - if (target === this.btnNavigator) { + if (btn === this.btnNavigator) { queue.publish('sidebar.select', 'navigator'); - } else if (target === this.btnBookmark) { + } else if (btn === this.btnBookmark) { queue.publish('sidebar.select', 'bookmark'); - } else if (target === this.btnSearch) { + } else if (btn === this.btnSearch) { queue.publish('sidebar.select', 'search'); - } else if (target === this.btnSetting) { + } else if (btn === this.btnSetting) { queue.publish('sidebar.select', 'setting'); - } else if (target === this.btnHelp) { + } else if (btn === this.btnHelp) { queue.publish('sidebar.select', 'help'); - } else if (target === this.btnColumnMode) { + } else if (btn === this.btnColumnMode) { queue.publish('read.column-mode.click', null); } } @@ -388,24 +409,32 @@ class ReadView { toolbarUpperClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnPrev) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnPrev) { queue.publish('read.prev.chapter', 1); - } else if (target === this.btnNext) { + } else if (btn === this.btnNext) { queue.publish('read.next.chapter', 2); } } } - themeUpdate(theme) { - this.theme = theme; - this.changeTheme(); - this.lastTheme = this.theme; + toolbarUpperClick(event) { + event.preventDefault(); + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBanner) { + this.toogleClipboardMode(); + } else if (btn === this.btnPrev) { + queue.publish('read.prev.chapter', 1); + } else if (btn === this.btnNext) { + queue.publish('read.next.chapter', 2); + } + } } updateBanner() { - this.banner.textContent = tomeChapters[this.chapterIdx][chapterName]; + this.btnBanner.textContent = tomeChapters[this.chapterIdx][chapterName]; } updateColumnMode() { diff --git a/js/View/SearchFilterView.js b/js/View/SearchFilterView.js index ae1b4cf..caa37fb 100644 --- a/js/View/SearchFilterView.js +++ b/js/View/SearchFilterView.js @@ -202,14 +202,14 @@ class SearchFilterView { listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-filter')) { - this.filterClick(target); - } else if (target.classList.contains('btn-icon--filter-down')) { - this.foldClick(target); - } else if (target.classList.contains('btn-icon--filter-next')) { - this.unfoldClick(target); + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-filter')) { + this.filterClick(btn); + } else if (btn.classList.contains('btn-icon--filter-down')) { + this.foldClick(btn); + } else if (btn.classList.contains('btn-icon--filter-next')) { + this.unfoldClick(btn); } } } @@ -247,9 +247,9 @@ class SearchFilterView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnSearchResult) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnSearchResult) { queue.publish('search-result', null); } } diff --git a/js/View/SearchHistoryView.js b/js/View/SearchHistoryView.js index d6e73cd..3da76f4 100644 --- a/js/View/SearchHistoryView.js +++ b/js/View/SearchHistoryView.js @@ -108,13 +108,13 @@ class SearchHistoryView { listClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target.classList.contains('btn-entry--history')) { - let query = target.textContent; + let btn = event.target.closest('button'); + if (btn) { + if (btn.classList.contains('btn-entry--history')) { + let query = btn.textContent; queue.publish('search-history.select', query); - } else if (target.classList.contains('btn-icon--delete')) { - let entry = target.previousSibling; + } else if (btn.classList.contains('btn-icon--delete')) { + let entry = btn.previousSibling; let query = entry.textContent; queue.publish('search-history.delete', query); } @@ -140,11 +140,11 @@ class SearchHistoryView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnResult) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnResult) { queue.publish('search-result', null); - } else if (target === this.btnHistoryClear) { + } else if (btn === this.btnHistoryClear) { queue.publish('search-history.clear', null); } } diff --git a/js/View/SearchLookupView.js b/js/View/SearchLookupView.js index c181561..942b357 100644 --- a/js/View/SearchLookupView.js +++ b/js/View/SearchLookupView.js @@ -136,11 +136,11 @@ class SearchLookupView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('search.back', null); - } else if (target === this.btnResult) { + } else if (btn === this.btnResult) { queue.publish('search-result', null); } } diff --git a/js/View/SearchResultView.js b/js/View/SearchResultView.js index 3047488..d2f2630 100644 --- a/js/View/SearchResultView.js +++ b/js/View/SearchResultView.js @@ -49,7 +49,7 @@ const lowerToolSet = [ ]; const upperToolSet = [ - { type: 'banner', cssModifier: 'search-result', text: null }, + { type: 'btn-banner', cssModifier: 'search-result', text: 'Toogle Clipboard' }, ]; const binIdx = 0; @@ -71,6 +71,9 @@ class SearchResultView { this.toolbarLower.addEventListener('click', (event) => { this.toolbarLowerClick(event); }); + this.toolbarUpper.addEventListener('click', (event) => { + this.toolbarUpperClick(event); + }); } applyFilter() { @@ -202,7 +205,7 @@ class SearchResultView { } getElements() { - this.banner = this.toolbarUpper.querySelector('.banner--search-result'); + this.btnBanner = this.toolbarUpper.querySelector('.btn-banner--search-result'); this.btnBack = this.toolbarLower.querySelector('.btn-icon--back'); this.btnFilter = this.toolbarLower.querySelector( @@ -224,14 +227,19 @@ class SearchResultView { this.subscribe(); this.lastFont = null; this.lastFontSize = null; + this.clipboardMode = false; } listClick(event) { event.preventDefault(); - let target = event.target; - let btn = target.closest('button'); - let verseIdx = parseInt(btn.dataset.verseIdx); - queue.publish('search-result.read-select', verseIdx); + let btn = event.target.closest('button'); + if (this.clipboardMode) { + let text = btn.textContent; + navigator.clipboard.writeText(text); + } else { + let verseIdx = parseInt(btn.dataset.verseIdx); + queue.publish('search-result.read-select', verseIdx); + } } loadMoreClick(event) { @@ -309,24 +317,43 @@ class SearchResultView { }); } + toogleClipboardMode() { + if (this.clipboardMode) { + this.btnBanner.classList.remove('btn-banner--active'); + } else { + this.btnBanner.classList.add('btn-banner--active'); + } + this.clipboardMode = !this.clipboardMode; + } + toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('search.back', null); - } else if (target === this.btnFilter) { + } else if (btn === this.btnFilter) { queue.publish('search-filter', null); - } else if (target === this.btnHistory) { + } else if (btn === this.btnHistory) { queue.publish('search-history', null); - } else if (target === this.btnSearchLookup) { + } else if (btn === this.btnSearchLookup) { queue.publish('search-lookup', null); } } } + toolbarUpperClick(event) { + event.preventDefault(); + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBanner) { + this.toogleClipboardMode(); + } + } + } + updateBanner() { - this.banner.innerHTML = `${this.citation} ` + + this.btnBanner.innerHTML = `${this.citation} ` + `(${this.wordCount}/${this.verseCount})
` + `${this.rig.query}`; } diff --git a/js/View/SettingView.js b/js/View/SettingView.js index e7b859a..898b911 100644 --- a/js/View/SettingView.js +++ b/js/View/SettingView.js @@ -288,9 +288,9 @@ class SettingView { toolbarLowerClick(event) { event.preventDefault(); - let target = event.target.closest('button'); - if (target) { - if (target === this.btnBack) { + let btn = event.target.closest('button'); + if (btn) { + if (btn === this.btnBack) { queue.publish('setting.back', null); } } diff --git a/js/template.js b/js/template.js index f9925de..8ad2d9c 100644 --- a/js/template.js +++ b/js/template.js @@ -35,6 +35,12 @@ export const templateActionMenu = (cssModifier, actionSet) => { return actionMenu; }; +export const templateBtnBanner = (cssModifier, ariaLabel) => { + let btnIcon = templateElement( + 'button', 'btn-banner', cssModifier, ariaLabel); + return btnIcon; +}; + export const templateBtnIcon = (svgId, cssModifier, ariaLabel) => { let svgTag = document.createElementNS(svgNS, 'svg'); svgTag.classList.add('icon-svg'); @@ -141,6 +147,9 @@ export const templateToolbarUpper = (toolSet) => { if (tool.type === 'btn') { element = templateBtnIcon(tool.icon, tool.icon, tool.ariaLabel); toolbarUpper.appendChild(element); + } else if (tool.type === 'btn-banner') { + element = templateBtnBanner(tool.cssModifier, tool.ariaLabel); + toolbarUpper.appendChild(element); } else if (tool.type === 'banner') { element = templateElement( 'div', 'banner', tool.cssModifier, null, tool.text); diff --git a/sw.js b/sw.js index b55f25e..a94eb70 100644 --- a/sw.js +++ b/sw.js @@ -2,7 +2,7 @@ let appCaches = [ { - name: 'core-20221120.01', + name: 'core-20221201.01', urls: [ '/', '/bundle.js', @@ -16,7 +16,7 @@ let appCaches = [ ] }, { - name: 'css-20221117.01', + name: 'css-20221201.01', urls: [ '/css/font.css', '/css/kja.css', @@ -37,9 +37,10 @@ let appCaches = [ ] }, { - name: 'help-20221117.01', + name: 'help-20221201.01', urls: [ '/help/bookmark.html', + '/help/clipboard-mode.html', '/help/help.html', '/help/navigator.html', '/help/overview.html',