// Edit plugin, https://github.com/datenstrom/yellow-plugins/tree/master/edit // Copyright (c) 2013-2018 Datenstrom, https://datenstrom.se // This file may be used and distributed under the terms of the public license. var yellow = { // Main event handlers action: function(action, status, args) { yellow.edit.action(action, status, args); }, onLoad: function() { yellow.edit.load(); }, onClickAction: function(e) { yellow.edit.clickAction(e); }, onClick: function(e) { yellow.edit.click(e); }, onKeydown: function(e) { yellow.edit.keydown(e); }, onDrag: function(e) { yellow.edit.drag(e); }, onDrop: function(e) { yellow.edit.drop(e); }, onUpdate: function() { yellow.edit.updatePane(yellow.edit.paneId, yellow.edit.paneAction, yellow.edit.paneStatus); }, onResize: function() { yellow.edit.resizePane(yellow.edit.paneId, yellow.edit.paneAction, yellow.edit.paneStatus); } }; yellow.edit = { paneId: 0, //visible pane ID paneActionOld: 0, //previous pane action paneAction: 0, //current pane action paneStatus: 0, //current pane status popupId: 0, //visible popup ID intervalId: 0, //timer interval ID // Handle initialisation load: function() { var body = document.getElementsByTagName("body")[0]; if (body && body.firstChild && !document.getElementById("yellow-bar")) { this.createBar("yellow-bar"); this.createPane("yellow-pane-edit", "none", "none"); this.action(yellow.page.action, yellow.page.status); clearInterval(this.intervalId); } }, // Handle action action: function(action, status, args) { status = status ? status : "none"; args = args ? args : "none"; switch (action) { case "login": this.showPane("yellow-pane-login", action, status); break; case "logout": this.sendPane("yellow-pane-logout", action); break; case "signup": this.showPane("yellow-pane-signup", action, status); break; case "confirm": this.showPane("yellow-pane-signup", action, status); break; case "approve": this.showPane("yellow-pane-signup", action, status); break; case "forgot": this.showPane("yellow-pane-forgot", action, status); break; case "recover": this.showPane("yellow-pane-recover", action, status); break; case "reactivate": this.showPane("yellow-pane-settings", action, status); break; case "settings": this.showPane("yellow-pane-settings", action, status); break; case "verify": this.showPane("yellow-pane-settings", action, status); break; case "change": this.showPane("yellow-pane-settings", action, status); break; case "version": this.showPane("yellow-pane-version", action, status); break; case "update": this.sendPane("yellow-pane-update", action, status, args); break; case "quit": this.showPane("yellow-pane-quit", action, status); break; case "remove": this.showPane("yellow-pane-quit", action, status); break; case "create": this.showPane("yellow-pane-edit", action, status, true); break; case "edit": this.showPane("yellow-pane-edit", action, status, true); break; case "delete": this.showPane("yellow-pane-edit", action, status, true); break; case "user": this.showPane("yellow-pane-user", action, status); break; case "send": this.sendPane(this.paneId, this.paneAction); break; case "close": this.hidePane(this.paneId); break; case "toolbar": this.processToolbar(status, args); break; case "help": this.processHelp(); break; } }, // Handle action clicked clickAction: function(e) { e.stopPropagation(); e.preventDefault(); var element = e.target; for (; element; element=element.parentNode) { if (element.tagName=="A") break; } this.action(element.getAttribute("data-action"), element.getAttribute("data-status"), element.getAttribute("data-args")); }, // Handle mouse clicked click: function(e) { if (this.popupId && !document.getElementById(this.popupId).contains(e.target)) this.hidePopup(this.popupId, true); if (this.paneId && !document.getElementById(this.paneId).contains(e.target)) this.hidePane(this.paneId, true); }, // Handle keyboard keydown: function(e) { if (this.paneId=="yellow-pane-edit") this.processShortcut(e); if (this.paneId && e.keyCode==27) this.hidePane(this.paneId); }, // Handle drag drag: function(e) { e.stopPropagation(); e.preventDefault(); }, // Handle drop drop: function(e) { e.stopPropagation(); e.preventDefault(); var elementText = document.getElementById("yellow-pane-edit-text"); var files = e.dataTransfer ? e.dataTransfer.files : e.target.files; for (var i=0; i"+ ""+this.getText("Edit")+""+ ""+ "
"+ ""+this.getText("Create")+""+ ""+this.getText("Delete")+""+ ""+yellow.toolbox.encodeHtml(yellow.config.userName)+""+ "
"+ "
"; } elementBar.appendChild(elementDiv); yellow.toolbox.insertBefore(elementBar, document.getElementsByTagName("body")[0].firstChild); this.bindActions(elementBar); }, // Create pane createPane: function(paneId, paneAction, paneStatus) { if (yellow.config.debug) console.log("yellow.edit.createPane id:"+paneId); var elementPane = document.createElement("div"); elementPane.className = "yellow-pane"; elementPane.setAttribute("id", paneId); elementPane.style.display = "none"; if (paneId=="yellow-pane-edit") { yellow.toolbox.addEvent(elementPane, "input", yellow.onUpdate); yellow.toolbox.addEvent(elementPane, "dragenter", yellow.onDrag); yellow.toolbox.addEvent(elementPane, "dragover", yellow.onDrag); yellow.toolbox.addEvent(elementPane, "drop", yellow.onDrop); } if (paneId=="yellow-pane-edit" || paneId=="yellow-pane-user") { var elementArrow = document.createElement("span"); elementArrow.className = "yellow-arrow"; elementArrow.setAttribute("id", paneId+"-arrow"); elementPane.appendChild(elementArrow); } var elementDiv = document.createElement("div"); elementDiv.className = "yellow-content"; elementDiv.setAttribute("id", paneId+"-content"); switch (paneId) { case "yellow-pane-login": elementDiv.innerHTML = "
"+ ""+ "

"+this.getText("LoginTitle")+"

"+ "
"+ ""+ "


"+ "


"+ "

"+ "
"+ ""+ "
"; break; case "yellow-pane-signup": elementDiv.innerHTML = "
"+ ""+ "

"+this.getText("SignupTitle")+"

"+ "

"+this.getText(paneAction+"Status", "", paneStatus)+"

"+ "
"+ ""+ "


"+ "


"+ "


"+ "

"+ "

"+ "
"+ ""+ "
"; break; case "yellow-pane-forgot": elementDiv.innerHTML = "
"+ ""+ "

"+this.getText("ForgotTitle")+"

"+ "

"+this.getText(paneAction+"Status", "", paneStatus)+"

"+ "
"+ ""+ "


"+ "

"+ "
"+ ""+ "
"; break; case "yellow-pane-recover": elementDiv.innerHTML = "
"+ ""+ "

"+this.getText("RecoverTitle")+"

"+ "

"+this.getText(paneAction+"Status", "", paneStatus)+"

"+ "
"+ "


"+ "

"+ "
"+ ""+ "
"; break; case "yellow-pane-settings": var rawDataLanguages = ""; if (yellow.config.serverLanguages && Object.keys(yellow.config.serverLanguages).length>1) { rawDataLanguages += "

"; for (var language in yellow.config.serverLanguages) { var checked = language==this.getRequest("language") ? " checked=\"checked\"" : ""; rawDataLanguages += "
"; } rawDataLanguages += "

"; } elementDiv.innerHTML = "
"+ ""+ "

"+this.getText("SettingsTitle")+"

"+ "

"+this.getText(paneAction+"Status", "", paneStatus)+"

"+ "
"+ ""+ ""+ "


"+ "


"+ "


"+rawDataLanguages+ "

"+this.getText("SettingsQuit")+" "+this.getText("SettingsMore")+"

"+ "

"+ "
"+ ""+ "
"; break; case "yellow-pane-version": elementDiv.innerHTML = "
"+ ""+ "

"+yellow.toolbox.encodeHtml(yellow.config.serverVersion)+"

"+ "

"+this.getText("VersionStatus", "", paneStatus)+"

"+ "
"+yellow.page.rawDataOutput+"
"+ ""+ "
"; break; case "yellow-pane-quit": elementDiv.innerHTML = "
"+ ""+ "

"+this.getText("QuitTitle")+"

"+ "

"+this.getText(paneAction+"Status", "", paneStatus)+"

"+ "
"+ ""+ ""+ "


"+ "

"+ "
"+ ""+ "
"; break; case "yellow-pane-edit": var rawDataButtons = ""; if (yellow.config.editToolbarButtons && yellow.config.editToolbarButtons!="none") { var tokens = yellow.config.editToolbarButtons.split(","); for (var i=0; i"; } else { rawDataButtons += "
  • "; } } if (yellow.config.debug) console.log("yellow.edit.createPane buttons:"+yellow.config.editToolbarButtons); } elementDiv.innerHTML = "
    "+ "
    "+ "

    "+this.getText("Edit")+"

    "+ "
      "+rawDataButtons+"
    "+ ""+ "
      "+ "
      "+ ""+ "
      "+ "
      "; break; case "yellow-pane-user": elementDiv.innerHTML = ""; break; } elementPane.appendChild(elementDiv); yellow.toolbox.insertAfter(elementPane, document.getElementsByTagName("body")[0].firstChild); this.bindActions(elementPane); }, // Update pane updatePane: function(paneId, paneAction, paneStatus, init) { if (yellow.config.debug) console.log("yellow.edit.updatePane id:"+paneId); var showFields = paneStatus!="next" && paneStatus!="done"; switch (paneId) { case "yellow-pane-login": if (yellow.config.editLoginRestrictions) { yellow.toolbox.setVisible(document.getElementById("yellow-pane-login-signup"), false); } break; case "yellow-pane-signup": yellow.toolbox.setVisible(document.getElementById("yellow-pane-signup-fields"), showFields); yellow.toolbox.setVisible(document.getElementById("yellow-pane-signup-buttons"), !showFields); break; case "yellow-pane-forgot": yellow.toolbox.setVisible(document.getElementById("yellow-pane-forgot-fields"), showFields); yellow.toolbox.setVisible(document.getElementById("yellow-pane-forgot-buttons"), !showFields); break; case "yellow-pane-recover": yellow.toolbox.setVisible(document.getElementById("yellow-pane-recover-fields"), showFields); yellow.toolbox.setVisible(document.getElementById("yellow-pane-recover-buttons"), !showFields); break; case "yellow-pane-settings": yellow.toolbox.setVisible(document.getElementById("yellow-pane-settings-fields"), showFields); yellow.toolbox.setVisible(document.getElementById("yellow-pane-settings-buttons"), !showFields); if (paneStatus=="none") { document.getElementById("yellow-pane-settings-status").innerHTML = ""+this.getText("VersionTitle")+""; document.getElementById("yellow-pane-settings-name").value = yellow.config.userName; document.getElementById("yellow-pane-settings-email").value = yellow.config.userEmail; document.getElementById("yellow-pane-settings-"+yellow.config.userLanguage).checked = true; } break; case "yellow-pane-version": if (paneStatus=="none" && this.isPlugin("update")) { document.getElementById("yellow-pane-version-status").innerHTML = this.getText("VersionStatusCheck"); document.getElementById("yellow-pane-version-output").innerHTML = ""; setTimeout("yellow.action('send');", 500); } if (paneStatus=="updates" && this.isPlugin("update")) { document.getElementById("yellow-pane-version-status").innerHTML = ""+this.getText("VersionStatusUpdates")+""; } break; case "yellow-pane-quit": yellow.toolbox.setVisible(document.getElementById("yellow-pane-quit-fields"), showFields); yellow.toolbox.setVisible(document.getElementById("yellow-pane-quit-buttons"), !showFields); if (paneStatus=="none") { document.getElementById("yellow-pane-quit-status").innerHTML = this.getText("QuitStatusNone"); document.getElementById("yellow-pane-quit-name").value = ""; } break; case "yellow-pane-edit": document.getElementById("yellow-pane-edit-text").focus(); if (init) { yellow.toolbox.setVisible(document.getElementById("yellow-pane-edit-text"), true); yellow.toolbox.setVisible(document.getElementById("yellow-pane-edit-preview"), false); document.getElementById("yellow-pane-edit-toolbar-title").innerHTML = yellow.toolbox.encodeHtml(yellow.page.title); document.getElementById("yellow-pane-edit-text").value = paneAction=="create" ? yellow.page.rawDataNew : yellow.page.rawDataEdit; var matches = document.getElementById("yellow-pane-edit-text").value.match(/^(\xEF\xBB\xBF)?\-\-\-[\r\n]+/); var position = document.getElementById("yellow-pane-edit-text").value.indexOf("\n", matches ? matches[0].length : 0); document.getElementById("yellow-pane-edit-text").setSelectionRange(position, position); if (yellow.config.editToolbarButtons!="none") { yellow.toolbox.setVisible(document.getElementById("yellow-pane-edit-toolbar-title"), false); this.updateToolbar(0, "yellow-toolbar-checked"); } if (yellow.config.userRestrictions) { yellow.toolbox.setVisible(document.getElementById("yellow-pane-edit-send"), false); document.getElementById("yellow-pane-edit-text").readOnly = true; } } if (!yellow.config.userRestrictions) { var key, className; switch (this.getAction(paneId, paneAction)) { case "create": key = "CreateButton"; className = "yellow-toolbar-btn yellow-toolbar-btn-create"; break; case "edit": key = "EditButton"; className = "yellow-toolbar-btn yellow-toolbar-btn-edit"; break; case "delete": key = "DeleteButton"; className = "yellow-toolbar-btn yellow-toolbar-btn-delete"; break; } if (document.getElementById("yellow-pane-edit-send").className != className) { document.getElementById("yellow-pane-edit-send").innerHTML = this.getText(key); document.getElementById("yellow-pane-edit-send").className = className; this.resizePane(paneId, paneAction, paneStatus); } } break; } this.bindActions(document.getElementById(paneId)); }, // Resize pane resizePane: function(paneId, paneAction, paneStatus) { var elementBar = document.getElementById("yellow-bar-content"); var paneLeft = yellow.toolbox.getOuterLeft(elementBar); var paneTop = yellow.toolbox.getOuterTop(elementBar) + yellow.toolbox.getOuterHeight(elementBar) + 10; var paneWidth = yellow.toolbox.getOuterWidth(elementBar); var paneHeight = yellow.toolbox.getWindowHeight() - paneTop - Math.min(yellow.toolbox.getOuterHeight(elementBar) + 10, (yellow.toolbox.getWindowWidth()-yellow.toolbox.getOuterWidth(elementBar))/2); switch (paneId) { case "yellow-pane-login": case "yellow-pane-signup": case "yellow-pane-forgot": case "yellow-pane-recover": case "yellow-pane-settings": case "yellow-pane-version": case "yellow-pane-quit": yellow.toolbox.setOuterLeft(document.getElementById(paneId), paneLeft); yellow.toolbox.setOuterTop(document.getElementById(paneId), paneTop); yellow.toolbox.setOuterWidth(document.getElementById(paneId), paneWidth); break; case "yellow-pane-edit": yellow.toolbox.setOuterLeft(document.getElementById("yellow-pane-edit"), paneLeft); yellow.toolbox.setOuterTop(document.getElementById("yellow-pane-edit"), paneTop); yellow.toolbox.setOuterHeight(document.getElementById("yellow-pane-edit"), paneHeight); yellow.toolbox.setOuterWidth(document.getElementById("yellow-pane-edit"), paneWidth); var elementWidth = yellow.toolbox.getWidth(document.getElementById("yellow-pane-edit")); yellow.toolbox.setOuterWidth(document.getElementById("yellow-pane-edit-text"), elementWidth); yellow.toolbox.setOuterWidth(document.getElementById("yellow-pane-edit-preview"), elementWidth); var buttonsWidth = 0; var buttonsWidthMax = yellow.toolbox.getOuterWidth(document.getElementById("yellow-pane-edit-toolbar")) - yellow.toolbox.getOuterWidth(document.getElementById("yellow-pane-edit-toolbar-main")) - 1; var element = document.getElementById("yellow-pane-edit-toolbar-buttons").firstChild; for (; element; element=element.nextSibling) { element.removeAttribute("style"); buttonsWidth += yellow.toolbox.getOuterWidth(element); if (buttonsWidth>buttonsWidthMax) yellow.toolbox.setVisible(element, false); } yellow.toolbox.setOuterWidth(document.getElementById("yellow-pane-edit-toolbar-title"), buttonsWidthMax); var height1 = yellow.toolbox.getHeight(document.getElementById("yellow-pane-edit")); var height2 = yellow.toolbox.getOuterHeight(document.getElementById("yellow-pane-edit-toolbar")); yellow.toolbox.setOuterHeight(document.getElementById("yellow-pane-edit-text"), height1 - height2); yellow.toolbox.setOuterHeight(document.getElementById("yellow-pane-edit-preview"), height1 - height2); var elementLink = document.getElementById("yellow-pane-"+paneAction+"-link"); var position = yellow.toolbox.getOuterLeft(elementLink) + yellow.toolbox.getOuterWidth(elementLink)/2; position -= yellow.toolbox.getOuterLeft(document.getElementById("yellow-pane-edit")) + 1; yellow.toolbox.setOuterLeft(document.getElementById("yellow-pane-edit-arrow"), position); break; case "yellow-pane-user": yellow.toolbox.setOuterLeft(document.getElementById("yellow-pane-user"), paneLeft + paneWidth - yellow.toolbox.getOuterWidth(document.getElementById("yellow-pane-user"))); yellow.toolbox.setOuterTop(document.getElementById("yellow-pane-user"), paneTop); var elementLink = document.getElementById("yellow-pane-user-link"); var position = yellow.toolbox.getOuterLeft(elementLink) + yellow.toolbox.getOuterWidth(elementLink)/2; position -= yellow.toolbox.getOuterLeft(document.getElementById("yellow-pane-user")); yellow.toolbox.setOuterLeft(document.getElementById("yellow-pane-user-arrow"), position); break; } }, // Show or hide pane showPane: function(paneId, paneAction, paneStatus, modal) { if (this.paneId!=paneId || this.paneAction!=paneAction) { this.hidePane(this.paneId); if (!document.getElementById(paneId)) this.createPane(paneId, paneAction, paneStatus); var element = document.getElementById(paneId); if (!yellow.toolbox.isVisible(element)) { if (yellow.config.debug) console.log("yellow.edit.showPane id:"+paneId); yellow.toolbox.setVisible(element, true); if (modal) { yellow.toolbox.addClass(document.body, "yellow-body-modal-open"); yellow.toolbox.addValue("meta[name=viewport]", "content", ", maximum-scale=1, user-scalable=0"); } this.paneId = paneId; this.paneAction = paneAction; this.paneStatus = paneStatus; this.updatePane(paneId, paneAction, paneStatus, this.paneActionOld!=this.paneAction); this.resizePane(paneId, paneAction, paneStatus); } } else { this.hidePane(this.paneId, true); } }, // Hide pane hidePane: function(paneId, fadeout) { var element = document.getElementById(paneId); if (yellow.toolbox.isVisible(element)) { yellow.toolbox.removeClass(document.body, "yellow-body-modal-open"); yellow.toolbox.removeValue("meta[name=viewport]", "content", ", maximum-scale=1, user-scalable=0"); yellow.toolbox.setVisible(element, false, fadeout); this.paneId = 0; this.paneActionOld = this.paneAction; this.paneAction = 0; this.paneStatus = 0; } this.hidePopup(this.popupId); }, // Send pane sendPane: function(paneId, paneAction, paneStatus, paneArgs) { if (yellow.config.debug) console.log("yellow.edit.sendPane id:"+paneId); var args = { "action":paneAction, "csrftoken":this.getCookie("csrftoken") }; if (paneId=="yellow-pane-edit") { args.action = this.getAction(paneId, paneAction); args.rawdatasource = yellow.page.rawDataSource; args.rawdataedit = document.getElementById("yellow-pane-edit-text").value; args.rawdataendofline = yellow.page.rawDataEndOfLine; } if (paneArgs) { var tokens = paneArgs.split("/"); for (var i=0; i ", "insert-multiline-block", true); break; case "pre": yellow.editor.setMarkdown(elementText, "```\n", "insert-fenced-block", true); break; case "bold": yellow.editor.setMarkdown(elementText, "**", "insert-inline", true); break; case "italic": yellow.editor.setMarkdown(elementText, "*", "insert-inline", true); break; case "strikethrough": yellow.editor.setMarkdown(elementText, "~~", "insert-inline", true); break; case "code": yellow.editor.setMarkdown(elementText, "`", "insert-autodetect", true); break; case "ul": yellow.editor.setMarkdown(elementText, "* ", "insert-multiline-block", true); break; case "ol": yellow.editor.setMarkdown(elementText, "1. ", "insert-multiline-block", true); break; case "tl": yellow.editor.setMarkdown(elementText, "- [ ] ", "insert-multiline-block", true); break; case "link": yellow.editor.setMarkdown(elementText, "[link](url)", "insert", false, yellow.editor.getMarkdownLink); break; case "text": yellow.editor.setMarkdown(elementText, args, "insert"); break; case "draft": yellow.editor.setMetaData(elementText, "status", "draft", true); break; case "file": this.showFileDialog(); break; case "undo": yellow.editor.undo(); break; case "redo": yellow.editor.redo(); break; } } if (status=="preview") this.showPreview(elementText, elementPreview); if (status=="save" && !yellow.config.userRestrictions && this.paneAction!="delete") this.action("send"); if (status=="help") window.open(this.getText("HelpUrl", "yellow"), "_blank"); if (status=="markdown") window.open(this.getText("MarkdownUrl", "yellow"), "_blank"); if (status=="format" || status=="heading" || status=="list" || status=="emojiawesome" || status=="fontawesome") { this.showPopup("yellow-popup-"+status, status); } else { this.hidePopup(this.popupId); } }, // Update toolbar updateToolbar: function(status, name) { if (status) { var element = document.getElementById("yellow-toolbar-"+status); if (element) yellow.toolbox.addClass(element, name); } else { var elements = document.getElementsByClassName(name); for (var i=0, l=elements.length; i"+ "
    • "+this.getText("ToolbarH1")+"
    • "+ "
    • "+this.getText("ToolbarH2")+"
    • "+ "
    • "+this.getText("ToolbarH3")+"
    • "+ "
    • "+this.getText("ToolbarParagraph")+"
    • "+ "
    • "+this.getText("ToolbarPre")+"
    • "+ "
    • "+this.getText("ToolbarQuote")+"
    • "+ ""; break; case "yellow-popup-heading": elementDiv.innerHTML = ""; break; case "yellow-popup-list": elementDiv.innerHTML = ""; break; case "yellow-popup-emojiawesome": var rawDataEmojis = ""; if (yellow.config.emojiawesomeToolbarButtons && yellow.config.emojiawesomeToolbarButtons!="none") { var tokens = yellow.config.emojiawesomeToolbarButtons.split(" "); for (var i=0; i"; } } elementDiv.innerHTML = "
        "+rawDataEmojis+"
      "; break; case "yellow-popup-fontawesome": var rawDataIcons = ""; if (yellow.config.fontawesomeToolbarButtons && yellow.config.fontawesomeToolbarButtons!="none") { var tokens = yellow.config.fontawesomeToolbarButtons.split(" "); for (var i=0; i"; } } elementDiv.innerHTML = "
        "+rawDataIcons+"
      "; break; } elementPopup.appendChild(elementDiv); yellow.toolbox.insertAfter(elementPopup, document.getElementsByTagName("body")[0].firstChild); this.bindActions(elementPopup); }, // Show or hide popup showPopup: function(popupId, status) { if (this.popupId!=popupId) { this.hidePopup(this.popupId); if (!document.getElementById(popupId)) this.createPopup(popupId); var element = document.getElementById(popupId); if (yellow.config.debug) console.log("yellow.edit.showPopup id:"+popupId); yellow.toolbox.setVisible(element, true); this.popupId = popupId; this.updateToolbar(status, "yellow-toolbar-selected"); var elementParent = document.getElementById("yellow-toolbar-"+status); var popupLeft = yellow.toolbox.getOuterLeft(elementParent); var popupTop = yellow.toolbox.getOuterTop(elementParent) + yellow.toolbox.getOuterHeight(elementParent) - 1; yellow.toolbox.setOuterLeft(document.getElementById(popupId), popupLeft); yellow.toolbox.setOuterTop(document.getElementById(popupId), popupTop); } else { this.hidePopup(this.popupId, true); } }, // Hide popup hidePopup: function(popupId, fadeout) { var element = document.getElementById(popupId); if (yellow.toolbox.isVisible(element)) { yellow.toolbox.setVisible(element, false, fadeout); this.popupId = 0; this.updateToolbar(0, "yellow-toolbar-selected"); } }, // Show or hide preview showPreview: function(elementText, elementPreview) { if (!yellow.toolbox.isVisible(elementPreview)) { var thisObject = this; var formData = new FormData(); formData.append("action", "preview"); formData.append("csrftoken", this.getCookie("csrftoken")); formData.append("rawdataedit", elementText.value); formData.append("rawdataendofline", yellow.page.rawDataEndOfLine); var request = new XMLHttpRequest(); request.open("POST", window.location.pathname, true); request.onload = function() { if (this.status==200) thisObject.showPreviewDone.call(thisObject, elementText, elementPreview, this.responseText); }; request.send(formData); } else { this.showPreviewDone(elementText, elementPreview, ""); } }, // Preview done showPreviewDone: function(elementText, elementPreview, responseText) { var showPreview = responseText.length!=0; yellow.toolbox.setVisible(elementText, !showPreview); yellow.toolbox.setVisible(elementPreview, showPreview); if (showPreview) { this.updateToolbar("preview", "yellow-toolbar-checked"); elementPreview.innerHTML = responseText; dispatchEvent(new Event("load")); } else { this.updateToolbar(0, "yellow-toolbar-checked"); elementText.focus(); } }, // Show file dialog and trigger upload showFileDialog: function() { var element = document.createElement("input"); element.setAttribute("id", "yellow-file-dialog"); element.setAttribute("type", "file"); element.setAttribute("accept", yellow.config.editUploadExtensions); element.setAttribute("multiple", "multiple"); yellow.toolbox.addEvent(element, "change", yellow.onDrop); element.click(); }, // Upload file uploadFile: function(elementText, file) { var extension = (file.name.lastIndexOf(".")!=-1 ? file.name.substring(file.name.lastIndexOf("."), file.name.length) : "").toLowerCase(); var extensions = yellow.config.editUploadExtensions.split(/\s*,\s*/); if (file.size<=yellow.config.serverFileSizeMax && extensions.indexOf(extension)!=-1) { var text = this.getText("UploadProgress")+"\u200b"; yellow.editor.setMarkdown(elementText, text, "insert"); var thisObject = this; var formData = new FormData(); formData.append("action", "upload"); formData.append("csrftoken", this.getCookie("csrftoken")); formData.append("file", file); var request = new XMLHttpRequest(); request.open("POST", window.location.pathname, true); request.onload = function() { if (this.status==200) { thisObject.uploadFileDone.call(thisObject, elementText, this.responseText); } else { thisObject.uploadFileError.call(thisObject, elementText, this.responseText); } }; request.send(formData); } }, // Upload done uploadFileDone: function(elementText, responseText) { var result = JSON.parse(responseText); if (result) { var textOld = this.getText("UploadProgress")+"\u200b"; var textNew; if (result.location.substring(0, yellow.config.imageLocation.length)==yellow.config.imageLocation) { textNew = "[image "+result.location.substring(yellow.config.imageLocation.length)+"]"; } else { textNew = "[link]("+result.location+")"; } yellow.editor.replace(elementText, textOld, textNew); } }, // Upload error uploadFileError: function(elementText, responseText) { var result = JSON.parse(responseText); if (result) { var textOld = this.getText("UploadProgress")+"\u200b"; var textNew = "["+result.error+"]"; yellow.editor.replace(elementText, textOld, textNew); } }, // Bind actions to links bindActions: function(element) { var elements = element.getElementsByTagName("a"); for (var i=0, l=elements.length; i0) top--; if (bottom==top && bottom\s]+)?(\s+\[.\]|\s*\d+\.)?[ \t]+/); if (matches) { textSelectionNew += lines[i].substring(matches[0].length); } else { textSelectionNew += lines[i]; } } textSelection = textSelectionNew; if (information.type.indexOf("remove")==-1) { textSelectionNew = ""; var linePrefix = information.prefix; lines = yellow.toolbox.getTextLines(textSelection.length!=0 ? textSelection : "\n"); for (var i=0; i=48 && e.keyCode<=90) { shortcut += (e.ctrlKey ? "ctrl+" : "")+(e.metaKey ? "meta+" : "")+(e.altKey ? "alt+" : "")+(e.shiftKey ? "shift+" : ""); shortcut += String.fromCharCode(e.keyCode).toLowerCase(); } return shortcut; }, // Return element width in pixel getWidth: function(element) { return element.offsetWidth - this.getBoxSize(element).width; }, // Return element height in pixel getHeight: function(element) { return element.offsetHeight - this.getBoxSize(element).height; }, // Set element width in pixel, including padding and border setOuterWidth: function(element, width) { element.style.width = Math.max(0, width - this.getBoxSize(element).width) + "px"; }, // Set element height in pixel, including padding and border setOuterHeight: function(element, height) { element.style.height = Math.max(0, height - this.getBoxSize(element).height) + "px"; }, // Return element width in pixel, including padding and border getOuterWidth: function(element, includeMargin) { var width = element.offsetWidth; if (includeMargin) width += this.getMarginSize(element).width; return width; }, // Return element height in pixel, including padding and border getOuterHeight: function(element, includeMargin) { var height = element.offsetHeight; if (includeMargin) height += this.getMarginSize(element).height; return height; }, // Set element left position in pixel setOuterLeft: function(element, left) { element.style.left = Math.max(0, left) + "px"; }, // Set element top position in pixel setOuterTop: function(element, top) { element.style.top = Math.max(0, top) + "px"; }, // Return element left position in pixel getOuterLeft: function(element) { return element.getBoundingClientRect().left + window.pageXOffset; }, // Return element top position in pixel getOuterTop: function(element) { return element.getBoundingClientRect().top + window.pageYOffset; }, // Return window width in pixel getWindowWidth: function() { return window.innerWidth; }, // Return window height in pixel getWindowHeight: function() { return window.innerHeight; }, // Return element CSS property getStyle: function(element, property) { return window.getComputedStyle(element).getPropertyValue(property); }, // Return element CSS padding and border getBoxSize: function(element) { var paddingLeft = parseFloat(this.getStyle(element, "padding-left")) || 0; var paddingRight = parseFloat(this.getStyle(element, "padding-right")) || 0; var borderLeft = parseFloat(this.getStyle(element, "border-left-width")) || 0; var borderRight = parseFloat(this.getStyle(element, "border-right-width")) || 0; var width = paddingLeft + paddingRight + borderLeft + borderRight; var paddingTop = parseFloat(this.getStyle(element, "padding-top")) || 0; var paddingBottom = parseFloat(this.getStyle(element, "padding-bottom")) || 0; var borderTop = parseFloat(this.getStyle(element, "border-top-width")) || 0; var borderBottom = parseFloat(this.getStyle(element, "border-bottom-width")) || 0; var height = paddingTop + paddingBottom + borderTop + borderBottom; return { "width":width, "height":height }; }, // Return element CSS margin getMarginSize: function(element) { var marginLeft = parseFloat(this.getStyle(element, "margin-left")) || 0; var marginRight = parseFloat(this.getStyle(element, "margin-right")) || 0; var width = marginLeft + marginRight; var marginTop = parseFloat(this.getStyle(element, "margin-top")) || 0; var marginBottom = parseFloat(this.getStyle(element, "margin-bottom")) || 0; var height = marginTop + marginBottom; return { "width":width, "height":height }; }, // Set element visibility setVisible: function(element, show, fadeout) { if (fadeout && !show) { var opacity = 1; function renderFrame() { opacity -= .1; if (opacity<=0) { element.style.opacity = "initial"; element.style.display = "none"; } else { element.style.opacity = opacity; requestAnimationFrame(renderFrame); } } renderFrame(); } else { element.style.display = show ? "block" : "none"; } }, // Check if element exists and is visible isVisible: function(element) { return element && element.style.display!="none"; }, // Convert first letter to lowercase toLowerFirst: function(string) { return string.charAt(0).toLowerCase()+string.slice(1); }, // Convert first letter to uppercase toUpperFirst: function(string) { return string.charAt(0).toUpperCase()+string.slice(1); }, // Return lines from text string, including newline getTextLines: function(string) { var lines = string.split("\n"); for (var i=0; i/g, ">") .replace(/"/g, """); }, // Submit form with post method submitForm: function(args) { var elementForm = document.createElement("form"); elementForm.setAttribute("method", "post"); for (var key in args) { if (!args.hasOwnProperty(key)) continue; var elementInput = document.createElement("input"); elementInput.setAttribute("type", "hidden"); elementInput.setAttribute("name", key); elementInput.setAttribute("value", args[key]); elementForm.appendChild(elementInput); } document.body.appendChild(elementForm); elementForm.submit(); } }; yellow.edit.intervalId = setInterval("yellow.onLoad()", 1);