1 /* state-override.js is part of Aloha Editor project http://aloha-editor.org 2 * 3 * Aloha Editor is a WYSIWYG HTML5 inline editing library and editor. 4 * Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria. 5 * Contributors http://aloha-editor.org/contribution.php 6 * 7 * Aloha Editor is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or any later version. 11 * 12 * Aloha Editor is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * As an additional permission to the GNU GPL version 2, you may distribute 22 * non-source (e.g., minimized or compacted) forms of the Aloha-Editor 23 * source code without the copy of the GNU GPL normally required, 24 * provided you include this license notice and a URL through which 25 * recipients can access the Corresponding Source. 26 */ 27 define([ 28 'aloha/core', 29 'jquery', 30 'aloha/selection', 31 'aloha/command', 32 'util/dom2', 33 'PubSub' 34 ], function ( 35 Aloha, 36 jQuery, 37 Selection, 38 Command, 39 Dom, 40 PubSub 41 ) { 42 'use strict'; 43 44 var enabled = Aloha.settings.stateOverride; 45 46 // https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#state-override 47 // "Whenever the number of ranges in the selection changes to 48 // something different, and whenever a boundary point of the range 49 // at a given index in the selection changes to something different, 50 // the state override and value override must be unset for every 51 // command." 52 Aloha.bind('aloha-selection-changed', function (event, range) { 53 if (Command.resetOverrides(range)) { 54 // Because the UI may reflect the any potentially state 55 // overrides that are now no longer in effect, we must 56 // redraw the UI according to the current selection. 57 58 PubSub.pub('aloha.selection.context-change', { 59 range: range, 60 event: event 61 }); 62 63 } 64 }); 65 66 function keyPressHandler(event) { 67 if (!enabled) { 68 return; 69 } 70 if (event.altKey || event.ctrlKey || !event.which) { 71 return; 72 } 73 var selection = Aloha.getSelection(); 74 if (!selection.getRangeCount()) { 75 return; 76 } 77 var text = String.fromCharCode(event.which); 78 var range = selection.getRangeAt(0); 79 // Because execCommand may invoke for example the bold command, 80 // which selects the inserted text to make it bold, and by doing 81 // so fires a selection-changed event. This is unnecessary and 82 // causes a flicker in the UI where the bold state of the button 83 // switches from bold to unbold and to bold again. 84 Aloha.Selection.preventSelectionChanged(); 85 Command.execCommand('insertText', null, text, range); 86 // Because we handled the character insert ourselves via 87 // insertText we must not let the browser's default action 88 // insert the character a second time. 89 event.preventDefault(); 90 } 91 92 function rangeFromRangeObject(alohaRange) { 93 var range = Aloha.createRange(); 94 range.setStart(alohaRange.startContainer, alohaRange.startOffset); 95 range.setEnd(alohaRange.endContainer, alohaRange.endOffset); 96 return range; 97 } 98 99 function setWithRangeObject(command, state, rangeObject) { 100 if (!enabled) { 101 return; 102 } 103 var range = rangeFromRangeObject(rangeObject); 104 Command.setStateOverride(command, state, range); 105 // Because without doing rangeObject.select(), the 106 // next insertText command (see editable.js) will 107 // not be reached and instead the browsers default 108 // insert behaviour will be applied (which doesn't 109 // know anything about state overrides). I don't 110 // know the exact reasons why; probably some 111 // stopPropagation somewhere by some plugin. 112 rangeObject.select(); 113 } 114 115 function enabledAccessor(trueFalse) { 116 if (null != trueFalse) { 117 enabled = trueFalse; 118 119 } 120 return enabled; 121 122 } 123 124 return { 125 enabled: enabledAccessor, 126 keyPressHandler: keyPressHandler, 127 setWithRangeObject: setWithRangeObject 128 }; 129 }); 130