/*jslint browser: true*/ /*global shortcut, Behave*/ (function () { "use strict"; var slides = [], syncFormElements = [], currentSlideNumber = 0, slideNext, slidePrev, commandBar, commandField, commandBarVisible = true, localStorageActions; /* Dom helper functions. Who needs JQuery?? */ function $(selector) { return document.querySelector(selector); } function $$(selector) { return Array.prototype.slice.call(document.querySelectorAll(selector), 0); } function setCurrentSlide(newSlideNumber, storeChange) { newSlideNumber = Math.max(Math.min(newSlideNumber, slides.length - 1), 0); if (newSlideNumber !== currentSlideNumber) { currentSlideNumber = newSlideNumber; if (storeChange) { localStorage.setItem("janus-currentSlideNumber", currentSlideNumber); } } slides.forEach(function (item, index, array) { if (index < currentSlideNumber) { if (slides[index].contains(slides[currentSlideNumber])) { item.setAttribute("janus-timeline", "present"); } else { item.setAttribute("janus-timeline", "past"); } } else if (index === currentSlideNumber) { item.setAttribute("janus-timeline", "present"); } else { item.setAttribute("janus-timeline", "future"); } }); } function sessionListener(event) { if (event.url === window.location.href && localStorageActions[event.key]) { localStorageActions[event.key](event); } } function toggleCommandBar(visible) { if (visible === false) { commandBar.style.display = "none"; commandBarVisible = false; } else if (visible === true) { commandBar.style.display = "flex"; commandField.value = ""; commandField.focus(); commandBarVisible = true; } } function setMouseX(value, storeChange) { $("section[janus-timeline=\"present\"]").style.setProperty("--mouse-x", value); if (storeChange) { localStorage.setItem("mouse-x", value); } } function mouseListener(event) { var x = event.clientX / window.innerWidth; if (event.ctrlKey) { setMouseX(x, true); } } function runCommand(command) { var commands, s; commands = { "s": function () { document.body.classList.toggle("simulate-projection"); }, "p": function () { document.body.classList.toggle("show-notes"); }, "c": function () { window.open(window.location.href, "_blank"); }, "r": function () { localStorage.clear(); setCurrentSlide(0, true); } }; s = command.split(); if (s.length === 1 && /^[0-9]+$/.test(s[0])) { setCurrentSlide(+s[0], true); } else if (s.length === 1 && commands[s]) { commands[s](); } } function commandListener(event) { var typed = String.fromCharCode(event.keyCode).toLowerCase(); if (/[0-9]/.test(typed)) { return; } else if (event.keyCode === 13) { runCommand(commandField.value); toggleCommandBar(false); } else if (/[spcr]/.test(typed)) { runCommand(commandField.value + typed); toggleCommandBar(false); } } function editorListenerGenerator(editor) { var markupEl, styleEl, scriptEl, frameEl, frameWindow, listener; markupEl = editor.querySelector("[name=\"html\"]"); styleEl = editor.querySelector("[name=\"css\"]"); scriptEl = editor.querySelector("[name=\"js\"]"); frameEl = editor.querySelector("iframe"); if (frameEl.contentWindow) { frameWindow = frameEl.contentWindow; } else { if (frameEl.contentDocument && frameEl.contentDocument.document) { frameWindow = frameEl.contentDocument.document; } else { frameWindow = frameEl.contentDocument; } } function editorAction() { var compiled = "" + markupEl.value + "" + scriptEl.value + ""; frameWindow.document.open(); frameWindow.document.write(compiled); frameWindow.document.close(); } [markupEl, styleEl, scriptEl].forEach(function (current, index, array) { var syncFormElementsIndex = syncFormElements.indexOf(current), editor; // // add a listener to do indenting // current.addEventListener('keydown', function(event) { // var initialScroll, beforeCursor, inSelection, afterCursor, selectionMin, selectionMax, replacedText; // beforeCursor = current.value.slice(0, selectionMin); // inSelection = current.value.slice(selectionMin, selectionMax); // afterCursor = current.value.slice(selectionMax); // initialScroll = current.scrollTop; // if (event.keyCode === 13) { // // NEWLINE // event.preventDefault(); // replacedText = "\n"; // document.execCommand("insertText", false, replacedText); // selectionMin += replacedText.length; // selectionMax = selectionMin; // current.scrollTop = initialScroll; // } else if (event.keyCode === 9) { // // TAB // event.preventDefault(); // event.stopPropagation(); // replacedText = "\t"; // document.execCommand("insertText", false, replacedText); // selectionMin += replacedText.length; // selectionMax = selectionMin; // current.scrollTop = initialScroll; // } // }); editor = new Behave({ textarea: current, replaceTab: true, softTabs: true, tabSize: 2, autoOpen: true, overwrite: true, autoStrip: true, autoIndent: true, fence: false }); // add a listener to build the source when the fields are changed current.addEventListener('input', editorAction); if (syncFormElementsIndex >= 0) { // add a listener to receive changes from localStorage localStorageActions["janus-input-" + syncFormElementsIndex] = function (event) { var storedValue = event.newValue, decodedValue = storedValue.split("/", 2); decodedValue.push(storedValue.slice(decodedValue.join(" ").length + 1)); current.value = decodedValue[2]; current.setSelectionRange(+decodedValue[0], +decodedValue[1]); editorAction(); current.focus(); }; } }); editorAction(); } function init() { var storedSlideNumber; commandField = $("#commandField"); commandField.addEventListener("keydown", commandListener); commandField.addEventListener("blur", function (event) { toggleCommandBar(false); }); commandBar = $("body > nav"); toggleCommandBar(false); slides = $$("main>section, [janus-timeline]"); shortcut.add("Page_down", function () { setCurrentSlide(currentSlideNumber + 1, true); }); shortcut.add("Page_up", function () { setCurrentSlide(currentSlideNumber - 1, true); }); shortcut.add("Escape", function () { toggleCommandBar(!commandBarVisible); }); storedSlideNumber = localStorage.getItem("janus-currentSlideNumber"); if (storedSlideNumber) { setCurrentSlide(storedSlideNumber, false); } else { setCurrentSlide(0); } document.addEventListener("mousemove", mouseListener); localStorageActions = { "janus-currentSlideNumber": function (event) { setCurrentSlide(+event.newValue, false); }, "mouse-x" : function (event) { setMouseX(event.newValue, false); } }; $$("[janus-sync]").forEach(function (current, index, array) { var currentKey, storedValue, decodedValue, group, replacedText; syncFormElements.push(current); if (current.type === "textarea" || current.type === "text") { currentKey = "janus-input-" + index; storedValue = localStorage.getItem(currentKey); if (storedValue) { decodedValue = storedValue.split("/", 2); decodedValue.push(storedValue.slice(decodedValue.join(" ").length + 1)); current.value = decodedValue[2]; current.setSelectionRange(+decodedValue[0], +decodedValue[1]); } else { localStorage.setItem(currentKey, "0/0/" + current.value); } // add a listener to store changes current.addEventListener("keyup", function (event) { localStorage.setItem(currentKey, current.selectionStart + "/" + current.selectionEnd + "/" + current.value); }); // add a listener to respond to localStorage updates if (!localStorageActions[currentKey]) { localStorageActions[currentKey] = function (event) { var storedValue = event.newValue, decodedValue = storedValue.split("/", 2); decodedValue.push(storedValue.slice(decodedValue.join(" ").length + 1)); current.value = decodedValue[2]; current.focus(); current.setSelectionRange(+decodedValue[0], +decodedValue[1]); }; } } else if (current.type === "checkbox") { currentKey = "janus-input-" + index; storedValue = localStorage.getItem(currentKey); if (storedValue !== null) { current.checked = (storedValue === "true"); } else { localStorage.setItem(currentKey, current.checked); } // add a listener to store changes current.addEventListener("change", function (event) { localStorage.setItem(currentKey, current.checked); }); // add a listener to respond to localStorage updates if (!localStorageActions[currentKey]) { localStorageActions[currentKey] = function (event) { current.checked = (event.newValue === "true"); }; } } else if (current.type === "radio") { group = current.getAttribute("name"); currentKey = "janus-input-" + group; storedValue = localStorage.getItem(currentKey); if (storedValue !== null && +storedValue === index) { current.checked = true; } else if (current.checked) { localStorage.setItem(currentKey, index); } // add a listener to store changes current.addEventListener("change", function () { localStorage.setItem(currentKey, index); }); // add a listener to respond to localStorage updates if (!localStorageActions[currentKey]) { localStorageActions[currentKey] = function (event) { syncFormElements[+event.newValue].checked = true; }; } } }); $$(".live-coding").forEach(function (current, index, array) { editorListenerGenerator(current); }); document.body.classList.remove("is-loading"); } document.addEventListener("DOMContentLoaded", init); window.addEventListener("storage", sessionListener); }());