399d5e7b7416900f940bd1343f0a191d728a04b2
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Resources / Public / JavaScript / HTMLArea / Extjs / ux / Combo.js
1 /*
2 * This file is part of the TYPO3 CMS project.
3 *
4 * It is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, either version 2
6 * of the License, or any later version.
7 *
8 * For the full copyright and license information, please read the
9 * LICENSE.txt file that was distributed with this source code.
10 *
11 * The TYPO3 project - inspiring people to share!
12 */
13
14 /**
15 * Ext.ux.form.HTMLAreaCombo extends Ext.form.ComboBox
16 */
17 define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Extjs/ux/Combo',
18 ['TYPO3/CMS/Rtehtmlarea/HTMLArea/UserAgent/UserAgent',
19 'TYPO3/CMS/Rtehtmlarea/HTMLArea/Event/Event'],
20 function (UserAgent, Event) {
21
22 var Combo = Ext.extend(Ext.form.ComboBox, {
23
24 /**
25 * Constructor
26 */
27 initComponent: function () {
28 this.superClass = Combo.superclass;
29 this.superClass.initComponent.call(this);
30 this.addListener({
31 afterrender: {
32 fn: this.initEventListeners,
33 single: true
34 }
35 });
36 },
37
38 /**
39 * Initialize listeners
40 */
41 initEventListeners: function () {
42 var self = this;
43 Event.on(this, 'HTMLAreaEventHotkey', function (event, key, event) { return self.onHotKey(key); });
44 this.addListener({
45 select: {
46 fn: this.onComboSelect
47 },
48 specialkey: {
49 fn: this.onSpecialKey
50 },
51 beforedestroy: {
52 fn: this.onBeforeDestroy,
53 single: true
54 }
55 });
56 // Monitor toolbar updates in order to refresh the state of the combo
57 Event.on(this.getToolbar(), 'HTMLAreaEventToolbarUpdate', function (event, mode, selectionEmpty, ancestors, endPointsInSameBlock) { Event.stopEvent(event); self.onUpdateToolbar(mode, selectionEmpty, ancestors, endPointsInSameBlock); return false; });
58 // Monitor framework becoming ready
59 Event.one(this.getToolbar().ownerCt, 'HTMLAreaEventFrameworkReady', function (event) { Event.stopEvent(event); self.onFrameworkReady(); return false; });
60 },
61
62 /**
63 * Get a reference to the editor
64 */
65 getEditor: function() {
66 return RTEarea[this.ownerCt.editorId].editor;
67 },
68
69 /**
70 * Get a reference to the toolbar
71 */
72 getToolbar: function() {
73 return this.ownerCt;
74 },
75
76 /**
77 * Handler invoked when an item is selected in the dropdown list
78 */
79 onComboSelect: function (combo, record, index) {
80 if (!combo.disabled) {
81 var editor = this.getEditor();
82 // In IE, reclaim lost focus on the editor iframe and restore the bookmarked selection
83 if (UserAgent.isIE) {
84 if (typeof this.savedRange === 'object' && this.savedRange !== null) {
85 editor.getSelection().selectRange(this.savedRange);
86 this.savedRange = null;
87 }
88 }
89 // Invoke the plugin onChange handler
90 this.plugins[this.action](editor, combo, record, index);
91 // In IE, bookmark the updated selection as the editor will be loosing focus
92 if (UserAgent.isIE) {
93 this.savedRange = editor.getSelection().createRange();
94 this.triggered = true;
95 }
96 if (UserAgent.isOpera) {
97 editor.focus();
98 }
99 this.getToolbar().update();
100 }
101 return false;
102 },
103
104 /**
105 * Handler invoked when the trigger element is clicked
106 * In IE, need to reclaim lost focus for the editor in order to restore the selection
107 */
108 onTriggerClick: function () {
109 this.superClass.onTriggerClick.call(this);
110 // In IE, avoid focus being stolen and selection being lost
111 if (UserAgent.isIE) {
112 this.triggered = true;
113 this.getEditor().focus();
114 }
115 },
116
117 /**
118 * Handler invoked when the list of options is clicked in
119 */
120 onViewClick: function (doFocus) {
121 // Avoid stealing focus from the editor
122 this.superClass.onViewClick.call(this, false);
123 },
124
125 /**
126 * Handler invoked in IE when the mouse moves out of the editor iframe
127 */
128 saveSelection: function (event) {
129 var editor = this.getEditor();
130 if (editor.document.hasFocus()) {
131 this.savedRange = editor.getSelection().createRange();
132 }
133 },
134
135 /**
136 * Handler invoked in IE when the editor gets the focus back
137 */
138 restoreSelection: function (event) {
139 if (typeof this.savedRange === 'object' && this.savedRange !== null && this.triggered) {
140 this.getEditor().getSelection().selectRange(this.savedRange);
141 this.triggered = false;
142 }
143 },
144
145 /**
146 * Handler invoked when the enter key is pressed while the combo has focus
147 */
148 onSpecialKey: function (combo, event) {
149 if (event.getKey() == event.ENTER) {
150 event.stopEvent();
151 }
152 return false;
153 },
154
155 /**
156 * Handler invoked when a hot key configured for this dropdown list is pressed
157 */
158 onHotKey: function (key) {
159 if (!this.disabled) {
160 this.plugins.onHotKey(this.getEditor(), key);
161 if (UserAgent.isOpera) {
162 this.getEditor().focus();
163 }
164 this.getToolbar().update();
165 }
166 return false;
167 },
168
169 /**
170 * Handler invoked when the toolbar is updated
171 */
172 onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) {
173 this.setDisabled(mode === 'textmode' && !this.textMode);
174 if (!this.disabled) {
175 this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
176 }
177 },
178
179 /**
180 * The iframe must have been rendered
181 */
182 onFrameworkReady: function () {
183 var iframe = this.getEditor().iframe;
184 // Close the combo on a click in the iframe
185 // Note: ExtJS is monitoring events only on the parent window
186 var self = this;
187 Event.on(iframe.document.documentElement, 'click', function (event) { self.collapse(); return true; });
188 // Special handling for combo stealing focus in IE
189 if (UserAgent.isIE) {
190 // Take a bookmark in case the editor looses focus by activation of this combo
191 Event.on(iframe.getEl().dom, 'mouseleave', function (event) { self.saveSelection(event); return true; });
192 // Restore the selection if combo was triggered
193 Event.on(iframe.getEl().dom, 'focus', function (event) { self.restoreSelection(event); return true; });
194 }
195 },
196
197 /**
198 * Cleanup
199 */
200 onBeforeDestroy: function () {
201 this.savedRange = null;
202 this.getStore().removeAll();
203 this.getStore().destroy();
204 }
205 });
206
207 return Combo;
208
209 });