HTML Bookmark Search with Regexp
-Note:
+Upload a bookmark file exported from browser, or a table html.
+Click column names in table to sort the values.
+Bookmark Table
+Total count:
++
diff --git a/site/assets/css/styles.css b/site/assets/css/styles.css index fe6fc48..8eb2ec6 100644 --- a/site/assets/css/styles.css +++ b/site/assets/css/styles.css @@ -1,15 +1,78 @@ body { - font-family: Arial, sans-serif; + font-family: sans-serif; margin: 0; padding: 0; } -#main { - margin: 0 auto; +header { + background-color: #4051b5; + color: #fff; + padding: 30px; +} + +header div { + display: inline; + +} + +header svg { + height: 32px; +} + +header h1 { + display: inline; +} + +main { + margin: 10px auto; max-width: 90%; } -#uploadArea { +footer { + background-color: #333; + color: #fff; + padding: 5px; + text-align: center; +} + +/* buttons */ +.upload-btn, +.clear-btn, +.search-btn, +.expand-btn, +.search-btn, +.reset-btn { + padding: 12px 24px; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 16px; + font-weight: 500; + text-transform: uppercase; + transition: background-color 0.3s; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +.upload-btn { + background-color: #1dca88; + color: white; +} + +.search-btn { + background-color: #007bff; + color: white; +} + +.reset-btn { + background-color: #f44336; + color: white; +} + +#note-area { + margin: auto 15%; +} + +#upload-area { border: 2px solid #1dca88; margin: auto; width: 80%; @@ -18,12 +81,12 @@ body { text-align: center; } -#uploadArea button { +#upload-area button { display: inline-block; } -#dropArea { - width: 300px; +#drop-area { + max-width: 300px; height: 200px; border: 2px dashed #ddd; text-align: center; @@ -31,7 +94,7 @@ body { margin: 0 auto; } -#searchArea { +#search-area { border: 2px solid #007bff; padding: 20px; margin: auto; @@ -41,42 +104,6 @@ body { text-align: center; } - -/* table */ -#fileContent { - margin: 30px auto 30px auto; - width: 90%; -} - -table, -th, -td { - border-collapse: collapse; - border: 1px solid #ddd; - padding: 8px; - -} - -th { - cursor: pointer; - position: relative; - background-color: #f2f2f2; - font-weight: bold; - text-align: center; -} - -th.asc::after { - content: " ⬆️"; - position: absolute; - right: 5px; -} - -th.desc::after { - content: " ⬇️"; - position: absolute; - right: 5px; -} - .filter-condition { margin-bottom: 10px; } @@ -95,46 +122,37 @@ th.desc::after { width: 250px; } -/* buttons */ -.upload-btn, -.clear-btn, -.search-btn, -.expand-btn, -.search-btn, -.reset-btn { - padding: 12px 24px; - border: none; - border-radius: 4px; - cursor: pointer; - font-size: 16px; - font-weight: 500; - text-transform: uppercase; - transition: background-color 0.3s; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +#file-area { + margin: 50px auto; + max-width: 90%; } -.upload-btn { - background-color: #1dca88; - color: white; +table, th, td { + border-collapse: collapse; + border: 1px solid #ddd; } -.search-btn { - background-color: #007bff; - color: white; +#file-area table { + margin: 0 auto; } -.reset-btn { - background-color: #f44336; - color: white; +#file-area th { + cursor: pointer; + position: relative; + background-color: #f2f2f2; + font-weight: bold; + text-align: center; + font-size: large; } -footer { - background-color: #333; - color: white; - padding-top: 10px; - text-align: center; - position: fixed; - bottom: 0; - width: 90%; - /* margin: 0 auto; */ +#file-area th.asc::after { + content: " ⬆️"; + position: absolute; + right: 5px; +} + +#file-area th.desc::after { + content: " ⬇️"; + position: absolute; + right: 5px; } \ No newline at end of file diff --git a/site/assets/js/loadfile.js b/site/assets/js/loadfile.js index 8fef717..4918d6a 100644 --- a/site/assets/js/loadfile.js +++ b/site/assets/js/loadfile.js @@ -25,10 +25,8 @@ function processFile(file) { } function displayTable(table) { - const tableDiv = document.getElementById('fileContent'); - tableDiv.innerHTML = ''; - table.id = "dataTable"; - tableDiv.appendChild(table.cloneNode(true)); + const tableDiv = document.getElementById('dataTable'); + tableDiv.innerHTML = table.innerHTML; } function findFolder(bookmarkElement) { @@ -48,12 +46,7 @@ function findFolder(bookmarkElement) { } function displayBookmarks(fileContent) { - const tableDiv = document.getElementById('fileContent'); - tableDiv.innerHTML = ''; - const table = document.createElement('table'); - table.id = "dataTable" - const thead = document.createElement('thead'); const tbody = document.createElement('tbody'); const trHead = document.createElement('tr'); @@ -93,13 +86,15 @@ function displayBookmarks(fileContent) { } tbody.appendChild(tr); }); + table.appendChild(tbody); - tableDiv.appendChild(table.cloneNode(true)); + displayTable(table) } function clearContent() { - document.getElementById('fileContent').innerHTML = ''; - document.getElementById("filterConditions").innerHTML = ""; + document.getElementById('dataTable').innerHTML = ''; + document.getElementById('dataCount').innerHTML = ''; + document.getElementById("search-options").innerHTML = ""; } function dragOverHandler(event) { @@ -120,7 +115,6 @@ function openFile() { fileInput.addEventListener('change', function(event) { const selectedFile = event.target.files[0]; if (selectedFile) { - // console.log("open", selectedFile.name) const file = event.target.files[0]; processFile(file); event.target.value = ''; // allow open same file again diff --git a/site/assets/js/search.js b/site/assets/js/search.js index b069e9c..7d4b8d5 100644 --- a/site/assets/js/search.js +++ b/site/assets/js/search.js @@ -1,17 +1,28 @@ +function getCheckboxHighlight() { + const searchOptions = document.querySelectorAll(".filter-condition"); + const selectedCheckboxes = []; + searchOptions[0].querySelectorAll('.filter-checkbox').forEach(checkbox => { + if (checkbox.checked) { + selectedCheckboxes.push(checkbox.value.toLowerCase()); + } + }); + const options = ['Highlight', 'Match Case', 'Regexp']; + return selectedCheckboxes.indexOf(options[0].toLowerCase()) >= 0 +} function filterTable() { const table = document.getElementById("dataTable"); const tr = table.getElementsByTagName("tr"); - const filterConditions = document.querySelectorAll(".filter-condition"); - const conditions = Array.from(filterConditions).filter(cond => cond.querySelector(".regex-input") && cond.querySelector(".regex-input").value.trim() !== ''); + const searchOptions = document.querySelectorAll(".filter-condition"); + const conditions = Array.from(searchOptions).filter(cond => cond.querySelector(".regex-input") && cond.querySelector(".regex-input").value.trim() !== ''); const selectedCheckboxes = []; - filterConditions[0].querySelectorAll('.filter-checkbox').forEach(checkbox => { + searchOptions[0].querySelectorAll('.filter-checkbox').forEach(checkbox => { if (checkbox.checked) { selectedCheckboxes.push(checkbox.value.toLowerCase()); } }); - const selectedRadioButton = filterConditions[0].querySelector('input[name="filterType"]:checked').value; + const selectedRadioButton = searchOptions[0].querySelector('input[name="filterType"]:checked').value; const options = ['Highlight', 'Match Case', 'Regexp']; const logicOptions = ['AND', 'OR'] @@ -40,8 +51,7 @@ function filterTable() { const query = useRegexp ? queryRaw:queryRaw.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');; const regex = new RegExp(query, matchCase? "g" :"gi"); - - console.log('query', query); + // Check if the condition matches the row if (td && ( (!notLogic && regex.test(td.textContent)) || @@ -49,16 +59,14 @@ function filterTable() { )) { matchCount++; if (highlight) { - // Highlight matching text const highlightedText = td.textContent.replace( regex, (match) => `${match}` ); - const alist = td.querySelectorAll('a'); - if (alist.length == 0) { + if (td.childElementCount == 0) { td.innerHTML = highlightedText; } else { - alist[0].innerHTML = highlightedText + td.childNodes[0].innerHTML = highlightedText } } } @@ -77,7 +85,7 @@ function filterTable() { } } } - document.getElementById("dataCount").innerHTML = "Total count = " + cnt; + document.getElementById("dataCount").innerHTML = cnt; } function resetFilters() { @@ -91,24 +99,21 @@ function resetFilters() { return } - // Reset table visibility - const tr = table.getElementsByTagName("tr"); - for (let i = 1; i < tr.length; i++) { - tr[i].style.display = ""; // Show all rows - } + const trs = table.querySelectorAll('tr[style*="display: none"]'); + trs.forEach(tr => { + tr.style.display = ''; + }); - // Remove highlighting - const tds = table.getElementsByTagName("td"); - for (let i = 0; i < tds.length; i++) { - const alist = tds[i].querySelectorAll('a'); - if (alist.length == 0) { - tds[i].innerHTML = tds[i].innerText; // Reset innerHTML to remove spans - } else { - alist[0].innerHTML = tds[i].innerText; - } + if(getCheckboxHighlight()) { + const tds = table.querySelectorAll('td span'); + tds.forEach(span => { + if(span.parentNode) + span.parentNode.innerHTML = span.parentNode.innerText + }) } + const cnt = document.getElementsByTagName("tr").length - 1; - document.getElementById("dataCount").innerHTML = "Total count = " + cnt; + document.getElementById("dataCount").innerHTML = cnt; } function addOption(i, container) { @@ -138,8 +143,7 @@ function addOption(i, container) { } function toggleFirstFilters() { - const container = document.getElementById("filterConditions"); - + const container = document.getElementById("search-options"); const newCondition = document.createElement("div"); newCondition.className = "filter-condition"; p = document.createElement("span"); @@ -186,7 +190,7 @@ function toggleFirstFilters() { } function toggleMoreFilters() { - const container = document.getElementById("filterConditions"); + const container = document.getElementById("search-options"); const rows = document.getElementById("dataTable").rows if (rows.length == 0) { return; @@ -244,7 +248,7 @@ function createLogicNotSelect() { function renderPages() { const cnt = document.getElementById("dataTable").rows.length; - document.getElementById("dataCount").innerHTML = "Total count = " + cnt; + document.getElementById("dataCount").innerHTML = cnt; toggleFirstFilters(); const headers = document diff --git a/site/index.html b/site/index.html index 45abacf..a3596f3 100644 --- a/site/index.html +++ b/site/index.html @@ -9,46 +9,59 @@
-Upload a bookmark file exported from browser, or a table html.
+Click column names in table to sort the values.
+Bookmark Table
+Total count:
+