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