diff options
Diffstat (limited to 'startpage.html')
| -rw-r--r-- | startpage.html | 5242 |
1 files changed, 2637 insertions, 2605 deletions
diff --git a/startpage.html b/startpage.html index 6a9a96d..6cce9d8 100644 --- a/startpage.html +++ b/startpage.html @@ -37,7 +37,7 @@ body { height: 100vh; - overflow: hidden; + margin: 0; } @@ -368,7 +368,7 @@ <p> <u>precise adjustments:</u> click on a container or settings slider to focus it, then use the arrow keys - to make minute changes. + to make minute changes (hold shift for a speed boost when moving containers). </p> <hr /> <p> @@ -417,7 +417,6 @@ layer's "text options" </p> </div> - </div> <div id="containerPage" class="tabContent"> @@ -472,7 +471,7 @@ <div id="ioPage" class="tabContent"> <div style="display: flex; flex-direction: column; margin: 2rem 0; gap: 1rem;align-items:center;"> <p class="menuHeader">import theme file</p> - <input id="import-input" type="file" accept".txt" style="width: 45%; align-self: center" /> + <input id="import-input" type="file" accept=".txt" style="width: 45%; align-self: center" /> <button style="width: 100%; height: 3rem;" onclick="importData()" > set new theme @@ -552,7 +551,7 @@ <h2 class="menuHeader">audio</h2> <div class="containerOptionListing"> - <label for=audioLinkInput">paste a direct URL to an audio file:</label> + <label for="audioLinkInput">paste a direct URL to an audio file:</label> <div style="display: flex; flex-direction: column; align-items: end;"> <input id="audioLinkInput" style="width: 80%" placeholder="paste file URL" /> @@ -584,3089 +583,3122 @@ <div class="containerOptionListing"> <label for="edit-toggle-alpha">set "edit mode" toggle opacity (%): </label> - <input id="edit-toggle-alpha"} type="range" min="0" max="100" /> + <input id="edit-toggle-alpha" type="range" min="0" max="100" /> </div> - - </div> + </div> </div> - </body> - <script> - // cookie holder for coordinates + size of settings menu - let settingsMenuData = {}; + <script> + // cookie holder for coordinates + size of settings menu + let settingsMenuData = {}; - // cookie holder for edit toggle mode customization - let editToggleRgba = "rbga(0,0,0,1)"; + // cookie holder for edit toggle mode customization + let editToggleRgba = "rbga(0,0,0,1)"; - // cookie holders for container data - let containerDataMap = new Map(); - let numberTotalContainers = 0; - let zIndexMap = new Map(); + // cookie holders for container data + let containerDataMap = new Map(); + let numberTotalContainers = 0; + let zIndexMap = new Map(); - // default values for easy resetting - let defaultTextContainerSettings = { - backgroundRgba: "rgba(255,255,255,.9)", - backgroundAlpha: 100, - borderWidth: "5", - borderRadius: "0", - borderColor: "grey", - fontName: "", - fontCode: "", - sectionColor: "", - sectionSize: "16", - sectionItalic: false, - sectionBold: false, - linkColor: "", - linkSize: "16", - linkDecor: true, - linkBold: false, - linkItalic: false, + // default values for easy resetting + let defaultTextContainerSettings = { + backgroundRgba: "rgba(255,255,255,.9)", + backgroundAlpha: 100, + borderWidth: "5", + borderRadius: "0", + borderColor: "grey", + fontName: "", + fontCode: "", + sectionColor: "", + sectionSize: "16", + sectionItalic: false, + sectionBold: false, + linkColor: "", + linkSize: "16", + linkDecor: true, + linkBold: false, + linkItalic: false, - enableDate: true, - enableClock: true, - headerColor: "", - headerSize: "16", - headerBold: false, - headerItalic: false, + enableDate: true, + enableClock: true, + headerColor: "", + headerSize: "16", + headerBold: false, + headerItalic: false, - enableDivider: true, - dividerColor: "", - textAlign: "center", - shadowX: "0", - shadowY: "0", - shadowBlur: "0", - shadowRgba: "rgba(255,255,255,.90)", - zIndex: "" - }; + enableDivider: true, + dividerColor: "", + textAlign: "center", + shadowX: "0", + shadowY: "0", + shadowBlur: "0", + shadowRgba: "rgba(255,255,255,.90)", + zIndex: "" + }; - let defaultImageContainerSettings = { - borderWidth: "0", - borderRadius: "0", - borderColor: "grey", - shadowX: "0", - shadowY: "0", - shadowBlur: "0", - shadowRgba: "rgba(255,255,255,.90)", - zIndex: "", - invertX: false, - invertY: false, - autoplay: false - }; + let defaultImageContainerSettings = { + borderWidth: "0", + borderRadius: "0", + borderColor: "grey", + shadowX: "0", + shadowY: "0", + shadowBlur: "0", + shadowRgba: "rgba(255,255,255,.90)", + zIndex: "", + invertX: false, + invertY: false, + autoplay: false + }; - let wallpaper = ""; + let wallpaper = ""; - // local states - let editing = false; - let moving = false; - let resizing = false; - let changingElement; - let lastMouseX = 0; - let lastMouseY = 0; - let justImported = false; - let activeTabId = ""; - let keepImageRatio = true; - let repeatWallpaper = false; - let audioLink = ""; - let autoplayAudio = true; + // local states + let editing = false; + let moving = false; + let resizing = false; + let changingElement; + let lastMouseX = 0; + let lastMouseY = 0; + let justImported = false; + let activeTabId = ""; + let keepImageRatio = true; + let repeatWallpaper = false; + let audioLink = ""; + let autoplayAudio = true; - let numberOfTextContainers = 0; - let numberOfMediaContainers = 0; + let numberOfTextContainers = 0; + let numberOfMediaContainers = 0; - let cursors = {}; + let cursors = {}; - // TODO: settings for italize / bold bookmark links + // TODO: settings for italize / bold bookmark links - class Container { - id; - name; - x; - y; - height; - width; - mediaUrl; - settings; - sections; - clockIntervalId; - youtubeId; - imageHyperlink; + class Container { + id; + name; + x; + y; + height; + width; + mediaUrl; + settings; + sections; + clockIntervalId; + youtubeId; + imageHyperlink; - constructor( - id, - name, - x, - y, - height, - width, - mediaUrl, - settings, - sections, - youtubeId, - imageHyperlink - ) { - /* check if id is already used - if (containerDataMap.has(name.replace(" ", "-").toLowerCase())) { - alert("that name is already used, please use another"); - return; - }*/ - // ensure there are no brackets in the name - if (name.indexOf("<") != -1 || name.indexOf(">") != -1) { - alert("no brackets in the name please"); - return; - } + constructor( + id, + name, + x, + y, + height, + width, + mediaUrl, + settings, + sections, + youtubeId, + imageHyperlink + ) { + /* check if id is already used + if (containerDataMap.has(name.replace(" ", "-").toLowerCase())) { + alert("that name is already used, please use another"); + return; + }*/ + // ensure there are no brackets in the name + if (name.indexOf("<") != -1 || name.indexOf(">") != -1) { + alert("no brackets in the name please"); + return; + } - let loadingFromSave = (id != undefined); - let isMedia = (mediaUrl != undefined); + let loadingFromSave = (id != undefined); + let isMedia = (mediaUrl != undefined); - if (isMedia) { - numberOfMediaContainers++; + if (isMedia) { + numberOfMediaContainers++; - if (loadingFromSave) { - this.name = name; - this.id = id; - this.x = x; - this.y = y; - this.height = height; - this.width = width; - this.settings = settings; - this.mediaUrl = mediaUrl; - this.youtubeId = youtubeId; - this.imageHyperlink = imageHyperlink; - } + if (loadingFromSave) { + this.name = name; + this.id = id; + this.x = x; + this.y = y; + this.height = height; + this.width = width; + this.settings = settings; + this.mediaUrl = mediaUrl; + this.youtubeId = youtubeId; + this.imageHyperlink = imageHyperlink; + } - else { - numberTotalContainers++; + else { + numberTotalContainers++; - if (mediaUrl.includes("youtu.be")) { - this.youtubeId = mediaUrl.slice(mediaUrl.indexOf(".be/")+4, mediaUrl.length); - } - else if (mediaUrl.includes("youtube.com")) { - // normal youtube.com link - this.youtubeId = mediaUrl.slice(mediaUrl.indexOf("v=")+2, mediaUrl.length); - if (this.youtubeId.includes("&")) { - this.youtubeId = this.youtubeId.slice(0, this.youtubeId.indexOf("&")); + if (mediaUrl.includes("youtu.be")) { + this.youtubeId = mediaUrl.slice(mediaUrl.indexOf(".be/")+4, mediaUrl.length); + } + else if (mediaUrl.includes("youtube.com")) { + // normal youtube.com link + this.youtubeId = mediaUrl.slice(mediaUrl.indexOf("v=")+2, mediaUrl.length); + if (this.youtubeId.includes("&")) { + this.youtubeId = this.youtubeId.slice(0, this.youtubeId.indexOf("&")); + } } - } - if (name == "") { - if (this.videoId != undefined) { - this.name = "video " + numberOfMediaContainers; + if (name == "") { + if (this.videoId != undefined) { + this.name = "video " + numberOfMediaContainers; + } + else { + this.name = "image " + numberOfMediaContainers; + } } else { - this.name = "image " + numberOfMediaContainers; + this.name = name; } - } - else { - this.name = name; - } - this.id = findLowestAvailableId(); - this.mediaUrl = mediaUrl; - - // deep copy default settings - this.settings = JSON.parse(JSON.stringify(defaultImageContainerSettings)); + this.id = findLowestAvailableId(); + this.mediaUrl = mediaUrl; + + // deep copy default settings + this.settings = JSON.parse(JSON.stringify(defaultImageContainerSettings)); - zIndexMap.set(String(numberOfMediaContainers + numberOfTextContainers), this.id); - this.settings.zIndex = numberOfMediaContainers + numberOfTextContainers; - } + zIndexMap.set(String(numberOfMediaContainers + numberOfTextContainers), this.id); + this.settings.zIndex = numberOfMediaContainers + numberOfTextContainers; + } - if (this.youtubeId != undefined) { - this.initializeYoutubeContainer(); + if (this.youtubeId != undefined) { + this.initializeYoutubeContainer(); + } + else { + this.initializeImageContainer(loadingFromSave); + } } else { - this.initializeImageContainer(loadingFromSave); - } - } - else { - numberOfTextContainers++; + numberOfTextContainers++; - if (loadingFromSave) { - this.name = name; - this.id = id; - this.x = x; - this.y = y; - this.height = height; - this.width = width; - this.settings = settings; - this.sections = sections; - } - else { - numberTotalContainers++; - if (name == "") this.name = "bookmark layer " + numberOfTextContainers; - else this.name = name; + if (loadingFromSave) { + this.name = name; + this.id = id; + this.x = x; + this.y = y; + this.height = height; + this.width = width; + this.settings = settings; + this.sections = sections; + } + else { + numberTotalContainers++; + if (name == "") this.name = "bookmark layer " + numberOfTextContainers; + else this.name = name; - this.id = findLowestAvailableId(); - this.sections = {}; + this.id = findLowestAvailableId(); + this.sections = {}; - // deep copy default settings - this.settings = JSON.parse(JSON.stringify(defaultTextContainerSettings)); - - zIndexMap.set(String(numberOfTextContainers + numberOfMediaContainers), this.id); - this.settings.zIndex = numberOfMediaContainers + numberOfTextContainers; - } + // deep copy default settings + this.settings = JSON.parse(JSON.stringify(defaultTextContainerSettings)); + + zIndexMap.set(String(numberOfTextContainers + numberOfMediaContainers), this.id); + this.settings.zIndex = numberOfMediaContainers + numberOfTextContainers; + } - this.initializeTextContainer(); - this.loadBookmarks(); - } + this.initializeTextContainer(); + this.loadBookmarks(); + } - this.applySettings(); - this.addContainerEventListeners(); + this.applySettings(); + this.addContainerEventListeners(); - // and save - containerDataMap.set(this.id, this); - } - + // and save + containerDataMap.set(this.id, this); + } + - /** - * creates image element, applySettings() will do the rest - */ - initializeImageContainer(loadingFromSave) { - document.body.insertAdjacentHTML( - "beforeend", + /** + * creates image element, applySettings() will do the rest + */ + initializeImageContainer(loadingFromSave) { + document.body.insertAdjacentHTML( + "beforeend", + ` + ${loadingFromSave && this.imageHyperlink ? + `<a id="` + this.id + `--hyperlink" href="` + this.imageHyperlink + `">` + : ``} + <img + class="movable ${this.imageHyperlink ? "hyperlinkedImage" : ""}" + id="${this.id}" + style="z-index: ${numberOfMediaContainers + numberOfTextContainers};" + src="${this.mediaUrl}" + draggable=false + tabindex="0" + ></img> + ${loadingFromSave ? `</a>` : ``} ` - ${loadingFromSave && this.imageHyperlink ? - `<a id="` + this.id + `--hyperlink" href="` + this.imageHyperlink + `">` - : ``} - <img - class="movable ${this.imageHyperlink ? "hyperlinkedImage" : ""}" - id="${this.id}" - style="z-index: ${numberOfMediaContainers + numberOfTextContainers};" - src="${this.mediaUrl}" - draggable=false - tabindex="0" - ></img> - ${loadingFromSave ? `</a>` : ``} - ` - ); - } - - initializeYoutubeContainer() { - let embedLink = "https://www.youtube.com/embed/" + this.youtubeId; - if (this.settings.autoplay) { - embedLink += "?autoplay=1"; + ); } - document.body.insertAdjacentHTML( - "beforeend", - ` - <div - id=${this.id} - class="movable media" - style="width:640px;height:480px" - tabindex="0" - > - <div class="youtubeEmbedCover" style="z-index: ${900 + numberOfMediaContainers + numberOfTextContainers}; ${editing ? 'display: block"' : 'display:none;"'}></div> - <iframe - class="youtubeEmbed" - id=${this.id + "--embed-frame"} - style="z-index: ${numberOfMediaContainers + numberOfTextContainers}; " - src="${embedLink}" - /> - </div> - ` - ); - } + initializeYoutubeContainer() { + let embedLink = "https://www.youtube.com/embed/" + this.youtubeId; + if (this.settings.autoplay) { + embedLink += "?autoplay=1"; + } - /** - * creates text container element, loadBookmarks() and applySettings() do the rest - */ - initializeTextContainer() { - // insert default container HTML - document.body.insertAdjacentHTML( - "beforeend", + document.body.insertAdjacentHTML( + "beforeend", + ` + <div + id=${this.id} + class="movable media" + style="width:640px;height:480px" + tabindex="0" + > + <div class="youtubeEmbedCover" style="z-index: ${900 + numberOfMediaContainers + numberOfTextContainers}; ${editing ? 'display: block"' : 'display:none;"'}></div> + <iframe + class="youtubeEmbed" + id=${this.id + "--embed-frame"} + style="z-index: ${numberOfMediaContainers + numberOfTextContainers}; " + src="${embedLink}" + /> + </div> ` - <div class="movable container" id=${this.id} tabindex="0" > - <div class="autoMarginHolder"> - <div id=${this.id + "-header"} class="containerHeader"> - <div id=${this.id + "-date"}></div> - <div id=${this.id + "-clock"}></div> + ); + } + + /** + * creates text container element, loadBookmarks() and applySettings() do the rest + */ + initializeTextContainer() { + // insert default container HTML + document.body.insertAdjacentHTML( + "beforeend", + ` + <div class="movable container" id=${this.id} tabindex="0" > + <div class="autoMarginHolder"> + <div id=${this.id + "-header"} class="containerHeader"> + <div id=${this.id + "-date"}></div> + <div id=${this.id + "-clock"}></div> + </div> + <hr id=${this.id + "-divider"} /> + <div id=${this.id + "-bookmarks"} ></div> </div> - <hr id=${this.id + "-divider"} /> - <div id=${this.id + "-bookmarks"} ></div> </div> - </div> - ` - ); + ` + ); - /** set up the time */ - const timeFormat = new Intl.DateTimeFormat([], { - timeZone: "America/New_York", - hour12: false, - hour: "numeric", - minute: "numeric", - second: "numeric", - }); - // set time immediately so it shows upon load - document.getElementById(this.id + "-clock").innerText = - timeFormat.format(new Date()); - // set time on interval to continue to update - this.clockIntervalId = setInterval(() => { + /** set up the time */ + const timeFormat = new Intl.DateTimeFormat([], { + timeZone: "America/New_York", + hour12: false, + hour: "numeric", + minute: "numeric", + second: "numeric", + }); + // set time immediately so it shows upon load document.getElementById(this.id + "-clock").innerText = timeFormat.format(new Date()); - }, 1000); + // set time on interval to continue to update + this.clockIntervalId = setInterval(() => { + document.getElementById(this.id + "-clock").innerText = + timeFormat.format(new Date()); + }, 1000); - /** set up date */ - const dateFormat = new Intl.DateTimeFormat([], { - weekday: "long", - day: "numeric", - month: "long", - }); - document.getElementById(this.id + "-date").innerText = - dateFormat.format(new Date()); + /** set up date */ + const dateFormat = new Intl.DateTimeFormat([], { + weekday: "long", + day: "numeric", + month: "long", + }); + document.getElementById(this.id + "-date").innerText = + dateFormat.format(new Date()); - // save data if not loading existing container - if (this.x == undefined && this.y == undefined) { - let newContainer = document.getElementById(this.id); - this.x = newContainer.offsetLeft; - this.y = newContainer.offsetTop; - this.height = newContainer.offsetHeight; - this.width = newContainer.offsetWidth; + // save data if not loading existing container + if (this.x == undefined && this.y == undefined) { + let newContainer = document.getElementById(this.id); + this.x = newContainer.offsetLeft; + this.y = newContainer.offsetTop; + this.height = newContainer.offsetHeight; + this.width = newContainer.offsetWidth; + } } - } - - /** - * inserts and populates the settings inputs for the given text container - */ - createTextContainerMenuListing() { - let zindex = parseInt(this.settings.zIndex); - let upButtons = ` - <div> - <button id="` + this.id + `--move-up-button"} onclick="reorderContainer(this, 'up')">move up</button> - <button id="` + this.id + `--move-top-button"} onclick="reorderContainer(this, 'top')">summon to top</button> - </div> - - `; - let downButtons = ` - <div ${zindex == 1 ? `` : `style="margin-top: .25rem;"`}> - <button id="` + this.id + `--move-down-button"} onclick="reorderContainer(this, 'down')">move down</button> - <button id="` + this.id + `--move-bottom-button"} onclick="reorderContainer(this, 'bottom')">banish to bottom</button> - </div> - `; + + /** + * inserts and populates the settings inputs for the given text container + */ + createTextContainerMenuListing() { + let zindex = parseInt(this.settings.zIndex); + let upButtons = ` + <div> + <button id="` + this.id + `--move-up-button"} onclick="reorderContainer(this, 'up')">move up</button> + <button id="` + this.id + `--move-top-button"} onclick="reorderContainer(this, 'top')">summon to top</button> + </div> + + `; + let downButtons = ` + <div ${zindex == 1 ? `` : `style="margin-top: .25rem;"`}> + <button id="` + this.id + `--move-down-button"} onclick="reorderContainer(this, 'down')">move down</button> + <button id="` + this.id + `--move-bottom-button"} onclick="reorderContainer(this, 'bottom')">banish to bottom</button> + </div> + `; - document.getElementById("containers").insertAdjacentHTML( - "afterbegin", - ` - <div class="containerListing" id=${this.id + "-container-listing"} tabIndex="0"> + document.getElementById("containers").insertAdjacentHTML( + "afterbegin", + ` + <div class="containerListing" id=${this.id + "-container-listing"} tabIndex="0"> - <div class="expandableMenuToggle active" onclick="toggleExpandableMenu(this)"> - <p id=${this.id + "--listing-header"}>[${this.settings.zIndex}]: ${this.name}</p> - <p class="expandedMenuIndicator">-</p> - </div> - <div class="expandableMenu" id=${this.id + "-settings-menu"} style="display: block; margin: 0;"> + <div class="expandableMenuToggle active" onclick="toggleExpandableMenu(this)"> + <p id=${this.id + "--listing-header"}>[${this.settings.zIndex}]: ${this.name}</p> + <p class="expandedMenuIndicator">-</p> + </div> + <div class="expandableMenu" id=${this.id + "-settings-menu"} style="display: block; margin: 0;"> - <div class="renameAndClone"> - <div> - <input id=${this.id + "--rename-input"} placeholder="new name here" /> - <button id=${this.id + "--rename-button"} onclick="renameContainer(this)">rename layer</button> + <div class="renameAndClone"> + <div> + <input id=${this.id + "--rename-input"} placeholder="new name here" /> + <button id=${this.id + "--rename-button"} onclick="renameContainer(this)">rename layer</button> + </div> + <button id=${this.id + "--clone-button"} onclick="cloneContainer(this)">clone layer</button> </div> - <button id=${this.id + "--clone-button"} onclick="cloneContainer(this)">clone layer</button> - </div> - <hr /> + <hr /> - <div class="expandableMenuToggle" onclick="toggleExpandableMenu(this)"> - <p>bookmarks</p> - <p class="expandedMenuIndicator">+</p> - </div> - <div class="expandableMenu" id=${this.id + "-bookmark-menu"} > <div class="expandableMenuToggle" onclick="toggleExpandableMenu(this)"> - <p>add new</p> + <p>bookmarks</p> <p class="expandedMenuIndicator">+</p> </div> - <div class="expandableMenu" id=${this.id + "-bookmark-menu--add-new"} > + <div class="expandableMenu" id=${this.id + "-bookmark-menu"} > + <div class="expandableMenuToggle" onclick="toggleExpandableMenu(this)"> + <p>add new</p> + <p class="expandedMenuIndicator">+</p> + </div> + <div class="expandableMenu" id=${this.id + "-bookmark-menu--add-new"} > - <div class="newBookmarkForm"> - <input - id=${this.id + "-url-input"} - type="text" name="url" - placeholder="enter URL for bookmark" - style="width: 100%;" - /> + <div class="newBookmarkForm"> + <input + id=${this.id + "-url-input"} + type="text" name="url" + placeholder="enter URL for bookmark" + style="width: 100%;" + /> - <input - id=${this.id + "-label-input"} - type="text" name="label" - placeholder="enter label for bookmark" - style="width: 100%" - /> + <input + id=${this.id + "-label-input"} + type="text" name="label" + placeholder="enter label for bookmark" + style="width: 100%" + /> - <input - id=${this.id + "-section-input"} - type="text" name="section" - placeholder="optional: enter a new or existing section name" - style="width: 100%" - /> + <input + id=${this.id + "-section-input"} + type="text" name="section" + placeholder="optional: enter a new or existing section name" + style="width: 100%" + /> - <button - id=${this.id + "-add-link-button"} - onclick="addLink(this)" - style="width: 50%"> - add it - </button> + <button + id=${this.id + "-add-link-button"} + onclick="addLink(this)" + style="width: 50%"> + add it + </button> + </div> </div> - </div> - <div class="menuHeader">current bookmarks</div> - <div id=${this.id + "-bookmark-menu--listings"} class="bookmarkListingContainer"> + <div class="menuHeader">current bookmarks</div> + <div id=${this.id + "-bookmark-menu--listings"} class="bookmarkListingContainer"> + </div> + </div> - </div> - - <div class="expandableMenuToggle" onclick="toggleExpandableMenu(this)"> - <p>container styling</p> - <p class="expandedMenuIndicator">+</p> - </div> - <div class="expandableMenu"> - - <p class="menuHeader">background color</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-bg-color"}>set background color: </label> - <input id=${this.id + "-settings-bg-color"} type="color" /> - </div> - - <div class="containerOptionListing"> - <label for=${this.id + "-settings-bg-alpha"}>set background opacity (%): </label> - <input id=${this.id + "-settings-bg-alpha"} type="range" min="0" max="100" /> - </div> + <div class="expandableMenuToggle" onclick="toggleExpandableMenu(this)"> + <p>container styling</p> + <p class="expandedMenuIndicator">+</p> + </div> + <div class="expandableMenu"> - <p class="menuHeader">shape</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-border-radius"}>roundness: </label> - <input id=${this.id + "-settings-border-radius"} type="range" max="175" /> - </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-rotation"}>rotation: </label> - <input id=${this.id + "-settings-rotation"} type="range" min="-180" max="180" /> - </div> + <p class="menuHeader">background color</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-bg-color"}>set background color: </label> + <input id=${this.id + "-settings-bg-color"} type="color" /> + </div> - <p class="menuHeader">border</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-border-color"}>set border color: </label> - <input id=${this.id + "-settings-border-color"} type="color" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-bg-alpha"}>set background opacity (%): </label> + <input id=${this.id + "-settings-bg-alpha"} type="range" min="0" max="100" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-border-width"}>set border width: </label> - <input id=${this.id + "-settings-border-width"} type="range" min="0" max="100" /> - </div> + <p class="menuHeader">shape</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-border-radius"}>roundness: </label> + <input id=${this.id + "-settings-border-radius"} type="range" max="175" /> + </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-rotation"}>rotation: </label> + <input id=${this.id + "-settings-rotation"} type="range" min="-180" max="180" /> + </div> - + <p class="menuHeader">border</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-border-color"}>set border color: </label> + <input id=${this.id + "-settings-border-color"} type="color" /> + </div> - <p class="menuHeader">shadow / glow</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-shadow-color"}>shadow color: </label> - <input id=${this.id + "-settings-shadow-color"} type="color" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-border-width"}>set border width: </label> + <input id=${this.id + "-settings-border-width"} type="range" min="0" max="100" /> + </div> - <div class="containerOptionListing"> - <label>shadow opacity:</label> - <input id=${this.id + "-settings-shadow-alpha"} type="range" min="0" max="100" /> - </div> + - <br /> + <p class="menuHeader">shadow / glow</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-shadow-color"}>shadow color: </label> + <input id=${this.id + "-settings-shadow-color"} type="color" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-shadow-x"}>shift shadow left/right: </label> - <input id=${this.id + "-settings-shadow-x"} type="range" min="-1000" max="1000" /> - </div> + <div class="containerOptionListing"> + <label>shadow opacity:</label> + <input id=${this.id + "-settings-shadow-alpha"} type="range" min="0" max="100" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-shadow-y"}>shift shadow up/down: </label> - <input id=${this.id + "-settings-shadow-y"} type="range" min="-1000" max="1000" /> - </div> + <br /> - <br /> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-shadow-x"}>shift shadow left/right: </label> + <input id=${this.id + "-settings-shadow-x"} type="range" min="-1000" max="1000" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-shadow-blur"}>shadow sharpness/fuzziness: </label> - <input id=${this.id + "-settings-shadow-blur"} type="range" min="0" max="200" /> - </div> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-shadow-y"}>shift shadow up/down: </label> + <input id=${this.id + "-settings-shadow-y"} type="range" min="-1000" max="1000" /> + </div> - <div class="expandableMenuToggle" onclick="toggleExpandableMenu(this)"> - <p>date / clock / divider</p> - <p class="expandedMenuIndicator">+</p> - </div> - <div class="expandableMenu"> + <br /> - <p class="menuHeader">date + time options</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-shadow-blur"}>shadow sharpness/fuzziness: </label> + <input id=${this.id + "-settings-shadow-blur"} type="range" min="0" max="200" /> + </div> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-clock-color"}>set font color: </label> - <input id=${this.id + "-settings-clock-color"} type="color" /> - </div> + <div class="expandableMenuToggle" onclick="toggleExpandableMenu(this)"> + <p>date / clock / divider</p> + <p class="expandedMenuIndicator">+</p> + </div> + <div class="expandableMenu"> - <div class="containerOptionListing"> - <label>set font size (px): </label> - <input id=${this.id + "-settings-clock-size"} /> - </div> + <p class="menuHeader">date + time options</p> - <br /> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-clock-color"}>set font color: </label> + <input id=${this.id + "-settings-clock-color"} type="color" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-date-toggle"}>show date?</label> - <input id=${this.id + "-settings-date-toggle"} type="checkbox" /> - </div> + <div class="containerOptionListing"> + <label>set font size (px): </label> + <input id=${this.id + "-settings-clock-size"} /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-date-bold"}>bold?</label> - <input id=${this.id + "-settings-date-bold"} type="checkbox" /> - </div> + <br /> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-date-italic"}>italic?</label> - <input id=${this.id + "-settings-date-italic"} type="checkbox" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-date-toggle"}>show date?</label> + <input id=${this.id + "-settings-date-toggle"} type="checkbox" /> + </div> - <br /> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-date-bold"}>bold?</label> + <input id=${this.id + "-settings-date-bold"} type="checkbox" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-clock-toggle"}>show clock?</label> - <input id=${this.id + "-settings-clock-toggle"} type="checkbox" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-date-italic"}>italic?</label> + <input id=${this.id + "-settings-date-italic"} type="checkbox" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-clock-bold"}>bold?</label> - <input id=${this.id + "-settings-clock-bold"} type="checkbox" /> - </div> + <br /> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-clock-italic"}>italic?</label> - <input id=${this.id + "-settings-clock-italic"} type="checkbox" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-clock-toggle"}>show clock?</label> + <input id=${this.id + "-settings-clock-toggle"} type="checkbox" /> + </div> - <p class="menuHeader">divider options</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-divider-toggle"}>display divider?</label> - <input id=${this.id + "-settings-divider-toggle"} type="checkbox" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-clock-bold"}>bold?</label> + <input id=${this.id + "-settings-clock-bold"} type="checkbox" /> + </div> - <div class="containerOptionListing"> - <label>divider color: </label> - <input id=${this.id + "-settings-divider-color"} type="color" /> - </div> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-clock-italic"}>italic?</label> + <input id=${this.id + "-settings-clock-italic"} type="checkbox" /> + </div> - <div class="expandableMenuToggle" onclick="toggleExpandableMenu(this)"> - <p>section / link / font options</p> - <p class="expandedMenuIndicator">+</p> - </div> - <div class="expandableMenu"> + <p class="menuHeader">divider options</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-divider-toggle"}>display divider?</label> + <input id=${this.id + "-settings-divider-toggle"} type="checkbox" /> + </div> - <p class="menuHeader">section text options</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-section-size"}>set section size (px): </label> - <input id=${this.id + "-settings-section-size"} /> - </div> + <div class="containerOptionListing"> + <label>divider color: </label> + <input id=${this.id + "-settings-divider-color"} type="color" /> + </div> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-section-color"}>set section color: </label> - <input id=${this.id + "-settings-section-color"} type="color" /> - </div> + <div class="expandableMenuToggle" onclick="toggleExpandableMenu(this)"> + <p>section / link / font options</p> + <p class="expandedMenuIndicator">+</p> + </div> + <div class="expandableMenu"> - <div class="containerOptionListing"> - <label for="sectionBoldToggle">bold?</label> - <input id=${this.id + "-settings-section-bold"} type="checkbox" /> - </div> + <p class="menuHeader">section text options</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-section-size"}>set section size (px): </label> + <input id=${this.id + "-settings-section-size"} /> + </div> - <div class="containerOptionListing"> - <label for="sectionItalicToggle">italic?</label> - <input id=${this.id + "-settings-section-italic"} type="checkbox" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-section-color"}>set section color: </label> + <input id=${this.id + "-settings-section-color"} type="color" /> + </div> - <p class="menuHeader">bookmark text options</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-link-size"}>set link size (px): </label> - <input id=${this.id + "-settings-link-size"} /> - </div> + <div class="containerOptionListing"> + <label for="sectionBoldToggle">bold?</label> + <input id=${this.id + "-settings-section-bold"} type="checkbox" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-link-color"}>set link color: </label> - <input id=${this.id + "-settings-link-color"} type="color" /> - </div> + <div class="containerOptionListing"> + <label for="sectionItalicToggle">italic?</label> + <input id=${this.id + "-settings-section-italic"} type="checkbox" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-link-decor"}>underline links?</label> - <input id=${this.id + "-settings-link-decor"} type="checkbox" /> - </div> + <p class="menuHeader">bookmark text options</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-link-size"}>set link size (px): </label> + <input id=${this.id + "-settings-link-size"} /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-link-bold"}>bold links?</label> - <input id=${this.id + "-settings-link-bold"} type="checkbox" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-link-color"}>set link color: </label> + <input id=${this.id + "-settings-link-color"} type="color" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-link-italic"}>italic links?</label> - <input id=${this.id + "-settings-link-italic"} type="checkbox" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-link-decor"}>underline links?</label> + <input id=${this.id + "-settings-link-decor"} type="checkbox" /> + </div> - <p class="menuHeader">general layer font options</p> - <div class="containerOptionListing"> - <div> - <p style="margin: 0;"> - change font:<br /><span style="font-size: .8rem">(see help tab for more info)</span><br /> - </p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-link-bold"}>bold links?</label> + <input id=${this.id + "-settings-link-bold"} type="checkbox" /> </div> - <div style="display: flex; flex-direction: column; align-items: end;"> - <input id=${this.id + "-settings-font-input"} /> - <br /> - <button id=${this.id + "-settings-set-font-button"}>set font</button> - <br /> - <b>current font:</b> - <span id=${this.id + "-settings-font-name"}></span> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-link-italic"}>italic links?</label> + <input id=${this.id + "-settings-link-italic"} type="checkbox" /> </div> - </div> - <br /> - <div class="containerOptionListing" > - <p style="margin-top: 0;">align text:</p> - <div style="display: flex; flex-direction: column; align-items: end;"> + <p class="menuHeader">general layer font options</p> + <div class="containerOptionListing"> <div> - <label for=${this.id + "-settings-left-align"}>left</label> - <input id=${this.id + "-settings-left-align"} type="radio" name="align" /> + <p style="margin: 0;"> + change font:<br /><span style="font-size: .8rem">(see help tab for more info)</span><br /> + </p> </div> - <div> - <label for=${this.id + "-settings-center-align"}>center</label> - <input id=${this.id + "-settings-center-align"} type="radio" name="align" /> + + <div style="display: flex; flex-direction: column; align-items: end;"> + <input id=${this.id + "-settings-font-input"} /> + <br /> + <button id=${this.id + "-settings-set-font-button"}>set font</button> + <br /> + <b>current font:</b> + <span id=${this.id + "-settings-font-name"}></span> </div> - <div> - <label for=${this.id + "-settings-right-align"}>right</label> - <input id=${this.id + "-settings-right-align"} type="radio" name="align" /> + </div> + <br /> + <div class="containerOptionListing" > + <p style="margin-top: 0;">align text:</p> + + <div style="display: flex; flex-direction: column; align-items: end;"> + <div> + <label for=${this.id + "-settings-left-align"}>left</label> + <input id=${this.id + "-settings-left-align"} type="radio" name="align" /> + </div> + <div> + <label for=${this.id + "-settings-center-align"}>center</label> + <input id=${this.id + "-settings-center-align"} type="radio" name="align" /> + </div> + <div> + <label for=${this.id + "-settings-right-align"}>right</label> + <input id=${this.id + "-settings-right-align"} type="radio" name="align" /> + </div> </div> </div> - </div> - </div> - </div> + </div> + </div> - <div class="manageButtons"> - <div id=${this.id + "--manage-buttons"} > - ${zindex == numberTotalContainers ? `` : upButtons} - ${zindex == 1 ? `` : downButtons} + <div class="manageButtons"> + <div id=${this.id + "--manage-buttons"} > + ${zindex == numberTotalContainers ? `` : upButtons} + ${zindex == 1 ? `` : downButtons} + </div> + <div> + <button id=${this.id + "--delete-button"} class="deleteButton" onclick="deleteContainer(this)">delete layer</button> </div> - <div> - <button id=${this.id + "--delete-button"} class="deleteButton" onclick="deleteContainer(this)">delete layer</button> </div> - </div> - ` - ); + ` + ); - /** fill in inputs with current values */ - let settings = this.settings; - // SHADOW / GLOW - document.getElementById(this.id + "-settings-shadow-x").value = - settings.shadowX; - document.getElementById(this.id + "-settings-shadow-y").value = - settings.shadowY; - document.getElementById(this.id + "-settings-shadow-blur").value = - settings.shadowBlur; - document.getElementById(this.id + "-settings-shadow-color").value = - rgbToHex( + /** fill in inputs with current values */ + let settings = this.settings; + // SHADOW / GLOW + document.getElementById(this.id + "-settings-shadow-x").value = + settings.shadowX; + document.getElementById(this.id + "-settings-shadow-y").value = + settings.shadowY; + document.getElementById(this.id + "-settings-shadow-blur").value = + settings.shadowBlur; + document.getElementById(this.id + "-settings-shadow-color").value = + rgbToHex( + settings.shadowRgba + .replace("rgba(", "") + .slice(0, -1) + .split(",") + .splice(0, 3) + ); + document.getElementById(this.id + "-settings-shadow-alpha").value = settings.shadowRgba .replace("rgba(", "") .slice(0, -1) - .split(",") - .splice(0, 3) - ); - document.getElementById(this.id + "-settings-shadow-alpha").value = - settings.shadowRgba - .replace("rgba(", "") - .slice(0, -1) - .split(",")[3] * 100; - // BORDER - document.getElementById(this.id + "-settings-border-color").value = - settings.borderColor; - document.getElementById(this.id + "-settings-border-width").value = - settings.borderWidth; - document.getElementById(this.id + "-settings-border-radius").value = - settings.borderRadius; - // ROTATION - document.getElementById(this.id + "-settings-rotation").value = - settings.rotation; - // FONT - if (settings.fontName == "") { - document.getElementById(this.id + "-settings-font-name").innerHTML = - "browser default"; - } else { - document.getElementById(this.id + "-settings-font-name").innerHTML = - settings.fontName; - } - // TEXT ALIGNMENT - document.getElementById(this.id + "-settings-left-align").checked = - !settings.textAlign == "left"; - document.getElementById(this.id + "-settings-center-align").checked = - settings.textAlign == "center"; - document.getElementById(this.id + "-settings-right-align").checked = - settings.textAlign == "right"; - // BOOKMARK OPTIONS - document.getElementById(this.id + "-settings-section-color").value = - settings.sectionColor; - document.getElementById(this.id + "-settings-section-size").value = - settings.sectionSize; - document.getElementById(this.id + "-settings-section-bold").checked = - settings.sectionBold; - document.getElementById(this.id + "-settings-section-italic").checked = - settings.sectionItalic; - document.getElementById(this.id + "-settings-link-color").value = - settings.linkColor; - document.getElementById(this.id + "-settings-link-size").value = - settings.linkSize; - document.getElementById(this.id + "-settings-link-decor").checked = - settings.linkDecor; - document.getElementById(this.id + "-settings-link-bold").checked = - settings.linkBold; - document.getElementById(this.id + "-settings-link-italic").checked = - settings.linkItalic; - // BACKGROUND COLOR - document.getElementById(this.id + "-settings-bg-color").value = - rgbToHex( + .split(",")[3] * 100; + // BORDER + document.getElementById(this.id + "-settings-border-color").value = + settings.borderColor; + document.getElementById(this.id + "-settings-border-width").value = + settings.borderWidth; + document.getElementById(this.id + "-settings-border-radius").value = + settings.borderRadius; + // ROTATION + document.getElementById(this.id + "-settings-rotation").value = + settings.rotation; + // FONT + if (settings.fontName == "") { + document.getElementById(this.id + "-settings-font-name").innerHTML = + "browser default"; + } else { + document.getElementById(this.id + "-settings-font-name").innerHTML = + settings.fontName; + } + // TEXT ALIGNMENT + document.getElementById(this.id + "-settings-left-align").checked = + !settings.textAlign == "left"; + document.getElementById(this.id + "-settings-center-align").checked = + settings.textAlign == "center"; + document.getElementById(this.id + "-settings-right-align").checked = + settings.textAlign == "right"; + // BOOKMARK OPTIONS + document.getElementById(this.id + "-settings-section-color").value = + settings.sectionColor; + document.getElementById(this.id + "-settings-section-size").value = + settings.sectionSize; + document.getElementById(this.id + "-settings-section-bold").checked = + settings.sectionBold; + document.getElementById(this.id + "-settings-section-italic").checked = + settings.sectionItalic; + document.getElementById(this.id + "-settings-link-color").value = + settings.linkColor; + document.getElementById(this.id + "-settings-link-size").value = + settings.linkSize; + document.getElementById(this.id + "-settings-link-decor").checked = + settings.linkDecor; + document.getElementById(this.id + "-settings-link-bold").checked = + settings.linkBold; + document.getElementById(this.id + "-settings-link-italic").checked = + settings.linkItalic; + // BACKGROUND COLOR + document.getElementById(this.id + "-settings-bg-color").value = + rgbToHex( + settings.backgroundRgba + .replace("rgba(", "") + .slice(0, -1) + .split(",") + .splice(0, 3) + ); + document.getElementById(this.id + "-settings-bg-alpha").value = settings.backgroundRgba .replace("rgba(", "") .slice(0, -1) - .split(",") - .splice(0, 3) - ); - document.getElementById(this.id + "-settings-bg-alpha").value = - settings.backgroundRgba - .replace("rgba(", "") - .slice(0, -1) - .split(",")[3] * 100; - // HEADER OPTIONS - document.getElementById(this.id + "-settings-date-toggle").checked = - settings.enableDate; - document.getElementById(this.id + "-settings-clock-toggle").checked = - settings.enableClock; - document.getElementById(this.id + "-settings-clock-color").value = - settings.headerColor; - document.getElementById(this.id + "-settings-clock-size").value = - settings.headerSize; - document.getElementById(this.id + "-settings-date-bold").checked = - settings.dateBold; - document.getElementById(this.id + "-settings-clock-bold").checked = - settings.clockBold; - document.getElementById(this.id + "-settings-date-italic").checked = - settings.dateItalic; - document.getElementById(this.id + "-settings-clock-italic").checked = - settings.clockItalic; - // DIVIDER - document.getElementById(this.id + "-settings-divider-toggle").checked = - settings.enableDivider; - document.getElementById(this.id + "-settings-divider-color").value = - settings.dividerColor; - } - - /** - * [re]renders bookmarks shown in the settings menu for a given text container - */ - loadBookmarkListings() { - if (Object.keys(this.sections).length == 0) { - let bookmarkListings = document.getElementById(this.id + "-bookmark-menu--listings"); - bookmarkListings.innerHTML = `<p style="padding: 0 0 .25rem 0; font-style: italic;">(there are no bookmarks to manage...)</p>`; - return; + .split(",")[3] * 100; + // HEADER OPTIONS + document.getElementById(this.id + "-settings-date-toggle").checked = + settings.enableDate; + document.getElementById(this.id + "-settings-clock-toggle").checked = + settings.enableClock; + document.getElementById(this.id + "-settings-clock-color").value = + settings.headerColor; + document.getElementById(this.id + "-settings-clock-size").value = + settings.headerSize; + document.getElementById(this.id + "-settings-date-bold").checked = + settings.dateBold; + document.getElementById(this.id + "-settings-clock-bold").checked = + settings.clockBold; + document.getElementById(this.id + "-settings-date-italic").checked = + settings.dateItalic; + document.getElementById(this.id + "-settings-clock-italic").checked = + settings.clockItalic; + // DIVIDER + document.getElementById(this.id + "-settings-divider-toggle").checked = + settings.enableDivider; + document.getElementById(this.id + "-settings-divider-color").value = + settings.dividerColor; } + + /** + * [re]renders bookmarks shown in the settings menu for a given text container + */ + loadBookmarkListings() { + if (Object.keys(this.sections).length == 0) { + let bookmarkListings = document.getElementById(this.id + "-bookmark-menu--listings"); + bookmarkListings.innerHTML = `<p style="padding: 0 0 .25rem 0; font-style: italic;">(there are no bookmarks to manage...)</p>`; + return; + } - let sectionData = Object.values(this.sections); - let settings = this.settings; - - let bookmarkListings = document.getElementById(this.id + "-bookmark-menu--listings"); - bookmarkListings.innerHTML = ""; - - // [in]render the section listings - for (let i = 0; i < sectionData.length; i++) { - bookmarkListings.insertAdjacentHTML( - "beforeend", - ` - ${i == 0 ? "" : `<br />`} - <div id="${this.id}-section-listing--${i}" class="sectionListingContainer"> - <span class=${this.id + "-section"}> - ${sectionData[i].label == "" ? "<u>uncategorized links</u>: " : "<u>section</u>: " + sectionData[i].label} - </span> - - <div class="bookmarkListingButtons"> - ${(i > 1) ? ` - <button onClick="reorderSection(this, 'up')" class="bookmarkButton"> - up - </button> - ` : `` } - - ${(i > 0) && (i < sectionData.length - 1) ? ` - <button onClick="reorderSection(this, 'down')" class="bookmarkButton"> - down - </button> - ` : `` } - <button onClick="deleteSection(this)" class="deleteButton">delete section</button> - </div> - </div> - ` - ); - } + let sectionData = Object.values(this.sections); + let settings = this.settings; - // [re]render the link listings - for (let s = sectionData.length - 1; s >= 0; s--) { - for (let l = sectionData[s].links.length - 1; l >= 0; l--) { - let targetSection = document.getElementById( - this.id + "-section-listing--" + s - ); + let bookmarkListings = document.getElementById(this.id + "-bookmark-menu--listings"); + bookmarkListings.innerHTML = ""; - targetSection.insertAdjacentHTML( - "afterend", + // [in]render the section listings + for (let i = 0; i < sectionData.length; i++) { + bookmarkListings.insertAdjacentHTML( + "beforeend", ` - <div id="${this.id}-section-listing--${s}--${l}" class="linkListingContainer"> - - <span class="${this.id}-link"> - ${sectionData[s].links[l].label} + ${i == 0 ? "" : `<br />`} + <div id="${this.id}-section-listing--${i}" class="sectionListingContainer"> + <span class=${this.id + "-section"}> + ${sectionData[i].label == "" ? "<u>uncategorized links</u>: " : "<u>section</u>: " + sectionData[i].label} </span> <div class="bookmarkListingButtons"> - ${l > 0 ? ` - <button onClick="reorderLink(this, 'up')" class="bookmarkButton"> + ${(i > 1) ? ` + <button onClick="reorderSection(this, 'up')" class="bookmarkButton"> up </button> - ` : `` - } - ${l < sectionData[s].links.length - 1 ? ` - <button onClick="reorderLink(this, 'down')" class="bookmarkButton"> - down + ` : `` } + + ${(i > 0) && (i < sectionData.length - 1) ? ` + <button onClick="reorderSection(this, 'down')" class="bookmarkButton"> + down </button> - ` : `` - } - <button onClick="deleteLink(this)" class="deleteButton">delete link</button> + ` : `` } + <button onClick="deleteSection(this)" class="deleteButton">delete section</button> </div> </div> ` ); } - } - } - createMediaContainerMenuListing() { - let zindex = this.settings.zIndex; - let upButtons = ` - <div> - <button id="` + this.id + `--move-up-button"} onclick="reorderContainer(this, 'up')">move up</button> - <button id="` + this.id + `--move-top-button"} onclick="reorderContainer(this, 'top')">summon to top</button> - </div> - `; - let downButtons = ` - <div ${zindex == 1 ? `` : `style="margin-top: .25rem;"`}> - <button id="` + this.id + `--move-down-button"} onclick="reorderContainer(this, 'down')">move down</button> - <button id="` + this.id + `--move-bottom-button"} onclick="reorderContainer(this, 'bottom')">banish to bottom</button> - </div> - `; - let youtubeEmbedOptions = ` - <p class="menuHeader">youtube autoplay</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-youtube-autoplay"}>autoplay on load?</label> - <input id=${this.id + "-settings-youtube-autoplay"} type="checkbox" onclick="toggleYoutubeAutoplay(this)" /> + // [re]render the link listings + for (let s = sectionData.length - 1; s >= 0; s--) { + for (let l = sectionData[s].links.length - 1; l >= 0; l--) { + let targetSection = document.getElementById( + this.id + "-section-listing--" + s + ); + + targetSection.insertAdjacentHTML( + "afterend", + ` + <div id="${this.id}-section-listing--${s}--${l}" class="linkListingContainer"> + + <span class="${this.id}-link"> + ${sectionData[s].links[l].label} + </span> + + <div class="bookmarkListingButtons"> + ${l > 0 ? ` + <button onClick="reorderLink(this, 'up')" class="bookmarkButton"> + up + </button> + ` : `` + } + ${l < sectionData[s].links.length - 1 ? ` + <button onClick="reorderLink(this, 'down')" class="bookmarkButton"> + down + </button> + ` : `` + } + <button onClick="deleteLink(this)" class="deleteButton">delete link</button> + </div> + </div> + ` + ); + } + } + } + createMediaContainerMenuListing() { + let zindex = this.settings.zIndex; + let upButtons = ` + <div> + <button id="` + this.id + `--move-up-button"} onclick="reorderContainer(this, 'up')">move up</button> + <button id="` + this.id + `--move-top-button"} onclick="reorderContainer(this, 'top')">summon to top</button> + </div> + `; + let downButtons = ` + <div ${zindex == 1 ? `` : `style="margin-top: .25rem;"`}> + <button id="` + this.id + `--move-down-button"} onclick="reorderContainer(this, 'down')">move down</button> + <button id="` + this.id + `--move-bottom-button"} onclick="reorderContainer(this, 'bottom')">banish to bottom</button> </div> - `; + `; - let imageHyperlinkOptions = ` - <p class="menuHeader">set image hyperlink</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-image-hyperlink-input"}>hyperlink image</label> + let youtubeEmbedOptions = ` + <p class="menuHeader">youtube autoplay</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-youtube-autoplay"}>autoplay on load?</label> + <input id=${this.id + "-settings-youtube-autoplay"} type="checkbox" onclick="toggleYoutubeAutoplay(this)" /> + </div> + `; + + let imageHyperlinkOptions = ` + <p class="menuHeader">set image hyperlink</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-image-hyperlink-input"}>hyperlink image</label> - <div style="display: flex; flex-direction: column; align-items: end;"> - <input - id=${this.id + "-settings-image-hyperlink-input"} - placeholder="URL to apply to image" - style="width: 100%;" - type="text" - /> - <button id=${this.id + "-settings-image-hyperlink-set-button"} onclick="setImageHyperlink(this)"> - set hyperlink - </button>`; + <div style="display: flex; flex-direction: column; align-items: end;"> + <input + id=${this.id + "-settings-image-hyperlink-input"} + placeholder="URL to apply to image" + style="width: 100%;" + type="text" + /> + <button id=${this.id + "-settings-image-hyperlink-set-button"} onclick="setImageHyperlink(this)"> + set hyperlink + </button>`; - if (this.imageHyperlink) { + if (this.imageHyperlink) { + imageHyperlinkOptions += ` + <button id=${this.id + "-settings-image-hyperlink-remove-button"} onclick="removeImageHyperlink(this)"> + remove hyperlink + </button>`; + } + imageHyperlinkOptions += ` - <button id=${this.id + "-settings-image-hyperlink-remove-button"} onclick="removeImageHyperlink(this)"> - remove hyperlink - </button>`; - } - - imageHyperlinkOptions += ` + </div> </div> - </div> - `; + `; - document.getElementById("containers").insertAdjacentHTML( - "afterbegin", - ` - <div class="containerListing" id=${this.id + "-container-listing"}> + document.getElementById("containers").insertAdjacentHTML( + "afterbegin", + ` + <div class="containerListing" id=${this.id + "-container-listing"}> - <div class="expandableMenuToggle active" onclick="toggleExpandableMenu(this)"> - <p id=${this.id + "--listing-header"}>[${this.settings.zIndex}]: ${this.name}</p> - <p class="expandedMenuIndicator">-</p> - </div> - <div class="expandableMenu" style="display: block; margin: 0;" id=${this.id + "-settings-menu"}> + <div class="expandableMenuToggle active" onclick="toggleExpandableMenu(this)"> + <p id=${this.id + "--listing-header"}>[${this.settings.zIndex}]: ${this.name}</p> + <p class="expandedMenuIndicator">-</p> + </div> + <div class="expandableMenu" style="display: block; margin: 0;" id=${this.id + "-settings-menu"}> - <div class="renameAndClone"> - <div> - <input id=${this.id + "--rename-input"} placeholder="new name here" /> - <button id=${this.id + "--rename-button"} onclick="renameContainer(this)">rename layer</button> + <div class="renameAndClone"> + <div> + <input id=${this.id + "--rename-input"} placeholder="new name here" /> + <button id=${this.id + "--rename-button"} onclick="renameContainer(this)">rename layer</button> + </div> + <button id=${this.id + "--clone-button"} onclick="cloneContainer(this)">clone layer</button> </div> - <button id=${this.id + "--clone-button"} onclick="cloneContainer(this)">clone layer</button> - </div> - <hr /> + <hr /> - ${this.youtubeId ? `` : imageHyperlinkOptions} + ${this.youtubeId ? `` : imageHyperlinkOptions} - <p class="menuHeader">shape</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-border-radius"}>roundness: </label> - <input id=${this.id + "-settings-border-radius"} type="range" max="175" /> - </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-rotation"}>rotation: </label> - <input id=${this.id + "-settings-rotation"} type="range" min="-360" max="360" /> - </div> - - <p class="menuHeader">border</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-border-color"}>set border color: </label> - <input id=${this.id + "-settings-border-color"} type="color" /> - </div> + <p class="menuHeader">shape</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-border-radius"}>roundness: </label> + <input id=${this.id + "-settings-border-radius"} type="range" max="175" /> + </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-rotation"}>rotation: </label> + <input id=${this.id + "-settings-rotation"} type="range" min="-360" max="360" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-border-width"}>set border width: </label> - <input id=${this.id + "-settings-border-width"} type="range" min="0" max="100" /> - </div> + <p class="menuHeader">border</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-border-color"}>set border color: </label> + <input id=${this.id + "-settings-border-color"} type="color" /> + </div> - <p class="menuHeader">shadow / glow</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-shadow-color"}>shadow color: </label> - <input id=${this.id + "-settings-shadow-color"} type="color" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-border-width"}>set border width: </label> + <input id=${this.id + "-settings-border-width"} type="range" min="0" max="100" /> + </div> - <div class="containerOptionListing"> - <label>shadow opacity:</label> - <input id=${this.id + "-settings-shadow-alpha"} type="range" min="0" max="100" /> - </div> + <p class="menuHeader">shadow / glow</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-shadow-color"}>shadow color: </label> + <input id=${this.id + "-settings-shadow-color"} type="color" /> + </div> - <br /> + <div class="containerOptionListing"> + <label>shadow opacity:</label> + <input id=${this.id + "-settings-shadow-alpha"} type="range" min="0" max="100" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-shadow-x"}>shift shadow left/right: </label> - <input id=${this.id + "-settings-shadow-x"} type="range" min="-1000" max="1000" /> - </div> + <br /> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-shadow-y"}>shift shadow up/down: </label> - <input id=${this.id + "-settings-shadow-y"} type="range" min="-1000" max="1000" /> - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-shadow-x"}>shift shadow left/right: </label> + <input id=${this.id + "-settings-shadow-x"} type="range" min="-1000" max="1000" /> + </div> - <br /> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-shadow-y"}>shift shadow up/down: </label> + <input id=${this.id + "-settings-shadow-y"} type="range" min="-1000" max="1000" /> + </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-shadow-blur"}>shadow sharpness/fuzziness: </label> - <input id=${this.id + "-settings-shadow-blur"} type="range" min="0" max="200" /> - </div> - - <p class="menuHeader">mirroring</p> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-mirror-x"}>mirror horizontally</label> - <input id=${this.id + "-settings-mirror-x"} type="checkbox" /> - </div> - <div class="containerOptionListing"> - <label for=${this.id + "-settings-mirror-y"}>mirror vertically</label> - <input id=${this.id + "-settings-mirror-y"} type="checkbox" /> - </div> + <br /> - ${this.youtubeId ? youtubeEmbedOptions : ``} - </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-shadow-blur"}>shadow sharpness/fuzziness: </label> + <input id=${this.id + "-settings-shadow-blur"} type="range" min="0" max="200" /> + </div> + + <p class="menuHeader">mirroring</p> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-mirror-x"}>mirror horizontally</label> + <input id=${this.id + "-settings-mirror-x"} type="checkbox" /> + </div> + <div class="containerOptionListing"> + <label for=${this.id + "-settings-mirror-y"}>mirror vertically</label> + <input id=${this.id + "-settings-mirror-y"} type="checkbox" /> + </div> - <div class="manageButtons"> - <div id=${this.id + "--manage-buttons"}> - ${zindex == numberTotalContainers ? `` : upButtons} - ${zindex == 1 ? `` : downButtons} + ${this.youtubeId ? youtubeEmbedOptions : ``} </div> - <div> - <button id=${this.id + "--delete-button"} onclick="deleteContainer(this)">delete layer</button> + + <div class="manageButtons"> + <div id=${this.id + "--manage-buttons"}> + ${zindex == numberTotalContainers ? `` : upButtons} + ${zindex == 1 ? `` : downButtons} + </div> + <div> + <button id=${this.id + "--delete-button"} onclick="deleteContainer(this)">delete layer</button> + </div> </div> </div> - </div> - ` - ); - - /** fill in inputs with current values */ - let settings = this.settings; - // SHADOW / GLOW - document.getElementById(this.id + "-settings-shadow-x").value = - settings.shadowX; - document.getElementById(this.id + "-settings-shadow-y").value = - settings.shadowY; - document.getElementById(this.id + "-settings-shadow-blur").value = - settings.shadowBlur; - document.getElementById(this.id + "-settings-shadow-color").value = - rgbToHex( + ` + ); + + /** fill in inputs with current values */ + let settings = this.settings; + // SHADOW / GLOW + document.getElementById(this.id + "-settings-shadow-x").value = + settings.shadowX; + document.getElementById(this.id + "-settings-shadow-y").value = + settings.shadowY; + document.getElementById(this.id + "-settings-shadow-blur").value = + settings.shadowBlur; + document.getElementById(this.id + "-settings-shadow-color").value = + rgbToHex( + settings.shadowRgba + .replace("rgba(", "") + .slice(0, -1) + .split(",") + .splice(0, 3) + ); + document.getElementById(this.id + "-settings-shadow-alpha").value = settings.shadowRgba .replace("rgba(", "") .slice(0, -1) - .split(",") - .splice(0, 3) - ); - document.getElementById(this.id + "-settings-shadow-alpha").value = - settings.shadowRgba - .replace("rgba(", "") - .slice(0, -1) - .split(",")[3] * 100; - // BORDER - document.getElementById(this.id + "-settings-border-color").value = - settings.borderColor; - document.getElementById(this.id + "-settings-border-width").value = - settings.borderWidth; - document.getElementById(this.id + "-settings-border-radius").value = - settings.borderRadius; - // ROTATION - document.getElementById(this.id + "-settings-rotation").value = - settings.rotation; - // MIRRORING - document.getElementById(this.id + "-settings-mirror-x").checked = - settings.invertX; - document.getElementById(this.id + "-settings-mirror-y").checked = - settings.invertY; - } - - /** - * applies event listeners on container options inputs in settings menu (both text+media containers) - */ - addSettingsMenuEventListeners() { - /** apply listeners for both text+media containers */ - // container border setting listeners - document - .getElementById(this.id + "-settings-border-color") - .addEventListener("input", changeContainerBorderColor, false); - document - .getElementById(this.id + "-settings-border-width") - .addEventListener("input", changeContainerBorderWidth, false); - document - .getElementById(this.id + "-settings-border-radius") - .addEventListener("input", changeContainerBorderRadius, false); // container color setting listeners - // container shadow setting listeners - document - .getElementById(this.id + "-settings-shadow-x") - .addEventListener("input", changeContainerShadow, false); - document - .getElementById(this.id + "-settings-shadow-y") - .addEventListener("input", changeContainerShadow, false); - document - .getElementById(this.id + "-settings-shadow-blur") - .addEventListener("input", changeContainerShadow, false); - document - .getElementById(this.id + "-settings-shadow-color") - .addEventListener("input", changeContainerShadow, false); - document - .getElementById(this.id + "-settings-shadow-alpha") - .addEventListener("input", changeContainerShadow, false); - // container rotation setting listeners - document - .getElementById(this.id + "-settings-rotation") - .addEventListener("input", changeContainerRotation, false); - - /** if this is an media container, settings diverge here */ - if (this.mediaUrl != undefined) { - document - .getElementById(this.id + "-settings-mirror-x") - .addEventListener("change", toggleMirrorX, false); - document - .getElementById(this.id + "-settings-mirror-y") - .addEventListener("change", toggleMirrorY, false); - return; - } - - /** text-only settings */ - // container background color setting listeners - document - .getElementById(this.id + "-settings-bg-color") - .addEventListener("input", changeContainerBackground, false); - document - .getElementById(this.id + "-settings-bg-alpha") - .addEventListener("input", changeContainerBackground, false); - // container text setting listeners - document - .getElementById(this.id + "-settings-set-font-button") - .addEventListener("click", changeFont, false); - document - .getElementById(this.id + "-settings-left-align") - .addEventListener("change", changeContainerAlignment, false); - document - .getElementById(this.id + "-settings-center-align") - .addEventListener("change", changeContainerAlignment, false); - document - .getElementById(this.id + "-settings-right-align") - .addEventListener("change", changeContainerAlignment, false); - - // bookmark section setting listeners - document - .getElementById(this.id + "-settings-section-color") - .addEventListener("input", changeSectionColor, false); - document - .getElementById(this.id + "-settings-section-size") - .addEventListener("input", changeSectionSize, false); - document - .getElementById(this.id + "-settings-section-bold") - .addEventListener("change", toggleSectionBold, false); - document - .getElementById(this.id + "-settings-section-italic") - .addEventListener("change", toggleSectionItalic, false); - // bookmark setting listeners - document - .getElementById(this.id + "-settings-link-color") - .addEventListener("input", changeLinkColor, false); - document - .getElementById(this.id + "-settings-link-size") - .addEventListener("input", changeLinkSize, false); - document - .getElementById(this.id + "-settings-link-decor") - .addEventListener("change", toggleLinkDecor, false); - document - .getElementById(this.id + "-settings-link-bold") - .addEventListener("change", toggleLinkBold, false); - document - .getElementById(this.id + "-settings-link-italic") - .addEventListener("change", toggleLinkItalic, false); - // clock setting listeners - document - .getElementById(this.id + "-settings-date-toggle") - .addEventListener("input", toggleDate, false); - document - .getElementById(this.id + "-settings-clock-toggle") - .addEventListener("input", toggleClock, false); - document - .getElementById(this.id + "-settings-clock-color") - .addEventListener("input", changeHeaderColor, false); - document - .getElementById(this.id + "-settings-clock-size") - .addEventListener("input", changeHeaderSize, false); - document - .getElementById(this.id + "-settings-date-bold") - .addEventListener("change", toggleDateBold, false); - document - .getElementById(this.id + "-settings-clock-bold") - .addEventListener("change", toggleClockBold, false); - document - .getElementById(this.id + "-settings-date-italic") - .addEventListener("change", toggleDateItalic, false); - document - .getElementById(this.id + "-settings-clock-italic") - .addEventListener("change", toggleClockItalic, false); - // container divider setting listeners - document - .getElementById(this.id + "-settings-divider-toggle") - .addEventListener("change", toggleDivider, false); - document - .getElementById(this.id + "-settings-divider-color") - .addEventListener("input", changeDividerColor, false); - } - - /* - * applies saved cosmetic customizations to container upon init (both text+media containers) - */ - applySettings() { - /** apply customizations relevant to both image and text containers */ - /** POSITION */ - document.getElementById(this.id).style.top = this.y; - document.getElementById(this.id).style.left = this.x; - document.getElementById(this.id).style.zIndex = this.settings.zIndex; - - /** SIZE */ - let settings = this.settings; - document.getElementById(this.id).style.width = this.width + "px"; - // this.width - 2 * parseInt(settings.borderWidth); - document.getElementById(this.id).style.height = this.height + "px"; - // this.height - 2 * parseInt(settings.borderWidth); - - /** SHADOW / GLOW */ - document.getElementById(this.id).style.boxShadow = - settings.shadowX + - "px " + - settings.shadowY + - "px " + - settings.shadowBlur + - "px " + - settings.shadowRgba; - - - /** - * if this is a media container, settings diverge here - */ - - /** BORDER */ - if (this.mediaUrl?.includes("youtube.com") || this.mediaUrl?.includes("youtu.be")) { - // apply border to iframe and cover element rather than containing div - document.getElementById(this.id).children[0].style.borderColor = + .split(",")[3] * 100; + // BORDER + document.getElementById(this.id + "-settings-border-color").value = settings.borderColor; - document.getElementById(this.id).children[1].style.borderColor = - settings.borderColor; - document.getElementById(this.id).children[0].style.borderWidth = - settings.borderWidth + "px"; - document.getElementById(this.id).children[1].style.borderWidth = - settings.borderWidth + "px"; - document.getElementById(this.id).children[0].style.borderRadius = - settings.borderRadius + "px"; - document.getElementById(this.id).children[1].style.borderRadius = - settings.borderRadius + "px"; + document.getElementById(this.id + "-settings-border-width").value = + settings.borderWidth; + document.getElementById(this.id + "-settings-border-radius").value = + settings.borderRadius; + // ROTATION + document.getElementById(this.id + "-settings-rotation").value = + settings.rotation; + // MIRRORING + document.getElementById(this.id + "-settings-mirror-x").checked = + settings.invertX; + document.getElementById(this.id + "-settings-mirror-y").checked = + settings.invertY; } - else { - document.getElementById(this.id).style.borderRadius = - settings.borderRadius + "px"; - document.getElementById(this.id).style.borderStyle = "solid"; - document.getElementById(this.id).style.borderWidth = - settings.borderWidth + "px"; - document.getElementById(this.id).style.borderColor = - settings.borderColor; - } + + /** + * applies event listeners on container options inputs in settings menu (both text+media containers) + */ + addSettingsMenuEventListeners() { + /** apply listeners for both text+media containers */ + // container border setting listeners + document + .getElementById(this.id + "-settings-border-color") + .addEventListener("input", changeContainerBorderColor, false); + document + .getElementById(this.id + "-settings-border-width") + .addEventListener("input", changeContainerBorderWidth, false); + document + .getElementById(this.id + "-settings-border-radius") + .addEventListener("input", changeContainerBorderRadius, false); // container color setting listeners + // container shadow setting listeners + document + .getElementById(this.id + "-settings-shadow-x") + .addEventListener("input", changeContainerShadow, false); + document + .getElementById(this.id + "-settings-shadow-y") + .addEventListener("input", changeContainerShadow, false); + document + .getElementById(this.id + "-settings-shadow-blur") + .addEventListener("input", changeContainerShadow, false); + document + .getElementById(this.id + "-settings-shadow-color") + .addEventListener("input", changeContainerShadow, false); + document + .getElementById(this.id + "-settings-shadow-alpha") + .addEventListener("input", changeContainerShadow, false); + // container rotation setting listeners + document + .getElementById(this.id + "-settings-rotation") + .addEventListener("input", changeContainerRotation, false); - /** MEDIA MIRRORING + ROTATOIN*/ - if (this.mediaUrl != undefined) { - let transformValue = - `scale(${settings.invertX ? `-1` : `1`}, ${settings.invertY ? `-1` : `1`}) `; - transformValue += - `rotate(${settings.rotation}deg)`; + /** if this is an media container, settings diverge here */ + if (this.mediaUrl != undefined) { + document + .getElementById(this.id + "-settings-mirror-x") + .addEventListener("change", toggleMirrorX, false); + document + .getElementById(this.id + "-settings-mirror-y") + .addEventListener("change", toggleMirrorY, false); + return; + } - document.getElementById(this.id).style.transform = transformValue; - return; - } - - /** apply text-container-only customizations */ + /** text-only settings */ + // container background color setting listeners + document + .getElementById(this.id + "-settings-bg-color") + .addEventListener("input", changeContainerBackground, false); + document + .getElementById(this.id + "-settings-bg-alpha") + .addEventListener("input", changeContainerBackground, false); + // container text setting listeners + document + .getElementById(this.id + "-settings-set-font-button") + .addEventListener("click", changeFont, false); + document + .getElementById(this.id + "-settings-left-align") + .addEventListener("change", changeContainerAlignment, false); + document + .getElementById(this.id + "-settings-center-align") + .addEventListener("change", changeContainerAlignment, false); + document + .getElementById(this.id + "-settings-right-align") + .addEventListener("change", changeContainerAlignment, false); - - /** FONT */ - if (settings.fontCode != "") { - document.head.insertAdjacentHTML( - "beforeend", - settings.fontCode - ); - document.getElementById(this.id).style.fontFamily = - settings.fontName; + // bookmark section setting listeners + document + .getElementById(this.id + "-settings-section-color") + .addEventListener("input", changeSectionColor, false); + document + .getElementById(this.id + "-settings-section-size") + .addEventListener("input", changeSectionSize, false); + document + .getElementById(this.id + "-settings-section-bold") + .addEventListener("change", toggleSectionBold, false); + document + .getElementById(this.id + "-settings-section-italic") + .addEventListener("change", toggleSectionItalic, false); + // bookmark setting listeners + document + .getElementById(this.id + "-settings-link-color") + .addEventListener("input", changeLinkColor, false); + document + .getElementById(this.id + "-settings-link-size") + .addEventListener("input", changeLinkSize, false); + document + .getElementById(this.id + "-settings-link-decor") + .addEventListener("change", toggleLinkDecor, false); + document + .getElementById(this.id + "-settings-link-bold") + .addEventListener("change", toggleLinkBold, false); + document + .getElementById(this.id + "-settings-link-italic") + .addEventListener("change", toggleLinkItalic, false); + // clock setting listeners + document + .getElementById(this.id + "-settings-date-toggle") + .addEventListener("input", toggleDate, false); + document + .getElementById(this.id + "-settings-clock-toggle") + .addEventListener("input", toggleClock, false); + document + .getElementById(this.id + "-settings-clock-color") + .addEventListener("input", changeHeaderColor, false); + document + .getElementById(this.id + "-settings-clock-size") + .addEventListener("input", changeHeaderSize, false); + document + .getElementById(this.id + "-settings-date-bold") + .addEventListener("change", toggleDateBold, false); + document + .getElementById(this.id + "-settings-clock-bold") + .addEventListener("change", toggleClockBold, false); + document + .getElementById(this.id + "-settings-date-italic") + .addEventListener("change", toggleDateItalic, false); + document + .getElementById(this.id + "-settings-clock-italic") + .addEventListener("change", toggleClockItalic, false); + // container divider setting listeners + document + .getElementById(this.id + "-settings-divider-toggle") + .addEventListener("change", toggleDivider, false); + document + .getElementById(this.id + "-settings-divider-color") + .addEventListener("input", changeDividerColor, false); } + + /* + * applies saved cosmetic customizations to container upon init (both text+media containers) + */ + applySettings() { + /** apply customizations relevant to both image and text containers */ + /** POSITION */ + document.getElementById(this.id).style.top = this.y; + document.getElementById(this.id).style.left = this.x; + document.getElementById(this.id).style.zIndex = this.settings.zIndex; + + /** SIZE */ + let settings = this.settings; + document.getElementById(this.id).style.width = this.width + "px"; + // this.width - 2 * parseInt(settings.borderWidth); + document.getElementById(this.id).style.height = this.height + "px"; + // this.height - 2 * parseInt(settings.borderWidth); - /** TEXT ALIGNMENT */ - if (settings.textAlign == "center") { - document.getElementById(this.id).style.textAlign = "center"; - } else if (settings.textAlign == "left") { - document.getElementById(this.id).style.textAlign = "left"; - } else if (settings.textAlign == "right") { - document.getElementById(this.id).style.textAlign = "right"; - } + /** SHADOW / GLOW */ + document.getElementById(this.id).style.boxShadow = + settings.shadowX + + "px " + + settings.shadowY + + "px " + + settings.shadowBlur + + "px " + + settings.shadowRgba; - /** BOOKMARK CUSTOMIZATION HAPPENS IN loadBookmarks() FOR EASIER, - LESS INTENSE RE-RENDERING WHEN BOOKMARK CUSTOMIZATIONS CHANGE */ + + /** + * if this is a media container, settings diverge here + */ - /** BACKGROUND COLOR */ - document.getElementById(this.id).style.backgroundColor = - settings.backgroundRgba; + /** BORDER */ + if (this.mediaUrl?.includes("youtube.com") || this.mediaUrl?.includes("youtu.be")) { + // apply border to iframe and cover element rather than containing div + document.getElementById(this.id).children[0].style.borderColor = + settings.borderColor; + document.getElementById(this.id).children[1].style.borderColor = + settings.borderColor; + document.getElementById(this.id).children[0].style.borderWidth = + settings.borderWidth + "px"; + document.getElementById(this.id).children[1].style.borderWidth = + settings.borderWidth + "px"; + document.getElementById(this.id).children[0].style.borderRadius = + settings.borderRadius + "px"; + document.getElementById(this.id).children[1].style.borderRadius = + settings.borderRadius + "px"; + } + else { + document.getElementById(this.id).style.borderRadius = + settings.borderRadius + "px"; + document.getElementById(this.id).style.borderStyle = "solid"; + document.getElementById(this.id).style.borderWidth = + settings.borderWidth + "px"; + document.getElementById(this.id).style.borderColor = + settings.borderColor; + } - /** HEADER */ - // show header elements - document.getElementById(this.id + "-date").style.display = - settings.enableDate ? "inline" : "none"; - document.getElementById(this.id + "-clock").style.display = - settings.enableClock ? "inline" : "none"; - // apply text customizations - document.getElementById(this.id + "-header").style.color = - settings.headerColor; - document.getElementById(this.id + "-header").style.fontSize = - settings.headerSize + "px"; - document.getElementById(this.id + "-date").style.fontWeight = - settings.dateBold ? "bold" : "normal"; - document.getElementById(this.id + "-clock").style.fontWeight = - settings.clockBold ? "bold" : "normal"; - document.getElementById(this.id + "-date").style.fontStyle = - settings.dateItalic ? "italic" : "normal"; - document.getElementById(this.id + "-clock").style.fontStyle = - settings.clockItalic ? "italic" : "normal"; + /** MEDIA MIRRORING + ROTATOIN*/ + if (this.mediaUrl != undefined) { + let transformValue = + `scale(${settings.invertX ? `-1` : `1`}, ${settings.invertY ? `-1` : `1`}) `; + transformValue += + `rotate(${settings.rotation}deg)`; - /** DIVIDER */ - let divider = document.getElementById(this.id + "-divider"); - if (!settings.enableDivider) { - document.getElementById(this.id + "-divider").hidden = true; - // if there are links in this container, add room under the divider - if (Object.keys(this.sections).length > 0) { - document.getElementById(this.id + "-header").style.marginBottom = - "18px"; + document.getElementById(this.id).style.transform = transformValue; + return; } - } else { - divider.style.color = settings.dividerColor; - divider.style.backgroundColor = settings.dividerColor; - divider.style.borderColor = settings.dividerColor; - } + + /** apply text-container-only customizations */ - /** ROTATION */ - document.getElementById(this.id).style.transform = - "rotate(" + settings.rotation + "deg)"; - - } + + /** FONT */ + if (settings.fontCode != "") { + document.head.insertAdjacentHTML( + "beforeend", + settings.fontCode + ); + document.getElementById(this.id).style.fontFamily = + settings.fontName; + } - /** - * applies event listeners (moving/resizing) for the container - */ - addContainerEventListeners() { - let container = document.getElementById(this.id); + /** TEXT ALIGNMENT */ + if (settings.textAlign == "center") { + document.getElementById(this.id).style.textAlign = "center"; + } else if (settings.textAlign == "left") { + document.getElementById(this.id).style.textAlign = "left"; + } else if (settings.textAlign == "right") { + document.getElementById(this.id).style.textAlign = "right"; + } - // make element movable + resizable - container.addEventListener( - "mousedown", - mouseDownMovableElement, - true - ); + /** BOOKMARK CUSTOMIZATION HAPPENS IN loadBookmarks() FOR EASIER, + LESS INTENSE RE-RENDERING WHEN BOOKMARK CUSTOMIZATIONS CHANGE */ - container.addEventListener( - "keydown", - keyDownMovableElement, - false - ); + /** BACKGROUND COLOR */ + document.getElementById(this.id).style.backgroundColor = + settings.backgroundRgba; - container.addEventListener("contextmenu", (e) => { - e.preventDefault(); - }); + /** HEADER */ + // show header elements + document.getElementById(this.id + "-date").style.display = + settings.enableDate ? "inline" : "none"; + document.getElementById(this.id + "-clock").style.display = + settings.enableClock ? "inline" : "none"; + // apply text customizations + document.getElementById(this.id + "-header").style.color = + settings.headerColor; + document.getElementById(this.id + "-header").style.fontSize = + settings.headerSize + "px"; + document.getElementById(this.id + "-date").style.fontWeight = + settings.dateBold ? "bold" : "normal"; + document.getElementById(this.id + "-clock").style.fontWeight = + settings.clockBold ? "bold" : "normal"; + document.getElementById(this.id + "-date").style.fontStyle = + settings.dateItalic ? "italic" : "normal"; + document.getElementById(this.id + "-clock").style.fontStyle = + settings.clockItalic ? "italic" : "normal"; - // stop resizing element if cursor leaves page - document.addEventListener("mouseleave", (mouseLeave) => { - if (resizing) { - resizing = false; - document.removeEventListener("mousemove", resizeElement); - storeElementData(); + /** DIVIDER */ + let divider = document.getElementById(this.id + "-divider"); + if (!settings.enableDivider) { + document.getElementById(this.id + "-divider").hidden = true; + // if there are links in this container, add room under the divider + if (Object.keys(this.sections).length > 0 && + (settings.enableDate || settings.enableClock) + ) { + document.getElementById(this.id + "-header").style.marginBottom = + "18px"; + } + } else { + divider.style.color = settings.dividerColor; + divider.style.backgroundColor = settings.dividerColor; + divider.style.borderColor = settings.dividerColor; } - }); - } - - /** - * [re]renders saved bookmark sections + links for container - */ - loadBookmarks() { - if (Object.keys(this.sections).length == 0) { - let containerBookmarks = document.getElementById(this.id + "-bookmarks"); - containerBookmarks.innerHTML = ""; - return; + /** ROTATION */ + document.getElementById(this.id).style.transform = + "rotate(" + settings.rotation + "deg)"; + } - let sectionData = Object.values(this.sections); - let settings = this.settings; + /** + * applies event listeners (moving/resizing) for the container + */ + addContainerEventListeners() { + let container = document.getElementById(this.id); - let containerBookmarks = document.getElementById(this.id + "-bookmarks"); - - containerBookmarks.innerHTML = ""; - for (let i = 0; i < sectionData.length; i++) { - containerBookmarks.insertAdjacentHTML( - "beforeend", - ` - ${i == 0 ? "" : `<br />`} - <div id="${this.id}-section-${i}"> - - <span class=${this.id + "-section"}> - ${sectionData[i].label} - </span> + // make element movable + resizable + container.addEventListener( + "mousedown", + mouseDownMovableElement, + true + ); - </div> - ` + container.addEventListener( + "keydown", + keyDownMovableElement, + false ); + + container.addEventListener("contextmenu", (e) => { + e.preventDefault(); + }); + + // stop resizing element if cursor leaves page + document.addEventListener("mouseleave", (mouseLeave) => { + if (resizing) { + resizing = false; + document.removeEventListener("mousemove", resizeElement); + storeElementData(); + } + }); } - // and then render the links - for (let s = 0; s < sectionData.length; s++) { - for (let l = 0; l < sectionData[s].links.length; l++) { - let targetSection = document.getElementById( - this.id + "-section-" + s - ); + + /** + * [re]renders saved bookmark sections + links for container + */ + loadBookmarks() { + if (Object.keys(this.sections).length == 0) { + let containerBookmarks = document.getElementById(this.id + "-bookmarks"); + containerBookmarks.innerHTML = ""; + return; + } - targetSection.insertAdjacentHTML( + let sectionData = Object.values(this.sections); + let settings = this.settings; + + let containerBookmarks = document.getElementById(this.id + "-bookmarks"); + + containerBookmarks.innerHTML = ""; + for (let i = 0; i < sectionData.length; i++) { + containerBookmarks.insertAdjacentHTML( "beforeend", ` - <div id="${this.id}-section-${s}-link-${l}" > + ${i == 0 ? "" : `<br />`} + <div id="${this.id}-section-${i}"> + + <span class=${this.id + "-section"}> + ${sectionData[i].label} + </span> - <a - class="${this.id}-link" - href="${sectionData[s].links[l].url}" - > - ${sectionData[s].links[l].label} - </a> </div> ` ); } - } - // ensure smooth ux when rerendering - if (!settings.enableDivider) { - document.getElementById(this.id + "-header").style.marginBottom = "18px"; - } + // and then render the links + for (let s = 0; s < sectionData.length; s++) { + for (let l = 0; l < sectionData[s].links.length; l++) { + let targetSection = document.getElementById( + this.id + "-section-" + s + ); - // apply link customization - let linkElements = document.getElementsByClassName(this.id + "-link"); - for (let i = 0; i < linkElements.length; i++) { - linkElements[i].style.color = settings.linkColor; - linkElements[i].style.fontSize = settings.linkSize + "px"; - linkElements[i].style.textDecoration = settings.linkDecor ? - "underline" : "none"; - linkElements[i].style.fontWeight = settings.linkBold ? - "bold" : "normal"; - linkElements[i].style.fontStyle = settings.linkItalic ? - "italic" : "normal"; - } - // apply section customization - let sectionElements = document.getElementsByClassName(this.id + "-section"); - for (let i = 0; i < sectionElements.length; i++) { - sectionElements[i].style.color = settings.sectionColor; - sectionElements[i].style.fontSize = settings.sectionSize + "px"; - sectionElements[i].style.fontWeight = settings.sectionBold ? "bold" : "normal"; - sectionElements[i].style.fontStyle = settings.sectionItalic ? "italic" : "normal"; + targetSection.insertAdjacentHTML( + "beforeend", + ` + <div id="${this.id}-section-${s}-link-${l}" + ${l < sectionData[s].links.length - 1 ? + `style="margin-bottom: .5rem"` : + `style="margin-bottom: 5px"`} + > + + <a + class="${this.id}-link" + href="${sectionData[s].links[l].url}" + + > + ${sectionData[s].links[l].label} + </a> + </div> + ` + ); + } + } + + // ensure smooth ux when rerendering + if (!settings.enableDivider && + (settings.enableDate || settings.enableClock) + ) { + document.getElementById(this.id + "-header").style.marginBottom = "18px"; + } + + // apply link customization + let linkElements = document.getElementsByClassName(this.id + "-link"); + for (let i = 0; i < linkElements.length; i++) { + linkElements[i].style.color = settings.linkColor; + linkElements[i].style.fontSize = settings.linkSize + "px"; + linkElements[i].style.textDecoration = settings.linkDecor ? + "underline" : "none"; + linkElements[i].style.fontWeight = settings.linkBold ? + "bold" : "normal"; + linkElements[i].style.fontStyle = settings.linkItalic ? + "italic" : "normal"; + } + // apply section customization + let sectionElements = document.getElementsByClassName(this.id + "-section"); + for (let i = 0; i < sectionElements.length; i++) { + sectionElements[i].style.color = settings.sectionColor; + sectionElements[i].style.fontSize = settings.sectionSize + "px"; + sectionElements[i].style.fontWeight = settings.sectionBold ? "bold" : "normal"; + sectionElements[i].style.fontStyle = settings.sectionItalic ? "italic" : "normal"; + } } + } - - } - /****************************** - * page constructor / init :p * - ******************************/ - (() => { - console.log("========== if you're looking in here because something is broken, reset the page with the `localStorage.clear()` command. that should fix everything"); - window.onbeforeunload = unloadPage; - - /** add keybinds */ - document.body.addEventListener("keydown", (e) => { - if (e.key == "e" && !editing) { - toggleEditMode(); + /****************************** + * page constructor / init :p * + ******************************/ + (() => { + console.log("========== if you're looking in here because something is broken, reset the page with the `localStorage.clear()` command. that should fix everything"); + window.onbeforeunload = unloadPage; + + /** add keybinds */ + document.body.addEventListener("keydown", (e) => { + if (e.key == "e" && !editing) { + toggleEditMode(); + } + if (e.key == "Escape" && editing) { + toggleEditMode(); + } + }); + + /** set edit mode toggle color */ + editToggleRgba = localStorage.getItem("editToggleRgba") + || "rgba(0,0,0,1)"; + document.getElementById("editToggle").style.color = editToggleRgba; + // fill in inputs with saved value + document.getElementById("edit-toggle-color").value = + rgbToHex( + editToggleRgba.replace("rgba(", "").slice(0, -1).split(",").splice(0, 3) + ); + document.getElementById("edit-toggle-alpha").value = + parseInt( + editToggleRgba.replace("rgba(", "").slice(0, -1).split(",")[3] + ) * 100; + // set event listeners + document + .getElementById("edit-toggle-color") + .addEventListener("input", changeEditToggleColor, false); + document + .getElementById("edit-toggle-alpha") + .addEventListener("input", changeEditToggleColor, false); + + /** set wallpaper */ + wallpaper = JSON.parse(localStorage.getItem("wallpaper")) || ""; + if (wallpaper.startsWith("#")) { + document.body.style.background = wallpaper; + document.getElementById("wallpaperColorPicker").value = wallpaper; + } else { + document.body.style.backgroundImage = "url('" + wallpaper + "')"; } - if (e.key == "Escape" && editing) { - toggleEditMode(); + repeatWallpaper = + JSON.parse(localStorage.getItem("repeatWallpaper")) || false; + if (repeatWallpaper) { + document.body.style.backgroundSize = "contain"; + document.getElementById("wallpaperRepeatToggle").checked = true; + } else { + document.body.style.backgroundSize = "cover"; + document.body.style.backgroundPosition = "center"; } - }); + // set wallpaper event listeners + document + .getElementById("wallpaperColorPicker") + .addEventListener("input", changeWallpaper, false); + document + .getElementById("wallpaperRepeatToggle") + .addEventListener("change", toggleWallpaperRepeat, false); - /** set edit mode toggle color */ - editToggleRgba = localStorage.getItem("editToggleRgba") - || "rgba(0,0,0,1)"; - document.getElementById("editToggle").style.color = editToggleRgba; - // fill in inputs with saved value - document.getElementById("edit-toggle-color").value = - rgbToHex( - editToggleRgba.replace("rgba(", "").slice(0, -1).split(",").splice(0, 3) - ); - document.getElementById("edit-toggle-alpha").value = - parseInt( - editToggleRgba.replace("rgba(", "").slice(0, -1).split(",")[3] - ) * 100; - // set event listeners - document - .getElementById("edit-toggle-color") - .addEventListener("input", changeEditToggleColor, false); - document - .getElementById("edit-toggle-alpha") - .addEventListener("input", changeEditToggleColor, false); + /* init audio + auto-play */ + audioLink = JSON.parse(localStorage.getItem("audioLink")) || ""; + document.getElementById("audioSource").src = audioLink; + autoplayAudio = + JSON.parse(localStorage.getItem("autoplayAudio")) || false; + document.getElementById("autoplayAudioToggle").checked = autoplayAudio; + if (audioLink != "" && autoplayAudio) { + document + .getElementById("audio") + .play() + .catch((error) => { + alert( + "auto-playing audio won't work unless you whitelist this page in your browser!" + ); + }); + } + // add event listeners + document + .getElementById("autoplayAudioToggle") + .addEventListener("change", toggleAutoplayAudio, false); - /** set wallpaper */ - wallpaper = JSON.parse(localStorage.getItem("wallpaper")) || ""; - if (wallpaper.startsWith("#")) { - document.body.style.background = wallpaper; - document.getElementById("wallpaperColorPicker").value = wallpaper; - } else { - document.body.style.backgroundImage = "url('" + wallpaper + "')"; - } - repeatWallpaper = - JSON.parse(localStorage.getItem("repeatWallpaper")) || false; - if (repeatWallpaper) { - document.body.style.backgroundSize = "contain"; - document.getElementById("wallpaperRepeatToggle").checked = true; - } else { - document.body.style.backgroundSize = "cover"; - document.body.style.backgroundPosition = "center"; - } - // set wallpaper event listeners - document - .getElementById("wallpaperColorPicker") - .addEventListener("input", changeWallpaper, false); - document - .getElementById("wallpaperRepeatToggle") - .addEventListener("change", toggleWallpaperRepeat, false); - /* init audio + auto-play */ - audioLink = JSON.parse(localStorage.getItem("audioLink")) || ""; - document.getElementById("audioSource").src = audioLink; - autoplayAudio = - JSON.parse(localStorage.getItem("autoplayAudio")) || false; - document.getElementById("autoplayAudioToggle").checked = autoplayAudio; - if (audioLink != "" && autoplayAudio) { - document - .getElementById("audio") - .play() - .catch((error) => { - alert( - "auto-playing audio won't work unless you whitelist this page in your browser!" - ); - }); - } - // add event listeners - document - .getElementById("autoplayAudioToggle") - .addEventListener("change", toggleAutoplayAudio, false); + /** load container data */ + let zIndexMapData = JSON.parse(localStorage.getItem("zIndexMapData")) || []; + let zIndexMapKeys = Object.keys(zIndexMapData) || []; + for (let i = 0; i < zIndexMapKeys.length; i++) { + zIndexMap.set( + zIndexMapKeys[i], + zIndexMapData[zIndexMapKeys[i]] + ); + } + let containerMapValues = + JSON.parse(localStorage.getItem("containerMapValues")) || []; + numberTotalContainers = containerMapValues.length; + + for (let i = 0; i < numberTotalContainers; i++) { + containerDataMap.set(containerMapValues[i].id, new Container( + containerMapValues[i].id, + containerMapValues[i].name, + containerMapValues[i].x, + containerMapValues[i].y, + containerMapValues[i].height, + containerMapValues[i].width, + containerMapValues[i].mediaUrl, + containerMapValues[i].settings, + containerMapValues[i].sections, + containerMapValues[i].youtubeId, + containerMapValues[i].imageHyperlink + )); + } - /** load container data */ - let zIndexMapData = JSON.parse(localStorage.getItem("zIndexMapData")) || []; - let zIndexMapKeys = Object.keys(zIndexMapData) || []; - for (let i = 0; i < zIndexMapKeys.length; i++) { - zIndexMap.set( - zIndexMapKeys[i], - zIndexMapData[zIndexMapKeys[i]] - ); - } + + /** set up + load settings menu data */ + settingsMenuData = JSON.parse( + localStorage.getItem("settingsMenuData") + ) || { + x: "", + y: "", + width: "", + height: "", + }; + setupSettingsContainer(); + // load last active settings tab user was on + activeTabId = + JSON.parse(localStorage.getItem("activeTabId")) || "helpTab"; + document.getElementById( + activeTabId.replace("Tab", "Page") + ).style.display = "flex"; + document.getElementById(activeTabId).classList.add("active"); + // add tab-switching listeners + let tabs = document.getElementsByClassName("tab"); + for (let i = 0; i < tabs.length; i++) { + tabs[i].addEventListener("click", changeActiveTab, false); + } - let containerMapValues = - JSON.parse(localStorage.getItem("containerMapValues")) || []; - numberTotalContainers = containerMapValues.length; - - for (let i = 0; i < numberTotalContainers; i++) { - containerDataMap.set(containerMapValues[i].id, new Container( - containerMapValues[i].id, - containerMapValues[i].name, - containerMapValues[i].x, - containerMapValues[i].y, - containerMapValues[i].height, - containerMapValues[i].width, - containerMapValues[i].mediaUrl, - containerMapValues[i].settings, - containerMapValues[i].sections, - containerMapValues[i].youtubeId, - containerMapValues[i].imageHyperlink - )); - } + /** set up cursors */ + cursors = JSON.parse(localStorage.getItem("cursors")) || {}; + if (cursors != {}) { + // apply new default cursor to entire html document + document.getElementsByTagName("html")[0].style.cursor = + cursors.link ? 'url("' + cursors.default + '"), auto' : ""; + // apply link hover cursor + let links = document.getElementsByTagName("a"); + for (let i = 0; i < links.length; i++) { + links[i].style.cursor = cursors.link ? 'url("' + cursors.link + '"), pointer' : "pointer"; + } + } - - /** set up + load settings menu data */ - settingsMenuData = JSON.parse( - localStorage.getItem("settingsMenuData") - ) || { - x: "", - y: "", - width: "", - height: "", - }; - setupSettingsContainer(); - // load last active settings tab user was on - activeTabId = - JSON.parse(localStorage.getItem("activeTabId")) || "helpTab"; - document.getElementById( - activeTabId.replace("Tab", "Page") - ).style.display = "flex"; - document.getElementById(activeTabId).classList.add("active"); - // add tab-switching listeners - let tabs = document.getElementsByClassName("tab"); - for (let i = 0; i < tabs.length; i++) { - tabs[i].addEventListener("click", changeActiveTab, false); - } + // lastly, set current state as download contents for export button + const exportData = new Blob([JSON.stringify(localStorage)], {type: 'text/plain'}); + const url = window.URL.createObjectURL(exportData); + document.getElementById("export-button").href = url; + })(); - /** set up cursors */ - cursors = JSON.parse(localStorage.getItem("cursors")) || {}; - if (cursors != {}) { - // apply new default cursor to entire html document - document.getElementsByTagName("html")[0].style.cursor = - cursors.link ? 'url("' + cursors.default + '"), auto' : ""; - // apply link hover cursor - let links = document.getElementsByTagName("a"); - for (let i = 0; i < links.length; i++) { - links[i].style.cursor = cursors.link ? 'url("' + cursors.link + '"), pointer' : "pointer"; + /************************** + * INITIALIZATION HELPERS * + **************************/ + function setupSettingsContainer() { + let settingsContainer = document.getElementById("settingsContainer"); + + if (numberTotalContainers == 0) { + document.getElementById("containers").insertAdjacentHTML( + "beforeend", + `<p id="noContainerWarning" style="text-align: center">(you have no layers right now)</p>` + ); } - } - // lastly, set current state as download contents for export button - const exportData = new Blob([JSON.stringify(localStorage)], {type: 'text/plain'}); - const url = window.URL.createObjectURL(exportData); - document.getElementById("export-button").href = url; - })(); + // render listings of existing containers in menu, in order of z-index + for (let i = 1; i <= numberTotalContainers; i++) { + let currentContainer = containerDataMap.get(zIndexMap.get(String(i))); + if (currentContainer.mediaUrl == undefined) { + currentContainer.createTextContainerMenuListing(); + currentContainer.loadBookmarkListings(); + } + else { + currentContainer.createMediaContainerMenuListing(); + } + currentContainer.addSettingsMenuEventListeners(); + } - /************************** - * INITIALIZATION HELPERS * - **************************/ - function setupSettingsContainer() { - let settingsContainer = document.getElementById("settingsContainer"); + /* place settings container at the last saved location */ + settingsContainer.style.top = settingsMenuData.y; + settingsContainer.style.left = settingsMenuData.x; + settingsContainer.style.width = settingsMenuData.width + "px"; + settingsContainer.style.height = settingsMenuData.height + "px"; - if (numberTotalContainers == 0) { - document.getElementById("containers").insertAdjacentHTML( - "beforeend", - `<p id="noContainerWarning" style="text-align: center">(you have no layers right now)</p>` + /* add event listeners */ + // moving / resizing + settingsContainer.addEventListener( + "mousedown", + mouseDownMovableElement, + true ); + // local state inputs + document.getElementById("imageRatioToggle").checked = !keepImageRatio; + document + .getElementById("imageRatioToggle") + .addEventListener("change", toggleImageRatio, false); + + + // prevent context menu when resizing + settingsContainer.addEventListener("contextmenu", (e) => { + e.preventDefault(); + }); + + // stop resizing element if cursor leaves page + document.addEventListener("mouseleave", (mouseLeave) => { + if (resizing) { + resizing = false; + document.removeEventListener("mousemove", resizeElement); + storeElementData(); + } + }); } - // render listings of existing containers in menu, in order of z-index - for (let i = 1; i <= numberTotalContainers; i++) { - let currentContainer = containerDataMap.get(zIndexMap.get(String(i))); - if (currentContainer.mediaUrl == undefined) { - currentContainer.createTextContainerMenuListing(); - currentContainer.loadBookmarkListings(); + /************************ + * LOCAL STATE MANAGERS * + ************************/ + + /** primary event handler for toggling page editing */ + function toggleEditMode() { + // enable editing mode (reveal hidden elements) + if (editing == false) { + editing = true; + toggleEditingElements(true); } + // disable editing mode + save element data else { - currentContainer.createMediaContainerMenuListing(); - } - currentContainer.addSettingsMenuEventListeners(); - } + editing = false; + toggleEditingElements(false); + document.getElementById("editToggle").innerHTML = "saving"; - /* place settings container at the last saved location */ - settingsContainer.style.top = settingsMenuData.y; - settingsContainer.style.left = settingsMenuData.x; - settingsContainer.style.width = settingsMenuData.width + "px"; - settingsContainer.style.height = settingsMenuData.height + "px"; + // if data was just imported directly to localStorage, don't save current element states (would overwrite import) + if (justImported) { + justImported = false; + return; + } - /* add event listeners */ - // moving / resizing - settingsContainer.addEventListener( - "mousedown", - mouseDownMovableElement, - true - ); - // local state inputs - document.getElementById("imageRatioToggle").checked = !keepImageRatio; - document - .getElementById("imageRatioToggle") - .addEventListener("change", toggleImageRatio, false); - - - // prevent context menu when resizing - settingsContainer.addEventListener("contextmenu", (e) => { - e.preventDefault(); - }); + // save state of settings menu + localStorage.setItem( + "settingsMenuData", + JSON.stringify(settingsMenuData) + ); - // stop resizing element if cursor leaves page - document.addEventListener("mouseleave", (mouseLeave) => { - if (resizing) { - resizing = false; - document.removeEventListener("mousemove", resizeElement); - storeElementData(); - } - }); - } + // save states of all containers + let valueArray = []; + containerDataMap.values().forEach((value) => { + valueArray.push(value); + }); + localStorage.setItem("containerMapValues", JSON.stringify(valueArray)); - /************************ - * LOCAL STATE MANAGERS * - ************************/ + /* save z-indexes */ + let temp = {}; + zIndexMap.keys().forEach((key) => { + temp[key] = zIndexMap.get(key); + }); + localStorage.setItem("zIndexMapData", JSON.stringify(temp)); - /** primary event handler for toggling page editing */ - function toggleEditMode() { - // enable editing mode (reveal hidden elements) - if (editing == false) { - editing = true; - toggleEditingElements(true); - } - // disable editing mode + save element data - else { - editing = false; - toggleEditingElements(false); - document.getElementById("editToggle").innerHTML = "saving"; + // save wallpaper info + localStorage.setItem("wallpaper", JSON.stringify(wallpaper)); + localStorage.setItem( + "repeatWallpaper", + JSON.stringify(repeatWallpaper) + ); - // if data was just imported directly to localStorage, don't save current element states (would overwrite import) - if (justImported) { - justImported = false; - return; - } + // save doodad + gadget cookies + localStorage.setItem("audioLink", JSON.stringify(audioLink)); + localStorage.setItem("autoplayAudio", JSON.stringify(autoplayAudio)); + localStorage.setItem("cursors", JSON.stringify(cursors)); - // save state of settings menu - localStorage.setItem( - "settingsMenuData", - JSON.stringify(settingsMenuData) - ); + // save active settings tab for next session + localStorage.setItem("activeTabId", JSON.stringify(activeTabId)); - // save states of all containers - let valueArray = []; - containerDataMap.values().forEach((value) => { - valueArray.push(value); - }); - localStorage.setItem("containerMapValues", JSON.stringify(valueArray)); + // save edit mode toggle customization + localStorage.setItem("editToggleRgba", editToggleRgba); - /* save z-indexes */ - let temp = {}; - zIndexMap.keys().forEach((key) => { - temp[key] = zIndexMap.get(key); - }); - localStorage.setItem("zIndexMapData", JSON.stringify(temp)); + // lastly, set current state as download contents for export button + const exportData = new Blob([JSON.stringify(localStorage)], {type: 'text/plain'}); + const url = window.URL.createObjectURL(exportData); + document.getElementById("export-button").href = url; - // save wallpaper info - localStorage.setItem("wallpaper", JSON.stringify(wallpaper)); - localStorage.setItem( - "repeatWallpaper", - JSON.stringify(repeatWallpaper) - ); + document.getElementById("editToggle").innerHTML = "edit page"; + } + } - // save doodad + gadget cookies - localStorage.setItem("audioLink", JSON.stringify(audioLink)); - localStorage.setItem("autoplayAudio", JSON.stringify(autoplayAudio)); - localStorage.setItem("cursors", JSON.stringify(cursors)); + /** handles the revealing/concealing of elements part of toggling edit mode */ + function toggleEditingElements(show) { + const editButton = document.getElementById("editToggle"); + const settingsContainer = document.getElementById("settingsContainer"); - // save active settings tab for next session - localStorage.setItem("activeTabId", JSON.stringify(activeTabId)); + /** when editing-mode is enabled, */ + if (show) { + editButton.innerHTML = "save + stop editing"; - // save edit mode toggle customization - localStorage.setItem("editToggleRgba", editToggleRgba); + // reveal settings container + settingsContainer.classList.remove("hidden"); - // lastly, set current state as download contents for export button - const exportData = new Blob([JSON.stringify(localStorage)], {type: 'text/plain'}); - const url = window.URL.createObjectURL(exportData); - document.getElementById("export-button").href = url; + // change cursor on movable elements to indicate grabbable + let movableElements = document.getElementsByClassName("movable"); + for (let i = 0; i < movableElements.length; i++) { + // mmovableElements[i].classList.add("grabbable"); + movableElements[i].style.cursor = cursors.grab ? 'url("' + cursors.grab + '"), grab' : "grab"; + } - document.getElementById("editToggle").innerHTML = "edit page"; - } - } + // take hyperlinked images out of anchor tags to enable moving/resizing + let hyperlinkedImages = document.getElementsByClassName("hyperlinkedImage"); + let parent, clone; + for (let i = 0; i < hyperlinkedImages.length; i++) { + parent = hyperlinkedImages[i].parentElement; + clone = hyperlinkedImages[i].cloneNode(); + hyperlinkedImages[i].remove(); + parent.parentNode.insertBefore(clone, parent); + parent.remove(); + containerDataMap.get(clone.id).addContainerEventListeners(); + } - /** handles the revealing/concealing of elements part of toggling edit mode */ - function toggleEditingElements(show) { - const editButton = document.getElementById("editToggle"); - const settingsContainer = document.getElementById("settingsContainer"); + // cover any youtube iframes to enable moving/resizing + let embeddedVideos = document.getElementsByClassName("youtubeEmbedCover"); + for (let i = 0; i < embeddedVideos.length; i++) { + embeddedVideos[i].style.display = "block"; + } - /** when editing-mode is enabled, */ - if (show) { - editButton.innerHTML = "save + stop editing"; + } else { + // remove grabbable cursor + let movableElements = document.getElementsByClassName("movable"); + for (let i = 0; i < movableElements.length; i++) { + movableElements[i].style.cursor = ""; + } - // reveal settings container - settingsContainer.classList.remove("hidden"); + // activate links on hyperlinked images + let hyperlinkedImages = document.getElementsByClassName("hyperlinkedImage"); + let link, clone; + for (let i = 0; i < hyperlinkedImages.length; i++) { + containerId = hyperlinkedImages[i].id; + link = containerDataMap.get(containerId).imageHyperlink; + clone = hyperlinkedImages[i].cloneNode(); + + hyperlinkedImages[i].insertAdjacentHTML("afterend", + `<a id="` + containerId + `--hyperlink" href="` + link + `"></a>` + ); + hyperlinkedImages[i].remove(); + document.getElementById(containerId + "--hyperlink").appendChild(clone); - // change cursor on movable elements to indicate grabbable - let movableElements = document.getElementsByClassName("movable"); - for (let i = 0; i < movableElements.length; i++) { - // mmovableElements[i].classList.add("grabbable"); - movableElements[i].style.cursor = cursors.grab ? 'url("' + cursors.grab + '"), grab' : "grab"; - } + if (cursors.link != undefined) { + document.getElementById(containerId + "--hyperlink").style.cursor = cursors.link ? 'url("' + cursors.link + '"), pointer' : ""; + } + } - // take hyperlinked images out of anchor tags to enable moving/resizing - let hyperlinkedImages = document.getElementsByClassName("hyperlinkedImage"); - let parent, clone; - for (let i = 0; i < hyperlinkedImages.length; i++) { - parent = hyperlinkedImages[i].parentElement; - clone = hyperlinkedImages[i].cloneNode(); - hyperlinkedImages[i].remove(); - parent.parentNode.insertBefore(clone, parent); - parent.remove(); - containerDataMap.get(clone.id).addContainerEventListeners(); - } + // remove any youtube iframe covers + let embeddedVideos = document.getElementsByClassName("youtubeEmbedCover"); + for (let i = 0; i < embeddedVideos.length; i++) { + embeddedVideos[i].style.display = "none"; + } - // cover any youtube iframes to enable moving/resizing - let embeddedVideos = document.getElementsByClassName("youtubeEmbedCover"); - for (let i = 0; i < embeddedVideos.length; i++) { - embeddedVideos[i].style.display = "block"; + // hide the settings container + settingsContainer.classList.add("hidden"); } + } - } else { - // remove grabbable cursor - let movableElements = document.getElementsByClassName("movable"); - for (let i = 0; i < movableElements.length; i++) { - movableElements[i].style.cursor = ""; + function toggleExpandableMenu(toggleButton) { + toggleButton.classList.toggle("active"); + let menuContent = toggleButton.nextElementSibling; + + if (menuContent.style.display === "block") { + menuContent.style.display = "none"; + toggleButton.children[1].innerHTML = "+"; + } else { + menuContent.style.display = "block"; + toggleButton.children[1].innerHTML = "-"; } + } - // activate links on hyperlinked images - let hyperlinkedImages = document.getElementsByClassName("hyperlinkedImage"); - let link, clone; - for (let i = 0; i < hyperlinkedImages.length; i++) { - containerId = hyperlinkedImages[i].id; - link = containerDataMap.get(containerId).imageHyperlink; - clone = hyperlinkedImages[i].cloneNode(); - - hyperlinkedImages[i].insertAdjacentHTML("afterend", - `<a id="` + containerId + `--hyperlink" href="` + link + `"></a>` - ); - hyperlinkedImages[i].remove(); - document.getElementById(containerId + "--hyperlink").appendChild(clone); + function collapseLayerListings() { + let listings = document.getElementsByClassName("containerListing"); - if (cursors.link != undefined) { - document.getElementById(containerId + "--hyperlink").style.cursor = cursors.link ? 'url("' + cursors.link + '"), pointer' : ""; + for (let i = 0; i < listings.length; i++) { + // first child of a container listing is always the menu toggle + if (listings[i].children[0].classList.contains("active")) { + toggleExpandableMenu(listings[i].children[0]); } } + } - // remove any youtube iframe covers - let embeddedVideos = document.getElementsByClassName("youtubeEmbedCover"); - for (let i = 0; i < embeddedVideos.length; i++) { - embeddedVideos[i].style.display = "none"; - } + function expandLayerListings() { + let listings = document.getElementsByClassName("containerListing"); - // hide the settings container - settingsContainer.classList.add("hidden"); + for (let i = 0; i < listings.length; i++) { + // first child of a container listing is always the menu toggle + if (!listings[i].children[0].classList.contains("active")) { + toggleExpandableMenu(listings[i].children[0]); + } + } } - } - function toggleExpandableMenu(toggleButton) { - toggleButton.classList.toggle("active"); - let menuContent = toggleButton.nextElementSibling; - - if (menuContent.style.display === "block") { - menuContent.style.display = "none"; - toggleButton.children[1].innerHTML = "+"; - } else { - menuContent.style.display = "block"; - toggleButton.children[1].innerHTML = "-"; + function toggleImageRatio() { + keepImageRatio = !document.getElementById("imageRatioToggle").checked; } - } - - function collapseLayerListings() { - let listings = document.getElementsByClassName("containerListing"); - for (let i = 0; i < listings.length; i++) { - // first child of a container listing is always the menu toggle - if (listings[i].children[0].classList.contains("active")) { - toggleExpandableMenu(listings[i].children[0]); + function toggleWallpaperRepeat(checkbox) { + repeatWallpaper = this.checked; + if (repeatWallpaper) { + document.body.style.backgroundSize = "contain"; + document.body.style.backgroundRepeat = "repeat"; + + } else { + document.body.style.backgroundSize = "cover"; + document.body.style.backgroundPosition = "center"; + document.body.style.backgroundRepeat = "no-repeat"; } } - } - function expandLayerListings() { - let listings = document.getElementsByClassName("containerListing"); - - for (let i = 0; i < listings.length; i++) { - // first child of a container listing is always the menu toggle - if (!listings[i].children[0].classList.contains("active")) { - toggleExpandableMenu(listings[i].children[0]); + function unloadPage() { + if (editing) { + return "you are currently editing and changes are unsaved. stay?"; } } - } - function toggleImageRatio() { - keepImageRatio = !document.getElementById("imageRatioToggle").checked; - } + function changeActiveTab(event) { + // remove 'active' state from current tab + document.getElementById(activeTabId).classList.remove("active"); - function toggleWallpaperRepeat(checkbox) { - repeatWallpaper = this.checked; - if (repeatWallpaper) { - document.body.style.backgroundSize = "contain"; - document.body.style.backgroundRepeat = "repeat"; - - } else { - document.body.style.backgroundSize = "cover"; - document.body.style.backgroundPosition = "center"; - document.body.style.backgroundRepeat = "no-repeat"; - } - } + document.getElementById( + activeTabId.replace("Tab", "Page") + ).style.display = "none"; + + // set new tab + activeTabId = event.target.id; + document.getElementById( + activeTabId.replace("Tab", "Page") + ).style.display = "flex"; - function unloadPage() { - if (editing) { - return "you are currently editing and changes are unsaved. stay?"; + document.getElementById(activeTabId).classList.add("active"); } - } - function changeActiveTab(event) { - // remove 'active' state from current tab - document.getElementById(activeTabId).classList.remove("active"); + /******************************************** + * DOCUMENT MANAGEMENT / MODIFICATION STUFF * + ********************************************/ - document.getElementById( - activeTabId.replace("Tab", "Page") - ).style.display = "none"; + function createNewTextContainer() { + let containerName = document.getElementById( + "newTextContainerNameInput" + ).value; + document.getElementById("newTextContainerNameInput").value = ""; - // set new tab - activeTabId = event.target.id; - document.getElementById( - activeTabId.replace("Tab", "Page") - ).style.display = "flex"; + let container = new Container( + undefined, + containerName, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined + ); - document.getElementById(activeTabId).classList.add("active"); - } + container.createTextContainerMenuListing(); + container.loadBookmarkListings(); + container.addSettingsMenuEventListeners(); + updateContainerListingOrder(); + } - /******************************************** - * DOCUMENT MANAGEMENT / MODIFICATION STUFF * - ********************************************/ + function createNewImageContainer() { + let containerName = document.getElementById( + "newImageContainerNameInput" + ).value; + let mediaUrl = document.getElementById( + "newImageContainerUrlInput" + ).value; + document.getElementById("newImageContainerNameInput").value = ""; + document.getElementById("newImageContainerUrlInput").value = ""; - function createNewTextContainer() { - let containerName = document.getElementById( - "newTextContainerNameInput" - ).value; - document.getElementById("newTextContainerNameInput").value = ""; + let container = new Container( + undefined, + containerName, + undefined, + undefined, + undefined, + undefined, + mediaUrl, + undefined, + undefined, + undefined, + undefined + ); - let container = new Container( - undefined, - containerName, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined - ); + container.createMediaContainerMenuListing(); + container.addSettingsMenuEventListeners(); + updateContainerListingOrder(); + } - container.createTextContainerMenuListing(); - container.loadBookmarkListings(); - container.addSettingsMenuEventListeners(); - updateContainerListingOrder(); - } + /** + * Used in the case of a container being reordered, deleted, or a new container being made. + * Updates all container listing order numbers + recalculates whether they should have up/down buttons + */ + function updateContainerListingOrder() { + // either show "you have no containers" or don't + if (numberTotalContainers > 0 && document.getElementById("noContainerWarning") != undefined) { + document.getElementById("noContainerWarning").remove(); + } + else if (numberTotalContainers == 0 && document.getElementById("noContainerWarning") == undefined) { + document.getElementById("containers").insertAdjacentHTML( + "beforeend", + `<p id="noContainerWarning">(you have no layers right now)</p>` + ); + return; + } - function createNewImageContainer() { - let containerName = document.getElementById( - "newImageContainerNameInput" - ).value; - let mediaUrl = document.getElementById( - "newImageContainerUrlInput" - ).value; - document.getElementById("newImageContainerNameInput").value = ""; - document.getElementById("newImageContainerUrlInput").value = ""; + // go through all container listings and make only the necessary updates + for (let i = 1; i <= numberTotalContainers; i++) { + let currentContainer = containerDataMap.get(zIndexMap.get(String(i))); + let containerListingHeader = document.getElementById(currentContainer.id + "--listing-header"); + let containerManageButtons = document.getElementById(currentContainer.id + "--manage-buttons"); - let container = new Container( - undefined, - containerName, - undefined, - undefined, - undefined, - undefined, - mediaUrl, - undefined, - undefined, - undefined, - undefined - ); + // update layer number + containerListingHeader.innerText = + "[" + currentContainer.settings.zIndex + "] " + currentContainer.name; - container.createMediaContainerMenuListing(); - container.addSettingsMenuEventListeners(); - updateContainerListingOrder(); - } + // remove / insert the necessary up/down buttons + containerManageButtons.innerHTML = ""; + if (currentContainer.settings.zIndex != numberTotalContainers) { + containerManageButtons.insertAdjacentHTML( + "beforeend", + ` + <button id="` + currentContainer.id + `--move-top-button"} onclick="reorderContainer(this, 'top')">summon to top</button> + <button id="` + currentContainer.id + `--move-up-button"} onclick="reorderContainer(this, 'up')">move up</button> + ` + ); + } + if (currentContainer.settings.zIndex != 1) { + containerManageButtons.insertAdjacentHTML( + "beforeend", + ` + <button id="` + currentContainer.id + `--move-down-button"} onclick="reorderContainer(this, 'down')">move down</button> + <button id="` + currentContainer.id + `--move-bottom-button"} onclick="reorderContainer(this, 'bottom')">banish to bottom</button> + ` + ); + } - /** - * Used in the case of a container being reordered, deleted, or a new container being made. - * Updates all container listing order numbers + recalculates whether they should have up/down buttons - */ - function updateContainerListingOrder() { - // either show "you have no containers" or don't - if (numberTotalContainers > 0 && document.getElementById("noContainerWarning") != undefined) { - document.getElementById("noContainerWarning").remove(); - } - else if (numberTotalContainers == 0 && document.getElementById("noContainerWarning") == undefined) { - document.getElementById("containers").insertAdjacentHTML( - "beforeend", - `<p id="noContainerWarning">(you have no layers right now)</p>` - ); - return; + } } - // go through all container listings and make only the necessary updates - for (let i = 1; i <= numberTotalContainers; i++) { - let currentContainer = containerDataMap.get(zIndexMap.get(String(i))); - let containerListingHeader = document.getElementById(currentContainer.id + "--listing-header"); - let containerManageButtons = document.getElementById(currentContainer.id + "--manage-buttons"); + function reorderContainer(buttonPressed, direction) { + /** first, deal with reordering container listings */ + let containerId = buttonPressed.id.split("--")[0]; + let movingContainer = containerDataMap.get(containerId); - // update layer number - containerListingHeader.innerText = - "[" + currentContainer.settings.zIndex + "] " + currentContainer.name; + let currentIndex = parseInt(movingContainer.settings.zIndex); + let destinationIndex; + + // clone + remove the relocating listing + let clickedListingCopy = document.getElementById(containerId + "-container-listing").cloneNode(true); + document.getElementById(containerId + "-container-listing").remove(); - // remove / insert the necessary up/down buttons - containerManageButtons.innerHTML = ""; - if (currentContainer.settings.zIndex != numberTotalContainers) { - containerManageButtons.insertAdjacentHTML( - "beforeend", - ` - <button id="` + currentContainer.id + `--move-top-button"} onclick="reorderContainer(this, 'top')">summon to top</button> - <button id="` + currentContainer.id + `--move-up-button"} onclick="reorderContainer(this, 'up')">move up</button> - ` - ); + /** then, deal with reordering the actual containers */ + + // for up/down, simply swap container element z-indexes + save to map + if (direction == "up" || direction == "down") { + + // determine destination + move listing + if (direction == "up") { + destinationIndex = String(currentIndex + 1); + document.getElementById(zIndexMap.get(destinationIndex) + "-container-listing").insertAdjacentElement("beforebegin", clickedListingCopy); } - if (currentContainer.settings.zIndex != 1) { - containerManageButtons.insertAdjacentHTML( - "beforeend", - ` - <button id="` + currentContainer.id + `--move-down-button"} onclick="reorderContainer(this, 'down')">move down</button> - <button id="` + currentContainer.id + `--move-bottom-button"} onclick="reorderContainer(this, 'bottom')">banish to bottom</button> - ` - ); + else if (direction == "down") { + destinationIndex = String(currentIndex - 1); + document.getElementById(zIndexMap.get(destinationIndex) + "-container-listing").insertAdjacentElement("afterend", clickedListingCopy); } + + // swap z-index of element in destination index with current + document.getElementById(containerId).style.zIndex = destinationIndex; + document.getElementById(zIndexMap.get(destinationIndex)).style.zIndex = currentIndex; + + // save new indexes to container data + movingContainer.settings.zIndex = parseInt(destinationIndex); + containerDataMap.get(zIndexMap.get(destinationIndex)).settings.zIndex = currentIndex; - } - } - - function reorderContainer(buttonPressed, direction) { - /** first, deal with reordering container listings */ - let containerId = buttonPressed.id.split("--")[0]; - let movingContainer = containerDataMap.get(containerId); + // save changes to map + zIndexMap.set(String(currentIndex), zIndexMap.get(destinationIndex)); + zIndexMap.set(destinationIndex, movingContainer.id); - let currentIndex = parseInt(movingContainer.settings.zIndex); - let destinationIndex; - - // clone + remove the relocating listing - let clickedListingCopy = document.getElementById(containerId + "-container-listing").cloneNode(true); - document.getElementById(containerId + "-container-listing").remove(); + // reapply listeners to menu that got remade + containerDataMap.get(zIndexMap.get(destinationIndex)).addSettingsMenuEventListeners(); + } + // for big jumps, we don't just swap z-indexes + else if (direction == "top") { + // moved container will be at end, so we need to ripple all zIndexes between Current and end down 1 + for (let i = currentIndex; i < numberTotalContainers; i++) { + zIndexMap.set(String(i), zIndexMap.get(String(i+1))) + document.getElementById(zIndexMap.get(String(i))).style.zIndex--; + containerDataMap.get(zIndexMap.get(String(i))).settings.zIndex--; + } - /** then, deal with reordering the actual containers */ + // then actually move the container and menu listing element + document.getElementById("containers").insertAdjacentElement("afterbegin", clickedListingCopy); + document.getElementById(containerId).style.zIndex = numberTotalContainers; - // for up/down, simply swap container element z-indexes + save to map - if (direction == "up" || direction == "down") { + // and save + containerDataMap.get(containerId).settings.zIndex = numberTotalContainers; + zIndexMap.set(String(numberTotalContainers), containerId); - // determine destination + move listing - if (direction == "up") { - destinationIndex = String(currentIndex + 1); - document.getElementById(zIndexMap.get(destinationIndex) + "-container-listing").insertAdjacentElement("beforebegin", clickedListingCopy); - } - else if (direction == "down") { - destinationIndex = String(currentIndex - 1); - document.getElementById(zIndexMap.get(destinationIndex) + "-container-listing").insertAdjacentElement("afterend", clickedListingCopy); } - - // swap z-index of element in destination index with current - document.getElementById(containerId).style.zIndex = destinationIndex; - document.getElementById(zIndexMap.get(destinationIndex)).style.zIndex = currentIndex; - - // save new indexes to container data - movingContainer.settings.zIndex = parseInt(destinationIndex); - containerDataMap.get(zIndexMap.get(destinationIndex)).settings.zIndex = currentIndex; + else if (direction == "bottom") { + // moved container is now at bottom, so we need to ripple all other zIndexes up 1 + for (let i = currentIndex; i > 1; i--) { + zIndexMap.set(String(i), zIndexMap.get(String(i - 1))) + document.getElementById(zIndexMap.get(String(i))).style.zIndex++; + containerDataMap.get(zIndexMap.get(String(i))).settings.zIndex++; + } - // save changes to map - zIndexMap.set(String(currentIndex), zIndexMap.get(destinationIndex)); - zIndexMap.set(destinationIndex, movingContainer.id); + document.getElementById("containers").insertAdjacentElement("beforeend", clickedListingCopy); + document.getElementById(containerId).style.zIndex = 1; - // reapply listeners to menu that got remade - containerDataMap.get(zIndexMap.get(destinationIndex)).addSettingsMenuEventListeners(); - } - // for big jumps, we don't just swap z-indexes - else if (direction == "top") { - // moved container will be at end, so we need to ripple all zIndexes between Current and end down 1 - for (let i = currentIndex; i < numberTotalContainers; i++) { - zIndexMap.set(String(i), zIndexMap.get(String(i+1))) - document.getElementById(zIndexMap.get(String(i))).style.zIndex--; - containerDataMap.get(zIndexMap.get(String(i))).settings.zIndex--; + // and save + containerDataMap.get(containerId).settings.zIndex = 1; + zIndexMap.set("1", containerId); } - // then actually move the container and menu listing element - document.getElementById("containers").insertAdjacentElement("afterbegin", clickedListingCopy); - document.getElementById(containerId).style.zIndex = numberTotalContainers; - - // and save - containerDataMap.get(containerId).settings.zIndex = numberTotalContainers; - zIndexMap.set(String(numberTotalContainers), containerId); + // since menu for moving container was removed+readded, we need to reapply listeners to inputs + movingContainer.addSettingsMenuEventListeners(); + // and refresh the listings based on the new saved data + updateContainerListingOrder(); } - else if (direction == "bottom") { - // moved container is now at bottom, so we need to ripple all other zIndexes up 1 - for (let i = currentIndex; i > 1; i--) { - zIndexMap.set(String(i), zIndexMap.get(String(i - 1))) - document.getElementById(zIndexMap.get(String(i))).style.zIndex++; - containerDataMap.get(zIndexMap.get(String(i))).settings.zIndex++; - } - document.getElementById("containers").insertAdjacentElement("beforeend", clickedListingCopy); - document.getElementById(containerId).style.zIndex = 1; + function renameContainer(buttonPressed) { + let containerId = buttonPressed.id.split("--")[0]; + let container = containerDataMap.get(containerId); - // and save - containerDataMap.get(containerId).settings.zIndex = 1; - zIndexMap.set("1", containerId); + let newName = document.getElementById(containerId + "--rename-input").value; + container.name = newName; + document.getElementById(containerId + "--rename-input").value = ""; + + document.getElementById(containerId + "--listing-header").innerText = + "[" + container.settings.zIndex + "]: " + newName; } - // since menu for moving container was removed+readded, we need to reapply listeners to inputs - movingContainer.addSettingsMenuEventListeners(); + function cloneContainer(buttonPressed) { + let containerId; + if (buttonPressed.id) { + containerId = buttonPressed.id.split("--")[0]; + } + else { + // if being called from keyboard shortcut + containerId = buttonPressed; + } + let container = containerDataMap.get(containerId); - // and refresh the listings based on the new saved data - updateContainerListingOrder(); - } + let newSettings = JSON.parse(JSON.stringify(container.settings)); + newSettings.zIndex = numberTotalContainers + 1; - function renameContainer(buttonPressed) { - let containerId = buttonPressed.id.split("--")[0]; - let container = containerDataMap.get(containerId); + let newX = parseInt(container.x.slice(0, -2)) + 10; + let newY = parseInt(container.y.slice(0, -2)) + 10; - let newName = document.getElementById(containerId + "--rename-input").value; - container.name = newName; - document.getElementById(containerId + "--rename-input").value = ""; + let clone = new Container( + findLowestAvailableId(), + container.name + " clone", + String(newX + "px"), + String(newY + "px"), + container.height, + container.width, + container.mediaUrl, + newSettings, + container.sections, + container.youtubeId, + container.imageHyperlink + ); + zIndexMap.set(numberTotalContainers + 1, clone.id); - document.getElementById(containerId + "--listing-header").innerText = - "[" + container.settings.zIndex + "]: " + newName; - } + if (clone.mediaUrl == undefined) { + clone.createTextContainerMenuListing(); + } + else { + clone.createMediaContainerMenuListing(); + } + clone.addSettingsMenuEventListeners(); - function cloneContainer(buttonPressed) { - let containerId; - if (buttonPressed.id) { - containerId = buttonPressed.id.split("--")[0]; + numberTotalContainers++; + updateContainerListingOrder(); } - else { - // if being called from keyboard shortcut - containerId = buttonPressed; - } - let container = containerDataMap.get(containerId); + function deleteContainer(buttonPressed) { + let containerId; + if (buttonPressed.id) { + containerId = buttonPressed.id.split("--")[0]; + } + else { + // if being called from keyboard shortcut + containerId = buttonPressed; + } - let newSettings = JSON.parse(JSON.stringify(container.settings)); - newSettings.zIndex = numberTotalContainers + 1; + let container = containerDataMap.get(containerId); - let newX = parseInt(container.x.slice(0, -2)) + 10; - let newY = parseInt(container.y.slice(0, -2)) + 10; + if (container.mediaUrl == undefined) { + numberOfTextContainers--; + clearInterval(container.clockIntervalId); + } + else { + numberOfMediaContainers--; + } - let clone = new Container( - findLowestAvailableId(), - container.name + " clone", - String(newX + "px"), - String(newY + "px"), - container.height, - container.width, - container.mediaUrl, - newSettings, - container.sections, - container.youtubeId, - container.imageHyperlink - ); - zIndexMap.set(numberTotalContainers + 1, clone.id); + // delete from zindex map and ripple zIndexes down + for (let i = container.settings.zIndex; i < numberTotalContainers; i++) { + zIndexMap.set(String(i), zIndexMap.get(String(i+1))); + containerDataMap.get(zIndexMap.get(String(i+1))).settings.zIndex--; + } + zIndexMap.delete(String(numberTotalContainers)); - if (clone.mediaUrl == undefined) { - clone.createTextContainerMenuListing(); - } - else { - clone.createMediaContainerMenuListing(); - } - clone.addSettingsMenuEventListeners(); + // remove data associated with container + containerDataMap.delete(containerId); + numberTotalContainers--; - numberTotalContainers++; - updateContainerListingOrder(); - } - function deleteContainer(buttonPressed) { - let containerId; - if (buttonPressed.id) { - containerId = buttonPressed.id.split("--")[0]; + document.getElementById(containerId).remove(); + document.getElementById(containerId + "-container-listing").remove(); + + updateContainerListingOrder(); } - else { - // if being called from keyboard shortcut - containerId = buttonPressed; + + /** + * uses map to determine the lowest available ID index for given type, to + * prevent accidentally using the same ID number for unnamed containers twice + */ + function findLowestAvailableId() { + let id = ""; + for(let index = 1; index < 200; index ++) { + id = "container-" + index; + if (!containerDataMap.has(id)) { + return id; + } + } + return -1; } - let container = containerDataMap.get(containerId); + /** upon click release on movable elements, store position data to save to localStorage when edit mode gets disabled */ + function storeElementData() { + let borderWidth = changingElement.style.borderWidth.slice(0, -2) * 2; // slice to remove "px" + let element = document.getElementById(changingElement.id); - if (container.mediaUrl == undefined) { - numberOfTextContainers--; - clearInterval(container.clockIntervalId); - } - else { - numberOfMediaContainers--; + if (changingElement.id == "settingsContainer") { + settingsMenuData.x = element.style.left; + settingsMenuData.y = element.style.top; + settingsMenuData.width = element.offsetWidth; + settingsMenuData.height = element.offsetHeight; + } + else { + let container = containerDataMap.get(element.id); + container.x = element.style.left; + container.y = element.style.top; + container.width = element.offsetWidth - borderWidth; + container.height = element.offsetHeight - borderWidth; + } } - // delete from zindex map and ripple zIndexes down - for (let i = container.settings.zIndex; i < numberTotalContainers; i++) { - zIndexMap.set(String(i), zIndexMap.get(String(i+1))); - containerDataMap.get(zIndexMap.get(String(i+1))).settings.zIndex--; + function setAudioLink() { + let link = document.getElementById("audioLinkInput").value; + if (link == "") { + return; + } + audioLink = link; + document.getElementById("audioLinkInput").value = ""; + document.getElementById("audioSource").src = audioLink; + document.getElementById("audio").load(); } - zIndexMap.delete(String(numberTotalContainers)); - - // remove data associated with container - containerDataMap.delete(containerId); - numberTotalContainers--; - document.getElementById(containerId).remove(); - document.getElementById(containerId + "-container-listing").remove(); - - updateContainerListingOrder(); - } + function toggleAutoplayAudio(checkbox) { + autoplayAudio = this.checked; + } - /** - * uses map to determine the lowest available ID index for given type, to - * prevent accidentally using the same ID number for unnamed containers twice - */ - function findLowestAvailableId() { - let id = ""; - for(let index = 1; index < 200; index ++) { - id = "container-" + index; - if (!containerDataMap.has(id)) { - return id; + function changeWallpaper(event) { + // if image set + if (event == undefined) { + // get background url + let url = document.getElementById("wallpaperUrl").value; + if (url == "") { + alert("must add image url to add background"); + return; + } + document.body.style.backgroundImage = "url('" + url + "')"; + document.getElementById("wallpaperUrl").value = ""; + wallpaper = url; + } + // if solid color set + else { + document.body.style.background = event.target.value; + wallpaper = event.target.value; } } - return -1; - } - /** upon click release on movable elements, store position data to save to localStorage when edit mode gets disabled */ - function storeElementData() { - let borderWidth = changingElement.style.borderWidth.slice(0, -2) * 2; // slice to remove "px" - let element = document.getElementById(changingElement.id); - - if (changingElement.id == "settingsContainer") { - settingsMenuData.x = element.style.left; - settingsMenuData.y = element.style.top; - settingsMenuData.width = element.offsetWidth; - settingsMenuData.height = element.offsetHeight; - } - else { - let container = containerDataMap.get(element.id); - container.x = element.style.left; - container.y = element.style.top; - container.width = element.offsetWidth - borderWidth; - container.height = element.offsetHeight - borderWidth; - } - } + function changeEditToggleColor(colorChange) { + editToggleRgba = hexToRgba( + document.getElementById("edit-toggle-color").value, + document.getElementById("edit-toggle-alpha").value + ); - function setAudioLink() { - let link = document.getElementById("audioLinkInput").value; - if (link == "") { - return; + document.getElementById("editToggle").style.color = editToggleRgba; } - audioLink = link; - document.getElementById("audioLinkInput").value = ""; - document.getElementById("audioSource").src = audioLink; - document.getElementById("audio").load(); - } - - function toggleAutoplayAudio(checkbox) { - autoplayAudio = this.checked; - } - function changeWallpaper(event) { - // if image set - if (event == undefined) { - // get background url - let url = document.getElementById("wallpaperUrl").value; - if (url == "") { - alert("must add image url to add background"); + function moveElement(mouseMove) { + if (!moving) { return; } - document.body.style.backgroundImage = "url('" + url + "')"; - document.getElementById("wallpaperUrl").value = ""; - wallpaper = url; - } - // if solid color set - else { - document.body.style.background = event.target.value; - wallpaper = event.target.value; - } - } - function changeEditToggleColor(colorChange) { - editToggleRgba = hexToRgba( - document.getElementById("edit-toggle-color").value, - document.getElementById("edit-toggle-alpha").value - ); + // calculate offset from last mouse position to current position (1 frame at a time) + let mouseOffsetX = lastMouseX - mouseMove.clientX; + let mouseOffsetY = lastMouseY - mouseMove.clientY; - document.getElementById("editToggle").style.color = editToggleRgba; - } + // save coords of mousepos for use above ^ next frame + lastMouseX = mouseMove.clientX; + lastMouseY = mouseMove.clientY; - function moveElement(mouseMove) { - if (!moving) { - return; + // move to element same distance as mouse offset + changingElement.style.top = + changingElement.offsetTop - mouseOffsetY + "px"; + changingElement.style.left = + changingElement.offsetLeft - mouseOffsetX + "px"; } - // calculate offset from last mouse position to current position (1 frame at a time) - let mouseOffsetX = lastMouseX - mouseMove.clientX; - let mouseOffsetY = lastMouseY - mouseMove.clientY; + function resizeElement(mouseMove) { + if (!resizing) { + return; + } - // save coords of mousepos for use above ^ next frame - lastMouseX = mouseMove.clientX; - lastMouseY = mouseMove.clientY; + // calculate offset from last mouse position to current position (1 frame at a time) + let mouseOffsetX = lastMouseX - mouseMove.clientX; + let mouseOffsetY = lastMouseY - mouseMove.clientY; - // move to element same distance as mouse offset - changingElement.style.top = - changingElement.offsetTop - mouseOffsetY + "px"; - changingElement.style.left = - changingElement.offsetLeft - mouseOffsetX + "px"; - } + // save coords of mousepos for use above ^ next frame + lastMouseX = mouseMove.clientX; + lastMouseY = mouseMove.clientY; - function resizeElement(mouseMove) { - if (!resizing) { - return; - } + let borderWidth = + window.getComputedStyle(changingElement).borderWidth.slice(0, -2) * 2 + + window.getComputedStyle(changingElement).padding.slice(0, -2) * 2; // remove "px" + let currentWidth = changingElement.offsetWidth - borderWidth; + let currentHeight = changingElement.offsetHeight - borderWidth; - // calculate offset from last mouse position to current position (1 frame at a time) - let mouseOffsetX = lastMouseX - mouseMove.clientX; - let mouseOffsetY = lastMouseY - mouseMove.clientY; + // if proportional image resizing enabled + if ((changingElement.tagName == "IMG" || changingElement.classList.contains("media")) && keepImageRatio) { + // growing + if (mouseOffsetY > 0) { + let newWidth = currentWidth * (1 + mouseOffsetY / 100); + let newHeight = currentHeight * (1 + mouseOffsetY / 100); - // save coords of mousepos for use above ^ next frame - lastMouseX = mouseMove.clientX; - lastMouseY = mouseMove.clientY; + // determine offset in px (to keep image center while resizing) + let offsetX = (currentWidth - newWidth) / 2.0; + let offsetY = (currentHeight - newHeight) / 2.0; - let borderWidth = - window.getComputedStyle(changingElement).borderWidth.slice(0, -2) * 2 + - window.getComputedStyle(changingElement).padding.slice(0, -2) * 2; // remove "px" - let currentWidth = changingElement.offsetWidth - borderWidth; - let currentHeight = changingElement.offsetHeight - borderWidth; + changingElement.style.width = newWidth + "px"; + changingElement.style.height = newHeight + "px"; - // if proportional image resizing enabled - if ((changingElement.tagName == "IMG" || changingElement.classList.contains("media")) && keepImageRatio) { - // growing - if (mouseOffsetY > 0) { - let newWidth = currentWidth * (1 + mouseOffsetY / 100); - let newHeight = currentHeight * (1 + mouseOffsetY / 100); + changingElement.style.left = + changingElement.offsetLeft + offsetX + "px"; + changingElement.style.top = + changingElement.offsetTop + offsetY + "px"; + } + // shrinking + else if (mouseOffsetY < 0) { + let newWidth = currentWidth * (1 + mouseOffsetY / 100); + let newHeight = currentHeight * (1 + mouseOffsetY / 100); - // determine offset in px (to keep image center while resizing) - let offsetX = (currentWidth - newWidth) / 2.0; - let offsetY = (currentHeight - newHeight) / 2.0; + // determine offset in px (to keep image center while resizing) + let offsetX = (currentWidth - newWidth) / 2.0; + let offsetY = (currentHeight - newHeight) / 2.0; - changingElement.style.width = newWidth + "px"; - changingElement.style.height = newHeight + "px"; + changingElement.style.width = newWidth + "px"; + changingElement.style.height = newHeight + "px"; - changingElement.style.left = - changingElement.offsetLeft + offsetX + "px"; - changingElement.style.top = - changingElement.offsetTop + offsetY + "px"; + changingElement.style.left = + changingElement.offsetLeft + offsetX + "px"; + changingElement.style.top = + changingElement.offsetTop + offsetY + "px"; + } } - // shrinking - else if (mouseOffsetY < 0) { - let newWidth = currentWidth * (1 + mouseOffsetY / 100); - let newHeight = currentHeight * (1 + mouseOffsetY / 100); - - // determine offset in px (to keep image center while resizing) - let offsetX = (currentWidth - newWidth) / 2.0; - let offsetY = (currentHeight - newHeight) / 2.0; - - changingElement.style.width = newWidth + "px"; + // if resizing container / image freely + else { + let newHeight = currentHeight - mouseOffsetY; + let newWidth = currentWidth - mouseOffsetX; changingElement.style.height = newHeight + "px"; - - changingElement.style.left = - changingElement.offsetLeft + offsetX + "px"; - changingElement.style.top = - changingElement.offsetTop + offsetY + "px"; + changingElement.style.width = newWidth + "px"; } } - // if resizing container / image freely - else { - let newHeight = currentHeight - mouseOffsetY; - let newWidth = currentWidth - mouseOffsetX; - changingElement.style.height = newHeight + "px"; - changingElement.style.width = newWidth + "px"; - } - } - function mouseDownMovableElement(mouseDown) { + function mouseDownMovableElement(mouseDown) { - /** MOVEMENT / RESIZING HANDLERS */ - if (!editing || - mouseDown.target.tagName == "BUTTON" || - mouseDown.target.tagName == "INPUT" || - mouseDown.target.tagName == "LABEL" || - mouseDown.target.parentElement.classList.contains("expandableMenuToggle") || - mouseDown.target.classList.contains("expandableMenuToggle") - ) { - return; - } + /** MOVEMENT / RESIZING HANDLERS */ + if (!editing || + mouseDown.target.tagName == "BUTTON" || + mouseDown.target.tagName == "INPUT" || + mouseDown.target.tagName == "LABEL" || + mouseDown.target.parentElement.classList.contains("expandableMenuToggle") || + mouseDown.target.classList.contains("expandableMenuToggle") + ) { + return; + } - changingElement = document.getElementById(mouseDown.currentTarget.id); + changingElement = document.getElementById(mouseDown.currentTarget.id); - // save mouse position prior to drag event - lastMouseX = mouseDown.clientX; - lastMouseY = mouseDown.clientY; + // save mouse position prior to drag event + lastMouseX = mouseDown.clientX; + lastMouseY = mouseDown.clientY; - // left click drag initiates movement, release on mouse up - if (mouseDown.button == 0) { - moving = true; - document.addEventListener("mousemove", moveElement); - document.addEventListener("mouseup", (mouseUp) => { - if (moving && mouseUp.button == 0) { - moving = false; - document.removeEventListener("mousemove", moveElement); - storeElementData(); - } - }); - } - // right click drag initiates movement, release on mouse up - if (mouseDown.button == 2) { - resizing = true; - document.addEventListener("mousemove", resizeElement); - document.addEventListener("mouseup", (mouseUp) => { - if (resizing && mouseUp.button == 2) { - resizing = false; - document.removeEventListener("mousemove", resizeElement); - storeElementData(); - } - }); + // left click drag initiates movement, release on mouse up + if (mouseDown.button == 0) { + moving = true; + document.addEventListener("mousemove", moveElement); + document.addEventListener("mouseup", (mouseUp) => { + if (moving && mouseUp.button == 0) { + moving = false; + document.removeEventListener("mousemove", moveElement); + storeElementData(); + } + }); + } + // right click drag initiates movement, release on mouse up + if (mouseDown.button == 2) { + resizing = true; + document.addEventListener("mousemove", resizeElement); + document.addEventListener("mouseup", (mouseUp) => { + if (resizing && mouseUp.button == 2) { + resizing = false; + document.removeEventListener("mousemove", resizeElement); + storeElementData(); + } + }); + } } - } - function keyDownMovableElement(keyDown) { - if (!editing || - keyDown.target.id == "settingsContainer" || - keyDown.key == "Escape" - ) { - return; - } - keyDown.stopPropagation(); + function keyDownMovableElement(keyDown) { + if (!editing || + keyDown.target.id == "settingsContainer" || + keyDown.key == "Escape" + ) { + return; + } + keyDown.stopPropagation(); - changingElement = document.getElementById(keyDown.target.id); + changingElement = document.getElementById(keyDown.target.id); - currentX = parseInt(changingElement.style.left.replace("px", "")); - currentY = parseInt(changingElement.style.top.replace("px", "")); + currentX = parseInt(changingElement.style.left.replace("px", "")); + currentY = parseInt(changingElement.style.top.replace("px", "")); - // deletion - if(keyDown.key == "Backspace") { - deleteContainer(keyDown.target.id); - } - // nudges - if(keyDown.key == "ArrowUp") { - changingElement.style.top =`${currentY - 1}px`; - storeElementData(); - } - if(keyDown.key == "ArrowRight") { - changingElement.style.left =`${currentX + 1}px`; - storeElementData(); - } - if(keyDown.key == "ArrowDown") { - changingElement.style.top =`${currentY + 1}px`; - storeElementData(); - } - if(keyDown.key == "ArrowLeft") { - changingElement.style.left =`${currentX - 1}px`; - storeElementData(); + // deletion + if(keyDown.key == "Backspace") { + deleteContainer(keyDown.target.id); + } + // nudges + if(keyDown.key == "ArrowUp") { + changingElement.style.top = + `${keyDown.shiftKey ? currentY - 5 : currentY - 1}px`; + storeElementData(); + } + if(keyDown.key == "ArrowRight") { + changingElement.style.left = + `${keyDown.shiftKey ? currentX + 5 : currentX + 1}px`; + storeElementData(); + } + if(keyDown.key == "ArrowDown") { + changingElement.style.top = + `${keyDown.shiftKey ? currentY + 5 : currentY + 1}px`; + storeElementData(); + } + if(keyDown.key == "ArrowLeft") { + changingElement.style.left = + `${keyDown.shiftKey ? currentX - 5 : currentX - 1}px`; + storeElementData(); + } } - } - function setDefaultCursor() { - cursors.default = document.getElementById("pointerCursorInput").value; - // apply new default cursor to entire html document - document.getElementsByTagName("html")[0].style.cursor = - 'url("' + cursors.default + '"), auto'; - - document.getElementById("pointerCursorInput").value = ""; - } + function setDefaultCursor() { + cursors.default = document.getElementById("pointerCursorInput").value; + // apply new default cursor to entire html document + document.getElementsByTagName("html")[0].style.cursor = + 'url("' + cursors.default + '"), auto'; - function setGrabCursor() { - cursors.grab = document.getElementById("grabCursorInput").value; - // apply new grab cursor to grabbable elements... - let movableElements = document.getElementsByClassName("movable"); - for (let i = 0; i < movableElements.length; i++) { - movableElements[i].style.cursor = cursors.grab ? 'url("' + cursors.grab + '"), grab' : "grab"; + document.getElementById("pointerCursorInput").value = ""; } - document.getElementById("grabCursorInput").value = ""; - } - function setLinkHoverCursor() { - cursors.link = document.getElementById("linkCursorInput").value; - // apply cursor on links... - let links = document.getElementsByTagName("a"); - for (let i = 0; i < links.length; i++) { - links[i].style.cursor = cursors.link ? 'url("' + cursors.link + '"), pointer' : "pointer"; + function setGrabCursor() { + cursors.grab = document.getElementById("grabCursorInput").value; + // apply new grab cursor to grabbable elements... + let movableElements = document.getElementsByClassName("movable"); + for (let i = 0; i < movableElements.length; i++) { + movableElements[i].style.cursor = cursors.grab ? 'url("' + cursors.grab + '"), grab' : "grab"; + } + document.getElementById("grabCursorInput").value = ""; } - document.getElementById("linkCursorInput").value = ""; - } - - /********************** - * BOOK MARK HANDLERS * - **********************/ - - function addLink(containerElement) { - let containerId = containerElement.id.split("-add-link-")[0]; - let container = containerDataMap.get(containerId); - // collect data from inputs - let url = document.getElementById(containerId + "-url-input").value; - let label = document.getElementById(containerId + "-label-input").value; - let section = document.getElementById(containerId + "-section-input").value; - - // sanitize input - if (url.length > 0 && !url.startsWith("http")) { - url = "https://" + url; // append HTTPS to link if needed - } - if (section == "" && (label == "" || url == "https://")) { - alert("you must specify url and label to add a bookmark"); - return; + function setLinkHoverCursor() { + cursors.link = document.getElementById("linkCursorInput").value; + // apply cursor on links... + let links = document.getElementsByTagName("a"); + for (let i = 0; i < links.length; i++) { + links[i].style.cursor = cursors.link ? 'url("' + cursors.link + '"), pointer' : "pointer"; + } + document.getElementById("linkCursorInput").value = ""; } - // store new link in container - let sectionData = Object.values(container.sections); - let sectionLabels = []; - for (let i = 0; i < sectionData.length; i++) { - sectionLabels.push(sectionData[i].label); - } + /********************** + * BOOK MARK HANDLERS * + **********************/ - let sectionIndex = sectionLabels.indexOf(section); - // add link to existing section - if (sectionIndex != -1) { - let tempSectionLinks = Object.values(container.sections)[sectionIndex].links; - tempSectionLinks.push({ - label: label, - url: url - }); - } - // or create new section + add link - else { - let newSectionLinks = []; - newSectionLinks.push({ - label: label, - url: url - }); + function addLink(containerElement) { + let containerId = containerElement.id.split("-add-link-")[0]; + let container = containerDataMap.get(containerId); - // ensure that uncategorized links stay at top of container - if (section == "" && sectionData.length > 0) { - let reorderedSections = {}; - reorderedSections[0] = {}; - reorderedSections[0].links = newSectionLinks; - reorderedSections[0].label = section; + // collect data from inputs + let url = document.getElementById(containerId + "-url-input").value; + let label = document.getElementById(containerId + "-label-input").value; + let section = document.getElementById(containerId + "-section-input").value; - // move existing sections down - for (let i = 0; i < sectionData.length; i++) { - reorderedSections[i+1] = sectionData[i]; - } + // sanitize input + if (url.length > 0 && !url.startsWith("http")) { + url = "https://" + url; // append HTTPS to link if needed + } + if (section == "" && (label == "" || url == "https://")) { + alert("you must specify url and label to add a bookmark"); + return; + } + + // store new link in container + let sectionData = Object.values(container.sections); + let sectionLabels = []; + for (let i = 0; i < sectionData.length; i++) { + sectionLabels.push(sectionData[i].label); + } - container.sections = reorderedSections; + let sectionIndex = sectionLabels.indexOf(section); + // add link to existing section + if (sectionIndex != -1) { + let tempSectionLinks = Object.values(container.sections)[sectionIndex].links; + tempSectionLinks.push({ + label: label, + url: url + }); } + // or create new section + add link else { - container.sections[sectionData.length] = {}; - container.sections[sectionData.length].links = newSectionLinks; - container.sections[sectionData.length].label = section; + let newSectionLinks = []; + newSectionLinks.push({ + label: label, + url: url + }); + + // ensure that uncategorized links stay at top of container + if (section == "" && sectionData.length > 0) { + let reorderedSections = {}; + reorderedSections[0] = {}; + reorderedSections[0].links = newSectionLinks; + reorderedSections[0].label = section; + + // move existing sections down + for (let i = 0; i < sectionData.length; i++) { + reorderedSections[i+1] = sectionData[i]; + } + + container.sections = reorderedSections; + } + else { + container.sections[sectionData.length] = {}; + container.sections[sectionData.length].links = newSectionLinks; + container.sections[sectionData.length].label = section; + } } + + // reset inputs + render + document.getElementById(containerId + "-url-input").value = ""; + document.getElementById(containerId + "-label-input").value = ""; + container.loadBookmarks(); + container.loadBookmarkListings(); } - // reset inputs + render - document.getElementById(containerId + "-url-input").value = ""; - document.getElementById(containerId + "-label-input").value = ""; - container.loadBookmarks(); - container.loadBookmarkListings(); - } + function reorderSection(buttonPressed, direction) { + let temp = buttonPressed.parentElement.parentElement.id.split("--"); + let container = containerDataMap.get(temp[0].split("-section-listing")[0]); + const sectionIndex = parseInt(temp[temp.length - 1]); - function reorderSection(buttonPressed, direction) { - let temp = buttonPressed.parentElement.parentElement.id.split("--"); - let container = containerDataMap.get(temp[0].split("-section-listing")[0]); - const sectionIndex = parseInt(temp[temp.length - 1]); + let copy = container.sections[sectionIndex]; + if (direction == "up" && sectionIndex != 0) { + container.sections[sectionIndex] = container.sections[sectionIndex - 1]; + container.sections[sectionIndex - 1] = copy; + } else if (direction == "down" && (sectionIndex + 1) != Object.keys(container.sections).length) { + container.sections[sectionIndex] = container.sections[sectionIndex + 1]; + container.sections[sectionIndex + 1] = copy; + } - let copy = container.sections[sectionIndex]; - if (direction == "up" && sectionIndex != 0) { - container.sections[sectionIndex] = container.sections[sectionIndex - 1]; - container.sections[sectionIndex - 1] = copy; - } else if (direction == "down" && (sectionIndex + 1) != Object.keys(container.sections).length) { - container.sections[sectionIndex] = container.sections[sectionIndex + 1]; - container.sections[sectionIndex + 1] = copy; + container.loadBookmarks(); + container.loadBookmarkListings(); } - container.loadBookmarks(); - container.loadBookmarkListings(); - } + function deleteSection(buttonPressed) { + let temp = buttonPressed.parentElement.parentElement.id.split("--"); + let container = containerDataMap.get(temp[0].split("-section-listing")[0]); + const sectionIndex = parseInt(temp[temp.length - 1]); - function deleteSection(buttonPressed) { - let temp = buttonPressed.parentElement.parentElement.id.split("--"); - let container = containerDataMap.get(temp[0].split("-section-listing")[0]); - const sectionIndex = parseInt(temp[temp.length - 1]); + // delete section + let numSections = Object.keys(container.sections).length; + for (let i = sectionIndex; i < numSections; i++) { + container.sections[i] = container.sections[i+1]; + } + // trim last section index that is no longer needed + delete container.sections[numSections - 1]; - // delete section - let numSections = Object.keys(container.sections).length; - for (let i = sectionIndex; i < numSections; i++) { - container.sections[i] = container.sections[i+1]; + // refresh screen + container.loadBookmarks(); + container.loadBookmarkListings(); } - // trim last section index that is no longer needed - delete container.sections[numSections - 1]; - - // refresh screen - container.loadBookmarks(); - container.loadBookmarkListings(); - } - function deleteLink(buttonPressed) { - let temp = buttonPressed.parentElement.parentElement.id.split("--"); - let container = containerDataMap.get(temp[0].split("-section-listing")[0]); - const sectionIndex = parseInt(temp[temp.length - 2]); - const linkIndex = parseInt(temp[temp.length - 1]); - - // delete link - container.sections[sectionIndex].links.splice(linkIndex, 1); + function deleteLink(buttonPressed) { + let temp = buttonPressed.parentElement.parentElement.id.split("--"); + let container = containerDataMap.get(temp[0].split("-section-listing")[0]); + const sectionIndex = parseInt(temp[temp.length - 2]); + const linkIndex = parseInt(temp[temp.length - 1]); + + // delete link + container.sections[sectionIndex].links.splice(linkIndex, 1); - // refresh screen - container.loadBookmarks(); - container.loadBookmarkListings(); - } + // refresh screen + container.loadBookmarks(); + container.loadBookmarkListings(); + } - function reorderLink(buttonPressed, direction) { - let temp = buttonPressed.parentElement.parentElement.id.split("--"); - let container = containerDataMap.get(temp[0].split("-section-listing")[0]); - const sectionIndex = parseInt(temp[temp.length - 2]); - const linkIndex = parseInt(temp[temp.length - 1]); - let links = container.sections[sectionIndex].links; + function reorderLink(buttonPressed, direction) { + let temp = buttonPressed.parentElement.parentElement.id.split("--"); + let container = containerDataMap.get(temp[0].split("-section-listing")[0]); + const sectionIndex = parseInt(temp[temp.length - 2]); + const linkIndex = parseInt(temp[temp.length - 1]); + let links = container.sections[sectionIndex].links; - // cut out section and re-insert into array - let link = container.sections[sectionIndex].links[linkIndex]; - container.sections[sectionIndex].links.splice(linkIndex, 1); - if (direction == "up" && linkIndex != 0) { - links.splice(linkIndex - 1, 0, link); - } else if (direction == "down" && linkIndex != links.length) { - links.splice(linkIndex + 1, 0, link); + // cut out section and re-insert into array + let link = container.sections[sectionIndex].links[linkIndex]; + container.sections[sectionIndex].links.splice(linkIndex, 1); + if (direction == "up" && linkIndex != 0) { + links.splice(linkIndex - 1, 0, link); + } else if (direction == "down" && linkIndex != links.length) { + links.splice(linkIndex + 1, 0, link); + } + + // refresh screen + container.loadBookmarks(); + container.loadBookmarkListings(); } - - // refresh screen - container.loadBookmarks(); - container.loadBookmarkListings(); - } - - /************************************ - * CONTAINER CUSTOMIZATION HANDLERS * - ************************************/ + + /************************************ + * CONTAINER CUSTOMIZATION HANDLERS * + ************************************/ - function changeContainerBackground(colorChange) { - let containerId = colorChange.currentTarget.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function changeContainerBackground(colorChange) { + let containerId = colorChange.currentTarget.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.backgroundRgba = hexToRgba( - document.getElementById(containerId + "-settings-bg-color").value, - document.getElementById(containerId + "-settings-bg-alpha").value - ); + container.settings.backgroundRgba = hexToRgba( + document.getElementById(containerId + "-settings-bg-color").value, + document.getElementById(containerId + "-settings-bg-alpha").value + ); - document.getElementById(containerId).style.backgroundColor = - container.settings.backgroundRgba; - } + document.getElementById(containerId).style.backgroundColor = + container.settings.backgroundRgba; + } - function changeLinkColor(colorChange) { - let containerId = colorChange.currentTarget.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function changeLinkColor(colorChange) { + let containerId = colorChange.currentTarget.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.linkColor = colorChange.target.value; + container.settings.linkColor = colorChange.target.value; - let linkElements = document.getElementsByClassName(container.id + "-link"); - for (let i = 0; i < linkElements.length; i++) { - linkElements[i].style.color = container.settings.linkColor; + let linkElements = document.getElementsByClassName(container.id + "-link"); + for (let i = 0; i < linkElements.length; i++) { + linkElements[i].style.color = container.settings.linkColor; + } } - } - function changeLinkSize(sizeChange) { - let containerId = sizeChange.currentTarget.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function changeLinkSize(sizeChange) { + let containerId = sizeChange.currentTarget.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.linkSize = - sizeChange.target.value == "" ? "0" : sizeChange.target.value; + container.settings.linkSize = + sizeChange.target.value == "" ? "0" : sizeChange.target.value; - let linkElements = document.getElementsByClassName(container.id + "-link"); - for (let i = 0; i < linkElements.length; i++) { - linkElements[i].style.fontSize = container.settings.linkSize + "px"; + let linkElements = document.getElementsByClassName(container.id + "-link"); + for (let i = 0; i < linkElements.length; i++) { + linkElements[i].style.fontSize = container.settings.linkSize + "px"; + } } - } - function toggleLinkDecor(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function toggleLinkDecor(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.linkDecor = checkboxChanged.target.checked; + container.settings.linkDecor = checkboxChanged.target.checked; - let linkElements = document.getElementsByClassName(container.id + "-link"); - for (let i = 0; i < linkElements.length; i++) { - linkElements[i].style.textDecoration = container.settings.linkDecor ? - "underline" : "none"; + let linkElements = document.getElementsByClassName(container.id + "-link"); + for (let i = 0; i < linkElements.length; i++) { + linkElements[i].style.textDecoration = container.settings.linkDecor ? + "underline" : "none"; + } } - } - function toggleLinkBold(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function toggleLinkBold(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.linkBold = checkboxChanged.target.checked; + container.settings.linkBold = checkboxChanged.target.checked; - let linkElements = document.getElementsByClassName(container.id + "-link"); - for (let i = 0; i < linkElements.length; i++) { - linkElements[i].style.fontWeight = container.settings.linkBold ? - "bold" : "normal"; + let linkElements = document.getElementsByClassName(container.id + "-link"); + for (let i = 0; i < linkElements.length; i++) { + linkElements[i].style.fontWeight = container.settings.linkBold ? + "bold" : "normal"; + } } - } - function toggleLinkItalic(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function toggleLinkItalic(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.linkItalic = checkboxChanged.target.checked; + container.settings.linkItalic = checkboxChanged.target.checked; - let linkElements = document.getElementsByClassName(container.id + "-link"); - for (let i = 0; i < linkElements.length; i++) { - linkElements[i].style.fontStyle = container.settings.linkItalic ? - "italic" : "normal"; + let linkElements = document.getElementsByClassName(container.id + "-link"); + for (let i = 0; i < linkElements.length; i++) { + linkElements[i].style.fontStyle = container.settings.linkItalic ? + "italic" : "normal"; + } } - } - function changeSectionColor(colorChange) { - let containerId = colorChange.currentTarget.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function changeSectionColor(colorChange) { + let containerId = colorChange.currentTarget.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.sectionColor = colorChange.target.value; - let sectionElements = document.getElementsByClassName(container.id + "-section"); - for (let i = 0; i < sectionElements.length; i++) { - sectionElements[i].style.color = container.settings.sectionColor; + container.settings.sectionColor = colorChange.target.value; + let sectionElements = document.getElementsByClassName(container.id + "-section"); + for (let i = 0; i < sectionElements.length; i++) { + sectionElements[i].style.color = container.settings.sectionColor; + } } - } - function changeSectionSize(sizeChange) { - let containerId = sizeChange.currentTarget.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function changeSectionSize(sizeChange) { + let containerId = sizeChange.currentTarget.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.sectionSize = - sizeChange.target.value == "" ? "0" : sizeChange.target.value; + container.settings.sectionSize = + sizeChange.target.value == "" ? "0" : sizeChange.target.value; - let sectionElements = document.getElementsByClassName(container.id + "-section"); - for (let i = 0; i < sectionElements.length; i++) { - sectionElements[i].style.fontSize = container.settings.sectionSize + "px"; + let sectionElements = document.getElementsByClassName(container.id + "-section"); + for (let i = 0; i < sectionElements.length; i++) { + sectionElements[i].style.fontSize = container.settings.sectionSize + "px"; + } } - } - function toggleSectionBold(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function toggleSectionBold(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - let sectionElements = document.getElementsByClassName(containerId + "-section"); - for (let i = 0; i < sectionElements.length; i++) { - sectionElements[i].style.fontWeight = checkboxChanged.target.checked ? "bold" : "normal"; + let sectionElements = document.getElementsByClassName(containerId + "-section"); + for (let i = 0; i < sectionElements.length; i++) { + sectionElements[i].style.fontWeight = checkboxChanged.target.checked ? "bold" : "normal"; + } + container.settings.sectionBold = checkboxChanged.target.checked; } - container.settings.sectionBold = checkboxChanged.target.checked; - } - function toggleSectionItalic(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function toggleSectionItalic(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - let sectionElements = document.getElementsByClassName(containerId + "-section"); - for (let i = 0; i < sectionElements.length; i++) { - sectionElements[i].style.fontStyle = checkboxChanged.target.checked ? "italic" : "normal"; + let sectionElements = document.getElementsByClassName(containerId + "-section"); + for (let i = 0; i < sectionElements.length; i++) { + sectionElements[i].style.fontStyle = checkboxChanged.target.checked ? "italic" : "normal"; + } + container.settings.sectionItalic = checkboxChanged.target.checked; } - container.settings.sectionItalic = checkboxChanged.target.checked; - } - // BORDER - function changeContainerBorderWidth(borderChange) { - let containerId = borderChange.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + // BORDER + function changeContainerBorderWidth(borderChange) { + let containerId = borderChange.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.borderWidth = borderChange.target.value; + container.settings.borderWidth = borderChange.target.value; - if (container.mediaUrl?.includes("youtube.com") || container.mediaUrl?.includes("youtu.be")) { - document.getElementById(containerId).children[0].style.borderWidth = - container.settings.borderWidth + "px"; - document.getElementById(containerId).children[1].style.borderWidth = - container.settings.borderWidth + "px"; - } - else { - document.getElementById(containerId).style.borderWidth = - container.settings.borderWidth + "px"; + if (container.mediaUrl?.includes("youtube.com") || container.mediaUrl?.includes("youtu.be")) { + document.getElementById(containerId).children[0].style.borderWidth = + container.settings.borderWidth + "px"; + document.getElementById(containerId).children[1].style.borderWidth = + container.settings.borderWidth + "px"; + } + else { + document.getElementById(containerId).style.borderWidth = + container.settings.borderWidth + "px"; + } } - } - function changeContainerBorderRadius(radiusChange) { - let containerId = radiusChange.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function changeContainerBorderRadius(radiusChange) { + let containerId = radiusChange.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.borderRadius = radiusChange.target.value; + container.settings.borderRadius = radiusChange.target.value; - if (container.mediaUrl?.includes("youtube.com") || container.mediaUrl?.includes("youtu.be")) { - document.getElementById(containerId).children[0].style.borderRadius = - container.settings.borderRadius + "px"; - document.getElementById(containerId).children[1].style.borderRadius = - container.settings.borderRadius + "px"; - } - else { - document.getElementById(containerId).style.borderRadius = - container.settings.borderRadius + "px"; + if (container.mediaUrl?.includes("youtube.com") || container.mediaUrl?.includes("youtu.be")) { + document.getElementById(containerId).children[0].style.borderRadius = + container.settings.borderRadius + "px"; + document.getElementById(containerId).children[1].style.borderRadius = + container.settings.borderRadius + "px"; + } + else { + document.getElementById(containerId).style.borderRadius = + container.settings.borderRadius + "px"; + } } - } - function changeContainerBorderColor(colorChange) { - let containerId = colorChange.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function changeContainerBorderColor(colorChange) { + let containerId = colorChange.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.borderColor = colorChange.target.value; + container.settings.borderColor = colorChange.target.value; - if (container.mediaUrl?.includes("youtube.com") || container.mediaUrl?.includes("youtu.be")) { - document.getElementById(containerId).children[0].style.borderColor = - container.settings.borderColor; - document.getElementById(containerId).children[1].style.borderColor = - container.settings.borderColor; - } - else { - document.getElementById(containerId).style.borderColor = - container.settings.borderColor; + if (container.mediaUrl?.includes("youtube.com") || container.mediaUrl?.includes("youtu.be")) { + document.getElementById(containerId).children[0].style.borderColor = + container.settings.borderColor; + document.getElementById(containerId).children[1].style.borderColor = + container.settings.borderColor; + } + else { + document.getElementById(containerId).style.borderColor = + container.settings.borderColor; + } } - } - // CLOCK - function toggleDate(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + // CLOCK + function toggleDate(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.enableDate = checkboxChanged.target.checked; - document.getElementById(containerId + "-date").style.display = - checkboxChanged.target.checked ? "inline" : "none"; - } - function toggleClock(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); - - container.settings.enableClock = checkboxChanged.target.checked; - document.getElementById(containerId + "-clock").style.display = - checkboxChanged.target.checked ? "inline" : "none"; - } - function changeHeaderColor(colorChange) { - let containerId = colorChange.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + container.settings.enableDate = checkboxChanged.target.checked; + document.getElementById(containerId + "-date").style.display = + checkboxChanged.target.checked ? "inline" : "none"; + + if (!checkboxChanged.target.checked && + Object.keys(container.sections).length > 0 && + container.settings.enableClock + ) { + document.getElementById(containerId + "-header").style.marginBottom = "18px"; + } else { + document.getElementById(containerId + "-header").style.marginBottom = "0px"; + } + } + function toggleClock(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.headerColor = colorChange.target.value; - document.getElementById(containerId + "-header").style.color = - container.settings.headerColor; - } - function changeHeaderSize(sizeChange) { - let containerId = sizeChange.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + container.settings.enableClock = checkboxChanged.target.checked; + document.getElementById(containerId + "-clock").style.display = + checkboxChanged.target.checked ? "inline" : "none"; - container.settings.headerSize = - sizeChange.target.value == "" ? "0" : sizeChange.target.value; - document.getElementById(containerId + "-header").style.fontSize = - container.settings.headerSize + "px"; - } - function toggleDateBold(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + if (!checkboxChanged.target.checked && + Object.keys(container.sections).length > 0 && + container.settings.enableDate + ) { + document.getElementById(containerId + "-header").style.marginBottom = "18px"; + } else { + document.getElementById(containerId + "-header").style.marginBottom = "0px"; + } + } + function changeHeaderColor(colorChange) { + let containerId = colorChange.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.dateBold = checkboxChanged.target.checked; - document.getElementById(containerId + "-date").style.fontWeight = - checkboxChanged.target.checked ? "bold" : "normal"; - } - function toggleDateItalic(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + container.settings.headerColor = colorChange.target.value; + document.getElementById(containerId + "-header").style.color = + container.settings.headerColor; + } + function changeHeaderSize(sizeChange) { + let containerId = sizeChange.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.dateItalic = checkboxChanged.target.checked; - document.getElementById(containerId + "-date").style.fontStyle = - checkboxChanged.target.checked ? "italic" : "normal"; - } - function toggleClockBold(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + container.settings.headerSize = + sizeChange.target.value == "" ? "0" : sizeChange.target.value; + document.getElementById(containerId + "-header").style.fontSize = + container.settings.headerSize + "px"; + } + function toggleDateBold(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.clockBold = checkboxChanged.target.checked; - document.getElementById(containerId + "-clock").style.fontWeight = - checkboxChanged.target.checked ? "bold" : "normal"; - } - function toggleClockItalic(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + container.settings.dateBold = checkboxChanged.target.checked; + document.getElementById(containerId + "-date").style.fontWeight = + checkboxChanged.target.checked ? "bold" : "normal"; + } + function toggleDateItalic(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.clockItalic = checkboxChanged.target.checked; - document.getElementById(containerId + "-clock").style.fontStyle = - checkboxChanged.target.checked ? "italic" : "normal"; - } + container.settings.dateItalic = checkboxChanged.target.checked; + document.getElementById(containerId + "-date").style.fontStyle = + checkboxChanged.target.checked ? "italic" : "normal"; + } + function toggleClockBold(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - // DIVIDER - function changeDividerColor(colorChange) { - let containerId = colorChange.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + container.settings.clockBold = checkboxChanged.target.checked; + document.getElementById(containerId + "-clock").style.fontWeight = + checkboxChanged.target.checked ? "bold" : "normal"; + } + function toggleClockItalic(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.settings.dividerColor = colorChange.target.value; - let divider = document.getElementById(containerId + "-divider"); - // set multiple places for compatibility - divider.style.color = container.settings.dividerColor; - divider.style.backgroundColor = container.settings.dividerColor; - divider.style.borderColor = container.settings.dividerColor; - } - function toggleDivider(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + container.settings.clockItalic = checkboxChanged.target.checked; + document.getElementById(containerId + "-clock").style.fontStyle = + checkboxChanged.target.checked ? "italic" : "normal"; + } - container.settings.enableDivider = checkboxChanged.target.checked; - document.getElementById(containerId + "-divider").style.display = - checkboxChanged.target.checked ? "block" : "none"; + // DIVIDER + function changeDividerColor(colorChange) { + let containerId = colorChange.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - if (!checkboxChanged.target.checked && Object.keys(container.sections).length > 0) { - document.getElementById(containerId + "-header").style.marginBottom = "18px"; - } else { - document.getElementById(containerId + "-header").style.marginBottom = "0px"; - } - } + container.settings.dividerColor = colorChange.target.value; + let divider = document.getElementById(containerId + "-divider"); + // set multiple places for compatibility + divider.style.color = container.settings.dividerColor; + divider.style.backgroundColor = container.settings.dividerColor; + divider.style.borderColor = container.settings.dividerColor; + } + function toggleDivider(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - // GENERAL TEXT SETTINGS - function changeContainerAlignment(alignmentChanged) { - let containerId = alignmentChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + container.settings.enableDivider = checkboxChanged.target.checked; + document.getElementById(containerId + "-divider").style.display = + checkboxChanged.target.checked ? "block" : "none"; - if (document.getElementById(containerId + "-settings-left-align").checked) { - container.settings.textAlign = "left"; - document.getElementById(containerId).style.textAlign = "left"; - } else if (document.getElementById(containerId + "-settings-center-align").checked) { - container.settings.textAlign = "center"; - document.getElementById(containerId).style.textAlign = "center"; - } else if (document.getElementById(containerId + "-settings-right-align").checked) { - container.settings.textAlign = "right"; - document.getElementById(containerId).style.textAlign = "right"; + if (!checkboxChanged.target.checked && + Object.keys(container.sections).length > 0 && + (container.settings.enableDate || container.settings.enableClock) + ) { + document.getElementById(containerId + "-header").style.marginBottom = "18px"; + } else { + document.getElementById(containerId + "-header").style.marginBottom = "0px"; + } } - } - function changeFont(buttonClicked) { - let containerId = buttonClicked.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + // GENERAL TEXT SETTINGS + function changeContainerAlignment(alignmentChanged) { + let containerId = alignmentChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - let input = document.getElementById(containerId + "-settings-font-input").value; - if (input == "") { - return; - } + if (document.getElementById(containerId + "-settings-left-align").checked) { + container.settings.textAlign = "left"; + document.getElementById(containerId).style.textAlign = "left"; + } else if (document.getElementById(containerId + "-settings-center-align").checked) { + container.settings.textAlign = "center"; + document.getElementById(containerId).style.textAlign = "center"; + } else if (document.getElementById(containerId + "-settings-right-align").checked) { + container.settings.textAlign = "right"; + document.getElementById(containerId).style.textAlign = "right"; + } - // parse input to extract name of font - fontCode = input; - fontName = fontCode.slice(fontCode.indexOf("family=") + 7); - if (fontName.indexOf("&") != -1) { - fontName = fontName.slice(0, fontName.indexOf("&") + 1); } - fontName = fontName.slice(0, fontName.indexOf(":")).replaceAll("+", " "); - // set font on container - document.head.insertAdjacentHTML("beforeend", fontCode); - document.getElementById(containerId).style.fontFamily = fontName; - document.getElementById(containerId + "-settings-font-name").innerHTML = fontName; - container.settings.fontCode = fontCode; - container.settings.fontName = fontName; - } + function changeFont(buttonClicked) { + let containerId = buttonClicked.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - // SHADOW - function changeContainerShadow(valueChanged) { - let containerId = valueChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + let input = document.getElementById(containerId + "-settings-font-input").value; + if (input == "") { + return; + } - container.settings.shadowX = - document.getElementById(containerId + "-settings-shadow-x").value == "" - ? 0 - : document.getElementById(containerId + "-settings-shadow-x").value; - container.settings.shadowY = - document.getElementById(containerId + "-settings-shadow-y").value == "" - ? 0 - : document.getElementById(containerId + "-settings-shadow-y").value; - container.settings.shadowBlur = - document.getElementById(containerId + "-settings-shadow-blur").value == "" - ? 0 - : document.getElementById(containerId + "-settings-shadow-blur").value; - container.settings.shadowRgba = hexToRgba( - document.getElementById(containerId + "-settings-shadow-color").value, - document.getElementById(containerId + "-settings-shadow-alpha").value - ); + // parse input to extract name of font + fontCode = input; + fontName = fontCode.slice(fontCode.indexOf("family=") + 7); + if (fontName.indexOf("&") != -1) { + fontName = fontName.slice(0, fontName.indexOf("&") + 1); + } + fontName = fontName.slice(0, fontName.indexOf(":")).replaceAll("+", " "); + // set font on container + document.head.insertAdjacentHTML("beforeend", fontCode); + document.getElementById(containerId).style.fontFamily = fontName; + document.getElementById(containerId + "-settings-font-name").innerHTML = fontName; + container.settings.fontCode = fontCode; + container.settings.fontName = fontName; + } - let shadow = - container.settings.shadowX + - "px " + - container.settings.shadowY + - "px " + - container.settings.shadowBlur + - "px " + - container.settings.shadowRgba; + // SHADOW + function changeContainerShadow(valueChanged) { + let containerId = valueChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - // set shadow - document.getElementById(containerId).style.boxShadow = shadow; - } + container.settings.shadowX = + document.getElementById(containerId + "-settings-shadow-x").value == "" + ? 0 + : document.getElementById(containerId + "-settings-shadow-x").value; + container.settings.shadowY = + document.getElementById(containerId + "-settings-shadow-y").value == "" + ? 0 + : document.getElementById(containerId + "-settings-shadow-y").value; + container.settings.shadowBlur = + document.getElementById(containerId + "-settings-shadow-blur").value == "" + ? 0 + : document.getElementById(containerId + "-settings-shadow-blur").value; + container.settings.shadowRgba = hexToRgba( + document.getElementById(containerId + "-settings-shadow-color").value, + document.getElementById(containerId + "-settings-shadow-alpha").value + ); - // ROTATION - function changeContainerRotation(valueChanged) { - let containerId = valueChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); - - let rotation = valueChanged.target.value; - let invertX = container.settings.invertX; - let invertY = container.settings.invertY; + let shadow = + container.settings.shadowX + + "px " + + container.settings.shadowY + + "px " + + container.settings.shadowBlur + + "px " + + container.settings.shadowRgba; - // save to container - container.settings.rotation = rotation; + // set shadow + document.getElementById(containerId).style.boxShadow = shadow; + } - // perform transformation - let transformValue = - `scale(${invertX ? `-1` : `1`}, ${invertY ? `-1` : `1`}) `; - transformValue += - `rotate(${container.settings.rotation}deg)`; - - document.getElementById(containerId).style.transform = transformValue; - } + // ROTATION + function changeContainerRotation(valueChanged) { + let containerId = valueChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); + + let rotation = valueChanged.target.value; + let invertX = container.settings.invertX; + let invertY = container.settings.invertY; - // IMAGE INVERSION - function toggleMirrorX(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + // save to container + container.settings.rotation = rotation; - let invertX = checkboxChanged.target.checked; - let invertY = container.settings.invertY; + // perform transformation + let transformValue = + `scale(${invertX ? `-1` : `1`}, ${invertY ? `-1` : `1`}) `; + transformValue += + `rotate(${container.settings.rotation}deg)`; + + document.getElementById(containerId).style.transform = transformValue; + } - // save to container - container.settings.invertX = invertX; + // IMAGE INVERSION + function toggleMirrorX(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - // perform transformation - let transformValue = - `scale(${invertX ? `-1` : `1`}, ${invertY ? `-1` : `1`}) `; - transformValue += - `rotate(${container.settings.rotation}deg)`; + let invertX = checkboxChanged.target.checked; + let invertY = container.settings.invertY; - document.getElementById(containerId).style.transform = transformValue; - - } + // save to container + container.settings.invertX = invertX; - function toggleMirrorY(checkboxChanged) { - let containerId = checkboxChanged.target.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + // perform transformation + let transformValue = + `scale(${invertX ? `-1` : `1`}, ${invertY ? `-1` : `1`}) `; + transformValue += + `rotate(${container.settings.rotation}deg)`; - let invertY = checkboxChanged.target.checked; - let invertX = container.settings.invertX; - - // save to container - container.settings.invertY = invertY; + document.getElementById(containerId).style.transform = transformValue; + + } - // perform transformation - let transformValue = - `scale(${invertX ? `-1` : `1`}, ${invertY ? `-1` : `1`}) `; - transformValue += - `rotate(${container.settings.rotation}deg)`; + function toggleMirrorY(checkboxChanged) { + let containerId = checkboxChanged.target.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - document.getElementById(containerId).style.transform = transformValue; - } + let invertY = checkboxChanged.target.checked; + let invertX = container.settings.invertX; + + // save to container + container.settings.invertY = invertY; - function toggleYoutubeAutoplay(checkbox) { - let containerId = checkbox.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + // perform transformation + let transformValue = + `scale(${invertX ? `-1` : `1`}, ${invertY ? `-1` : `1`}) `; + transformValue += + `rotate(${container.settings.rotation}deg)`; - container.settings.autoplay = checkbox.checked; - } + document.getElementById(containerId).style.transform = transformValue; + } - // IMAGE HYPERLINKS - function setImageHyperlink(button) { - let containerId = button.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function toggleYoutubeAutoplay(checkbox) { + let containerId = checkbox.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - let input = document.getElementById(containerId + "-settings-image-hyperlink-input").value; - if (input == "") { - return; + container.settings.autoplay = checkbox.checked; } - document.getElementById(containerId + "-settings-image-hyperlink-input").value = ""; - if (container.imageHyperlink == undefined) { - document.getElementById(containerId + "-settings-image-hyperlink-set-button") - .insertAdjacentHTML("afterend", ` - <button id=${containerId + "-settings-image-hyperlink-remove-button"} onclick="removeImageHyperlink(this)">remove hyperlink</button>`); + // IMAGE HYPERLINKS + function setImageHyperlink(button) { + let containerId = button.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); + + let input = document.getElementById(containerId + "-settings-image-hyperlink-input").value; + if (input == "") { + return; + } + document.getElementById(containerId + "-settings-image-hyperlink-input").value = ""; + + if (container.imageHyperlink == undefined) { + document.getElementById(containerId + "-settings-image-hyperlink-set-button") + .insertAdjacentHTML("afterend", ` + <button id=${containerId + "-settings-image-hyperlink-remove-button"} onclick="removeImageHyperlink(this)">remove hyperlink</button>`); + } + container.imageHyperlink = input; + document.getElementById(containerId).classList.add("hyperlinkedImage"); } - container.imageHyperlink = input; - document.getElementById(containerId).classList.add("hyperlinkedImage"); - } - function removeImageHyperlink(button) { - let containerId = button.id.split("-settings")[0]; - let container = containerDataMap.get(containerId); + function removeImageHyperlink(button) { + let containerId = button.id.split("-settings")[0]; + let container = containerDataMap.get(containerId); - container.imageHyperlink = undefined; - document.getElementById(containerId).classList.remove("hyperlinkedImage"); - document.getElementById(containerId + "-settings-image-hyperlink-remove-button").remove(); - } - /************************************ - * RESET / IMPORT & EXPORT HANDLERS * - ************************************/ - function importData(buttonClick) { - let input = document.getElementById("import-input").files[0]; - if (!input) { - return; + container.imageHyperlink = undefined; + document.getElementById(containerId).classList.remove("hyperlinkedImage"); + document.getElementById(containerId + "-settings-image-hyperlink-remove-button").remove(); } + /************************************ + * RESET / IMPORT & EXPORT HANDLERS * + ************************************/ + function importData(buttonClick) { + let input = document.getElementById("import-input").files[0]; + if (!input) { + return; + } - try { - const reader = new FileReader(); - reader.onload = () => { - let themeData = reader.result; - themeData = JSON.parse(themeData); - for (const [key, value] of Object.entries(themeData)) { - localStorage.setItem(key, value); - } + try { + const reader = new FileReader(); + reader.onload = () => { + let themeData = reader.result; + themeData = JSON.parse(themeData); + for (const [key, value] of Object.entries(themeData)) { + localStorage.setItem(key, value); + } - alert( - "data import successful. " + - "please refresh the page!" + - "\n(you can ignore unsaved changes warning, the imported data has already been loaded + stored)" - ); - justImported = true; + alert( + "data import successful. " + + "please refresh the page!" + + "\n(you can ignore unsaved changes warning, the imported data has already been loaded + stored)" + ); + justImported = true; + } + reader.readAsText(input); + } + catch (error) { + console.log(error); + alert("please only enter data that was provided by the export button!"); } - reader.readAsText(input); - } - catch (error) { - console.log(error); - alert("please only enter data that was provided by the export button!"); - } - - } + + } - /***************** - * COLOR HELPERS * - *****************/ + /***************** + * COLOR HELPERS * + *****************/ - function hexToRgba(hex, alpha) { - const sanitizedHex = hex.replace(/^#/, ""); - const parsedHex = parseInt(sanitizedHex, 16); + function hexToRgba(hex, alpha) { + const sanitizedHex = hex.replace(/^#/, ""); + const parsedHex = parseInt(sanitizedHex, 16); - return ( - "rgba(" + - ((parsedHex >> 16) & 255) + - "," + - ((parsedHex >> 8) & 255) + - "," + - (parsedHex & 255) + - "," + - alpha / 100 + - ")" - ); - } + return ( + "rgba(" + + ((parsedHex >> 16) & 255) + + "," + + ((parsedHex >> 8) & 255) + + "," + + (parsedHex & 255) + + "," + + alpha / 100 + + ")" + ); + } - function rgbToHex(rgb) { - const toHex = (c) => { - const hex = c.toString(16); - return hex.length === 1 ? "0" + hex : hex; - }; - return ( - "#" + - toHex(parseInt(rgb[0])) + - toHex(parseInt(rgb[1])) + - toHex(parseInt(rgb[2])) - ); - } - </script> + function rgbToHex(rgb) { + const toHex = (c) => { + const hex = c.toString(16); + return hex.length === 1 ? "0" + hex : hex; + }; + return ( + "#" + + toHex(parseInt(rgb[0])) + + toHex(parseInt(rgb[1])) + + toHex(parseInt(rgb[2])) + ); + } + </script> + </body> </html> |
