]> git.wh0rd.org - tt-rss.git/blob - lib/dijit/_editor/plugins/FullScreen.js.uncompressed.js
update dojo to 1.7.3
[tt-rss.git] / lib / dijit / _editor / plugins / FullScreen.js.uncompressed.js
1 define("dijit/_editor/plugins/FullScreen", [
2 "dojo/aspect",
3 "dojo/_base/declare", // declare
4 "dojo/dom-class", // domClass.add domClass.remove
5 "dojo/dom-geometry",
6 "dojo/dom-style",
7 "dojo/_base/event", // event.stop
8 "dojo/i18n", // i18n.getLocalization
9 "dojo/keys", // keys.F11 keys.TAB
10 "dojo/_base/lang", // lang.hitch
11 "dojo/on", // on()
12 "dojo/_base/sniff", // has("ie"), has("quirks")
13 "dojo/_base/window", // win.body
14 "dojo/window", // winUtils.getBox winUtils.scrollIntoView
15 "../../focus", // focus.focus(), focus.curNode
16 "../_Plugin",
17 "../../form/ToggleButton",
18 "../../registry", // registry.getEnclosingWidget()
19 "dojo/i18n!../nls/commands"
20 ], function(aspect, declare, domClass, domGeometry, domStyle, event, i18n, keys, lang, on, has, win, winUtils,
21 focus, _Plugin, ToggleButton, registry){
22
23 /*=====
24 var _Plugin = dijit._editor._Plugin;
25 =====*/
26
27
28 // module:
29 // dijit/_editor/plugins/FullScreen
30 // summary:
31 // This plugin provides FullScreen capability to the editor. When
32 // toggled on, it will render the editor into the full window and
33 // overlay everything. It also binds to the hotkey: CTRL-SHIFT-F11
34 // for toggling fullscreen mode.
35
36
37 var FullScreen = declare("dijit._editor.plugins.FullScreen",_Plugin,{
38 // summary:
39 // This plugin provides FullScreen capability to the editor. When
40 // toggled on, it will render the editor into the full window and
41 // overlay everything. It also binds to the hotkey: CTRL-SHIFT-F11
42 // for toggling fullscreen mode.
43
44 // zIndex: [public] Number
45 // zIndex value used for overlaying the full page.
46 // default is 500.
47 zIndex: 500,
48
49 // _origState: [private] Object
50 // The original view state of the editor.
51 _origState: null,
52
53 // _origiFrameState: [private] Object
54 // The original view state of the iframe of the editor.
55 _origiFrameState: null,
56
57 // _resizeHandle: [private] Object
58 // Connection point used for handling resize when window resizes.
59 _resizeHandle: null,
60
61 // isFullscreen: [const] boolean
62 // Read-Only variable used to denote of the editor is in fullscreen mode or not.
63 isFullscreen: false,
64
65 toggle: function(){
66 // summary:
67 // Function to allow programmatic toggling of the view.
68 this.button.set("checked", !this.button.get("checked"));
69 },
70
71 _initButton: function(){
72 // summary:
73 // Over-ride for creation of the resize button.
74 var strings = i18n.getLocalization("dijit._editor", "commands"),
75 editor = this.editor;
76 this.button = new ToggleButton({
77 label: strings["fullScreen"],
78 dir: editor.dir,
79 lang: editor.lang,
80 showLabel: false,
81 iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "FullScreen",
82 tabIndex: "-1",
83 onChange: lang.hitch(this, "_setFullScreen")
84 });
85 },
86
87 setEditor: function(editor){
88 // summary:
89 // Over-ride for the setting of the editor.
90 // editor: Object
91 // The editor to configure for this plugin to use.
92 this.editor = editor;
93 this._initButton();
94
95 this.editor.addKeyHandler(keys.F11, true, true, lang.hitch(this, function(e){
96 // Enable the CTRL-SHIFT-F11 hotkey for fullscreen mode.
97 this.toggle();
98 event.stop(e);
99 setTimeout(lang.hitch(this, function(){this.editor.focus();}), 250);
100 return true;
101 }));
102 this.connect(this.editor.domNode, "onkeydown", "_containFocus");
103 },
104
105 _containFocus: function(e){
106 // summary:
107 // When in Full Screen mode, it's good to try and retain focus in the editor
108 // so this function is intended to try and constrain the TAB key.
109 // e: Event
110 // The key event.
111 // tags:
112 // private
113 if(this.isFullscreen){
114 var ed = this.editor;
115 if(!ed.isTabIndent &&
116 ed._fullscreen_oldOnKeyDown &&
117 e.keyCode === keys.TAB){
118 // If we're in fullscreen mode, we want to take over how tab moves focus a bit.
119 // to keep it within the editor since it's hiding the rest of the page.
120 // IE hates changing focus IN the event handler, so need to put calls
121 // in a timeout. Gotta love IE.
122 // Also need to check for alternate view nodes if present and active.
123 var f = focus.curNode;
124 var avn = this._getAltViewNode();
125 if(f == ed.iframe ||
126 (avn && f === avn)){
127 setTimeout(lang.hitch(this, function(){
128 ed.toolbar.focus();
129 }), 10);
130 }else{
131 if(avn && domStyle.get(ed.iframe, "display") === "none"){
132 setTimeout(lang.hitch(this, function(){
133 focus.focus(avn);
134 }), 10);
135 }else{
136 setTimeout(lang.hitch(this, function(){
137 ed.focus();
138 }), 10);
139 }
140 }
141 event.stop(e);
142 }else if(ed._fullscreen_oldOnKeyDown){
143 // Only call up when it's a different function. Traps corner case event issue
144 // on IE which caused stack overflow on handler cleanup.
145 ed._fullscreen_oldOnKeyDown(e);
146 }
147 }
148 },
149
150 _resizeEditor: function(){
151 // summary:
152 // Function to handle resizing the editor as the viewport
153 // resizes (window scaled)
154 // tags:
155 // private
156 var vp = winUtils.getBox();
157 domGeometry.setMarginBox(this.editor.domNode, {
158 w: vp.w,
159 h: vp.h
160 });
161
162 //Adjust the internal heights too, as they can be a bit off.
163 var hHeight = this.editor.getHeaderHeight();
164 var fHeight = this.editor.getFooterHeight();
165 var extents = domGeometry.getPadBorderExtents(this.editor.domNode);
166 var fcpExtents = domGeometry.getPadBorderExtents(this.editor.iframe.parentNode);
167 var fcmExtents = domGeometry.getMarginExtents(this.editor.iframe.parentNode);
168
169 var cHeight = vp.h - (hHeight + extents.h + fHeight);
170 domGeometry.setMarginBox(this.editor.iframe.parentNode, {
171 h: cHeight,
172 w: vp.w
173 });
174 domGeometry.setMarginBox(this.editor.iframe, {
175 h: cHeight - (fcpExtents.h + fcmExtents.h)
176 });
177 },
178
179 _getAltViewNode: function(){
180 // summary:
181 // This function is intended as a hook point for setting an
182 // alternate view node for when in full screen mode and the
183 // editable iframe is hidden.
184 // tags:
185 // protected.
186 },
187
188 _setFullScreen: function(full){
189 // summary:
190 // Function to handle toggling between full screen and
191 // regular view.
192 // tags:
193 // private
194 var vp = winUtils.getBox();
195
196 //Alias this for shorter code.
197 var ed = this.editor;
198 var body = win.body();
199 var editorParent = ed.domNode.parentNode;
200
201 this.isFullscreen = full;
202
203 if(full){
204 //Parent classes can royally screw up this plugin, so we
205 //have to set everything to position static.
206 while(editorParent && editorParent !== win.body()){
207 domClass.add(editorParent, "dijitForceStatic");
208 editorParent = editorParent.parentNode;
209 }
210
211 // Save off the resize function. We want to kill its behavior.
212 this._editorResizeHolder = this.editor.resize;
213 ed.resize = function(){} ;
214
215 // Try to constrain focus control.
216 ed._fullscreen_oldOnKeyDown = ed.onKeyDown;
217 ed.onKeyDown = lang.hitch(this, this._containFocus);
218
219 this._origState = {};
220 this._origiFrameState = {};
221
222 // Store the basic editor state we have to restore later.
223 // Not using domStyle.get here, had problems, didn't
224 // give me stuff like 100%, gave me pixel calculated values.
225 // Need the exact original values.
226 var domNode = ed.domNode,
227 rawStyle = domNode && domNode.style || {};
228 this._origState = {
229 width: rawStyle.width || "",
230 height: rawStyle.height || "",
231 top: domStyle.get(domNode, "top") || "",
232 left: domStyle.get(domNode, "left") || "",
233 position: domStyle.get(domNode, "position") || "static",
234 marginBox: domGeometry.getMarginBox(ed.domNode)
235 };
236
237 // Store the iframe state we have to restore later.
238 // Not using domStyle.get here, had problems, didn't
239 // give me stuff like 100%, gave me pixel calculated values.
240 // Need the exact original values.
241 var iframe = ed.iframe,
242 iframeStyle = iframe && iframe.style || {};
243
244 var bc = domStyle.get(ed.iframe, "backgroundColor");
245 this._origiFrameState = {
246 backgroundColor: bc || "transparent",
247 width: iframeStyle.width || "auto",
248 height: iframeStyle.height || "auto",
249 zIndex: iframeStyle.zIndex || ""
250 };
251
252 // Okay, size everything.
253 domStyle.set(ed.domNode, {
254 position: "absolute",
255 top: "0px",
256 left: "0px",
257 zIndex: this.zIndex,
258 width: vp.w + "px",
259 height: vp.h + "px"
260 });
261
262 domStyle.set(ed.iframe, {
263 height: "100%",
264 width: "100%",
265 zIndex: this.zIndex,
266 backgroundColor: bc !== "transparent" &&
267 bc !== "rgba(0, 0, 0, 0)"?bc:"white"
268 });
269
270 domStyle.set(ed.iframe.parentNode, {
271 height: "95%",
272 width: "100%"
273 });
274
275 // Store the overflow state we have to restore later.
276 // IE had issues, so have to check that it's defined. Ugh.
277 if(body.style && body.style.overflow){
278 this._oldOverflow = domStyle.get(body, "overflow");
279 }else{
280 this._oldOverflow = "";
281 }
282
283 if(has("ie") && !has("quirks")){
284 // IE will put scrollbars in anyway, html (parent of body)
285 // also controls them in standards mode, so we have to
286 // remove them, argh.
287 if(body.parentNode &&
288 body.parentNode.style &&
289 body.parentNode.style.overflow){
290 this._oldBodyParentOverflow = body.parentNode.style.overflow;
291 }else{
292 try{
293 this._oldBodyParentOverflow = domStyle.get(body.parentNode, "overflow");
294 }catch(e){
295 this._oldBodyParentOverflow = "scroll";
296 }
297 }
298 domStyle.set(body.parentNode, "overflow", "hidden");
299 }
300 domStyle.set(body, "overflow", "hidden");
301
302 var resizer = function(){
303 // function to handle resize events.
304 // Will check current VP and only resize if
305 // different.
306 var vp = winUtils.getBox();
307 if("_prevW" in this && "_prevH" in this){
308 // No actual size change, ignore.
309 if(vp.w === this._prevW && vp.h === this._prevH){
310 return;
311 }
312 }else{
313 this._prevW = vp.w;
314 this._prevH = vp.h;
315 }
316 if(this._resizer){
317 clearTimeout(this._resizer);
318 delete this._resizer;
319 }
320 // Timeout it to help avoid spamming resize on IE.
321 // Works for all browsers.
322 this._resizer = setTimeout(lang.hitch(this, function(){
323 delete this._resizer;
324 this._resizeEditor();
325 }), 10);
326 };
327 this._resizeHandle = on(window, "resize", lang.hitch(this, resizer));
328
329 // Also monitor for direct calls to resize and adapt editor.
330 this._resizeHandle2 = aspect.after(ed, "onResize", lang.hitch(this, function(){
331 if(this._resizer){
332 clearTimeout(this._resizer);
333 delete this._resizer;
334 }
335 this._resizer = setTimeout(lang.hitch(this, function(){
336 delete this._resizer;
337 this._resizeEditor();
338 }), 10);
339 }));
340
341 // Call it once to work around IE glitchiness. Safe for other browsers too.
342 this._resizeEditor();
343 var dn = this.editor.toolbar.domNode;
344 setTimeout(function(){winUtils.scrollIntoView(dn);}, 250);
345 }else{
346 if(this._resizeHandle){
347 // Cleanup resizing listeners
348 this._resizeHandle.remove();
349 this._resizeHandle = null;
350 }
351 if(this._resizeHandle2){
352 // Cleanup resizing listeners
353 this._resizeHandle2.remove();
354 this._resizeHandle2 = null;
355 }
356 if(this._rst){
357 clearTimeout(this._rst);
358 this._rst = null;
359 }
360
361 //Remove all position static class assigns.
362 while(editorParent && editorParent !== win.body()){
363 domClass.remove(editorParent, "dijitForceStatic");
364 editorParent = editorParent.parentNode;
365 }
366
367 // Restore resize function
368 if(this._editorResizeHolder){
369 this.editor.resize = this._editorResizeHolder;
370 }
371
372 if(!this._origState && !this._origiFrameState){
373 // If we actually didn't toggle, then don't do anything.
374 return;
375 }
376 if(ed._fullscreen_oldOnKeyDown){
377 ed.onKeyDown = ed._fullscreen_oldOnKeyDown;
378 delete ed._fullscreen_oldOnKeyDown;
379 }
380
381 // Add a timeout to make sure we don't have a resize firing in the
382 // background at the time of minimize.
383 var self = this;
384 setTimeout(function(){
385 // Restore all the editor state.
386 var mb = self._origState.marginBox;
387 var oh = self._origState.height;
388 if(has("ie") && !has("quirks")){
389 body.parentNode.style.overflow = self._oldBodyParentOverflow;
390 delete self._oldBodyParentOverflow;
391 }
392 domStyle.set(body, "overflow", self._oldOverflow);
393 delete self._oldOverflow;
394
395 domStyle.set(ed.domNode, self._origState);
396 domStyle.set(ed.iframe.parentNode, {
397 height: "",
398 width: ""
399 });
400 domStyle.set(ed.iframe, self._origiFrameState);
401 delete self._origState;
402 delete self._origiFrameState;
403 // In case it is contained in a layout and the layout changed size,
404 // go ahead and call resize.
405 var pWidget = registry.getEnclosingWidget(ed.domNode.parentNode);
406 if(pWidget && pWidget.resize){
407 pWidget.resize();
408 }else{
409 if(!oh || oh.indexOf("%") < 0){
410 // Resize if the original size wasn't set
411 // or wasn't in percent. Timeout is to avoid
412 // an IE crash in unit testing.
413 setTimeout(lang.hitch(this, function(){ed.resize({h: mb.h});}), 0);
414 }
415 }
416 winUtils.scrollIntoView(self.editor.toolbar.domNode);
417 }, 100);
418 }
419 },
420
421 updateState: function(){
422 // summary:
423 // Over-ride for button state control for disabled to work.
424 this.button.set("disabled", this.get("disabled"));
425 },
426
427 destroy: function(){
428 // summary:
429 // Over-ride to ensure the resize handle gets cleaned up.
430 if(this._resizeHandle){
431 // Cleanup resizing listeners
432 this._resizeHandle.remove();
433 this._resizeHandle = null;
434 }
435 if(this._resizeHandle2){
436 // Cleanup resizing listeners
437 this._resizeHandle2.remove();
438 this._resizeHandle2 = null;
439 }
440 if(this._resizer){
441 clearTimeout(this._resizer);
442 this._resizer = null;
443 }
444 this.inherited(arguments);
445 }
446 });
447
448 // Register this plugin.
449 // For back-compat accept "fullscreen" (all lowercase) too, remove in 2.0
450 _Plugin.registry["fullScreen"] = _Plugin.registry["fullscreen"] = function(args){
451 return new FullScreen({
452 zIndex: ("zIndex" in args)?args.zIndex:500
453 });
454 };
455
456 return FullScreen;
457 });