var link = (function() { var stagedGroup = { position: { origin: null, destination: null }, group: { name: null, openAll: null, items: null } }; stagedGroup.init = function() { stagedGroup.group.items = []; stagedGroup.group.openAll = true; }; stagedGroup.reset = function() { stagedGroup.position.origin = null; stagedGroup.position.destination = null; stagedGroup.group.name = null; stagedGroup.group.openAll = null; stagedGroup.group.items = null; }; var stagedLink = { position: { origin: { group: null, item: null }, destination: { group: null, item: null }, group: { new: null, name: null } }, link: { display: null, letter: null, icon: { name: null, prefix: null, label: null }, name: null, url: null, timeStamp: null, accent: { override: null, color: { r: null, g: null, b: null } } }, searchMatch: null }; stagedLink.init = function() { stagedLink.position.origin.group = 0; stagedLink.position.origin.item = 0; stagedLink.position.destination.group = 0; stagedLink.position.destination.item = 0; stagedLink.position.group.new = false; stagedLink.link.display = "letter"; stagedLink.link.accent.override = false; stagedLink.link.searchMatch = false; }; stagedLink.reset = function() { stagedLink.position.origin.group = null; stagedLink.position.origin.item = null; stagedLink.position.destination.group = null; stagedLink.position.destination.item = null; stagedLink.position.group.new = null; stagedLink.position.group.name = null; stagedLink.link.display = null; stagedLink.link.letter = null; stagedLink.link.icon.name = null; stagedLink.link.icon.prefix = null; stagedLink.link.icon.label = null; stagedLink.link.name = null; stagedLink.link.url = null; stagedLink.link.timeStamp = null; stagedLink.link.accent.override = null; stagedLink.link.accent.color.r = null; stagedLink.link.accent.color.g = null; stagedLink.link.accent.color.b = null; stagedLink.link.searchMatch = null; }; var mod = {}; mod.accent = { clear: function() { bookmarks.get().forEach(function(arrayItem, index) { arrayItem.items.forEach(function(arrayItem, index) { arrayItem.accent = { override: false, color: { r: null, g: null, b: null } }; }); }); }, rainbow: function() { var units = 360 / bookmarks.count(); var degree = 0; bookmarks.get().forEach(function(arrayItem, index) { arrayItem.items.forEach(function(arrayItem, index) { arrayItem.accent.override = true; var rgb = helper.convertColor.hsl.rgb({ h: degree, s: 100, l: 50 }); arrayItem.accent.color = { r: parseInt(rgb.r, 10), g: parseInt(rgb.g, 10), b: parseInt(rgb.b, 10) }; degree = degree + units; }); }); } }; mod.edit = { mode: { open: function() { helper.setObject({ object: state.get.current(), path: "edit", newValue: true }); }, close: function() { helper.setObject({ object: state.get.current(), path: "edit", newValue: false }); } }, item: { open: function() { helper.setObject({ object: state.get.current(), path: "link.edit", newValue: true }); }, close: function() { helper.setObject({ object: state.get.current(), path: "link.edit", newValue: false }); } }, group: { open: function() { helper.setObject({ object: state.get.current(), path: "group.edit", newValue: true }); }, close: function() { helper.setObject({ object: state.get.current(), path: "group.edit", newValue: false }); } } }; mod.add = { item: { open: function() { helper.setObject({ object: state.get.current(), path: "link.add", newValue: true }); }, close: function() { helper.setObject({ object: state.get.current(), path: "link.add", newValue: false }); } }, group: { open: function() { helper.setObject({ object: state.get.current(), path: "group.add", newValue: true }); }, close: function() { helper.setObject({ object: state.get.current(), path: "group.add", newValue: false }); } } }; var bind = {}; bind.sort = { update: { func: { group: function(event) { stagedGroup.position.origin = event.detail.origin.index; stagedGroup.position.destination = event.detail.destination.index; bookmarks.mod.move.group(stagedGroup); data.save(); groupAndItems(); }, item: function(event) { stagedLink.position.origin.group = Array.from(helper.getClosest(event.detail.origin.container, ".group").parentNode.children).indexOf(helper.getClosest(event.detail.origin.container, ".group")); stagedLink.position.origin.item = event.detail.origin.index; stagedLink.position.destination.group = Array.from(helper.getClosest(event.detail.destination.container, ".group").parentNode.children).indexOf(helper.getClosest(event.detail.destination.container, ".group")); stagedLink.position.destination.item = event.detail.destination.index bookmarks.mod.move.link(stagedLink); data.save(); groupAndItems(); } }, remove: { group: function() { helper.eA(".link-area").forEach(function(arrayItem, index) { sortable(arrayItem)[0].removeEventListener("sortupdate", bind.sort.update.func.group, false); }); }, item: function() { helper.eA(".group-body").forEach(function(arrayItem, index) { sortable(arrayItem)[0].removeEventListener("sortupdate", bind.sort.update.func.item, false); }); } } }, group: function() { sortable(".link-area", { items: ".group", handle: ".group-control-item-handle", orientation: "vertical", placeholder: helper.node("div|class:link-sort-placeholder"), forcePlaceholderSize: true }); bind.sort.update.remove.group(); helper.eA(".link-area").forEach(function(arrayItem, index) { sortable(arrayItem)[0].addEventListener("sortupdate", bind.sort.update.func.group, false, event); }); }, item: function() { sortable(".group-body", { items: ".link-item", handle: ".link-control-item-handle", acceptFrom: ".group-body", placeholder: helper.node("div|class:link-sort-placeholder"), forcePlaceholderSize: true }); bind.sort.update.remove.item(); helper.eA(".group-body").forEach(function(arrayItem, index) { sortable(arrayItem)[0].addEventListener("sortupdate", bind.sort.update.func.item, false, event); }); } }; var render = {}; render.move = { group: { up: function(copyStagedGroup) { stagedGroup.group = JSON.parse(JSON.stringify(copyStagedGroup.group)); stagedGroup.position = JSON.parse(JSON.stringify(copyStagedGroup.position)); stagedGroup.position.destination = stagedGroup.position.destination - 1; if (stagedGroup.position.destination < 0) { stagedGroup.position.destination = 0; }; bookmarks.mod.move.group(stagedGroup); data.save(); groupAndItems(); if (!state.get.current().search) { render.focus.group.previous.up(copyStagedGroup); }; }, down: function(copyStagedGroup) { stagedGroup.group = JSON.parse(JSON.stringify(copyStagedGroup.group)); stagedGroup.position = JSON.parse(JSON.stringify(copyStagedGroup.position)); stagedGroup.position.destination = stagedGroup.position.destination + 1; bookmarks.mod.move.group(stagedGroup); data.save(); groupAndItems(); if (!state.get.current().search) { render.focus.group.next.down(copyStagedGroup); }; } }, item: { left: function(copyStagedLink) { stagedLink.link = JSON.parse(JSON.stringify(copyStagedLink.link)); stagedLink.position = JSON.parse(JSON.stringify(copyStagedLink.position)); stagedLink.position.destination.item = stagedLink.position.destination.item - 1; if (stagedLink.position.destination.item < 0) { stagedLink.position.destination.item = 0; }; bookmarks.mod.move.link(JSON.parse(JSON.stringify(stagedLink))); data.save(); groupAndItems(); if (!state.get.current().search) { render.focus.item.previous.left(copyStagedLink); }; }, right: function(copyStagedLink) { stagedLink.link = JSON.parse(JSON.stringify(copyStagedLink.link)); stagedLink.position = JSON.parse(JSON.stringify(copyStagedLink.position)); stagedLink.position.destination.item = stagedLink.position.destination.item + 1; bookmarks.mod.move.link(JSON.parse(JSON.stringify(stagedLink))); data.save(); groupAndItems(); if (!state.get.current().search) { render.focus.item.next.right(copyStagedLink); }; } } }; render.clear = { group: function() { var link = helper.e(".link"); while (link.lastChild) { link.removeChild(link.lastChild); }; }, item: function() { var groupBody = helper.eA(".group-body"); groupBody.forEach(function(arrayItem, index) { while (arrayItem.lastChild) { arrayItem.removeChild(arrayItem.lastChild); }; }); } }; render.area = { width: function() { var html = helper.e("html"); html.style.setProperty("--link-area-width", state.get.current().link.area.width + "%"); } }; render.group = { area: function() { var copyStagedGroup = JSON.parse(JSON.stringify(stagedGroup)); var group = helper.node("div|class:group"); var groupHeader = helper.node("div|class:group-header"); var groupHeaderItemControl = helper.node("div|class:group-header-item group-header-item-control"); var groupHeaderItemName = helper.node("div|class:group-header-item group-header-item-name"); var groupHeaderItemOpenall = helper.node("div|class:group-header-item group-header-item-openall"); var groupBody = helper.node("div|class:group-body"); var groupName = helper.node("div|class:group-name"); var groupNameText = helper.makeNode({ tag: "h1", text: stagedGroup.group.name, attr: [{ key: "class", value: "group-name-text" }] }); groupName.appendChild(groupNameText); groupHeaderItemName.appendChild(groupName); var groupControl = helper.node("div|class:group-control form-group"); var groupControlItemUp = helper.node("button|class:button group-control-item group-control-item-up,tabindex:-1,title:Move this group up"); var groupControlItemUpIcon = helper.node("span|class:icon-arrow-up"); var groupControlItemUpBaselineAlignmentCharacter = helper.node("span:-|class:baseline-alignment-icon-character,aria-hidden:true"); groupControlItemUp.appendChild(groupControlItemUpBaselineAlignmentCharacter); groupControlItemUp.appendChild(groupControlItemUpIcon); groupControl.appendChild(groupControlItemUp); var groupControlItemHandle = helper.node("div|class:button group-control-item group-control-item-handle,tabindex:-1,title:Drag group to reorder"); var groupControlItemHandleIcon = helper.node("span|class:icon-reorder"); var groupControlItemHandleBaselineAlignmentCharacter = helper.node("span:-|class:baseline-alignment-icon-character,aria-hidden:true"); groupControlItemHandle.appendChild(groupControlItemHandleBaselineAlignmentCharacter); groupControlItemHandle.appendChild(groupControlItemHandleIcon); groupControl.appendChild(groupControlItemHandle); var groupControlItemDown = helper.node("button|class:button group-control-item group-control-item-down,tabindex:-1,title:Move this group down"); var groupControlItemDownIcon = helper.node("span|class:icon-arrow-down"); var groupControlItemDownBaselineAlignmentCharacter = helper.node("span:-|class:baseline-alignment-icon-character,aria-hidden:true"); groupControlItemDown.appendChild(groupControlItemDownBaselineAlignmentCharacter); groupControlItemDown.appendChild(groupControlItemDownIcon); groupControl.appendChild(groupControlItemDown); var groupControlItemEdit = helper.node("button|class:button group-control-item group-control-item-edit,tabindex:-1,title:Edit this group"); var groupControlItemEditIcon = helper.node("span|class:icon-edit"); var groupControlItemEditBaselineAlignmentCharacter = helper.node("span:-|class:baseline-alignment-icon-character,aria-hidden:true"); groupControlItemEdit.appendChild(groupControlItemEditBaselineAlignmentCharacter); groupControlItemEdit.appendChild(groupControlItemEditIcon); groupControl.appendChild(groupControlItemEdit); var groupControlItemRemove = helper.node("button|class:button group-control-item group-control-item-remove,tabindex:-1,title:Remove this group"); var groupControlItemRemoveIcon = helper.node("span|class:icon-close"); var groupControlItemRemoveBaselineAlignmentCharacter = helper.node("span:-|class:baseline-alignment-icon-character,aria-hidden:true"); groupControlItemRemove.appendChild(groupControlItemRemoveBaselineAlignmentCharacter); groupControlItemRemove.appendChild(groupControlItemRemoveIcon); groupControl.appendChild(groupControlItemRemove); if (state.get.current().search) { groupControlItemUp.disabled = true; helper.addClass(groupControlItemHandle, "disabled"); groupControlItemDown.disabled = true; }; groupHeaderItemControl.appendChild(groupControl); groupControlItemUp.addEventListener("click", function(event) { render.move.group.up(copyStagedGroup); }, false); groupControlItemDown.addEventListener("click", function() { render.move.group.down(copyStagedGroup); }, false); groupControlItemEdit.addEventListener("click", function() { edit.group.open(copyStagedGroup); }, false); groupControlItemRemove.addEventListener("click", function() { render.remove.group(copyStagedGroup); }, false); var groupOpenall = helper.node("div|class:group-openall form-group"); var groupOpenallItem = helper.node("button|class:button group-openall-item,tabindex:1,title:Open all Bookmarks in this Group"); var groupOpenallItemText = helper.node("span:Open all|class:button-text"); groupOpenallItem.appendChild(groupOpenallItemText); groupOpenall.appendChild(groupOpenallItem); if (state.get.current().group.openAll.style == "clear") { helper.addClass(groupOpenallItem, "button-link"); }; groupOpenallItem.addEventListener("click", function() { render.group.openall.all(copyStagedGroup); }); groupHeaderItemOpenall.appendChild(groupOpenall); groupHeader.appendChild(groupHeaderItemControl); if (state.get.current().group.name.show) { groupHeader.appendChild(groupHeaderItemName); }; if (state.get.current().group.openAll.show && stagedGroup.group.openAll && stagedGroup.group.items.length > 0) { groupHeader.appendChild(groupHeaderItemOpenall); }; group.appendChild(groupHeader); group.appendChild(groupBody); return group; }, form: function(override) { var options = { new: null, useStagedGroup: null }; if (override) { options = helper.applyOptions(options, override); }; var form = helper.node("form|class:group-form"); var fieldset = helper.node("fieldset"); // group position var groupFormPositionInputWrap = helper.node("div|class:form-wrap"); var groupFormPositionLabel = helper.node("label:Position|for:group-form-position"); var groupFormPositionSelect = helper.node("select|id:group-form-position,class:group-form-position,tabindex:1"); var groupFormRandomNameButtonWrap = helper.node("div|class:form-wrap"); var groupFormRandomNameButton = helper.node("button:Random Group name|class:button,type:button,tabindex:1"); // group name var groupFormNameInputWrap = helper.node("div|class:form-wrap"); var groupFormInputNameLabel = helper.node("label:Name|for:group-form-input-name"); var groupFormInputName = helper.node("input|type:text,class:group-form-input-name,id:group-form-input-name,placeholder:Example group,tabindex:1,autocomplete:off,autocorrect:off,autocapitalize:off,spellcheck:false"); // open all var groupFormOpenAllInputWrap = helper.node("div|class:form-wrap"); var groupFormInputOpenallLabel = helper.node("label|for:group-form-input-openall"); var groupFormInputOpenallLabelText = helper.node("span:Show Open all in this Group"); var groupFormInputOpenallLabelIcon = helper.node("span|class:label-icon"); var groupFormOpenAllInput = helper.node("input|type:checkbox,class:group-form-input-openall,id:group-form-input-openall,placeholder:Example group,tabindex:1,autocomplete:off,autocorrect:off,autocapitalize:off,spellcheck:false,checked"); var groupFormOpenAllInputHelper1 = helper.node("div|class:form-helper"); var groupFormOpenAllInputHelper1Item = helper.node("p:Override the global Group setting to show or hide the Open all button.|class:link-form-input-icon-helper form-helper-item"); var groupFormOpenAllInputHelper2 = helper.node("div|class:form-helper"); var groupFormOpenAllInputHelper2Item = helper.node("p:The Open all button will show when there is at least one Bookmark in this Group.|class:link-form-input-icon-helper form-helper-item"); groupFormPositionInputWrap.appendChild(groupFormPositionLabel); groupFormPositionInputWrap.appendChild(groupFormPositionSelect); groupFormRandomNameButtonWrap.appendChild(groupFormRandomNameButton); groupFormNameInputWrap.appendChild(groupFormInputNameLabel); groupFormNameInputWrap.appendChild(groupFormInputName); groupFormInputOpenallLabel.appendChild(groupFormInputOpenallLabelIcon); groupFormInputOpenallLabel.appendChild(groupFormInputOpenallLabelText); groupFormOpenAllInputHelper1.appendChild(groupFormOpenAllInputHelper1Item); groupFormOpenAllInputHelper2.appendChild(groupFormOpenAllInputHelper2Item); groupFormOpenAllInputWrap.appendChild(groupFormOpenAllInput); groupFormOpenAllInputWrap.appendChild(groupFormInputOpenallLabel); groupFormOpenAllInputWrap.appendChild(groupFormOpenAllInputHelper1); groupFormOpenAllInputWrap.appendChild(groupFormOpenAllInputHelper2); fieldset.appendChild(groupFormNameInputWrap); fieldset.appendChild(groupFormRandomNameButtonWrap); fieldset.appendChild(helper.node("hr")); fieldset.appendChild(groupFormPositionInputWrap); fieldset.appendChild(helper.node("hr")); fieldset.appendChild(groupFormOpenAllInputWrap); form.appendChild(fieldset); var makeGroupOptions = function() { var optionCount = bookmarks.get().length; if (options.new) { optionCount = optionCount + 1; }; for (var i = 1; i <= optionCount; i++) { groupFormPositionSelect.appendChild(helper.node("option:" + helper.ordinalNumber(i))); }; }; var populateForm = function() { groupFormPositionSelect.selectedIndex = stagedGroup.position.origin; groupFormInputName.value = stagedGroup.group.name; groupFormOpenAllInput.checked = stagedGroup.group.openAll; }; var setLastPosition = function() { groupFormPositionSelect.selectedIndex = groupFormPositionSelect.length - 1; stagedGroup.position.destination = groupFormPositionSelect.selectedIndex; }; makeGroupOptions(); if (options.useStagedGroup) { populateForm(); }; if (options.new) { setLastPosition(); }; form.addEventListener("keydown", function(event) { if (event.keyCode == 13) { event.preventDefault(); return false; }; }, false); groupFormPositionSelect.addEventListener("change", function(event) { stagedGroup.position.destination = this.selectedIndex; }, false); groupFormInputName.addEventListener("input", function(event) { stagedGroup.group.name = this.value; }, false); groupFormRandomNameButton.addEventListener("click", function(event) { var randomName = helper.randomString({ mix: true }); stagedGroup.group.name = randomName; groupFormInputName.value = randomName; }, false); groupFormOpenAllInput.addEventListener("change", function(event) { stagedGroup.group.openAll = this.checked; }, false); return form; }, name: { size: function() { var html = helper.e("html"); html.style.setProperty("--group-name-size", state.get.current().group.name.size + "em"); } }, openall: { all: function(copyStagedGroup) { if (state.get.current().link.item.newTab) { copyStagedGroup.group.items.forEach(function(arrayItem, index) { chrome.tabs.create({ url: arrayItem.url }); }); } else { var first = copyStagedGroup.group.items.shift(); copyStagedGroup.group.items.forEach(function(arrayItem, index) { chrome.tabs.create({ url: arrayItem.url }); }); window.location.href = first.url; }; }, size: function() { var html = helper.e("html"); html.style.setProperty("--group-openall-size", state.get.current().group.openAll.size + "em"); } }, border: function() { var html = helper.e("html"); html.style.setProperty("--group-border", state.get.current().group.border); }, tabindex: function() { var allGroupControlItem = helper.eA(".group-control-item"); if (state.get.current().edit) { allGroupControlItem.forEach(function(arrayItem, index) { arrayItem.tabIndex = 1; }); } else { allGroupControlItem.forEach(function(arrayItem, index) { arrayItem.tabIndex = -1; }); }; } }; render.item = { color: { custom: function() { helper.e("html").style.setProperty("--link-item-color-custom", state.get.current().link.item.color.rgb.r + ", " + state.get.current().link.item.color.rgb.g + ", " + state.get.current().link.item.color.rgb.b); } }, link: function() { var linkItemOptions = { tag: "div", attr: [{ key: "class", value: "link-item" }] }; if (stagedLink.link.accent.override) { linkItemOptions.attr.push({ key: "style", value: "--theme-accent: " + stagedLink.link.accent.color.r + ", " + stagedLink.link.accent.color.g + ", " + stagedLink.link.accent.color.b }); if (invert(stagedLink.link.accent.color, true) == "#000000") { linkItemOptions.attr[0].value = linkItemOptions.attr[0].value + " link-text-dark"; } else if (invert(stagedLink.link.accent.color, true) == "#ffffff") { linkItemOptions.attr[0].value = linkItemOptions.attr[0].value + " link-text-light"; }; } else { if (invert(state.get.current().theme.accent.rgb, true) == "#000000") { linkItemOptions.attr[0].value = linkItemOptions.attr[0].value + " link-text-dark"; } else if (invert(state.get.current().theme.accent.rgb, true) == "#ffffff") { linkItemOptions.attr[0].value = linkItemOptions.attr[0].value + " link-text-light"; }; }; var linkItem = helper.makeNode(linkItemOptions); var linkPanelFrontOptions = { tag: "a", attr: [{ key: "class", value: "link-panel-front" }, { key: "href", value: stagedLink.link.url }, { key: "tabindex", value: 1 }] }; if (state.get.current().link.item.newTab) { linkPanelFrontOptions.attr.push({ key: "target", value: "_blank" }); }; var linkPanelFront = helper.makeNode(linkPanelFrontOptions); var linkPanelBack = helper.node("div|class:link-panel-back"); var linkDisplay = helper.node("div|class:link-display"); var linkDisplayLetcon = helper.node("div|class:link-display-letcon"); var linkDisplayLetter = null; var linkDisplayIcon = null; if (stagedLink.link.display == "letter") { var letterText = stagedLink.link.letter; if (letterText == null) { letterText = ""; }; linkDisplayLetter = helper.node("p:" + letterText + "|class:link-display-letter"); } else if (stagedLink.link.display == "icon" && stagedLink.link.icon.prefix != null && stagedLink.link.icon.name != null) { linkDisplayIcon = helper.node("div|class:link-display-icon " + stagedLink.link.icon.prefix + " fa-" + stagedLink.link.icon.name); }; var nameText = stagedLink.link.name; if (nameText == null) { nameText = ""; }; var linkDisplayName = helper.node("p:" + nameText + "|class:link-display-name"); var linkUrl = helper.node("div|class:link-url"); var url = ""; if (stagedLink.link.url != null) { url = stagedLink.link.url.replace(/^https?\:\/\//i, "").replace(/\/$/, ""); }; var linkUrlText = helper.makeNode({ tag: "p", text: url, attr: [{ key: "class", value: "link-url-text" }, { key: "title", value: url }] }); var linkControl = helper.node("div|class:link-control"); var linkHandle = helper.node("div|class:button button-small link-control-item link-control-item-handle,tabindex:-1,title:Drag bookmark to reorder"); var linkHandleIcon = helper.node("span|class:button-icon icon-reorder"); var linkEdit = helper.node("button|class:button button-small link-control-item link-control-item-edit,tabindex:-1,title:Edit this bookmark"); var linkEditIcon = helper.node("span|class:button-icon icon-edit"); var linkLeft = helper.node("button|class:button button-small link-control-item link-control-item-left,tabindex:-1,title:Move this bookmark left"); var linkLeftIcon = helper.node("span|class:button-icon icon-arrow-left"); var linkRight = helper.node("button|class:button button-small link-control-item link-control-item-right,tabindex:-1,title:Move this bookmark right"); var linkRightIcon = helper.node("span|class:button-icon icon-arrow-right"); var linkRemove = helper.node("button|class:button button-small link-control-item link-control-item-remove,tabindex:-1,title:Remove this bookmark"); var linkRemoveIcon = helper.node("span|class:button-icon icon-close"); if (stagedLink.link.display == "letter") { linkDisplayLetcon.appendChild(linkDisplayLetter); } else if (stagedLink.link.display == "icon" && stagedLink.link.icon.prefix != null && stagedLink.link.icon.name != null) { linkDisplayLetcon.appendChild(linkDisplayIcon); }; linkDisplay.appendChild(linkDisplayLetcon); linkDisplay.appendChild(linkDisplayName); linkPanelFront.appendChild(linkDisplay); linkLeft.appendChild(linkLeftIcon); linkControl.appendChild(linkLeft); linkHandle.appendChild(linkHandleIcon); linkControl.appendChild(linkHandle); linkRight.appendChild(linkRightIcon); linkControl.appendChild(linkRight); linkEdit.appendChild(linkEditIcon); linkControl.appendChild(linkEdit); linkRemove.appendChild(linkRemoveIcon); linkControl.appendChild(linkRemove); linkUrl.appendChild(linkUrlText); linkPanelBack.appendChild(linkUrl); linkPanelBack.appendChild(linkControl); linkItem.appendChild(linkPanelFront); linkItem.appendChild(linkPanelBack); if (state.get.current().search) { linkLeft.disabled = true; helper.addClass(linkHandle, "disabled"); linkRight.disabled = true; }; var copyStagedLink = JSON.parse(JSON.stringify(stagedLink)); linkLeft.addEventListener("click", function() { render.move.item.left(copyStagedLink); }, false); linkRight.addEventListener("click", function() { render.move.item.right(copyStagedLink); }, false); linkEdit.addEventListener("click", function() { edit.item.open(copyStagedLink); }, false); linkRemove.addEventListener("click", function() { render.remove.item(copyStagedLink); }, false); return linkItem; }, form: function(override) { var options = { useStagedLink: null }; if (override) { options = helper.applyOptions(options, override); }; var form = helper.node("form|class:link-form"); var fieldset = helper.node("fieldset"); // group existing var groupExistingRadioWrap = helper.node("div|class:form-wrap"); var groupExistingRadio = helper.node("input|class:link-form-input-group-existing,id:link-form-input-group-existing,type:radio,name:link-form-input-group,tabindex:1,checked,value:existing"); var groupExistingLable = helper.node("label|for:link-form-input-group-existing"); var groupExistingLableText = helper.node("span:Existing Group"); var groupExistingLableIcon = helper.node("span|class:label-icon"); var groupExistingFormIndentWrap = helper.node("div|class:form-wrap"); var groupExistingFormIndent = helper.node("div|class:form-indent"); var groupExistingGroupInputWrap = helper.node("div|class:form-wrap"); var groupExistingGroup = helper.node("select|id:link-form-select-group,class:link-form-select-group,tabindex:1"); var groupExistingPositionInputWrap = helper.node("div|class:form-wrap"); var groupExistingPositionLabel = helper.node("label:Position|for:link-form-position"); var groupExistingPosition = helper.node("select|id:link-form-position,class:link-form-position,tabindex:1"); // group new var groupNewRadioWrap = helper.node("div|class:form-wrap"); var groupNewRadio = helper.node("input|class:link-form-input-group-new,id:link-form-input-group-new,type:radio,name:link-form-input-group,tabindex:1,value:new"); var groupNewLable = helper.node("label|for:link-form-input-group-new"); var groupNewLableLableText = helper.node("span:New Group"); var groupNewLableLableIcon = helper.node("span|class:label-icon"); var groupNewFormIndentWrap = helper.node("div|class:form-wrap"); var groupNewFormIndent = helper.node("div|class:form-indent"); var groupNewInputWrap = helper.node("div|class:form-wrap"); var groupNewInput = helper.node("input|type:text,class:link-form-input-new-group,id:link-form-input-new-group,placeholder:Example group,tabindex:1,autocomplete:off,autocorrect:off,autocapitalize:off,spellcheck:false,disabled"); var groupNewRandomNameButtonWrap = helper.node("div|class:form-wrap"); var groupNewRandomNameButton = helper.node("button:Random Group name|class:button,type:button,tabindex:1,disabled"); // letter var displayLetterRadioWrap = helper.node("div|class:form-wrap"); var displayLetterRadio = helper.node("input|class:link-form-input-display-letter,id:link-form-input-display-letter,type:radio,name:link-form-input-display,tabindex:1,checked,value:letter"); var displayLetterLable = helper.node("label|for:link-form-input-display-letter"); var displayLetterLableText = helper.node("span:Letters"); var displayLetterLableIcon = helper.node("span|class:label-icon"); var displayLetterFormIndentWrap = helper.node("div|class:form-wrap"); var displayLetterFormIndent = helper.node("div|class:form-indent"); var displayLetterInputWrap = helper.node("div|class:form-wrap"); var displayLetterInput = helper.node("input|type:text,class:link-form-input-letter,id:link-form-input-letter,placeholder:E,tabindex:1,autocomplete:off,autocorrect:off,autocapitalize:off,spellcheck:false"); // icon var displayIconRadiotWrap = helper.node("div|class:form-wrap"); var displayIconRadio = helper.node("input|class:link-form-input-display-icon,id:link-form-input-display-icon,type:radio,name:link-form-input-display,tabindex:1,value:icon"); var displayIconLable = helper.node("label|for:link-form-input-display-icon"); var displayIconLableText = helper.node("span:Icon"); var displayIconLableIcon = helper.node("span|class:label-icon"); var displayIconFormIndentWrap = helper.node("div|class:form-wrap"); var displayIconFormIndent = helper.node("div|class:form-indent"); var displayIconInputWrap = helper.node("div|class:form-wrap"); var displayIconFormGroup = helper.node("div|class:form-group form-group-block auto-suggest-input"); var displayIconInput = helper.node("input|type:text,class:form-group-item-grow link-form-input-icon auto-suggest-input,id:link-form-input-icon,placeholder:Search for Brands or Icons,tabindex:1,autocomplete:off,autocorrect:off,autocapitalize:off,spellcheck:false,disabled"); var displayIconFormGroupText = helper.node("div|class:form-group-text link-form-text-icon disabled,tabindex:-1"); var displayIconFormGroupClear = helper.node("button|class:link-form-icon-clear button,type:button,tabindex:1,disabled"); var displayIconFormGroupClearIcon = helper.node("span|class:icon-close"); var displayIconHelper = helper.node("div|class:form-helper"); var displayIconHelperItem = helper.node("p:Refer to the \"Free\" and \"Brand\" icons from FontAwesome for full set of icons supported.|class:link-form-input-icon-helper form-helper-item disabled"); // name var nameInputWrap = helper.node("div|class:form-wrap"); var nameLabel = helper.node("label:Name|for:link-form-input-name"); var nameInput = helper.node("input|type:text,class:link-form-input-name,id:link-form-input-name,placeholder:Example,tabindex:1,autocomplete:off,autocorrect:off,autocapitalize:off,spellcheck:false"); // url var urlInputWrap = helper.node("div|class:form-wrap"); var urlLabel = helper.node("label:URL|for:link-form-input-url"); var urlInput = helper.node("input|type:text,class:link-form-input-url,id:link-form-input-url,placeholder:https://www.example.com/,tabindex:1,autocomplete:off,autocorrect:off,autocapitalize:off,spellcheck:false"); var urlInputHelper = helper.node("div|class:form-helper"); var urlInputHelperItem = helper.makeNode({ tag: "p", text: "Be sure to use the full URL and include \"http://\" or \"https://\".", attr: [{ key: "class", value: "form-helper-item" }] }); // accent var accentLabelWrap = helper.node("div|class:form-wrap"); var accentLabel = helper.node("label:Accent colour"); var accentGlobalRadioWrap = helper.node("div|class:form-wrap"); var accentGlobalRadio = helper.node("input|class:link-form-input-accent-global,id:link-form-input-accent-global,type:radio,name:link-form-input-accent,tabindex:1,checked,value:global"); var accentGlobalLabel = helper.node("label|for:link-form-input-accent-global"); var accentGlobalLabelText = helper.node("span:Global"); var accentGlobalLabelIcon = helper.node("span|class:label-icon"); var accentCustomInputWrap = helper.node("div|class:form-wrap"); var accentCustomRadio = helper.node("input|class:link-form-input-accent-custom,id:link-form-input-accent-custom,type:radio,name:link-form-input-accent,tabindex:1,value:custom"); var accentCustomLabel = helper.node("label|for:link-form-input-accent-custom"); var accentCustomLabelText = helper.node("span:Custom"); var accentCustomLabelIcon = helper.node("span|class:label-icon"); var accentColorFormIndentWrap = helper.node("div|class:form-wrap"); var accentColorFormIndent = helper.node("div|class:form-indent"); var accentColorInputWrap = helper.node("div|class:form-wrap"); var accentColorFormGroup = helper.node("div|class:form-group form-group-block"); var accentColorPicker = helper.node("input|id:link-form-input-accent-picker,class:form-group-item-half link-form-input-accent-picker,type:color,value:#000000,tabindex:1,disabled"); var accentColorHex = helper.node("input|id:link-form-input-accent-hex,class:form-group-item-half link-form-input-accent-hex,type:text,placeholder:Hex code,value:#000000,tabindex:1,maxlength:7,disabled"); var accentColorInputHelper = helper.node("div|class:form-helper"); var accentColorInputHelperItem = helper.node("p:Use this colour to override the global accent colour.|class:link-form-input-accent-helper form-helper-item"); groupExistingRadioWrap.appendChild(groupExistingRadio); groupExistingLable.appendChild(groupExistingLableIcon); groupExistingLable.appendChild(groupExistingLableText); groupExistingRadioWrap.appendChild(groupExistingLable); groupExistingGroupInputWrap.appendChild(groupExistingGroup); groupExistingPositionInputWrap.appendChild(groupExistingPositionLabel); groupExistingPositionInputWrap.appendChild(groupExistingPosition); groupExistingFormIndent.appendChild(groupExistingGroupInputWrap); groupExistingFormIndent.appendChild(groupExistingPositionInputWrap); groupExistingFormIndentWrap.appendChild(groupExistingFormIndent); fieldset.appendChild(groupExistingRadioWrap); fieldset.appendChild(groupExistingFormIndentWrap); groupNewRadioWrap.appendChild(groupNewRadio); groupNewLable.appendChild(groupNewLableLableIcon); groupNewLable.appendChild(groupNewLableLableText); groupNewRadioWrap.appendChild(groupNewLable); groupNewInputWrap.appendChild(groupNewInput); groupNewRandomNameButtonWrap.appendChild(groupNewRandomNameButton); groupNewFormIndent.appendChild(groupNewInputWrap); groupNewFormIndent.appendChild(groupNewRandomNameButtonWrap); groupNewFormIndentWrap.appendChild(groupNewFormIndent); fieldset.appendChild(groupNewRadioWrap); fieldset.appendChild(groupNewFormIndentWrap); fieldset.appendChild(helper.node("hr")); displayLetterRadioWrap.appendChild(displayLetterRadio); displayLetterLable.appendChild(displayLetterLableIcon); displayLetterLable.appendChild(displayLetterLableText); displayLetterRadioWrap.appendChild(displayLetterLable); fieldset.appendChild(displayLetterRadioWrap); displayLetterInputWrap.appendChild(displayLetterInput); displayLetterFormIndent.appendChild(displayLetterInputWrap); displayLetterFormIndentWrap.appendChild(displayLetterFormIndent); fieldset.appendChild(displayLetterFormIndentWrap); displayIconRadiotWrap.appendChild(displayIconRadio); displayIconLable.appendChild(displayIconLableIcon); displayIconLable.appendChild(displayIconLableText); displayIconRadiotWrap.appendChild(displayIconLable); fieldset.appendChild(displayIconRadiotWrap); displayIconFormGroupClear.appendChild(displayIconFormGroupClearIcon); displayIconFormGroup.appendChild(displayIconInput); displayIconFormGroup.appendChild(displayIconFormGroupText); displayIconFormGroup.appendChild(displayIconFormGroupClear); displayIconInputWrap.appendChild(displayIconFormGroup); displayIconFormIndent.appendChild(displayIconInputWrap); displayIconHelper.appendChild(displayIconHelperItem); displayIconFormIndent.appendChild(displayIconHelper); displayIconFormIndentWrap.appendChild(displayIconFormIndent); fieldset.appendChild(displayIconFormIndentWrap); fieldset.appendChild(helper.node("hr")); nameInputWrap.appendChild(nameLabel); nameInputWrap.appendChild(nameInput); fieldset.appendChild(nameInputWrap); urlInputWrap.appendChild(urlLabel); urlInputWrap.appendChild(urlInput); fieldset.appendChild(urlInputWrap); urlInputHelper.appendChild(urlInputHelperItem); fieldset.appendChild(urlInputHelper); fieldset.appendChild(helper.node("hr")); accentLabelWrap.appendChild(accentLabel); fieldset.appendChild(accentLabelWrap); accentGlobalRadioWrap.appendChild(accentGlobalRadio); accentGlobalLabel.appendChild(accentGlobalLabelIcon); accentGlobalLabel.appendChild(accentGlobalLabelText); accentGlobalRadioWrap.appendChild(accentGlobalLabel); fieldset.appendChild(accentGlobalRadioWrap); accentCustomInputWrap.appendChild(accentCustomRadio); accentCustomLabel.appendChild(accentCustomLabelIcon); accentCustomLabel.appendChild(accentCustomLabelText); accentCustomInputWrap.appendChild(accentCustomLabel); fieldset.appendChild(accentCustomInputWrap); accentColorFormGroup.appendChild(accentColorPicker); accentColorFormGroup.appendChild(accentColorHex); accentColorInputWrap.appendChild(accentColorFormGroup); accentColorFormIndent.appendChild(accentColorInputWrap); accentColorInputHelper.appendChild(accentColorInputHelperItem); accentColorFormIndent.appendChild(accentColorInputHelper); accentColorFormIndentWrap.appendChild(accentColorFormIndent); fieldset.appendChild(accentColorFormIndentWrap); form.appendChild(fieldset); var makeGroupOptions = function() { if (bookmarks.get().length > 0) { bookmarks.get().forEach(function(arrayItem, index) { var option = helper.makeNode({ tag: "option", text: arrayItem.name, attr: [{ key: "value", value: arrayItem.name }] }); groupExistingGroup.appendChild(option); }); } else { groupNewRadio.checked = true; groupExistingRadio.setAttribute("disabled", ""); groupExistingGroup.setAttribute("disabled", ""); helper.addClass(groupExistingPositionLabel, "disabled"); groupExistingPosition.setAttribute("disabled", ""); groupNewInput.removeAttribute("disabled"); groupNewRandomNameButton.removeAttribute("disabled"); stagedLink.position.group.new = true; }; }; var makePostionOptions = function() { if (bookmarks.get().length > 0) { while (groupExistingPosition.lastChild) { groupExistingPosition.removeChild(groupExistingPosition.lastChild); }; var optionCount = 0; if (bookmarks.get().length > 0) { if (options.useStagedLink && stagedLink.position.origin.group == stagedLink.position.destination.group) { optionCount = optionCount + bookmarks.get()[stagedLink.position.origin.group].items.length; } else { optionCount = optionCount + bookmarks.get()[stagedLink.position.destination.group].items.length + 1; }; } else { optionCount = 1; }; for (var i = 1; i <= optionCount; i++) { groupExistingPosition.appendChild(helper.node("option:" + helper.ordinalNumber(i))); if (optionCount == i) { groupExistingPosition.selectedIndex = i - 1; } }; }; }; var populateForm = function() { groupExistingGroup.selectedIndex = stagedLink.position.origin.group; groupExistingPosition.selectedIndex = stagedLink.position.origin.item; if (stagedLink.link.display == "letter") { displayLetterInput.removeAttribute("disabled"); displayIconInput.setAttribute("disabled", ""); helper.addClass(displayIconFormGroupText, "disabled"); displayIconInput.setAttribute("disabled", ""); helper.addClass(displayIconHelper, "disabled"); displayIconFormGroupClear.setAttribute("disabled", ""); displayIconFormGroupText.tabIndex = -1; } else if (stagedLink.link.display == "icon") { displayLetterInput.setAttribute("disabled", ""); displayIconInput.removeAttribute("disabled"); helper.removeClass(displayIconFormGroupText, "disabled"); displayIconInput.removeAttribute("disabled"); helper.removeClass(displayIconHelper, "disabled"); displayIconFormGroupClear.removeAttribute("disabled"); displayIconRadio.checked = true; displayIconFormGroupText.tabIndex = 1; }; if (stagedLink.link.icon.name != null && stagedLink.link.icon.prefix != null && stagedLink.link.icon.label != null) { displayIconFormGroupText.appendChild(helper.node("span|class:link-form-icon " + stagedLink.link.icon.prefix + " fa-" + stagedLink.link.icon.name)); }; displayLetterInput.value = stagedLink.link.letter; displayIconInput.value = stagedLink.link.icon.label; nameInput.value = stagedLink.link.name; urlInput.value = stagedLink.link.url; if (stagedLink.link.accent.override) { accentGlobalRadio.checked = false; accentCustomRadio.checked = true; accentColorPicker.removeAttribute("disabled"); accentColorHex.removeAttribute("disabled"); helper.removeClass(form.querySelector(".link-form-input-accent-helper"), "disabled"); } else { accentGlobalRadio.checked = true; accentCustomRadio.checked = false; accentColorPicker.setAttribute("disabled", ""); accentColorHex.setAttribute("disabled", ""); helper.addClass(form.querySelector(".link-form-input-accent-helper"), "disabled"); }; if (stagedLink.link.accent.color.r != null && stagedLink.link.accent.color.g != null && stagedLink.link.accent.color.b != null) { accentColorPicker.value = helper.convertColor.rgb.hex(stagedLink.link.accent.color); accentColorHex.value = helper.convertColor.rgb.hex(stagedLink.link.accent.color); }; }; makeGroupOptions(); makePostionOptions(); if (options.useStagedLink) { populateForm(); }; form.addEventListener("keydown", function(event) { if (event.keyCode == 13) { event.preventDefault(); return false; }; }, false); groupExistingRadio.addEventListener("change", function(event) { stagedLink.position.destination.group = groupExistingGroup.selectedIndex; stagedLink.position.group.new = false; groupExistingGroup.removeAttribute("disabled"); groupExistingPosition.removeAttribute("disabled"); helper.removeClass(groupExistingPositionLabel, "disabled"); groupNewInput.setAttribute("disabled", ""); groupNewRandomNameButton.setAttribute("disabled", ""); }, false); groupExistingGroup.addEventListener("change", function(event) { stagedLink.position.destination.group = this.selectedIndex; makePostionOptions(); stagedLink.position.destination.item = groupExistingPosition.selectedIndex; }, false); groupExistingPosition.addEventListener("change", function(event) { stagedLink.position.destination.item = this.selectedIndex; }, false); groupNewRadio.addEventListener("change", function(event) { stagedLink.position.destination.group = bookmarks.get().length; stagedLink.position.group.new = true; groupExistingGroup.setAttribute("disabled", ""); groupExistingPosition.setAttribute("disabled", ""); helper.addClass(groupExistingPositionLabel, "disabled"); groupNewInput.removeAttribute("disabled"); groupNewRandomNameButton.removeAttribute("disabled"); }, false); groupNewInput.addEventListener("input", function(event) { stagedLink.position.group.name = this.value; }, false); groupNewRandomNameButton.addEventListener("click", function(event) { var randomName = helper.randomString({ mix: true }); stagedLink.position.group.name = randomName; groupNewInput.value = randomName; }, false); displayLetterRadio.addEventListener("change", function(event) { stagedLink.link.display = this.value; }, false); displayIconRadio.addEventListener("change", function(event) { stagedLink.link.display = this.value; }, false); displayLetterInput.addEventListener("input", function(event) { stagedLink.link.letter = this.value; }, false); nameInput.addEventListener("input", function(event) { stagedLink.link.name = this.value; }, false); urlInput.addEventListener("input", function(event) { stagedLink.link.url = this.value; }, false); accentGlobalRadio.addEventListener("change", function() { stagedLink.link.accent.override = false; accentColorPicker.setAttribute("disabled", ""); accentColorHex.setAttribute("disabled", ""); helper.addClass(accentColorInputHelper, "disabled"); }, false); accentCustomRadio.addEventListener("change", function() { stagedLink.link.accent.override = true; stagedLink.link.accent.color = helper.convertColor.hex.rgb(accentColorPicker.value); accentColorPicker.removeAttribute("disabled"); accentColorHex.removeAttribute("disabled"); helper.removeClass(accentColorInputHelper, "disabled"); }, false); accentColorPicker.addEventListener("change", function() { if (helper.isHexNumber(this.value)) { stagedLink.link.accent.color = helper.convertColor.hex.rgb(this.value); accentColorHex.value = this.value; }; }, false); accentColorHex.addEventListener("input", function() { if (helper.isHexNumber(this.value)) { stagedLink.link.accent.color = helper.convertColor.hex.rgb(this.value); accentColorPicker.value = this.value; }; }, false); displayIconFormGroupClear.addEventListener("click", function(event) { stagedLink.link.icon.name = null; stagedLink.link.icon.prefix = null; stagedLink.link.icon.label = null; var existingIcon = helper.e(".link-form-icon"); if (existingIcon) { existingIcon.remove(); }; displayIconInput.value = ""; }, false); displayLetterRadio.addEventListener("change", function(event) { displayLetterInput.removeAttribute("disabled"); displayIconInput.setAttribute("disabled", ""); helper.addClass(displayIconFormGroupText, "disabled"); helper.addClass(displayIconHelper, "disabled"); displayIconFormGroupClear.setAttribute("disabled", ""); displayIconFormGroupText.tabIndex = -1; }, false); displayIconRadio.addEventListener("change", function(event) { displayLetterInput.setAttribute("disabled", ""); displayIconInput.removeAttribute("disabled"); helper.removeClass(displayIconFormGroupText, "disabled"); helper.removeClass(displayIconHelper, "disabled"); displayIconFormGroupClear.removeAttribute("disabled"); displayIconFormGroupText.tabIndex = 1; }, false); autoSuggest.bind.input({ input: displayIconInput, type: "fontawesomeIcon", postFocus: displayIconFormGroupText }); return form; }, display: { letter: function() { var html = helper.e("html"); html.style.setProperty("--link-item-display-letter-size", state.get.current().link.item.display.letcon.letter.size + "em"); }, icon: function() { var html = helper.e("html"); html.style.setProperty("--link-item-display-icon-size", state.get.current().link.item.display.letcon.icon.size + "em"); } }, name: function() { var html = helper.e("html"); html.style.setProperty("--link-item-display-name-size", state.get.current().link.item.display.name.size + "em"); }, size: function() { var html = helper.e("html"); html.style.setProperty("--link-item-size", state.get.current().link.item.size + "em"); }, tabindex: function() { var allLinkControlItem = helper.eA(".link-control-item"); if (state.get.current().edit) { allLinkControlItem.forEach(function(arrayItem, index) { arrayItem.tabIndex = 1; }); } else { allLinkControlItem.forEach(function(arrayItem, index) { arrayItem.tabIndex = -1; }); }; }, border: function() { var html = helper.e("html"); html.style.setProperty("--link-item-border", state.get.current().link.item.border); }, rotate: function() { var html = helper.e("html"); html.style.setProperty("--link-item-display-rotate", state.get.current().link.item.display.rotate + "deg"); }, translate: { x: function() { var html = helper.e("html"); html.style.setProperty("--link-item-display-translate-x", state.get.current().link.item.display.translate.x + "em"); }, y: function() { var html = helper.e("html"); html.style.setProperty("--link-item-display-translate-y", state.get.current().link.item.display.translate.y + "em"); } }, gutter: function() { var html = helper.e("html"); html.style.setProperty("--link-item-display-gutter", state.get.current().link.item.display.gutter); } }; render.all = function() { var linkSection = helper.e(".link"); var linkArea = helper.node("div|class:link-area"); linkSection.appendChild(linkArea); var make = { bookmarks: function() { bookmarks.get().forEach(function(arrayItem, index) { stagedGroup.position.origin = index; stagedGroup.position.destination = index; stagedGroup.position.origin = index; stagedGroup.group = JSON.parse(JSON.stringify(arrayItem)); stagedLink.position.origin.group = index; stagedLink.position.destination.group = index; group = render.group.area(); if (arrayItem.items.length > 0) { arrayItem.items.forEach(function(arrayItem, index) { stagedLink.link = JSON.parse(JSON.stringify(arrayItem)); stagedLink.position.origin.item = index; stagedLink.position.destination.item = index; stagedLink.position.group.new = null; stagedLink.position.group.name = null; if (state.get.current().search) { if (stagedLink.link.searchMatch) { group.querySelector(".group-body").appendChild(render.item.link()); }; } else { group.querySelector(".group-body").appendChild(render.item.link()); }; }); } else { group.querySelector(".group-body").appendChild(render.empty.item(stagedGroup.position.destination)); }; if (state.get.current().search) { if (search.mod.searching.count.group(index) > 0) { linkArea.appendChild(group); }; } else { linkArea.appendChild(group); }; stagedGroup.reset(); stagedLink.reset(); }); }, empty: { search: function() { linkArea.appendChild(render.empty.search()); }, bookmarks: function() { linkArea.appendChild(render.empty.group()); } } }; // if bookmarks exist if (bookmarks.get().length > 0) { // if searching if (state.get.current().search) { search.mod.searching.get(); // if matching results found if (search.mod.searching.count.all() > 0) { make.bookmarks(); } else { make.empty.search(); }; } else { search.mod.searching.clear(); make.bookmarks(); }; } else { make.empty.bookmarks(); }; }; render.empty = { group: function() { var group = helper.node("div|class:group"); var groupBody = helper.node("div|class:group-body"); var linkEmpty = helper.node("div|class:link-empty link-item"); var para = helper.node("p:No Groups or Bookmarks|class:small muted"); var addButton = helper.node("button:Add a Bookmark|class:button button-small,type:button,tabindex:1"); linkEmpty.appendChild(para); linkEmpty.appendChild(addButton); groupBody.appendChild(linkEmpty); group.appendChild(groupBody); addButton.addEventListener("click", function(event) { link.add.item.open(); }, false); return group; }, item: function(groupIndex) { var linkEmpty = helper.node("div|class:link-empty link-item"); var para = helper.node("p:Empty Group|class:small muted"); var addButton = helper.node("button:Add a Bookmark|class:button button-small,type:button,tabindex:1"); linkEmpty.appendChild(para); linkEmpty.appendChild(addButton); addButton.addEventListener("click", function(event) { link.add.item.open(); link.add.item.selectGroup(groupIndex); }, false); return linkEmpty; }, search: function() { var group = helper.node("div|class:group"); var groupBody = helper.node("div|class:group-body"); var linkEmpty = helper.node("div|class:link-empty link-item"); var para1 = helper.makeNode({ tag: "p", text: "No bookmarks matching \"" + helper.e(".search-input").value + "\" found" }); var para2 = helper.node("p:\"Enter\" to Search " + state.get.current().header.search.engine[state.get.current().header.search.engine.selected].name + ".|class:small muted"); linkEmpty.appendChild(para1); linkEmpty.appendChild(para2); groupBody.appendChild(linkEmpty); group.appendChild(groupBody); return group; } }; render.focus = { group: { previous: { remove: function(copyStagedGroup) { var allGroup = helper.eA(".group"); var target = copyStagedGroup.position.origin - 1; if (target < 0) { target = 0; }; if (allGroup.length > 0) { if (allGroup[target].querySelector(".group-control-item-remove")) { allGroup[target].querySelector(".group-control-item-remove").focus(); }; } else { helper.e("body").focus(); }; }, up: function(copyStagedGroup) { var allGroup = helper.eA(".group"); var target = copyStagedGroup.position.origin - 1; if (target < 0) { target = 0; }; if (allGroup.length > 0) { if (allGroup[target].querySelector(".group-control-item-up")) { allGroup[target].querySelector(".group-control-item-up").focus(); }; } else { helper.e("body").focus(); }; } }, next: { down: function(copyStagedGroup) { var allGroup = helper.eA(".group"); var target = copyStagedGroup.position.origin + 1; if (target > allGroup.length - 1) { target = allGroup.length - 1; }; if (allGroup.length > 0) { if (allGroup[target].querySelector(".group-control-item-down")) { allGroup[target].querySelector(".group-control-item-down").focus(); }; } else { helper.e("body").focus(); }; } }, current: { edit: function(copyStagedGroup) { var allGroup = helper.eA(".group"); var target = copyStagedGroup.position.destination; if (allGroup.length > 0) { if (allGroup[target].querySelector(".group-control-item-edit")) { allGroup[target].querySelector(".group-control-item-edit").focus(); }; } else { helper.e("body").focus(); }; } } }, item: { previous: { remove: function(copyStagedLink) { var allGroup = helper.eA(".group"); var allLinkItem = allGroup[copyStagedLink.position.origin.group].querySelectorAll(".link-item"); var target = copyStagedLink.position.origin.item - 1; if (target < 0) { target = 0; }; if (allLinkItem.length > 0) { if (allLinkItem[target].querySelector(".link-control-item-remove")) { allLinkItem[target].querySelector(".link-control-item-remove").focus(); }; } else { helper.e("body").focus(); }; }, left: function(copyStagedLink) { var allGroup = helper.eA(".group"); var allLinkItem = allGroup[copyStagedLink.position.origin.group].querySelectorAll(".link-item"); var target = copyStagedLink.position.origin.item - 1; if (target < 0) { target = 0; }; if (allLinkItem.length > 0) { if (allLinkItem[target].querySelector(".link-control-item-left")) { allLinkItem[target].querySelector(".link-control-item-left").focus(); }; } else { helper.e("body").focus(); }; } }, next: { right: function(copyStagedLink) { var allGroup = helper.eA(".group"); var allLinkItem = allGroup[copyStagedLink.position.origin.group].querySelectorAll(".link-item"); var target = copyStagedLink.position.origin.item + 1; if (target > allLinkItem.length - 1) { target = allLinkItem.length - 1; }; if (allLinkItem.length > 0) { if (allLinkItem[target].querySelector(".link-control-item-right")) { allLinkItem[target].querySelector(".link-control-item-right").focus(); }; } else { helper.e("body").focus(); }; } }, current: { edit: function(copyStagedLink) { var allGroup = helper.eA(".group"); var allLinkItem = allGroup[copyStagedLink.position.destination.group].querySelectorAll(".link-item"); var target = copyStagedLink.position.destination.item; if (copyStagedLink.position.group.new) { allLinkItem[0].querySelector(".link-control-item-edit").focus(); } else { if (allLinkItem.length > 0) { allLinkItem[target].querySelector(".link-control-item-edit").focus(); } else { helper.e("body").focus(); }; }; } } } }; render.autoSuggestIconAction = function(autoSuggestData) { stagedLink.link.icon.label = autoSuggestData.label; stagedLink.link.icon.name = autoSuggestData.name; if (autoSuggestData.styles.includes("solid")) { stagedLink.link.icon.prefix = "fas"; } else if (autoSuggestData.styles.includes("brands")) { stagedLink.link.icon.prefix = "fab"; }; var existingIcon = helper.e(".link-form-icon"); if (existingIcon) { existingIcon.remove(); }; helper.e(".link-form-input-icon").value = autoSuggestData.label; helper.e(".link-form-text-icon").appendChild(helper.node("span|class:link-form-icon " + stagedLink.link.icon.prefix + " fa-" + stagedLink.link.icon.name)); helper.e(".link-form-text-icon").focus(); }; render.add = { item: { open: function() { stagedLink.init(); var successAction = function() { stagedLink.link.timeStamp = new Date().getTime(); bookmarks.mod.add.link(JSON.parse(JSON.stringify(stagedLink))); add.item.close(); data.save(); groupAndItems(); control.render.dependents(); control.render.class(); shade.close(); pagelock.unlock(); }; var cancelAction = function() { add.item.close(); shade.close(); }; modal.open({ heading: "Add a new Bookmark", successAction: successAction, cancelAction: cancelAction, actionText: "Add", size: "small", content: render.item.form() }); shade.open({ action: function() { add.item.close(); modal.close(); } }); pagelock.lock(); stagedLink.position.destination.item = helper.e(".link-form-position").selectedIndex; }, close: function() { stagedLink.reset(); autoSuggest.close(); pagelock.unlock(); }, selectGroup: function(groupIndex) { stagedLink.position.destination.group = groupIndex; stagedLink.position.destination.item = 0; helper.e(".link-form-select-group").selectedIndex = stagedLink.position.destination.group; var linkFormPosition = helper.e(".link-form-position"); while (linkFormPosition.lastChild) { linkFormPosition.removeChild(linkFormPosition.lastChild); }; linkFormPosition.appendChild(helper.node("option:" + helper.ordinalNumber(1))); } }, group: { open: function() { stagedGroup.init(); var successAction = function() { bookmarks.mod.add.group(JSON.parse(JSON.stringify(stagedGroup))); add.group.close(); data.save(); groupAndItems(); control.render.dependents(); control.render.class(); shade.close(); pagelock.unlock(); }; var cancelAction = function() { add.group.close(); shade.close(); }; modal.open({ heading: "Add a new Group", successAction: successAction, cancelAction: cancelAction, actionText: "Add", size: "small", content: render.group.form({ new: true }) }); shade.open({ action: function() { add.group.close(); modal.close(); } }); pagelock.lock(); stagedGroup.position.destination = helper.e(".group-form-position").selectedIndex; }, close: function() { stagedGroup.reset(); autoSuggest.close(); pagelock.unlock(); } } }; render.edit = { item: { open: function(copyStagedLink) { stagedLink.link = JSON.parse(JSON.stringify(copyStagedLink.link)); stagedLink.position = JSON.parse(JSON.stringify(copyStagedLink.position)); var form = render.item.form({ useStagedLink: true }); var heading; if (stagedLink.link.name != null && stagedLink.link.name != "") { heading = "Edit " + stagedLink.link.name; } else { heading = "Edit unnamed bookmark"; }; var successAction = function() { var copyStagedLink = JSON.parse(JSON.stringify(stagedLink)); bookmarks.mod.edit.link(copyStagedLink); edit.item.close(); data.save(); groupAndItems(); if (!state.get.current().search) { render.focus.item.current.edit(copyStagedLink); }; autoSuggest.close(); shade.close(); pagelock.unlock(); }; var cancelAction = function() { edit.item.close(); shade.close(); }; modal.open({ heading: heading, successAction: successAction, cancelAction: cancelAction, actionText: "Save", size: "small", content: form }); shade.open({ action: function() { edit.item.close(); modal.close(); } }); pagelock.lock(); }, close: function() { stagedLink.reset(); autoSuggest.close(); pagelock.unlock(); } }, group: { open: function(copyStagedGroup) { stagedGroup.group = JSON.parse(JSON.stringify(copyStagedGroup.group)); stagedGroup.position = JSON.parse(JSON.stringify(copyStagedGroup.position)); var form = render.group.form({ useStagedGroup: true }); var heading = "Edit " + stagedGroup.group.name; var successAction = function() { var copyStagedGroup = JSON.parse(JSON.stringify(stagedGroup)); bookmarks.mod.edit.group(copyStagedGroup); edit.group.close(); data.save(); groupAndItems(); if (!state.get.current().search) { render.focus.group.current.edit(copyStagedGroup); }; autoSuggest.close(); shade.close(); pagelock.unlock(); }; var cancelAction = function() { edit.group.close(); shade.close(); }; modal.open({ heading: heading, successAction: successAction, cancelAction: cancelAction, actionText: "Save", size: "small", content: form }); shade.open({ action: function() { edit.group.close(); modal.close(); } }); pagelock.lock(); }, close: function() { stagedGroup.reset(); autoSuggest.close(); pagelock.unlock(); } } }; render.remove = { item: function(copyStagedLink) { stagedLink.link = JSON.parse(JSON.stringify(copyStagedLink.link)); stagedLink.position = JSON.parse(JSON.stringify(copyStagedLink.position)); var heading; if (stagedLink.link.name != null && stagedLink.link.name != "") { heading = "Remove " + stagedLink.link.name; } else { heading = "Remove unnamed bookmark"; }; var successAction = function() { var copyStagedLink = JSON.parse(JSON.stringify(stagedLink)); bookmarks.remove.link(copyStagedLink); edit.mode.check(); data.save(); groupAndItems(); control.render.dependents(); control.render.class(); if (!state.get.current().search) { render.focus.item.previous.remove(copyStagedLink); }; shade.close(); pagelock.unlock(); stagedLink.reset(); }; var cancelAction = function() { stagedLink.reset(); shade.close(); pagelock.unlock(); }; modal.open({ heading: heading, content: "Are you sure you want to remove this Bookmark? This can not be undone.", successAction: successAction, cancelAction: cancelAction, actionText: "Remove", size: "small" }); shade.open({ action: function() { stagedLink.reset(); autoSuggest.close(); pagelock.unlock(); modal.close(); } }); pagelock.lock(); }, group: function(copyStagedGroup) { stagedGroup.group = JSON.parse(JSON.stringify(copyStagedGroup.group)); stagedGroup.position = JSON.parse(JSON.stringify(copyStagedGroup.position)); var heading; if (stagedGroup.group.name != null && stagedGroup.group.name != "") { heading = "Remove " + stagedGroup.group.name; } else { heading = "Remove unnamed group"; }; var successAction = function() { var copyStagedGroup = JSON.parse(JSON.stringify(stagedGroup)); bookmarks.remove.group(copyStagedGroup); edit.mode.check(); data.save(); groupAndItems(); control.render.dependents(); control.render.class(); if (!state.get.current().search) { render.focus.group.previous.remove(copyStagedGroup); }; shade.close(); pagelock.unlock(); stagedGroup.reset(); }; var cancelAction = function() { stagedGroup.reset(); shade.close(); pagelock.unlock(); }; modal.open({ heading: heading, content: "Are you sure you want to remove this Group and all the Bookmarks within? This can not be undone.", successAction: successAction, cancelAction: cancelAction, actionText: "Remove", size: "small" }); shade.open({ action: function() { stagedGroup.reset(); autoSuggest.close(); pagelock.unlock(); modal.close(); } }); pagelock.lock(); } }; var add = { item: { open: function() { mod.add.item.open(); render.add.item.open(); }, close: function() { mod.add.item.close(); render.add.item.close(); }, selectGroup: function(groupIndex) { render.add.item.selectGroup(groupIndex); } }, group: { open: function() { mod.add.group.open(); render.add.group.open(); }, close: function() { mod.add.group.close(); render.add.group.close(); } } }; var edit = { mode: { open: function() { mod.edit.mode.open(); control.render.update.control.header(); control.render.update.control.menu(); control.render.class(); }, close: function() { mod.edit.mode.close(); control.render.update.control.header(); control.render.update.control.menu(); control.render.class(); }, check: function() { if (bookmarks.get().length <= 0) { edit.mode.close(); }; }, toggle: function() { if (state.get.current().edit) { edit.mode.close(); } else { edit.mode.open(); }; render.group.tabindex(); render.item.tabindex(); } }, item: { open: function(copyStagedLink) { mod.edit.item.open(); render.edit.item.open(copyStagedLink); }, close: function() { mod.edit.item.close(); render.edit.item.close(); } }, group: { open: function(copyStagedGroup) { mod.edit.group.open(); render.edit.group.open(copyStagedGroup); }, close: function() { mod.edit.group.close(); render.edit.group.close(); } } }; var tabindex = function() { render.group.tabindex(); render.item.tabindex(); }; var groupAndItems = function() { render.clear.item(); render.clear.group(); render.all(); render.group.tabindex(); render.item.tabindex(); if (!state.get.current().search) { bind.sort.group(); bind.sort.item(); }; }; var init = function() { mod.add.item.close(); mod.add.group.close(); groupAndItems(); render.group.name.size(); render.group.openall.size(); render.group.border(); render.item.color.custom(); render.item.size(); render.item.display.letter(); render.item.display.icon(); render.item.name(); render.item.border(); render.item.rotate(); render.item.translate.x(); render.item.translate.y(); render.item.gutter(); render.area.width(); }; // exposed methods return { init: init, mod: mod, render: render, add: add, edit: edit, tabindex: tabindex, groupAndItems: groupAndItems, stagedLink: stagedLink, stagedGroup: stagedGroup }; })();