From c45152e34631db79172bc0015bf95c692b4d01c6 Mon Sep 17 00:00:00 2001 From: vyshane Date: Thu, 30 Nov 2006 08:33:29 +0000 Subject: [PATCH] Editor keyboard shortcuts. MDL-7466. --- lib/editor/htmlarea/htmlarea.php | 232 +++++++++++++++++++++---------- 1 file changed, 156 insertions(+), 76 deletions(-) diff --git a/lib/editor/htmlarea/htmlarea.php b/lib/editor/htmlarea/htmlarea.php index 0e42fb792e..2082771406 100644 --- a/lib/editor/htmlarea/htmlarea.php +++ b/lib/editor/htmlarea/htmlarea.php @@ -79,6 +79,7 @@ function HTMLArea(textarea, config) { this._customUndo = true; this._mdoc = document; // cache the document, we need it in plugins this.doctype = ''; + this.dropdowns = []; // Array of select elements in the toolbar } }; @@ -419,6 +420,8 @@ HTMLArea.prototype._createToolbar = function () { editor._comboSelected(el, txt); }); } + editor.dropdowns[txt] = el; // Keep track of the element for keyboard + // access later. return el; }; // END of function: createSelect @@ -790,37 +793,38 @@ HTMLArea.prototype.generate = function () { textarea.style.width = iframe.style.width; textarea.style.height = iframe.style.height; - if (HTMLArea.is_ie) { - doc.body.contentEditable = true; - } + if (HTMLArea.is_ie) { + doc.body.contentEditable = true; + } - // intercept some events; for updating the toolbar & keyboard handlers - HTMLArea._addEvents - (doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"], - function (event) { - return editor._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event : event); - }); + // intercept some events; for updating the toolbar & keyboard handlers + HTMLArea._addEvents + (doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"], + function (event) { + return editor._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event : event); + }); - // check if any plugins have registered refresh handlers - for (var i in editor.plugins) { - var plugin = editor.plugins[i].instance; - if (typeof plugin.onGenerate == "function") - plugin.onGenerate(); + // check if any plugins have registered refresh handlers + for (var i in editor.plugins) { + var plugin = editor.plugins[i].instance; + if (typeof plugin.onGenerate == "function") { + plugin.onGenerate(); + } if (typeof plugin.onGenerateOnce == "function") { plugin.onGenerateOnce(); plugin.onGenerateOnce = null; } - } - - // Moodle fix for bug Bug #2521 Too long statusbar line in IE - // - //setTimeout(function() { - //editor.updateToolbar(); - //}, 250); + } - if (typeof editor.onGenerate == "function") - editor.onGenerate(); + // Moodle fix for bug Bug #2521 Too long statusbar line in IE + // + //setTimeout(function() { + // editor.updateToolbar(); + //}, 250); + if (typeof editor.onGenerate == "function") { + editor.onGenerate(); + } }; @@ -1935,72 +1939,144 @@ HTMLArea.prototype.execCommand = function(cmdID, UI, param) { return false; }; -/** A generic event handler for things that happen in the IFRAME's document. - * This function also handles key bindings. */ + +/** + * A generic event handler for things that happen in the IFRAME's document. + * This function also handles key bindings. + */ HTMLArea.prototype._editorEvent = function(ev) { + var editor = this; var keyEvent = (HTMLArea.is_ie && ev.type == "keydown") || (ev.type == "keypress"); - if (keyEvent) { - for (var i in editor.plugins) { + + if (keyEvent) { + + for (var i in editor.plugins) { var plugin = editor.plugins[i].instance; if (typeof plugin.onKeyPress == "function") plugin.onKeyPress(ev); } - } - if (keyEvent && ev.ctrlKey && ! ev.altKey) { - var sel = null; + + var sel = null; var range = null; var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase(); var cmd = null; var value = null; - switch (key) { - case 'a': - if (!HTMLArea.is_ie) { - // KEY select all - sel = this._getSelection(); - sel.removeAllRanges(); - range = this._createRange(); - range.selectNodeContents(this._doc.body); - sel.addRange(range); - HTMLArea._stopEvent(ev); - } - break; - // simple key commands follow - - case 'b': cmd = "bold"; break; - case 'i': cmd = "italic"; break; - case 'u': cmd = "underline"; break; - case 's': cmd = "strikethrough"; break; - case 'l': cmd = "justifyleft"; break; - case 'e': cmd = "justifycenter"; break; - case 'r': cmd = "justifyright"; break; - case 'j': cmd = "justifyfull"; break; - case 'z': cmd = "undo"; break; - case 'y': cmd = "redo"; break; - case 'v': if (! HTMLArea.is_gecko ) { cmd = "paste"; } break; - - case '0': cmd = "killword"; break; - - // headings - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - cmd = "formatblock"; - value = "h" + key; - if (HTMLArea.is_ie) { - value = "<" + value + ">"; - } - break; - } - if (cmd) { + if (ev.ctrlKey && !ev.altKey) { + /** + * Ctrl modifier only. + * We use these for shortcuts that change existing content, + * e.g. make text bold. + */ + switch (key) { + + case 'a': + // Select all. + if (!HTMLArea.is_ie) { + // KEY select all + sel = this._getSelection(); + sel.removeAllRanges(); + range = this._createRange(); + range.selectNodeContents(this._doc.body); + sel.addRange(range); + HTMLArea._stopEvent(ev); + } + break; + + // For the dropdowns, we assign focus to them so that they are + // keyboard accessible. + case 'o': + editor.dropdowns['fontname'].focus(); + break; + case 'p': + editor.dropdowns['fontsize'].focus(); + break; + case 'h': + editor.dropdowns['formatblock'].focus(); + break; + + case 'b': cmd = "bold"; break; + case 'i': cmd = "italic"; break; + case 'u': cmd = "underline"; break; + case 's': cmd = "strikethrough"; break; + case ',': cmd = "subscript"; break; + case '.': cmd = "superscript"; break; + + case 'v': + if (! HTMLArea.is_gecko ) { + cmd = "paste"; + } + break; + + case '0': cmd = "killword"; break; + case 'z': cmd = "undo"; break; + case 'y': cmd = "redo"; break; + case 'l': cmd = "justifyleft"; break; + case 'e': cmd = "justifycenter"; break; + case 'r': cmd = "justifyright"; break; + case 'j': cmd = "justifyfull"; break; + case '/': cmd = "lefttoright"; break; + case '|': cmd = "righttoleft"; break; + case ';': cmd = "outdent"; break; + case "'": cmd = "indent"; break; + case 'g': cmd = "forecolor"; break; + case 'k': cmd = "hilitecolor"; break; + case 'f': cmd = "searchandreplace"; break; + case '`': cmd = "htmlmode"; break; // FIXME: can't toggle from source code to wysiwyg + + case 'm': + // Toggle fullscreen on or off. + if (this.config.btnList['popupeditor'][0] == 'Enlarge Editor') { + cmd = 'popupeditor'; + } else { + window.close(); + } + break; + + // Headings. + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + cmd = "formatblock"; + value = "h" + key; + if (HTMLArea.is_ie) { + value = "<" + value + ">"; + } + break; + + } // End switch (key) + + + } else if (ev.ctrlKey && ev.altKey) { + /** + * Ctrl + Alt modifiers. + * We use these for shortcuts that insert stuff, e.g. images. + */ + switch (key) { + case 'o': cmd = "insertorderedlist"; break; + case 'u': cmd = "insertunorderedlist"; break; + case 'r': cmd = "inserthorizontalrule"; break; + case 'a': cmd = "createanchor"; break; + case 'l': cmd = "createlink"; break; + case 'd': cmd = "unlink"; break; + case 'n': cmd = "nolink"; break; + case 'i': cmd = 'insertimage'; break; + case 't': cmd = 'inserttable'; break; + case 's': cmd = 'insertsmile'; break; + case 'c': cmd = 'insertchar'; break; + } + } + + if (cmd) { // execute simple command this.execCommand(cmd, false, value); HTMLArea._stopEvent(ev); } - } + } // End if (keyEvent) + /* else if (keyEvent) { // other keys here @@ -2014,7 +2090,8 @@ HTMLArea.prototype._editorEvent = function(ev) { } } */ - // update the toolbar state after some time + + // Update the toolbar state after some time. if (editor._timerToolbar) { clearTimeout(editor._timerToolbar); } @@ -2024,6 +2101,7 @@ HTMLArea.prototype._editorEvent = function(ev) { }, 50); }; + // retrieve the HTML HTMLArea.prototype.getHTML = function() { switch (this._editMode) { @@ -2147,7 +2225,9 @@ HTMLArea.prototype._createRange = function(sel) { if (HTMLArea.is_ie) { return sel.createRange(); } else { - this.focusEditor(); + // Commented out because we need the dropdowns to be able to keep + // focus for keyboard accessibility. Comment by Vy-Shane Sin Fat. + //this.focusEditor(); if (typeof sel != "undefined") { try { return sel.getRangeAt(0); -- 2.39.5