diff --git a/css/button.css b/css/button.css index 974e3223..b75191d0 100644 --- a/css/button.css +++ b/css/button.css @@ -40,7 +40,7 @@ input[type="reset"]:focus, input[type="submit"]:hover, input[type="submit"]:focus { background-color: var(--gray-03); - border-bottom-color: rgb(var(--accent)); + border-bottom-color: var(--gray-08); color: var(--white); outline: 0; } @@ -51,6 +51,7 @@ input[type="button"]:active, input[type="reset"]:active, input[type="submit"]:active { background-color: var(--gray-04); + border-bottom-color: rgb(var(--accent)); color: var(--white); transition: none; } diff --git a/css/form.css b/css/form.css index 9c934808..ba0fbcc8 100644 --- a/css/form.css +++ b/css/form.css @@ -72,7 +72,7 @@ input[type="search"]:hover, input[type="tel"]:hover, input[type="text"]:hover { background-color: var(--gray-16); - border-color: rgb(var(--accent)); + border-color: var(--gray-10); color: var(--black); outline: 0; } @@ -300,17 +300,32 @@ input[type="checkbox"]:focus+.input-label-button, input[type="radio"]:hover+.input-label-button, input[type="radio"]:focus+.input-label-button { background-color: var(--gray-03); - border-bottom-color: rgb(var(--accent)); + border-bottom-color: var(--gray-10); color: var(--white); outline: 0; } +input[type="color"]:active+.input-label-button, +input[type="checkbox"]:active+.input-label-button, +input[type="radio"]:active+.input-label-button { + border-bottom-color: rgb(var(--accent)); +} + input[type="color"]:checked+.input-label-button, input[type="checkbox"]:checked+.input-label-button, input[type="radio"]:checked+.input-label-button { border-bottom-color: rgb(var(--accent)); } +input[type="color"][disabled]+.input-label-button, +input[type="checkbox"][disabled]+.input-label-button, +input[type="radio"][disabled]+.input-label-button { + background-color: var(--gray-02); + border-color: transparent; + color: var(--gray-04); + cursor: default; +} + input[type="checkbox"][disabled]+label, input[type="radio"][disabled]+label { color: var(--gray-04); diff --git a/css/header.css b/css/header.css index ccc4c85a..0f60d419 100644 --- a/css/header.css +++ b/css/header.css @@ -19,9 +19,6 @@ } .header-item { - margin-left: var(--gutter); - margin-right: var(--gutter); - margin-bottom: 1em; margin: var(--gutter); display: flex; flex-wrap: nowrap; diff --git a/css/link.css b/css/link.css index 04a26a00..eb3aec7a 100644 --- a/css/link.css +++ b/css/link.css @@ -230,6 +230,16 @@ text-overflow: ellipsis; } +.link-empty { + grid-column-start: 1; + grid-column-end: -1; + text-align: center; +} + +.link-empty-heading { + color: var(--gray-04); +} + .is-link-block .link-name { text-align: center; } diff --git a/index.html b/index.html index 39d3621c..2ae8ed69 100644 --- a/index.html +++ b/index.html @@ -70,7 +70,7 @@ -
+
@@ -252,13 +252,6 @@
- + diff --git a/js/bookmarks.js b/js/bookmarks.js index ec0174d8..871d3b73 100644 --- a/js/bookmarks.js +++ b/js/bookmarks.js @@ -134,14 +134,16 @@ var bookmarks = (function() { var get = function(timeStamp) { var _singleBookmark = function() { + var found = false; for (var i = 0; i < all.length; i++) { if (all[i].timeStamp === timeStamp) { - return all[i]; + found = all[i]; }; }; + return found; }; var _allBookmarks = function() { - var by = { + var action = { none: function(array) { return helper.sortObject(array, "timeStamp"); }, @@ -152,9 +154,9 @@ var bookmarks = (function() { return helper.sortObject(array, "letter"); } }; - return by[state.get().link.sort](all); + return action[state.get().link.sort](all); }; - if (timeStamp) { + if (timeStamp && typeof timeStamp == "number") { return _singleBookmark(timeStamp); } else { return _allBookmarks(); diff --git a/js/control.js b/js/control.js index 63d21706..5db0d0ef 100644 --- a/js/control.js +++ b/js/control.js @@ -108,7 +108,19 @@ var control = (function() { _layout(); }; - var _dependents = function() { + var dependents = function() { + var _edit = function() { + if (bookmarks.get().length > 0) { + helper.e(".control-edit").disabled = false; + } else { + helper.e(".control-edit").disabled = true; + helper.e(".control-edit").checked = false; + state.change({ + path: "edit.active", + value: false + }); + }; + }; var _date = function() { var activeCount = 0; var toCheck = [state.get().header.date.show.date, state.get().header.date.show.day, state.get().header.date.show.month, state.get().header.date.show.year]; @@ -180,6 +192,7 @@ var control = (function() { helper.e(".control-header-search-engine-custom-url").disabled = true; }; }; + _edit(); _date(); _clock(); _search(); @@ -198,6 +211,7 @@ var control = (function() { value: this.checked }); render(); + dependents(); data.save(); }, false); helper.e(".control-layout-theme").addEventListener("change", function() { @@ -252,7 +266,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); header.render(); data.save(); }, false); @@ -262,7 +276,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); header.render(); data.save(); }, false); @@ -273,7 +287,7 @@ var control = (function() { value: this.value }); render(); - _dependents(); + dependents(); search.update(); data.save(); }, false); @@ -292,7 +306,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); date.clear(); date.render(); header.render(); @@ -304,7 +318,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); date.clear(); date.render(); header.render(); @@ -316,7 +330,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); date.clear(); date.render(); header.render(); @@ -328,7 +342,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); date.clear(); date.render(); header.render(); @@ -340,7 +354,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); date.clear(); date.render(); header.render(); @@ -365,7 +379,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); clock.clear(); clock.render(); header.render(); @@ -377,7 +391,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); clock.clear(); clock.render(); header.render(); @@ -389,7 +403,7 @@ var control = (function() { value: this.checked }); render(); - _dependents(); + dependents(); clock.clear(); clock.render(); header.render(); @@ -410,7 +424,7 @@ var control = (function() { path: "header.clock.hour24", value: this.checked }); - _dependents(); + dependents(); clock.clear(); clock.render(); header.render(); @@ -508,15 +522,16 @@ var control = (function() { var init = function() { _bind(); update(); - _dependents(); + dependents(); render(); }; // exposed methods return { init: init, - update: update, - render: render + render: render, + dependents: dependents, + update: update }; })(); diff --git a/js/data.js b/js/data.js index 053a76f7..962e285f 100644 --- a/js/data.js +++ b/js/data.js @@ -10,7 +10,7 @@ var data = (function() { return localStorage.getItem(key); }; - var clear = function(key) { + var remove = function(key) { localStorage.removeItem(key); }; @@ -24,6 +24,10 @@ var data = (function() { console.log("data saved"); }; + var wipe = function() { + remove(saveName); + }; + var load = function() { var data = JSON.parse(get(saveName)); return data; @@ -48,14 +52,10 @@ var data = (function() { _checkForSavedData(load()); }; - var wipe = function() { - clear(saveName); - }; - return { init: init, save: save, - clear: clear, + remove: remove, set: set, get: get, load: load, diff --git a/js/helper.js b/js/helper.js index a297c069..20477989 100644 --- a/js/helper.js +++ b/js/helper.js @@ -113,10 +113,7 @@ var helper = (function() { var makeNode = function(override) { var options = { tag: null, - classes: null, text: null, - url: null, - index: null, attr: null }; if (override) { diff --git a/js/link.js b/js/link.js index 736089f9..556cdd38 100644 --- a/js/link.js +++ b/js/link.js @@ -3,7 +3,8 @@ var link = (function() { var _bind = function(override) { var options = { element: null, - action: null + action: null, + bookmarkData: null }; if (override) { options = helper.applyOptions(options, override); @@ -11,88 +12,98 @@ var link = (function() { var action = { edit: function() { options.element.addEventListener("click", function() { - edit(this); + edit(options.bookmarkData); }, false); }, - delete: function() { + remove: function() { options.element.addEventListener("click", function() { - remove(this); + remove(options.bookmarkData); + control.dependents(); + control.render(); }, false); } }; if (options.element != null) { action[options.action](); - } + }; }; - var add = function() { - state.get().link.action = "add"; - var form = _makeLinkForm(); - modal.render({ - heading: "Add a new bookmark", - action: save, - actionText: "Add", - size: "small", - content: form - }); - }; - - var edit = function(button) { - state.get().link.action = "edit"; - state.get().link.editObject = bookmarks.get(parseInt(button.closest(".link-item").dataset.timeStamp, 10)); - var currentBookmark = bookmarks.get(state.get().link.editObject.timeStamp); + var edit = function(bookmarkData) { + var currentBookmark = bookmarks.get(bookmarkData.timeStamp); var form = _makeLinkForm(); form.querySelector(".link-form-input-letter").value = currentBookmark.letter; form.querySelector(".link-form-input-name").value = currentBookmark.name; form.querySelector(".link-form-input-url").value = currentBookmark.url; modal.render({ heading: "Edit " + currentBookmark.name, - action: save, + action: function() { + save({ + action: "edit", + form: form, + bookmarkData: bookmarkData + }); + }, actionText: "Save", size: "small", content: form }); }; - var save = function(button) { - var action = { - add: function(newLinkData) { - newLinkData.timeStamp = new Date().getTime(); - bookmarks.add(newLinkData); + var add = function() { + var form = _makeLinkForm(); + modal.render({ + heading: "Add a new bookmark", + action: function() { + save({ + action: "add", + form: form + }); + control.dependents(); + control.render(); }, - edit: function(newLinkData) { - newLinkData.timeStamp = state.get().link.editObject.timeStamp; - bookmarks.edit(newLinkData, state.get().link.editObject.timeStamp); - } - }; - var form = helper.e(".link-form"); - var newLinkData = { - letter: form.querySelector(".link-form-input-letter").value, - name: form.querySelector(".link-form-input-name").value, - url: form.querySelector(".link-form-input-url").value - }; - action[state.get().link.action](newLinkData); - state.get().link.editObject = null; - state.get().link.action = null; - clear(); - if (state.get().header.search.searching) { - search.render(); - } else { - render(); - }; - data.save(); + actionText: "Add", + size: "small", + content: form + }); }; - var remove = function(button) { - var timeStamp = parseInt(button.closest(".link-item").dataset.timeStamp, 10); - bookmarks.remove(timeStamp); - clear(); - if (state.get().header.search.searching) { - search.render(); - } else { - render(); + var save = function(override) { + var options = { + action: null, + form: null, + bookmarkData: null }; + if (override) { + options = helper.applyOptions(options, override); + }; + var action = { + add: function() { + var newBookmarkData = { + letter: options.form.querySelector(".link-form-input-letter").value, + name: options.form.querySelector(".link-form-input-name").value, + url: options.form.querySelector(".link-form-input-url").value, + timeStamp: new Date().getTime() + }; + bookmarks.add(newBookmarkData); + }, + edit: function() { + options.bookmarkData.letter = options.form.querySelector(".link-form-input-letter").value; + options.bookmarkData.name = options.form.querySelector(".link-form-input-name").value; + options.bookmarkData.url = options.form.querySelector(".link-form-input-url").value; + bookmarks.edit(options.bookmarkData, options.bookmarkData.timeStamp); + } + }; + action[options.action](); data.save(); + clear(); + render(); + }; + + var remove = function(bookmarkData) { + bookmarks.remove(bookmarkData.timeStamp); + data.save(); + clear(); + render(); }; var _makeLinkForm = function() { @@ -212,9 +223,6 @@ var link = (function() { attr: [{ key: "class", value: "link-item" - }, { - key: "data-time-stamp", - value: data.timeStamp }] }); var linkOptions = { @@ -286,7 +294,7 @@ var link = (function() { tag: "button", attr: [{ key: "class", - value: "button button-small link-control-item link-edit" + value: "button button-small link-control-item" }, { key: "tabindex", value: -1 @@ -299,17 +307,17 @@ var link = (function() { value: "button-icon icon-edit" }] }); - var linkDelete = helper.makeNode({ + var linkRemove = helper.makeNode({ tag: "button", attr: [{ key: "class", - value: "button button-small link-control-item link-delete" + value: "button button-small link-control-item" }, { key: "tabindex", value: -1 }] }); - var linkDeleteIcon = helper.makeNode({ + var linkRemoveIcon = helper.makeNode({ tag: "span", attr: [{ key: "class", @@ -319,9 +327,9 @@ var link = (function() { linkPanelFront.appendChild(linkLetter); linkPanelFront.appendChild(linkName); linkEdit.appendChild(linkEditIcon); - linkDelete.appendChild(linkDeleteIcon); + linkRemove.appendChild(linkRemoveIcon); linkControl.appendChild(linkEdit); - linkControl.appendChild(linkDelete); + linkControl.appendChild(linkRemove); linkUrl.appendChild(linkUrlText); linkPanelBack.appendChild(linkUrl); linkPanelBack.appendChild(linkControl); @@ -329,21 +337,105 @@ var link = (function() { linkItem.appendChild(linkPanelBack); _bind({ element: linkEdit, - action: "edit" + action: "edit", + bookmarkData: data }); _bind({ - element: linkDelete, - action: "delete" + element: linkRemove, + action: "remove", + bookmarkData: data }); return linkItem; }; - var render = function(array) { - var linkArea = helper.e(".link-area"); - var bookmarksToRender = array || bookmarks.get(); - bookmarksToRender.forEach(function(arrayItem) { - linkArea.appendChild(_makeLink(arrayItem)); + var _makeEmptySearch = function() { + var searchInput = helper.e(".search-input"); + var div = helper.makeNode({ + tag: "div", + attr: [{ + key: "class", + value: "link-empty" + }] }); + var h1 = helper.makeNode({ + tag: "h1", + attr: [{ + key: "class", + value: "link-empty-heading" + }], + text: "No matching bookmarks found" + }); + div.appendChild(h1); + return div; + }; + + var _makeEmptyBookmarks = function() { + var searchInput = helper.e(".search-input"); + var div = helper.makeNode({ + tag: "div", + attr: [{ + key: "class", + value: "link-empty" + }] + }); + var h1 = helper.makeNode({ + tag: "h1", + attr: [{ + key: "class", + value: "link-empty-heading" + }], + text: "No bookmarks added" + }); + div.appendChild(h1); + return div; + }; + + var render = function() { + var linkArea = helper.e(".link-area"); + var bookmarksToRender = false; + if (state.get().header.search.searching) { + bookmarksToRender = search.get(); + } else { + bookmarksToRender = bookmarks.get(); + }; + var action = { + render: { + bookmarks: function(array) { + array.forEach(function(arrayItem, index) { + linkArea.appendChild(_makeLink(arrayItem)); + }); + }, + empty: { + search: function() { + linkArea.appendChild(_makeEmptySearch()); + }, + bookmarks: function() { + linkArea.appendChild(_makeEmptyBookmarks()); + } + } + } + }; + // if searching + if (state.get().header.search.searching) { + // if bookmarks exist to be searched + if (bookmarksToRender.total > 0) { + // if matching bookmarks found + if (bookmarksToRender.matching.length > 0) { + action.render.bookmarks(bookmarksToRender.matching); + } else { + action.render.empty.search(); + }; + } else { + action.render.empty.bookmarks(); + }; + } else { + // if bookmarks exist + if (bookmarksToRender.length > 0) { + action.render.bookmarks(bookmarksToRender); + } else { + action.render.empty.bookmarks(); + }; + }; }; var tabIndex = function() { diff --git a/js/search.js b/js/search.js index c33671dc..83c2d025 100644 --- a/js/search.js +++ b/js/search.js @@ -6,7 +6,8 @@ var search = (function() { searchInput.addEventListener("input", function() { _toggle(this); _searchClear(); - render(); + link.clear(); + link.render(); }, false); searchClear.addEventListener("click", function() { _toggle(this); @@ -17,9 +18,15 @@ var search = (function() { var _toggle = function(input) { if (input.value != "") { - state.get().header.search.searching = true; + state.change({ + path: "header.search.searching", + value: true + }) } else { - state.get().header.search.searching = false; + state.change({ + path: "header.search.searching", + value: false + }) }; }; @@ -33,22 +40,21 @@ var search = (function() { }; }; - var render = function() { + var get = function() { var searchInput = helper.e(".search-input"); if (state.get().header.search.searching) { - var searchedBookmarks = []; + var searchedBookmarks = { + total: 0, + matching: [] + }; + searchedBookmarks.total = bookmarks.get().length; bookmarks.get().forEach(function(arrayItem, index) { - if (arrayItem.url.replace(/^https?\:\/\//i, "").replace(/\/$/, "").toLowerCase().includes(searchInput.value.toLowerCase()) || arrayItem.name.toLowerCase().includes(searchInput.value.toLowerCase())) { - var copy = JSON.parse(JSON.stringify(arrayItem)); - copy.index = index; - searchedBookmarks.push(copy); + if (arrayItem.url.replace(/^https?\:\/\//i, "").replace(/\/$/, "").toLowerCase().includes(searchInput.value.toLowerCase().replace(/\s/g, "")) || arrayItem.name.toLowerCase().includes(searchInput.value.toLowerCase().replace(/\s/g, ""))) { + var bookmarkDataCopy = JSON.parse(JSON.stringify(arrayItem)); + searchedBookmarks.matching.push(bookmarkDataCopy); }; }); - link.clear(); - link.render(searchedBookmarks); - } else { - link.clear(); - link.render(); + return searchedBookmarks; }; }; @@ -73,7 +79,7 @@ var search = (function() { // exposed methods return { init: init, - render: render, + get: get, update: update, clear: clear }; diff --git a/js/state.js b/js/state.js index 2c54aceb..236e71e2 100644 --- a/js/state.js +++ b/js/state.js @@ -54,7 +54,6 @@ var state = (function() { }, link: { editObject: null, - action: null, newTab: false, style: "block", sort: "none" diff --git a/js/version.js b/js/version.js index a2e13ee5..9de8d1b6 100644 --- a/js/version.js +++ b/js/version.js @@ -1,5 +1,6 @@ var version = (function() { + // version is normally bumped when the state needs changing or any new functionality is added var current = "2.1.0"; var get = function() {