1 define("dijit/_editor/plugins/FullScreen", [
3 "dojo/_base/declare", // declare
4 "dojo/dom-class", // domClass.add domClass.remove
7 "dojo/_base/event", // event.stop
8 "dojo/i18n", // i18n.getLocalization
9 "dojo/keys", // keys.F11 keys.TAB
10 "dojo/_base/lang", // lang.hitch
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
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){
24 var _Plugin = dijit._editor._Plugin;
29 // dijit/_editor/plugins/FullScreen
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.
37 var FullScreen = declare("dijit._editor.plugins.FullScreen",_Plugin,{
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.
44 // zIndex: [public] Number
45 // zIndex value used for overlaying the full page.
49 // _origState: [private] Object
50 // The original view state of the editor.
53 // _origiFrameState: [private] Object
54 // The original view state of the iframe of the editor.
55 _origiFrameState: null,
57 // _resizeHandle: [private] Object
58 // Connection point used for handling resize when window resizes.
61 // isFullscreen: [const] boolean
62 // Read-Only variable used to denote of the editor is in fullscreen mode or not.
67 // Function to allow programmatic toggling of the view.
68 this.button.set("checked", !this.button.get("checked"));
71 _initButton: function(){
73 // Over-ride for creation of the resize button.
74 var strings = i18n.getLocalization("dijit._editor", "commands"),
76 this.button = new ToggleButton({
77 label: strings["fullScreen"],
81 iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "FullScreen",
83 onChange: lang.hitch(this, "_setFullScreen")
87 setEditor: function(editor){
89 // Over-ride for the setting of the editor.
91 // The editor to configure for this plugin to use.
95 this.editor.addKeyHandler(keys.F11, true, true, lang.hitch(this, function(e){
96 // Enable the CTRL-SHIFT-F11 hotkey for fullscreen mode.
99 setTimeout(lang.hitch(this, function(){this.editor.focus();}), 250);
102 this.connect(this.editor.domNode, "onkeydown", "_containFocus");
105 _containFocus: function(e){
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.
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();
127 setTimeout(lang.hitch(this, function(){
131 if(avn && domStyle.get(ed.iframe, "display") === "none"){
132 setTimeout(lang.hitch(this, function(){
136 setTimeout(lang.hitch(this, function(){
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);
150 _resizeEditor: function(){
152 // Function to handle resizing the editor as the viewport
153 // resizes (window scaled)
156 var vp = winUtils.getBox();
157 domGeometry.setMarginBox(this.editor.domNode, {
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);
169 var cHeight = vp.h - (hHeight + extents.h + fHeight);
170 domGeometry.setMarginBox(this.editor.iframe.parentNode, {
174 domGeometry.setMarginBox(this.editor.iframe, {
175 h: cHeight - (fcpExtents.h + fcmExtents.h)
179 _getAltViewNode: function(){
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.
188 _setFullScreen: function(full){
190 // Function to handle toggling between full screen and
194 var vp = winUtils.getBox();
196 //Alias this for shorter code.
197 var ed = this.editor;
198 var body = win.body();
199 var editorParent = ed.domNode.parentNode;
201 this.isFullscreen = 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;
211 // Save off the resize function. We want to kill its behavior.
212 this._editorResizeHolder = this.editor.resize;
213 ed.resize = function(){} ;
215 // Try to constrain focus control.
216 ed._fullscreen_oldOnKeyDown = ed.onKeyDown;
217 ed.onKeyDown = lang.hitch(this, this._containFocus);
219 this._origState = {};
220 this._origiFrameState = {};
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 || {};
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)
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 || {};
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 || ""
252 // Okay, size everything.
253 domStyle.set(ed.domNode, {
254 position: "absolute",
262 domStyle.set(ed.iframe, {
266 backgroundColor: bc !== "transparent" &&
267 bc !== "rgba(0, 0, 0, 0)"?bc:"white"
270 domStyle.set(ed.iframe.parentNode, {
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");
280 this._oldOverflow = "";
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;
293 this._oldBodyParentOverflow = domStyle.get(body.parentNode, "overflow");
295 this._oldBodyParentOverflow = "scroll";
298 domStyle.set(body.parentNode, "overflow", "hidden");
300 domStyle.set(body, "overflow", "hidden");
302 var resizer = function(){
303 // function to handle resize events.
304 // Will check current VP and only resize if
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){
317 clearTimeout(this._resizer);
318 delete this._resizer;
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();
327 this._resizeHandle = on(window, "resize", lang.hitch(this, resizer));
329 // Also monitor for direct calls to resize and adapt editor.
330 this._resizeHandle2 = aspect.after(ed, "onResize", lang.hitch(this, function(){
332 clearTimeout(this._resizer);
333 delete this._resizer;
335 this._resizer = setTimeout(lang.hitch(this, function(){
336 delete this._resizer;
337 this._resizeEditor();
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);
346 if(this._resizeHandle){
347 // Cleanup resizing listeners
348 this._resizeHandle.remove();
349 this._resizeHandle = null;
351 if(this._resizeHandle2){
352 // Cleanup resizing listeners
353 this._resizeHandle2.remove();
354 this._resizeHandle2 = null;
357 clearTimeout(this._rst);
361 //Remove all position static class assigns.
362 while(editorParent && editorParent !== win.body()){
363 domClass.remove(editorParent, "dijitForceStatic");
364 editorParent = editorParent.parentNode;
367 // Restore resize function
368 if(this._editorResizeHolder){
369 this.editor.resize = this._editorResizeHolder;
372 if(!this._origState && !this._origiFrameState){
373 // If we actually didn't toggle, then don't do anything.
376 if(ed._fullscreen_oldOnKeyDown){
377 ed.onKeyDown = ed._fullscreen_oldOnKeyDown;
378 delete ed._fullscreen_oldOnKeyDown;
381 // Add a timeout to make sure we don't have a resize firing in the
382 // background at the time of minimize.
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;
392 domStyle.set(body, "overflow", self._oldOverflow);
393 delete self._oldOverflow;
395 domStyle.set(ed.domNode, self._origState);
396 domStyle.set(ed.iframe.parentNode, {
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){
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);
416 winUtils.scrollIntoView(self.editor.toolbar.domNode);
421 updateState: function(){
423 // Over-ride for button state control for disabled to work.
424 this.button.set("disabled", this.get("disabled"));
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;
435 if(this._resizeHandle2){
436 // Cleanup resizing listeners
437 this._resizeHandle2.remove();
438 this._resizeHandle2 = null;
441 clearTimeout(this._resizer);
442 this._resizer = null;
444 this.inherited(arguments);
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