From 4ddd503616e406256c55ad7fa0c01d24205c6148 Mon Sep 17 00:00:00 2001 From: DashCampbell Date: Fri, 29 Dec 2023 16:17:03 -0700 Subject: [PATCH] Updated search menu and toolbar --- content/temp_index.json | 93 ++++++ themes/zettels/assets/js/search.js | 313 ++++++++++--------- themes/zettels/assets/js/thumbnails.js | 30 +- themes/zettels/layouts/partials/search.html | 233 +++++++------- themes/zettels/layouts/partials/toolbar.html | 77 +++-- 5 files changed, 444 insertions(+), 302 deletions(-) create mode 100644 content/temp_index.json diff --git a/content/temp_index.json b/content/temp_index.json new file mode 100644 index 0000000..65874e8 --- /dev/null +++ b/content/temp_index.json @@ -0,0 +1,93 @@ +{ + "index": [ + { + "permalink": "/heaviside-unit-step-function-lec-18.html", + "summary": "We got a joke! Heaviside (British electrician) was told during a …", + "tags": [ + "\n#heaviside", + " #mouc", + " #voparam", + "\n#ex", + " #heaviside", + "\n#end" + ], + "thumbnail": "", + "title": "(Heaviside) Unit step function (lec 18)" + }, + { + "permalink": "/bernoulli-equations-lec-3.html", + "summary": "Bernoulli's equation: $$\\frac{ dy }{ dx } +P(x)y=Q(x)y^n \\quad\\quad …", + "tags": [ + " #de_b_type1", + " #de_s_type1", + "\n#ex", + "\n#end" + ], + "thumbnail": "", + "title": "Bernoulli equations (lec 3)" + }, + { + "permalink": "/cauchy-euler-equations-lec-10-11.html", + "summary": "We know how to solve second order equations where a, b, c are …", + "tags": [ + "\n#cauchy-euler", + " #remember", + "\n#ex", + " #second_order", + " #second_order_nonhomogenous", + " #cauchy-euler", + "\n#end", + " #start" + ], + "thumbnail": "", + "title": "Cauchy-Euler equations (lec 10-11)" + }, + { + "permalink": "/convolution-lec-19-20.html", + "summary": "Convolution #convolution A convolution is an operation on two …", + "tags": [ + "\n#convolution", + "\n#end", + " #start", + "\n#ex", + " #convolution", + " #inv_LT", + " #partial_fractions", + " #remember", + " #IVP", + " #integral-differential" + ], + "thumbnail": "", + "title": "Convolution (lec 19-20)" + }, + { + "permalink": "/dirak-%CE%B4-function-lec-21.html", + "summary": "#start of lec 21 From newton's second law: $ma=F$ …", + "tags": [ + "\n#start", + "\n#dirak_delta", + "\n#ex", + " #second_order_nonhomogenous", + " #dirak_delta", + " #IVP", + " #voparam" + ], + "thumbnail": "drawings/Drawing-2023-10-25-13.16.20.excalidraw.png", + "title": "Dirak δ-function (lec 21)" + }, + { + "permalink": "/drawings/2023-12-06-13.14.28.excalidraw.html", + "summary": "==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this …", + "tags": [], + "thumbnail": "", + "title": "2023-12-06-13.14.28.excalidraw" + }, + { + "permalink": "/drawings/2023-12-18-16.29.58.excalidraw.html", + "summary": "==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this …", + "tags": [], + "thumbnail": "", + "title": "2023-12-18-16.29.58.excalidraw" + } + ] +} \ No newline at end of file diff --git a/themes/zettels/assets/js/search.js b/themes/zettels/assets/js/search.js index 7feeed8..de51ea7 100644 --- a/themes/zettels/assets/js/search.js +++ b/themes/zettels/assets/js/search.js @@ -3,7 +3,7 @@ loadIndex() // Highlight with jQuery // from: https://stackoverflow.com/questions/41533785/how-to-highlight-search-text-in-html-with-the-help-of-js // @todo: This is the only use of jQuery. Find a vanila JS way -jQuery.fn.highlight = function(pat) { +jQuery.fn.highlight = function (pat) { function innerHighlight(node, pat) { @@ -15,16 +15,16 @@ jQuery.fn.highlight = function(pat) { if (pos >= 0) { - var spannode = document.createElement('span'); + var spannode = document.createElement('span'); spannode.className = 'highlighted'; - var middlebit = node.splitText(pos); - var endbit = middlebit.splitText(pat.length); - var middleclone = middlebit.cloneNode(true); + var middlebit = node.splitText(pos); + var endbit = middlebit.splitText(pat.length); + var middleclone = middlebit.cloneNode(true); spannode.appendChild(middleclone); middlebit.parentNode.replaceChild(spannode, middlebit); - skip = 1; + skip = 1; } @@ -41,15 +41,15 @@ jQuery.fn.highlight = function(pat) { } - return this.each(function() { + return this.each(function () { innerHighlight(this, pat.toUpperCase()); }); - }; +}; -jQuery.fn.removeHighlight = function() { +jQuery.fn.removeHighlight = function () { function newNormalize(node) { @@ -71,7 +71,7 @@ jQuery.fn.removeHighlight = function() { if (next == null || next.nodeType != 3) { continue; } var combined_text = child.nodeValue + next.nodeValue; - new_node = node.ownerDocument.createTextNode(combined_text); + new_node = node.ownerDocument.createTextNode(combined_text); node.insertBefore(new_node, child); node.removeChild(child); @@ -83,7 +83,7 @@ jQuery.fn.removeHighlight = function() { } - return this.find("span.highlighted").each(function() { + return this.find("span.highlighted").each(function () { var thisParent = this.parentNode; thisParent.replaceChild(this.firstChild, this); @@ -93,9 +93,9 @@ jQuery.fn.removeHighlight = function() { }; -$(function() { +$(function () { - $('#search-input').bind('keyup change', function(ev) { + $('#search-input').bind('keyup change', function (ev) { // pull in the new value var searchTerm = $(this).val(); @@ -104,64 +104,72 @@ $(function() { $('body').removeHighlight(); // disable highlighting if empty - if ( searchTerm ) { + if (searchTerm) { // highlight the new term - $('body').highlight( searchTerm ); + $('body').highlight(searchTerm); } - }); - }); /// var scrollTop = 0 -document.addEventListener("turbolinks:before-render", function() { - var search_index = document.getElementById("search-results"); - var y = search_index.scrollTop; - scrollTop = y +document.addEventListener("turbolinks:before-render", function () { + var search_index = document.getElementById("search-results"); + var y = search_index.scrollTop; + scrollTop = y + - }) -document.addEventListener("turbolinks:render", function() { +document.addEventListener("turbolinks:render", function () { var search_index = document.getElementById("search-results"); search_index.scrollTop = scrollTop }) - -document.addEventListener("turbolinks:load", function() { + +document.addEventListener("turbolinks:load", function () { setNoteWrapperState() - - + + const current = window.location.href - - var els = document.getElementsByTagName("a"); - for (var i = 0, l = els.length; i < l; i++) { - var el = els[i]; - - if (el.href === current) { - el.classList.add("selected") - } else { - el.classList.remove("selected") - } - } + var els = document.getElementsByTagName("a"); + for (var i = 0, l = els.length; i < l; i++) { + var el = els[i]; + + if (el.href === current) { + el.classList.add("selected") + } else { + el.classList.remove("selected") + } + } }) function loadIndex() { - fetchJSON(function(response) { - + // On localhost the root url is /MATH201 + // On sasserisop the root url is /sasserisop + const localhost = true; + const root = localhost ? "" : "/MATH201"; + + fetchJSON(function (response) { const notes = response; const search_results = document.getElementById('search-results'); const tags = document.getElementById('tags'); const current_note = window.location.href; - notes.index.forEach(note => { - const title = '

'+ note.title + '

'; + + // sorted notes by lecture number + const lecture_notes = new Map(); + const non_lecture_notes = []; + + // Fixed a bug where the search results had unwanted notes. + // The notes are now filtered first. + notes.index.filter(n => !/^Drawing|^20/.test(n.title)).forEach(note => { + const title = '

' + note.title + '

'; const summary = '
' + note.summary + '
'; - + const permalink = note.permalink - + var thumbnail = "" if (note.thumbnail === "") { thumbnail = "" @@ -175,20 +183,42 @@ function loadIndex() { // use lazy loading. thumbnail = '@attachments' } - + const tags = '' + note.tags + '' var list_content; if (current_note === permalink) { - list_content = '' + title + summary + '' + list_content = '' + title + summary + '' } else { - list_content = '' + title + summary + thumbnail + tags + '' + list_content = '' + title + summary + thumbnail + tags + '' } - + const child = document.createElement("li"); child.innerHTML = list_content; - search_results.append(child) + + // Add lecture notes to a dictionary, and then sort them by lecture number. + // second last character of the title may be first digit of lecture number + const d1 = note.title[note.title.length - 2]; + // find the lecture number, if there is one + if (/\d/.test(d1)) { + // it has a lecture number + // if the third last character is a digit, then the lecture number is 2 digits + const d2 = note.title[note.title.length - 3]; + const lecture_number = /\d/.test(d2) ? Number(d2 + d1) : Number(d1); + lecture_notes.set(lecture_number, child); + } else { + non_lecture_notes.push(child); + } }); - + // sort notes by lecture number + const sorted_notes = new Map([...lecture_notes.entries()].sort((a, b) => (a[0] - b[0]))); + // Add sorted notes first + sorted_notes.forEach(val => { + search_results.append(val); + }); + non_lecture_notes.forEach(child => { + search_results.append(child); + }) + // @todo: wip // notes.tags.forEach(tag => { // const child = document.createElement("li"); @@ -196,20 +226,19 @@ function loadIndex() { // tags.append(child) // }); // - }); - } - - -function fetchJSON(callback) { - - const requestURL = '/MATH201/index.json'; + }, root); +} + + +function fetchJSON(callback, root) { + const requestURL = root + '/index.json'; const request = new XMLHttpRequest(); request.open('GET', requestURL, true); request.responseType = 'json'; - request.onreadystatechange = function() { - if (request.readyState === 4 && request.status === 200) { - callback(request.response); - } + request.onreadystatechange = function () { + if (request.readyState === 4 && request.status === 200) { + callback(request.response); + } }; request.send(null); } @@ -217,76 +246,76 @@ function fetchJSON(callback) { function focusTag(a) { showNav() performSearchWith(a.innerText) - + } function performSearchWith(query) { - - // document.getElementById('search-input').value = query - - var filter, ul, li, a, i, txtValue; - - filter = query.toLowerCase(); - filter = filter.replace('/[.*+?^${}()|[\]\\]/g', '\\$&'); - - var re = new RegExp(filter, 'g'); - - ul = document.getElementById("search-results"); - li = ul.getElementsByTagName('li'); - for (i = 0; i < li.length; i++) { + // document.getElementById('search-input').value = query + + var filter, ul, li, a, i, txtValue; + + filter = query.toLowerCase(); + filter = filter.replace('/[.*+?^${}()|[\]\\]/g', '\\$&'); + + var re = new RegExp(filter, 'g'); + + ul = document.getElementById("search-results"); + li = ul.getElementsByTagName('li'); + + for (i = 0; i < li.length; i++) { a = li[i].getElementsByTagName("a")[0]; - + txtValue = a.textContent || a.innerText; if (txtValue.toLowerCase().indexOf(filter) > -1) { - li[i].style.display = "block"; - + li[i].style.display = "block"; + } else { - li[i].style.display = "none"; + li[i].style.display = "none"; } - } + } } function performSearch() { - - var input, filter, ul, li, a, i, txtValue; - input = document.getElementById('search-input'); - - filter = input.value.toLowerCase(); - filter = filter.replace('/[.*+?^${}()|[\]\\]/g', '\\$&'); - - var re = new RegExp(filter, 'g'); - - ul = document.getElementById("search-results"); - li = ul.getElementsByTagName('li'); - for (i = 0; i < li.length; i++) { + var input, filter, ul, li, a, i, txtValue; + input = document.getElementById('search-input'); + + filter = input.value.toLowerCase(); + filter = filter.replace('/[.*+?^${}()|[\]\\]/g', '\\$&'); + + var re = new RegExp(filter, 'g'); + + ul = document.getElementById("search-results"); + li = ul.getElementsByTagName('li'); + + for (i = 0; i < li.length; i++) { a = li[i].getElementsByTagName("a")[0]; - + txtValue = a.textContent || a.innerText; if (txtValue.toLowerCase().indexOf(filter) > -1) { - li[i].style.display = "block"; - + li[i].style.display = "block"; + } else { - li[i].style.display = "none"; + li[i].style.display = "none"; } - } + } } // Keyboard shortcuts -document.addEventListener('keydown', function(evt) { - +document.addEventListener('keydown', function (evt) { + if (evt.metaKey && evt.which === 75 || evt.ctrlKey && evt.which === 75) { document.getElementById("search-input").focus(); handleNavVisibility() } - + if (evt.key === "Escape" || evt.key === "Esc" | evt.keyCode === 27) { hideNav() } - + }); var nav_is_visible = false; @@ -300,13 +329,13 @@ function handleNavVisibility() { } function showNav() { - + document.getElementById("search").style.width = "300px"; document.getElementById("search").style.opacity = 1; document.getElementById("search-header").style.opacity = 1; document.getElementById("search-header").style.width = "299px"; pushNoteWrapper() - + nav_is_visible = true; } @@ -315,9 +344,9 @@ function hideNav() { document.getElementById("search-header").style.width = "0"; document.getElementById("search").style.opacity = 0; document.getElementById("search-header").style.opacity = 0; - document.getElementById("main").style.marginLeft= "0"; + document.getElementById("main").style.marginLeft = "0"; pullNoteWrapper() - + nav_is_visible = false; } @@ -344,54 +373,54 @@ const hoverTime = 300 const fetchers = {} const doc = document.implementation.createHTMLDocument('prefetch') -function fetchPage (url, success) { - const xhr = new XMLHttpRequest() - xhr.open('GET', url) - xhr.setRequestHeader('VND.PREFETCH', 'true') - xhr.setRequestHeader('Accept', 'text/html') - xhr.onreadystatechange = () => { - if (xhr.readyState !== XMLHttpRequest.DONE) return - if (xhr.status !== 200) return - success(xhr.responseText) - } - xhr.send() +function fetchPage(url, success) { + const xhr = new XMLHttpRequest() + xhr.open('GET', url) + xhr.setRequestHeader('VND.PREFETCH', 'true') + xhr.setRequestHeader('Accept', 'text/html') + xhr.onreadystatechange = () => { + if (xhr.readyState !== XMLHttpRequest.DONE) return + if (xhr.status !== 200) return + success(xhr.responseText) + } + xhr.send() } -function prefetchTurbolink (url) { - fetchPage(url, responseText => { - doc.open() - doc.write(responseText) - doc.close() - const snapshot = Turbolinks.Snapshot.fromHTMLElement(doc.documentElement) - Turbolinks.controller.cache.put(url, snapshot) - }) +function prefetchTurbolink(url) { + fetchPage(url, responseText => { + doc.open() + doc.write(responseText) + doc.close() + const snapshot = Turbolinks.Snapshot.fromHTMLElement(doc.documentElement) + Turbolinks.controller.cache.put(url, snapshot) + }) } -function prefetch (url) { - if (prefetched(url)) return - prefetchTurbolink(url) +function prefetch(url) { + if (prefetched(url)) return + prefetchTurbolink(url) } -function prefetched (url) { - return location.href === url || Turbolinks.controller.cache.has(url) +function prefetched(url) { + return location.href === url || Turbolinks.controller.cache.has(url) } -function prefetching (url) { - return !!fetchers[url] +function prefetching(url) { + return !!fetchers[url] } -function cleanup (event) { - const element = event.target - clearTimeout(fetchers[element.href]) - element.removeEventListener('mouseleave', cleanup) +function cleanup(event) { + const element = event.target + clearTimeout(fetchers[element.href]) + element.removeEventListener('mouseleave', cleanup) } document.addEventListener('mouseover', event => { - if (!event.target.dataset.prefetch) return - const url = event.target.href - if (prefetched(url)) return - if (prefetching(url)) return - cleanup(event) - event.target.addEventListener('mouseleave', cleanup) - fetchers[url] = setTimeout(() => prefetch(url), hoverTime) + if (!event.target.dataset.prefetch) return + const url = event.target.href + if (prefetched(url)) return + if (prefetching(url)) return + cleanup(event) + event.target.addEventListener('mouseleave', cleanup) + fetchers[url] = setTimeout(() => prefetch(url), hoverTime) }) diff --git a/themes/zettels/assets/js/thumbnails.js b/themes/zettels/assets/js/thumbnails.js index 604e9b6..2b0125a 100644 --- a/themes/zettels/assets/js/thumbnails.js +++ b/themes/zettels/assets/js/thumbnails.js @@ -1,19 +1,13 @@ -var thumbnail_mode = false -function imageMode() { - const note_wrapper = document.getElementById('note-wrapper') - const images = note_wrapper.getElementsByTagName('img') - - if (thumbnail_mode) { - var els = note_wrapper.getElementsByTagName('img') - for(var i = 0, all = els.length; i < all; i++){ - els[i].classList.remove('thumbnail'); - } - thumbnail_mode = false - } else { - var els = note_wrapper.getElementsByTagName('img') - for(var i = 0, all = els.length; i < all; i++){ - els[i].classList.add('thumbnail'); - } - thumbnail_mode = true - } +// Resize images using an input range. +function resizeImage() { + // make p tags wrapping img tags inline, to resize images correctly + $("#main p").has("img").css("display", "inline-block"); + + // toggle vectical input range + $("#toolbar input[type=range][orient=vertical]").slideToggle() + + // resize image + $("#toolbar input[type=range][orient=vertical]").mouseup(function () { + $("#main p img").css("width", this.value + "%") + }); } \ No newline at end of file diff --git a/themes/zettels/layouts/partials/search.html b/themes/zettels/layouts/partials/search.html index 33254ae..3c85f1c 100644 --- a/themes/zettels/layouts/partials/search.html +++ b/themes/zettels/layouts/partials/search.html @@ -6,130 +6,141 @@ - Focused current note --> + color: var(--text-base-color); + border-bottom: 1px solid var(--separator-color); + border-left: 6px solid var(--background-search); + + } + + #search-results a:first-child:hover, + a:first-child:focus, + .selected { + outline: 0; + background-color: var(--note-table-cell-selected-color); + border-left: 6px solid var(--note-table-cell-ribbon-color) !important; + } + + /* // Reseting default styles inside search component scope */ + #search-results li { + text-indent: 0; + } + + #search-results li:before, + #search-results h1:before, + #search-results h2:before, + #search-results h3:before, + #search-results h4:before, + #search-results h5:before, + #search-results h6:before { + content: ""; + visibility: hidden; + display: none; + } + -
-
- - - - - - -
-
- - +
+
+ + + + + + +
+
+ +
\ No newline at end of file diff --git a/themes/zettels/layouts/partials/toolbar.html b/themes/zettels/layouts/partials/toolbar.html index 2a95058..7b85e76 100644 --- a/themes/zettels/layouts/partials/toolbar.html +++ b/themes/zettels/layouts/partials/toolbar.html @@ -1,42 +1,57 @@ - - \ No newline at end of file + + + + \ No newline at end of file