]> git.wh0rd.org Git - 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 });