@qooxdoo/framework
Version:
The JS Framework for Coders
393 lines (345 loc) • 10.6 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2004-2010 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Alexander Steitz (aback)
************************************************************************ */
/**
* Includes library functions to work with browser windows
*/
qx.Class.define("qx.bom.Window",
{
statics :
{
/** Internal blocker instance for all browsers which need an additional
* blocker for modal windows because they do not support it natively.
*/
__blocker : null,
/** Window handle which is currently blocked. */
__blockerWindow : null,
/** Timer instance to poll for unblocking if the modal window was closed */
__timer : null,
/** Supported options and their mapping to window options */
__modalOptions :
{
"top" : "dialogTop",
left : "dialogLeft",
width : "dialogWidth",
height : "dialogHeight",
scrollbars : "scroll",
resizable : "resizable"
},
/** Supported options for modeless windows */
__modelessOptions :
{
"top" : 1,
left : 1,
width : 1,
height : 1,
dependent : 1,
resizable : 1,
status : 1,
location : 1,
menubar : 1,
scrollbars : 1,
toolbar : 1
},
/**
* Whether the browser can open native modal window.
*
* @return {Boolean} Capability of open modal windows
*/
__isCapableToOpenModalWindows : function() {
return window.showModalDialog != null;
},
/**
* Opens a native window with the given options.
*
* Modal windows can have the following options:
*
* * top
*
* * left
*
* * width
*
* * height
*
* * scrollbars
*
* * resizable
*
* Modeless windows have the following options:
*
* * top
*
* * left
*
* * width
*
* * height
*
* * dependent
*
* * resizable
*
* * status
*
* * location
*
* * menubar
*
* * scrollbars
*
* * toolbar
*
* Except of dimension and location options all other options are boolean
* values.
*
* *Important infos for native modal windows*
*
* If you want to reference the opened window from within the native modal
* window you need to use
*
* <pre class='javascript'>
* var opener = window.dialogArguments[0];
* </pre>
*
* since a reference to the opener is passed automatically to the modal window.
*
* *Passing window arguments*
*
* This is only working if the page of the modal window is from the same origin.
* This is at least true for Firefox browsers.
*
* @param url {String} URL of the window
* @param name {String} Name of the window
* @param options {Map} Window options
* @param modal {Boolean} Whether the window should be opened modal
* @param useNativeModalDialog {Boolean} controls if modal windows are opened
* using the native method or a blocker
* should be used to fake modality.
* Default is <b>true</b>
* @param listener {Function ?} listener function for onload event on the new window
* @param self {Object ?} Reference to the 'this' variable inside
* the event listener. When not given, 'this' variable will be the new window
* @return {Window} native window object
*/
open : function(url, name, options, modal, useNativeModalDialog, listener, self)
{
var newWindow = null;
if (url == null) {
url = "javascript:/";
}
if (name == null) {
name = "qxNativeWindow" + new Date().getTime();
}
if (useNativeModalDialog == null) {
useNativeModalDialog = true;
}
var configurationString = this.__generateConfigurationString(options, modal && useNativeModalDialog);
if (modal)
{
if (this.__isCapableToOpenModalWindows() && useNativeModalDialog) {
newWindow = window.showModalDialog(url, [ window.self ], configurationString);
}
else
{
this.getBlocker().block();
if (this.__timer == null)
{
this.__timer = new qx.event.Timer(500);
this.__timer.addListener("interval", this.__checkForUnblocking, this);
}
this.__blockerWindow = window.open(url, name, configurationString);
this.__timer.restart();
newWindow = this.__blockerWindow;
}
} else {
newWindow = window.open(url, name, configurationString);
}
if(newWindow && listener && (listener instanceof Function)){
var context = self || newWindow;
var onLoadFunction = qx.lang.Function.bind(listener, context);
var onNativeLoad = function(){
onLoadFunction();
qx.bom.Event.removeNativeListener(newWindow, 'load', onNativeLoad);
}
qx.bom.Event.addNativeListener(newWindow, 'load', onNativeLoad);
}
return newWindow;
},
/**
* Returns the given config as string for direct use for the "window.open" method
*
* @param options {Array} Array with all configuration options
* @param modality {Boolean} whether the config should be for a modal window
*
* @return {String} configuration as string representation
*/
__generateConfigurationString : function(options, modality)
{
var configurationString;
var value;
var configuration = [];
if (modality && this.__isCapableToOpenModalWindows())
{
for (var key in options)
{
if (qx.bom.Window.__modalOptions[key])
{
var suffix = "";
if (key != "scrollbars" && key != "resizable") {
suffix = "px";
}
value = qx.bom.Window.__modalOptions[key] + ":" + options[key] + suffix;
configuration.push(value);
}
else {
qx.log.Logger.warn("Option '" + key + "' is not supported for modal windows.");
}
}
configurationString = configuration.join(";");
}
else
{
for (var key in options)
{
if (qx.bom.Window.__modelessOptions[key])
{
if (qx.lang.Type.isBoolean(options[key])) {
value = key + "=" + (options[key] ? "yes" : "no");
}
else {
value = key + "=" + options[key];
}
configuration.push(value);
}
else {
qx.log.Logger.warn("Option '" + key + "' is not supported for native windows.");
}
}
configurationString = configuration.join(",");
}
return configurationString;
},
/**
* Interval method which checks if the native window was closed to also
* stop the associated timer.
*/
__checkForUnblocking : function()
{
if (this.isClosed(this.__blockerWindow))
{
this.getBlocker().unblock();
this.__timer.stop();
}
},
/**
* If a modal window is opened with the option
*
* <pre class='javascript'>
* useNativeModalWindow = false;
* </pre>
*
* an instance of <b>qx.bom.Blocker</b> is used to fake modality. This method
* can be used to get a reference to the blocker to style it.
*
* @return {qx.bom.Blocker?null} Blocker instance or null if no blocker is used
*/
getBlocker : function()
{
if (this.__blocker == null) {
this.__blocker = new qx.bom.Blocker;
}
return this.__blocker;
},
/**
* Closes the given window
*
* @param win {Window} Native window object
* @return {var} The return value (if any) of the window's native
* <code>close</code> method
*/
close : function(win)
{
if (win) {
return win.close();
}
},
/**
* Checks if the window is closed
*
* @param win {Window} Native window object
* @return {Boolean} Closed state
*/
isClosed : function(win)
{
var closed = true;
if (win)
{
try {
closed = win.closed;
} catch(ex) {}
}
return closed;
},
/**
* Moving an opened window is not allowed in the most browsers anymore.
*
* @param win {Window} Native window object
* @param top {Integer} Y-coordinate
* @param left {Integer} X-coordinate
*/
moveTo : function(win, top, left)
{
/*
http://www.microsoft.com/technet/prodtechnol/winxppro/maintain/sp2brows.mspx
Changes to Functionality in Microsoft Windows XP Service Pack 2
Part 5: Enhanced Browsing Security
URLACTION_FEATURE_WINDOW_RESTRICTIONS
Allow script-initiated windows without size or position constraints
Code: 2102
*/
if (!qx.bom.Window.isClosed(win))
{
try {
win.moveTo(left, top);
} catch(ex) {
qx.log.Logger.error("Cross-Domain Scripting problem: Could not move window!", ex);
}
}
},
/**
* Resizing an opened window is not allowed in the most browsers anymore.
*
* @param win {Window} Native window object
* @param width {Integer} New width
* @param height {Integer} New height
*/
resizeTo : function(win, width, height)
{
/*
http://www.microsoft.com/technet/prodtechnol/winxppro/maintain/sp2brows.mspx
Changes to Functionality in Microsoft Windows XP Service Pack 2
Part 5: Enhanced Browsing Security
URLACTION_FEATURE_WINDOW_RESTRICTIONS
Allow script-initiated windows without size or position constraints
Code: 2102
*/
if (!qx.bom.Window.isClosed(win))
{
try {
win.resizeTo(width, height);
} catch(ex) {
qx.log.Logger.error("Cross-Domain Scripting problem: Could not resize window!", ex);
}
}
}
}
});