tt-rss/lib/dijit/_editor/plugins/FullScreen.js.uncompressed.js
2012-08-14 18:59:18 +04:00

457 lines
14 KiB
JavaScript

define("dijit/_editor/plugins/FullScreen", [
"dojo/aspect",
"dojo/_base/declare", // declare
"dojo/dom-class", // domClass.add domClass.remove
"dojo/dom-geometry",
"dojo/dom-style",
"dojo/_base/event", // event.stop
"dojo/i18n", // i18n.getLocalization
"dojo/keys", // keys.F11 keys.TAB
"dojo/_base/lang", // lang.hitch
"dojo/on", // on()
"dojo/_base/sniff", // has("ie"), has("quirks")
"dojo/_base/window", // win.body
"dojo/window", // winUtils.getBox winUtils.scrollIntoView
"../../focus", // focus.focus(), focus.curNode
"../_Plugin",
"../../form/ToggleButton",
"../../registry", // registry.getEnclosingWidget()
"dojo/i18n!../nls/commands"
], function(aspect, declare, domClass, domGeometry, domStyle, event, i18n, keys, lang, on, has, win, winUtils,
focus, _Plugin, ToggleButton, registry){
/*=====
var _Plugin = dijit._editor._Plugin;
=====*/
// module:
// dijit/_editor/plugins/FullScreen
// summary:
// This plugin provides FullScreen capability to the editor. When
// toggled on, it will render the editor into the full window and
// overlay everything. It also binds to the hotkey: CTRL-SHIFT-F11
// for toggling fullscreen mode.
var FullScreen = declare("dijit._editor.plugins.FullScreen",_Plugin,{
// summary:
// This plugin provides FullScreen capability to the editor. When
// toggled on, it will render the editor into the full window and
// overlay everything. It also binds to the hotkey: CTRL-SHIFT-F11
// for toggling fullscreen mode.
// zIndex: [public] Number
// zIndex value used for overlaying the full page.
// default is 500.
zIndex: 500,
// _origState: [private] Object
// The original view state of the editor.
_origState: null,
// _origiFrameState: [private] Object
// The original view state of the iframe of the editor.
_origiFrameState: null,
// _resizeHandle: [private] Object
// Connection point used for handling resize when window resizes.
_resizeHandle: null,
// isFullscreen: [const] boolean
// Read-Only variable used to denote of the editor is in fullscreen mode or not.
isFullscreen: false,
toggle: function(){
// summary:
// Function to allow programmatic toggling of the view.
this.button.set("checked", !this.button.get("checked"));
},
_initButton: function(){
// summary:
// Over-ride for creation of the resize button.
var strings = i18n.getLocalization("dijit._editor", "commands"),
editor = this.editor;
this.button = new ToggleButton({
label: strings["fullScreen"],
dir: editor.dir,
lang: editor.lang,
showLabel: false,
iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "FullScreen",
tabIndex: "-1",
onChange: lang.hitch(this, "_setFullScreen")
});
},
setEditor: function(editor){
// summary:
// Over-ride for the setting of the editor.
// editor: Object
// The editor to configure for this plugin to use.
this.editor = editor;
this._initButton();
this.editor.addKeyHandler(keys.F11, true, true, lang.hitch(this, function(e){
// Enable the CTRL-SHIFT-F11 hotkey for fullscreen mode.
this.toggle();
event.stop(e);
setTimeout(lang.hitch(this, function(){this.editor.focus();}), 250);
return true;
}));
this.connect(this.editor.domNode, "onkeydown", "_containFocus");
},
_containFocus: function(e){
// summary:
// When in Full Screen mode, it's good to try and retain focus in the editor
// so this function is intended to try and constrain the TAB key.
// e: Event
// The key event.
// tags:
// private
if(this.isFullscreen){
var ed = this.editor;
if(!ed.isTabIndent &&
ed._fullscreen_oldOnKeyDown &&
e.keyCode === keys.TAB){
// If we're in fullscreen mode, we want to take over how tab moves focus a bit.
// to keep it within the editor since it's hiding the rest of the page.
// IE hates changing focus IN the event handler, so need to put calls
// in a timeout. Gotta love IE.
// Also need to check for alternate view nodes if present and active.
var f = focus.curNode;
var avn = this._getAltViewNode();
if(f == ed.iframe ||
(avn && f === avn)){
setTimeout(lang.hitch(this, function(){
ed.toolbar.focus();
}), 10);
}else{
if(avn && domStyle.get(ed.iframe, "display") === "none"){
setTimeout(lang.hitch(this, function(){
focus.focus(avn);
}), 10);
}else{
setTimeout(lang.hitch(this, function(){
ed.focus();
}), 10);
}
}
event.stop(e);
}else if(ed._fullscreen_oldOnKeyDown){
// Only call up when it's a different function. Traps corner case event issue
// on IE which caused stack overflow on handler cleanup.
ed._fullscreen_oldOnKeyDown(e);
}
}
},
_resizeEditor: function(){
// summary:
// Function to handle resizing the editor as the viewport
// resizes (window scaled)
// tags:
// private
var vp = winUtils.getBox();
domGeometry.setMarginBox(this.editor.domNode, {
w: vp.w,
h: vp.h
});
//Adjust the internal heights too, as they can be a bit off.
var hHeight = this.editor.getHeaderHeight();
var fHeight = this.editor.getFooterHeight();
var extents = domGeometry.getPadBorderExtents(this.editor.domNode);
var fcpExtents = domGeometry.getPadBorderExtents(this.editor.iframe.parentNode);
var fcmExtents = domGeometry.getMarginExtents(this.editor.iframe.parentNode);
var cHeight = vp.h - (hHeight + extents.h + fHeight);
domGeometry.setMarginBox(this.editor.iframe.parentNode, {
h: cHeight,
w: vp.w
});
domGeometry.setMarginBox(this.editor.iframe, {
h: cHeight - (fcpExtents.h + fcmExtents.h)
});
},
_getAltViewNode: function(){
// summary:
// This function is intended as a hook point for setting an
// alternate view node for when in full screen mode and the
// editable iframe is hidden.
// tags:
// protected.
},
_setFullScreen: function(full){
// summary:
// Function to handle toggling between full screen and
// regular view.
// tags:
// private
var vp = winUtils.getBox();
//Alias this for shorter code.
var ed = this.editor;
var body = win.body();
var editorParent = ed.domNode.parentNode;
this.isFullscreen = full;
if(full){
//Parent classes can royally screw up this plugin, so we
//have to set everything to position static.
while(editorParent && editorParent !== win.body()){
domClass.add(editorParent, "dijitForceStatic");
editorParent = editorParent.parentNode;
}
// Save off the resize function. We want to kill its behavior.
this._editorResizeHolder = this.editor.resize;
ed.resize = function(){} ;
// Try to constrain focus control.
ed._fullscreen_oldOnKeyDown = ed.onKeyDown;
ed.onKeyDown = lang.hitch(this, this._containFocus);
this._origState = {};
this._origiFrameState = {};
// Store the basic editor state we have to restore later.
// Not using domStyle.get here, had problems, didn't
// give me stuff like 100%, gave me pixel calculated values.
// Need the exact original values.
var domNode = ed.domNode,
rawStyle = domNode && domNode.style || {};
this._origState = {
width: rawStyle.width || "",
height: rawStyle.height || "",
top: domStyle.get(domNode, "top") || "",
left: domStyle.get(domNode, "left") || "",
position: domStyle.get(domNode, "position") || "static",
marginBox: domGeometry.getMarginBox(ed.domNode)
};
// Store the iframe state we have to restore later.
// Not using domStyle.get here, had problems, didn't
// give me stuff like 100%, gave me pixel calculated values.
// Need the exact original values.
var iframe = ed.iframe,
iframeStyle = iframe && iframe.style || {};
var bc = domStyle.get(ed.iframe, "backgroundColor");
this._origiFrameState = {
backgroundColor: bc || "transparent",
width: iframeStyle.width || "auto",
height: iframeStyle.height || "auto",
zIndex: iframeStyle.zIndex || ""
};
// Okay, size everything.
domStyle.set(ed.domNode, {
position: "absolute",
top: "0px",
left: "0px",
zIndex: this.zIndex,
width: vp.w + "px",
height: vp.h + "px"
});
domStyle.set(ed.iframe, {
height: "100%",
width: "100%",
zIndex: this.zIndex,
backgroundColor: bc !== "transparent" &&
bc !== "rgba(0, 0, 0, 0)"?bc:"white"
});
domStyle.set(ed.iframe.parentNode, {
height: "95%",
width: "100%"
});
// Store the overflow state we have to restore later.
// IE had issues, so have to check that it's defined. Ugh.
if(body.style && body.style.overflow){
this._oldOverflow = domStyle.get(body, "overflow");
}else{
this._oldOverflow = "";
}
if(has("ie") && !has("quirks")){
// IE will put scrollbars in anyway, html (parent of body)
// also controls them in standards mode, so we have to
// remove them, argh.
if(body.parentNode &&
body.parentNode.style &&
body.parentNode.style.overflow){
this._oldBodyParentOverflow = body.parentNode.style.overflow;
}else{
try{
this._oldBodyParentOverflow = domStyle.get(body.parentNode, "overflow");
}catch(e){
this._oldBodyParentOverflow = "scroll";
}
}
domStyle.set(body.parentNode, "overflow", "hidden");
}
domStyle.set(body, "overflow", "hidden");
var resizer = function(){
// function to handle resize events.
// Will check current VP and only resize if
// different.
var vp = winUtils.getBox();
if("_prevW" in this && "_prevH" in this){
// No actual size change, ignore.
if(vp.w === this._prevW && vp.h === this._prevH){
return;
}
}else{
this._prevW = vp.w;
this._prevH = vp.h;
}
if(this._resizer){
clearTimeout(this._resizer);
delete this._resizer;
}
// Timeout it to help avoid spamming resize on IE.
// Works for all browsers.
this._resizer = setTimeout(lang.hitch(this, function(){
delete this._resizer;
this._resizeEditor();
}), 10);
};
this._resizeHandle = on(window, "resize", lang.hitch(this, resizer));
// Also monitor for direct calls to resize and adapt editor.
this._resizeHandle2 = aspect.after(ed, "onResize", lang.hitch(this, function(){
if(this._resizer){
clearTimeout(this._resizer);
delete this._resizer;
}
this._resizer = setTimeout(lang.hitch(this, function(){
delete this._resizer;
this._resizeEditor();
}), 10);
}));
// Call it once to work around IE glitchiness. Safe for other browsers too.
this._resizeEditor();
var dn = this.editor.toolbar.domNode;
setTimeout(function(){winUtils.scrollIntoView(dn);}, 250);
}else{
if(this._resizeHandle){
// Cleanup resizing listeners
this._resizeHandle.remove();
this._resizeHandle = null;
}
if(this._resizeHandle2){
// Cleanup resizing listeners
this._resizeHandle2.remove();
this._resizeHandle2 = null;
}
if(this._rst){
clearTimeout(this._rst);
this._rst = null;
}
//Remove all position static class assigns.
while(editorParent && editorParent !== win.body()){
domClass.remove(editorParent, "dijitForceStatic");
editorParent = editorParent.parentNode;
}
// Restore resize function
if(this._editorResizeHolder){
this.editor.resize = this._editorResizeHolder;
}
if(!this._origState && !this._origiFrameState){
// If we actually didn't toggle, then don't do anything.
return;
}
if(ed._fullscreen_oldOnKeyDown){
ed.onKeyDown = ed._fullscreen_oldOnKeyDown;
delete ed._fullscreen_oldOnKeyDown;
}
// Add a timeout to make sure we don't have a resize firing in the
// background at the time of minimize.
var self = this;
setTimeout(function(){
// Restore all the editor state.
var mb = self._origState.marginBox;
var oh = self._origState.height;
if(has("ie") && !has("quirks")){
body.parentNode.style.overflow = self._oldBodyParentOverflow;
delete self._oldBodyParentOverflow;
}
domStyle.set(body, "overflow", self._oldOverflow);
delete self._oldOverflow;
domStyle.set(ed.domNode, self._origState);
domStyle.set(ed.iframe.parentNode, {
height: "",
width: ""
});
domStyle.set(ed.iframe, self._origiFrameState);
delete self._origState;
delete self._origiFrameState;
// In case it is contained in a layout and the layout changed size,
// go ahead and call resize.
var pWidget = registry.getEnclosingWidget(ed.domNode.parentNode);
if(pWidget && pWidget.resize){
pWidget.resize();
}else{
if(!oh || oh.indexOf("%") < 0){
// Resize if the original size wasn't set
// or wasn't in percent. Timeout is to avoid
// an IE crash in unit testing.
setTimeout(lang.hitch(this, function(){ed.resize({h: mb.h});}), 0);
}
}
winUtils.scrollIntoView(self.editor.toolbar.domNode);
}, 100);
}
},
updateState: function(){
// summary:
// Over-ride for button state control for disabled to work.
this.button.set("disabled", this.get("disabled"));
},
destroy: function(){
// summary:
// Over-ride to ensure the resize handle gets cleaned up.
if(this._resizeHandle){
// Cleanup resizing listeners
this._resizeHandle.remove();
this._resizeHandle = null;
}
if(this._resizeHandle2){
// Cleanup resizing listeners
this._resizeHandle2.remove();
this._resizeHandle2 = null;
}
if(this._resizer){
clearTimeout(this._resizer);
this._resizer = null;
}
this.inherited(arguments);
}
});
// Register this plugin.
// For back-compat accept "fullscreen" (all lowercase) too, remove in 2.0
_Plugin.registry["fullScreen"] = _Plugin.registry["fullscreen"] = function(args){
return new FullScreen({
zIndex: ("zIndex" in args)?args.zIndex:500
});
};
return FullScreen;
});