Mercurial > eldonilo > barbecue
view script.js @ 3:6ef82d6818f4
readme
author | Fabien Cazenave <fabien@cazenave.cc> |
---|---|
date | Mon, 19 Dec 2011 19:00:15 +0100 |
parents | 683f56999fb3 |
children |
line wrap: on
line source
/** Copyright (c) 2010-2011 Fabien Cazenave and Sonny Piers. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ /** * File : barbecue.js * Author : Fabien Cazenave <fabien@cazenave.cc> * Version : 0.1 * License : MIT * Last Modified : 2011-12-19 */ /** wysiwyg Editor * expected compatibility: all browsers except IE<9. * * This HTML content editor is not intended to compete with CKEditor or * TinyMCE: it is designed to *test* the various implementations of * contentEditable and execCommand in modern browsers. * * Note: a specific micro-format is expected for the format toolbar. */ !function(window, document, undefined) { var gActiveEditor = null, // active editing host gCommandDump = null; // command dump field (debug) function ExecCommand(toolbarElement) { var argVal, argStr, type = toolbarElement.getAttribute("type"), command = toolbarElement.getAttribute("data-command"); // get the execCommand argument according to the button type switch (type) { case "button": // toolbar button: no argument argVal = argStr = false; break; case "checkbox": // styleWithCSS: boolean argument argVal = argStr = "" + toolbarElement.checked + ""; break; default: // <select> menu: string argument if (!toolbarElement.selectedIndex) return; argVal = toolbarElement.value; argStr = "'" + argVal.replace("<", "<").replace(">", ">") + "'"; toolbarElement.selectedIndex = 0; // reset drop-down list } // send requested action and re-focus the editable element document.execCommand(command, false, argVal); if (gActiveEditor) gActiveEditor.focus(); // debug gCommandDump.innerHTML = "document.execCommand('" + command + "', false, '" + argStr + "');"; } window.addEventListener("DOMContentLoaded", function() { var i, buttons = document.querySelectorAll("*[data-command]"), editors = document.querySelectorAll("*[contenteditable]"); // initialize all toolbar buttons for (i = 0; i < buttons.length; i++) { buttons[i].onclick = function() { ExecCommand(this); }; buttons[i].onchange = function() { ExecCommand(this); }; } // remember last-focused editable element for (i = 0; i < editors.length; i++) editors[i].onfocus = function() { gActiveEditor = this; }; // debug gCommandDump = document.querySelector("#execCommand"); ExecCommand(document.querySelector("#useCSS")); }, false); } (this, document); /** DOMNodeFocused * expected compatibility: all browsers except IE<9. * * This custom (non-standard) event is fired when a node in an editable element * gets the user focus. */ !function(window, document, undefined) { var gLastFocusNode = null; function onCaretMove(event) { var selection = document.getSelection(); var node = selection.isCollapsed ? selection.focusNode : selection.getRangeAt(0).commonAncestorContainer; if (node != gLastFocusNode) { gLastFocusNode = node; // fire a 'DOMNodeFocused' mutation event with bubbling to set the .target //var evtObject = document.createEvent("MutationEvent"); //evtObject.initMutationEvent("DOMNodeFocused", true, false, node, "", "", "", 0); // note that a standard event works fine, too :-) var evtObject = document.createEvent("Event"); evtObject.initEvent("DOMNodeFocused", true, false); node.dispatchEvent(evtObject); } } // trigger a 'DOMNodeFocused' event when the user moves the caret window.addEventListener("DOMContentLoaded", function() { var i, editors = document.querySelectorAll("*[contenteditable]"); for (i = 0; i < editors.length; i++) { editors[i].addEventListener("keyup", onCaretMove, false); editors[i].addEventListener("mouseup", onCaretMove, false); } }, false); } (this, document); /** Mutation Events -- demo! * expected compatibility: Firefox Aurora, possibly other modern browsers. * reference: https://developer.mozilla.org/en/XUL/Events#Mutation_DOM_events * http://help.dottoro.com/ljifcdwx.php * * SXE requires these (standard) mutation events: * - 'new': DOMNodeInserted * - 'remove': DOMNodeRemoved * - 'set': DOMSubtreeModified, DOMAttrModified, DOMCharacterDataModified * * Note: webkit doesn't support DOMAttrModified * https://bugs.webkit.org/show_bug.cgi?id=8191 */ window.addEventListener("DOMContentLoaded", function() { var breadcrumb = document.querySelector("#breadcrumb"); function updateBreadCrumb(event) { if (!breadcrumb || !event || !event.target) return; var body = document.body, node = event.target, text = node.nodeName, tmp = node.parentNode; while (tmp && tmp != body) { text = tmp.nodeName + " > " + text; tmp = tmp.parentNode; } text = event.type + ": " + text; breadcrumb.innerHTML = text; console.log(text); } // listening to mutation events on 'document' freezes Firefox :-/ var i, editors = document.querySelectorAll("*[contenteditable]"); for (i = 0; i < editors.length; i++) { // set editors[i].addEventListener("DOMAttrModified", updateBreadCrumb, false); editors[i].addEventListener("DOMSubtreeModified", updateBreadCrumb, false); editors[i].addEventListener("DOMCharacterDataModified", updateBreadCrumb, false); // new, remove editors[i].addEventListener("DOMNodeInserted", updateBreadCrumb, false); editors[i].addEventListener("DOMNodeRemoved", updateBreadCrumb, false); // focus (non-standard but can be useful) editors[i].addEventListener("DOMNodeFocused", updateBreadCrumb, false); } }, false);