mirror of
https://github.com/e107inc/e107.git
synced 2025-07-29 10:50:25 +02:00
1932 lines
53 KiB
JavaScript
1932 lines
53 KiB
JavaScript
/**
|
|
* Copyright (C) 2008-2009 e107 Inc (e107.org)
|
|
* Released under the terms and conditions of the
|
|
* GNU General Public License (http://gnu.org).
|
|
*
|
|
* e107 Core modal window widget
|
|
* Based on Prorotype UI Window http://prototype-ui.com/
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
* Global prefs
|
|
*/
|
|
e107Base.setPrefs('core-dialog', {
|
|
id: null,
|
|
theme : '', /* omit to use default */
|
|
shadow: false, /* use shadow widget, need to be extra included (shadow.js) */
|
|
shadowTheme: '', /* if the above is true, which theme to use for shadow widget, omit for default */
|
|
top: null, /* initial window position */
|
|
left: null, /* initial window left position */
|
|
width: 300, /* initial window width */
|
|
height: 200, /* initial window height */
|
|
minWidth: 200, /* window min width */
|
|
minHeight: 100, /* window min height */
|
|
maxHeight: null, /* window max height */
|
|
maxWidth: null, /* window max width */
|
|
maxAdaptWidth: null, /* window max width when adapt() is called (fit the content when e.g. dynamically added via AJAX) */
|
|
maxAdaptHeight: null, /* window max height when adapt() is called (fit the content when e.g. dynamically added via AJAX) */
|
|
adaptWidthOffset: 0, /* width offset to be added when adapting */
|
|
adaptHeightOffset: 0, /* height offset to be added when adapting */
|
|
gridX: 1,
|
|
gridY: 1,
|
|
wired: false, /* wired element shown when resizing/moving the window (browser performance) */
|
|
draggable : true, /* allow drag, requires draggable.js */
|
|
resizable : true, /* allow resize, requires draggable.js */
|
|
activeOnClick : true, /* activate (set on top) when clicking on an window body, if false, activate works only on window header bar click */
|
|
show: Element.show, /* show callback, used when window.show() is called, defaults to Element.show() */
|
|
hide: Element.hide, /* hide callback, used when window.show() is called, defaults to Element.hide() */
|
|
maximizeEffects: true, /* use effect when maximizing (uses scripty Effect library) */
|
|
superflousEffects: false, /* enable various 'superflous' effects (uses scripty Effect library, currently used on adapt() only) */
|
|
adaptOnAjaxContent: true, /* auto-fire adapt (only when no callback is registered) when setAjaxContent() finish AJAX update */
|
|
dialogManager: null, /* dialog manager for the current instance, defaults to e107Widgets.DialogManagerDefault */
|
|
positionningStrategyOffset: null, /* offset used to auto-position a window when multiple windows are opened, defaults to 20 */
|
|
close: 'destroy', /* e107Widgets.Dialog callback method for closing dialog or false to disable */
|
|
hideOptions: null,
|
|
hideShadowOptions: null,
|
|
maximize: 'toggleMaximize' /* e107Widgets.Dialog method for closing dialog or false to disable */
|
|
});
|
|
|
|
/**
|
|
* Example usage:
|
|
* <code>
|
|
* // basic example - create, activate and show empty dialog window in the middle of the screen
|
|
* new e107Widgets.Dialog({
|
|
* id: 'unique-window-id'
|
|
* }).center().activate().show();
|
|
*
|
|
* // more advanced example - create, activate and show centered 400px300px dialog window, on top 30 position
|
|
* // set body, header and footer data;
|
|
* new e107Widgets.Dialog({
|
|
* id: 'unique-window-id',
|
|
* width: 400,
|
|
* height: 300
|
|
* }).center({top: 30}).setHeader('My Header').setFooter('My Footer').setContent('My Body').activate().show();
|
|
*
|
|
* // create from DOM example
|
|
* // DOM elements required to make it work:
|
|
* // <a href="#" id="dialog" title="Window Title">Open a window</a>
|
|
* // <div id="dialog-source" style="display: none">Window (HTML) content</a>
|
|
* $('dialog').observe('click', function(event){
|
|
* var target = event.findElement('a'), source = $('dialog-source');
|
|
* event.stop(); // prevent default
|
|
* new e107Widgets.Dialog({
|
|
* id: target.id + '-window',
|
|
* }).center({top: 30}).setHeader(target.readAttribute('title')).setContent(source.innerHTML).activate().show();
|
|
* });
|
|
*
|
|
* // AJAX example, call to http://yoursite.com/e107_plugins/myplugin/myAjaxScript.php?id=someId
|
|
* new e107Widgets.Dialog({
|
|
* id: 'unique-window-id',
|
|
* width: 400,
|
|
* height: 300
|
|
* }).setAjaxContent(('#{e_PLUGIN}myplugin/myAjaxScript.php').parsePath(), {
|
|
* method: 'get',
|
|
* params: { id: 'someId' }
|
|
* }).center({top: 30}).activate().show();
|
|
* </code>
|
|
*
|
|
* Example JSON response from e107_plugins/myplugin/myAjaxScript.php
|
|
* <code>
|
|
* <?php
|
|
* require_once('../../class2.php');
|
|
* if(!e_AJAX_REQUEST) exit();
|
|
*
|
|
* $ret = array();
|
|
* $ret['header'] = 'Window Title';
|
|
* $ret['footer'] = 'Window Footer';
|
|
* $ret['body'] = 'Window Body';
|
|
*
|
|
* $jshelper = e107::getJshelper();
|
|
* echo $jshelper->buildJsonResponse($ret);
|
|
* $jshelper->sendJsonResponse(null);
|
|
* </code>
|
|
*
|
|
* PREFFERED WAY - Example JSON response within a controller (single entry point)
|
|
* File: e107_plugins/myplugin/controllers/ajax.php
|
|
* URL: http://yoursite.com/myplugin/ajax
|
|
* <code>
|
|
* <?php
|
|
* if (!defined('e107_INIT')) { exit; }
|
|
*
|
|
* class plugin_myplugin_ajax_controller extends eController
|
|
* {
|
|
* public function actionIndex()
|
|
* {
|
|
* $this->addTitle('My page title', false);
|
|
* $this->addBody('My page body');
|
|
*
|
|
* // optional - override and/or add footer information
|
|
* $more = array('footer' => 'Footer details');
|
|
*
|
|
* // send the response
|
|
* $this->getResponse()
|
|
* ->sendJson($more);
|
|
* }
|
|
* }
|
|
* </code>
|
|
*
|
|
* e107Widgets.Dialog#setAjaxContent() Options:
|
|
* Any valid e107Ajax.Request() options + additional 'onAfterComplete' callback
|
|
*
|
|
*/
|
|
e107Widgets.Dialog = Class.create(e107WidgetAbstract, {
|
|
Version : '1.0',
|
|
style : "position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;",
|
|
wiredElement: null,
|
|
events : null,
|
|
element : null, /* window element */
|
|
header : null, /* window header element */
|
|
content : null, /* window content element */
|
|
footer : null, /* window footer element */
|
|
visible: false, /* window visibility */
|
|
focused: false, /* windows on focus */
|
|
modal: false, /* modal window */
|
|
zIndex: 0,
|
|
shadow: null,
|
|
|
|
action: function(name) {
|
|
var action = this.options[name];
|
|
if (action)
|
|
Object.isString(action) ? this[action]() : action.call(this, this);
|
|
},
|
|
|
|
initialize : function(options) {
|
|
this.events = new e107EventManager(this);
|
|
|
|
this.initMod('core-dialog', options);
|
|
if(!e107Widgets['DialogManagerDefault']) e107Widgets.DialogManagerDefault = new e107Widgets.DialogManager();
|
|
|
|
this.dialogManager = this.options.dialogManager || e107Widgets.DialogManagerDefault;
|
|
|
|
if(this.options.id && this.dialogManager.getWindow($(this.options.id))) return;
|
|
|
|
this.setMethodChains();
|
|
|
|
this.create();
|
|
this.id = this.element.id;
|
|
|
|
this.dialogManager.register(this);
|
|
this.render();
|
|
|
|
if (this.options.activeOnClick)
|
|
this.overlay.setStyle({
|
|
zIndex: this.lastZIndex + 1
|
|
}).show();
|
|
},
|
|
|
|
getTheme: function() {
|
|
return this.options.theme || this.dialogManager.getTheme();
|
|
},
|
|
|
|
setTheme: function(theme, managerTheme) {
|
|
this.element.removeClassName(this.getTheme()).addClassName(theme);
|
|
// window has it's own theme
|
|
if (!managerTheme)
|
|
this.options.theme = theme;
|
|
|
|
return this;
|
|
},
|
|
|
|
// shadows are under construction
|
|
getShadowTheme: function() {
|
|
return this.options.shadowTheme || this.dialogManager.getShadowTheme();
|
|
},
|
|
|
|
setMethodChains: function() {
|
|
|
|
this.events.observe('create', this.createButtons)//bind create and createButtons
|
|
.observe('destroy', this.destroyButtons); //bind destroy and destroyButtons
|
|
|
|
|
|
if(Object.isUndefined(e107Widgets.Shadow))
|
|
this.options.shadow = false;
|
|
|
|
if(this.options.shadow) {
|
|
this.events.observe('create', this.createShadow)
|
|
.observe('addElements', this.addElementsShadow)
|
|
.observe('setZIndex:pre', this.setZIndexShadow)
|
|
.observe('setPosition', this.setPositionShadow)
|
|
.observe('setSize', this.setSizeShadow)
|
|
.observe('setBounds', this.setBoundsShadow);
|
|
}
|
|
},
|
|
|
|
create : function() {
|
|
function createDiv(className, options) {
|
|
return new Element('div', Object.extend( {
|
|
className : className
|
|
}, options));
|
|
}
|
|
|
|
// Main div FIXME - this.options.className should go to dialogManager.className
|
|
this.element = createDiv(this.dialogManager.options.className + " " + this.getTheme(), {
|
|
id: this.options.id,
|
|
style: "top:-10000px; left:-10000px"
|
|
});
|
|
|
|
// Create window HTML code
|
|
this.header = createDiv('n move_handle').enableDrag();
|
|
this.content = createDiv('content').appendText(' ');
|
|
this.footer = createDiv('s move_handle').enableDrag();
|
|
|
|
var header = createDiv('nw').insert( createDiv('ne').insert(this.header));
|
|
var content = createDiv('w').insert(createDiv('e', {
|
|
style : "position:relative"
|
|
}).insert(this.content));
|
|
var footer = createDiv('sw').insert(createDiv('se' + (this.options.resizable ? " se_resize_handle" : "")).insert(this.footer));
|
|
|
|
this.element.insert(header).insert(content).insert(footer);
|
|
this.options.id = this.element.identify();
|
|
this.header.observe('mousedown', this.activate.bind(this));
|
|
|
|
this.setDraggable(this.options.draggable);
|
|
this.setResizable(this.options.resizable);
|
|
|
|
this.overlay = new Element('div', {
|
|
style : this.style + "display: none"
|
|
}).observe('mousedown', this.activate.bind(this));
|
|
|
|
if (this.options.activeOnClick)
|
|
this.content.insert( {
|
|
before : this.overlay
|
|
});
|
|
this.events.notify('create');
|
|
},
|
|
|
|
createWiredElement: function() {
|
|
this.wiredElement = this.wiredElement || new Element("div", {
|
|
className: this.getTheme() + "_wired",
|
|
style: "display: none; position: absolute; top: 0; left: 0"
|
|
});
|
|
},
|
|
|
|
createResizeHandles: function() {
|
|
$w("n w e s nw ne sw se").each(function(id) {
|
|
this.insert(new Element("div", {
|
|
className: id + "_sizer resize_handle",
|
|
drag_prefix: id
|
|
}).enableDrag());
|
|
}, this.element);
|
|
this.createResizeHandles = Prototype.emptyFunction;
|
|
},
|
|
|
|
// First rendering, pre-compute window border size
|
|
render: function() {
|
|
this.addElements();
|
|
|
|
this.computeBorderSize();
|
|
this.updateButtonsOrder();
|
|
this.element.hide().remove();
|
|
|
|
// this.options contains top, left, width and height keys
|
|
return this.setBounds(this.options);
|
|
},
|
|
|
|
show: function(modal) {
|
|
if (this.visible)
|
|
return this;
|
|
|
|
this.fire('showing');
|
|
this.effect('show');
|
|
|
|
if (modal) {
|
|
this.dialogManager.startModalSession(this);
|
|
this.modalSession = true;
|
|
}
|
|
|
|
this.addElements();
|
|
this.visible = true;
|
|
|
|
new PeriodicalExecuter(function(executer) {
|
|
if (this.element && !this.element.visible())
|
|
return;
|
|
this.fire('shown');
|
|
executer.stop();
|
|
}.bind(this), 0.1);
|
|
|
|
return this;
|
|
},
|
|
|
|
/*
|
|
* Method: hide Hides the window, (removes it from the DOM)
|
|
*
|
|
* Returns: this
|
|
*/
|
|
hide: function() {
|
|
if (!this.visible)
|
|
return this;
|
|
|
|
this.fire('hiding');
|
|
this.effect('hide', null, this.options['hideOptions']);
|
|
|
|
if (this.modalSession) {
|
|
this.dialogManager.endModalSession(this);
|
|
this.modalSession = false;
|
|
}
|
|
|
|
new PeriodicalExecuter(function(executer) {
|
|
if (this.element && this.element.visible())
|
|
return;
|
|
this.visible = false;
|
|
this.element.remove();
|
|
this.fire('hidden');
|
|
executer.stop();
|
|
}.bind(this), 0.1);
|
|
|
|
return this;
|
|
},
|
|
|
|
close: function() {
|
|
return this.action('close');
|
|
},
|
|
|
|
activate: function() {
|
|
return this.bringToFront().focus();
|
|
},
|
|
|
|
bringToFront: function() {
|
|
return this.setAltitude('front');
|
|
},
|
|
|
|
sendToBack: function() {
|
|
return this.setAltitude('back');
|
|
},
|
|
|
|
focus: function() {
|
|
if (this.focused)
|
|
return this;
|
|
|
|
this.dialogManager.focus(this);
|
|
// Hide the overlay that catch events
|
|
this.overlay.hide();
|
|
// Add focused class name
|
|
this.element.addClassName(this.getTheme() + '_focused');
|
|
|
|
this.focused = true;
|
|
this.fire('focused');
|
|
return this;
|
|
},
|
|
|
|
/*
|
|
* Method: blur Blurs the window (without changing windows order)
|
|
*/
|
|
blur: function() {
|
|
if (!this.focused)
|
|
return this;
|
|
|
|
this.dialogManager.blur(this);
|
|
this.element.removeClassName(this.getTheme() + '_focused');
|
|
|
|
// Show the overlay to catch events
|
|
if (this.options.activeOnClick)
|
|
this.overlay.setStyle( {
|
|
zIndex: this.lastZIndex + 1
|
|
}).show();
|
|
|
|
this.focused = false;
|
|
this.fire('blurred');
|
|
return this;
|
|
},
|
|
|
|
/*
|
|
* Method: maximize Maximizes window inside its viewport (managed by
|
|
* WindowManager) Makes window take full size of its viewport
|
|
*/
|
|
maximize: function() {
|
|
if (this.maximized)
|
|
return this;
|
|
|
|
// Get bounds has to be before this.dialogManager.maximize for IE!!
|
|
// this.dialogManager.maximize remove overflow
|
|
// and it breaks this.getBounds()
|
|
var bounds = this.getBounds();
|
|
if (this.dialogManager.maximize(this)) {
|
|
this.disableButton('minimize').setResizable(false).setDraggable(false);
|
|
|
|
this.activate();
|
|
this.maximized = true;
|
|
this.savedArea = bounds;
|
|
var newBounds = Object.extend(this.dialogManager.viewport.getDimensions(), {
|
|
top: 0,
|
|
left: 0
|
|
});
|
|
this[this.options.maximizeEffects && !e107API.Browser.IE ? "morph" : "setBounds"](newBounds);
|
|
|
|
this.fire('maximized');
|
|
return this;
|
|
}
|
|
},
|
|
|
|
/*
|
|
* Function: restore Restores a maximized window to its initial size
|
|
*/
|
|
restore: function() {
|
|
if (!this.maximized)
|
|
return this;
|
|
|
|
if (this.dialogManager.restore(this)) {
|
|
this[this.options.maximizeEffects && !e107API.Browser.IE ? "morph" : "setBounds"](this.savedArea);
|
|
this.enableButton("minimize").setResizable(true).setDraggable(true);
|
|
|
|
this.maximized = false;
|
|
|
|
this.fire('restored');
|
|
return this;
|
|
}
|
|
},
|
|
|
|
/*
|
|
* Function: toggleMaximize Maximizes/Restores window inside it's
|
|
* viewport (managed by DialogManager)
|
|
*/
|
|
toggleMaximize: function() {
|
|
return this.maximized ? this.restore() : this.maximize();
|
|
},
|
|
|
|
/*
|
|
* Function: adapt Adapts window size to fit its content
|
|
*
|
|
* Returns: this
|
|
*/
|
|
adapt: function() {
|
|
var dimensions = this.content.getScrollDimensions();
|
|
|
|
dimensions.height += this.options.adaptHeightOffset;
|
|
dimensions.width += this.options.adaptWidthOffset;
|
|
|
|
if(this.options.maxAdaptHeight && dimensions.height > this.options.maxAdaptHeight)
|
|
dimensions.height = this.options.maxAdaptHeight;
|
|
|
|
if(this.options.maxAdaptWidth && dimensions.width > this.options.maxAdaptWidth)
|
|
dimensions.width = this.options.maxAdaptWidth;
|
|
|
|
|
|
if(this.options.maxWidth && dimensions.width > this.options.maxWidth)
|
|
dimensions.height = this.options.maxWidth;
|
|
|
|
if(this.options.maxHeight && dimensions.height > this.options.maxHeight)
|
|
dimensions.height = this.options.maxHeight;
|
|
|
|
if (this.options.superflousEffects)
|
|
this.morph(dimensions, true);
|
|
else
|
|
this.setSize(dimensions.width, dimensions.height, true);
|
|
return this;
|
|
},
|
|
|
|
/*
|
|
* Function: fit Fits window size to its inner content
|
|
*
|
|
* @param string selector
|
|
* @param boolean fitWidth
|
|
*/
|
|
fit: function(selector, fitWidth) {
|
|
var target = this.content.select(selector), dimensions;
|
|
|
|
if(!target || !target.length) return this;
|
|
dimensions = target[0].getDimensions();
|
|
|
|
if(!fitWidth) dimensions.width = this.content.getDimensions().width;
|
|
|
|
if(this.options.maxWidth && dimensions.width > this.options.maxWidth)
|
|
dimensions.width = this.options.maxWidth;
|
|
|
|
if(this.options.maxHeight && dimensions.height > this.options.maxHeight)
|
|
dimensions.height = this.options.maxHeight;
|
|
|
|
|
|
if(this.options.minWidth && dimensions.width < this.options.minWidth)
|
|
dimensions.width = this.options.minWidth;
|
|
|
|
if(this.options.minHeight && dimensions.height < this.options.minHeight)
|
|
dimensions.height = this.options.minHeight;
|
|
|
|
if (this.options.superflousEffects)
|
|
this.morph(dimensions, true);
|
|
else
|
|
this.setSize(dimensions.width, dimensions.height, true);
|
|
return this;
|
|
},
|
|
|
|
/*
|
|
* Method: destroy Destructor, closes window, cleans up DOM and memory
|
|
*/
|
|
destroy: function() {
|
|
this.hide();
|
|
if (this.centerOptions)
|
|
Event.stopObserving(this.dialogManager.scrollContainer, "scroll", this.centerOptions.handler);
|
|
|
|
// clean-up all content container events
|
|
this.content.stopObserving();
|
|
|
|
this.dialogManager.unregister(this);
|
|
this.events.notify('destroy');
|
|
this.fire('destroyed');
|
|
},
|
|
|
|
setHeader: function(header) {
|
|
this.header.update(header);
|
|
return this;
|
|
},
|
|
|
|
setContent: function(content) {
|
|
this.content.update(content);
|
|
return this;
|
|
},
|
|
|
|
setAjaxContent: function(url, options) {
|
|
if (!options)
|
|
options = {};
|
|
|
|
// bind all callbacks to the window
|
|
Object.keys(options).each(function(name) {
|
|
if (Object.isFunction(options[name]))
|
|
options[name] = options[name].bind(this);
|
|
}, this);
|
|
|
|
var onComplete = options.onComplete, afterComplete = options.onAfterComplete;
|
|
options.onComplete = (function(response, json) {
|
|
|
|
if (Object.isFunction(onComplete))
|
|
onComplete(response, json);
|
|
else {
|
|
if(response.responseJSON) {
|
|
this.setContent(response.responseJSON['body']);
|
|
this.setHeader(response.responseJSON['header']);
|
|
this.setFooter(response.responseJSON['footer']);
|
|
}
|
|
else this.setContent(response.responseText);
|
|
Object.extend(response.request.options, { element: this.content } );
|
|
e107Event.trigger('ajax_update_after', response.request.options, response.request.options.element);
|
|
if(this.options.adaptOnAjaxContent) this.adapt();
|
|
}
|
|
|
|
if (Object.isFunction(afterComplete))
|
|
afterComplete(response, json);
|
|
}).bind(this);
|
|
|
|
new e107Ajax.Request(url, options);
|
|
return this;
|
|
},
|
|
|
|
setFooter : function(footer) {
|
|
this.footer.update(footer);
|
|
return this;
|
|
},
|
|
|
|
getPosition: function() {
|
|
return {
|
|
left: this.options.left,
|
|
top: this.options.top
|
|
};
|
|
},
|
|
|
|
setPosition: function(top, left) {
|
|
var pos = this.computePosition(top, left);
|
|
this.options.top = pos.top;
|
|
this.options.left = pos.left;
|
|
|
|
var elementStyle = this.element.style;
|
|
elementStyle.top = pos.top + 'px';
|
|
elementStyle.left = pos.left + 'px';
|
|
|
|
this.events.notify('setPosition', top, left);
|
|
this.fire('position:changed');
|
|
return this;
|
|
},
|
|
|
|
center: function(options) {
|
|
var size = this.getSize(), dManager = this.dialogManager, viewport = dManager.viewport;
|
|
viewportArea = viewport.getDimensions(), offset = viewport.getScrollOffset();
|
|
|
|
if (options && options.auto) {
|
|
this.centerOptions = Object.extend( {
|
|
handler: this.recenter.bind(this)
|
|
}, options);
|
|
Event.observe(dManager.scrollContainer, "scroll", this.centerOptions.handler);
|
|
Event.observe(window, "resize", this.centerOptions.handler);
|
|
}
|
|
|
|
options = Object.extend( {
|
|
top: (viewportArea.height - size.height) / 2,
|
|
left: (viewportArea.width - size.width) / 2
|
|
}, options || {});
|
|
|
|
return this.setPosition(options.top + offset.top, options.left + offset.left);
|
|
},
|
|
|
|
getSize: function(innerSize) {
|
|
if (innerSize)
|
|
return {
|
|
width: this.options.width - this.borderSize.width,
|
|
height: this.options.height - this.borderSize.height
|
|
}
|
|
else
|
|
return {
|
|
width: this.options.width,
|
|
height: this.options.height
|
|
};
|
|
},
|
|
|
|
/*
|
|
* innerSize: if true change set content size, else set window size
|
|
* (defaults to false)
|
|
*/
|
|
setSize: function(width, height, innerSize) {
|
|
var size = this.computeSize(width, height, innerSize);
|
|
var elementStyle = this.element.style, contentStyle = this.content.style;
|
|
|
|
this.options.width = size.outerWidth;
|
|
this.options.height = size.outerHeight;
|
|
|
|
elementStyle.width = size.outerWidth + "px", elementStyle.height = size.outerHeight + "px";
|
|
contentStyle.width = size.innerWidth + "px", contentStyle.height = size.innerHeight + "px";
|
|
this.overlay.style.height = size.innerHeight + "px";
|
|
|
|
this.events.notify('setSize', width, height, innerSize);
|
|
this.fire('size:changed');
|
|
return this;
|
|
},
|
|
|
|
/*
|
|
* innerSize: returns content size if true, window size
|
|
* otherwise
|
|
*/
|
|
getBounds: function(innerSize) {
|
|
return Object.extend(this.getPosition(), this.getSize(innerSize));
|
|
},
|
|
|
|
/*
|
|
* Method: setBounds Sets window bounds (in pixels), fires
|
|
* position:changed and size:changed
|
|
*
|
|
* Parameters bounds: Hash {top:, left:, width:, height:} where all
|
|
* values are optional
|
|
* innerSize: sets content size if true, window size
|
|
* otherwise
|
|
*
|
|
* Returns: Hash {top:, left:, width:, height:}
|
|
*/
|
|
setBounds: function(bounds, innerSize) {
|
|
var ret = this.setPosition(bounds.top, bounds.left).setSize(bounds.width, bounds.height, innerSize);
|
|
this.events.notify('setBounds', bounds, innerSize);
|
|
return ret;
|
|
},
|
|
|
|
morph: function(bounds, innerSize) {
|
|
bounds = Object.extend(this.getBounds(innerSize), bounds || {});
|
|
|
|
if (this.centerOptions && this.centerOptions.auto)
|
|
bounds = Object.extend(bounds, this.computeRecenter(bounds));
|
|
|
|
if (innerSize) {
|
|
bounds.width += this.borderSize.width;
|
|
bounds.height += this.borderSize.height;
|
|
}
|
|
|
|
if (this.options.wired) {
|
|
this.createWiredElement();
|
|
if(this.shadow) this.shadow.hide();
|
|
this.wiredElement.style.cssText = this.element.style.cssText;
|
|
this.element.hide();
|
|
this.savedElement = this.element;
|
|
this.dialogManager.container.appendChild(this.wiredElement);
|
|
this.element = this.wiredElement;
|
|
}
|
|
|
|
this.animating = true;
|
|
|
|
new e107Widgets.Dialog.Effects.Morph(this, bounds, {
|
|
duration: 0.3,
|
|
afterFinish: function() {
|
|
this.animating = false;
|
|
if (this.options.wired) {
|
|
this.savedElement.style.cssText = this.wiredElement.style.cssText;
|
|
this.wiredElement.remove();
|
|
this.element = this.savedElement;
|
|
if(this.shadow) this.shadow.show();
|
|
this.savedElement = false;
|
|
}
|
|
}.bind(this)
|
|
});
|
|
|
|
Object.extend(this.options, bounds);
|
|
return this;
|
|
},
|
|
|
|
/*
|
|
* Method: getAltitude Returns window altitude, an integer between 0 and
|
|
* the number of windows, the higher the altitude number - the higher
|
|
* the window position.
|
|
*/
|
|
getAltitude: function() {
|
|
return this.dialogManager.getAltitude(this);
|
|
},
|
|
|
|
/*
|
|
* Method: setAltitude Sets window altitude, fires 'altitude:changed' if
|
|
* altitude was changed
|
|
*/
|
|
setAltitude: function(altitude) {
|
|
if (this.dialogManager.setAltitude(this, altitude))
|
|
this.fire('altitude:changed');
|
|
return this;
|
|
},
|
|
|
|
setDraggable : function(draggable) {
|
|
var element = this.savedElement || this.element;
|
|
this.options.draggable = draggable;
|
|
element[(draggable ? 'add' : 'remove') + 'ClassName']('draggable');
|
|
return this;
|
|
},
|
|
|
|
setResizable: function(resizable) {
|
|
this.options.resizable = resizable;
|
|
|
|
var toggleClassName = (resizable ? 'add' : 'remove') + 'ClassName',
|
|
element = this.savedElement || this.element;
|
|
|
|
element[toggleClassName]('resizable').select('div:[class*=_sizer]').invoke(resizable ? 'show' : 'hide');
|
|
if (resizable)
|
|
this.createResizeHandles();
|
|
|
|
element.select('div.se').first()[toggleClassName]('se_resize_handle');
|
|
return this;
|
|
},
|
|
|
|
fire: function(eventName, memo) {
|
|
memo = memo || {};
|
|
memo.window = this;
|
|
return (this.savedElement || this.element).fire('edialog:' + eventName, memo);
|
|
},
|
|
|
|
observe: function(eventName, handler) {
|
|
(this.savedElement || this.element).observe('edialog:' + eventName, handler.bind(this));
|
|
return this;
|
|
},
|
|
|
|
addElements: function() {
|
|
this.dialogManager.container.appendChild(this.element);
|
|
this.events.notify('addElements');
|
|
},
|
|
|
|
effect: function(name, element, options) {
|
|
var effect = this.options[name] || Prototype.emptyFunction;
|
|
effect(element || this.element, options || {});
|
|
},
|
|
|
|
// Set z-index to all window elements
|
|
setZIndex: function(zIndex) {
|
|
if (this.zIndex != zIndex) {
|
|
this.events.notify('setZIndex:pre', zIndex);
|
|
this.zIndex = zIndex;
|
|
[ this.element ].concat(this.element.childElements()).each(function(element) {
|
|
element.style.zIndex = zIndex++;
|
|
});
|
|
this.lastZIndex = zIndex;
|
|
this.events.notify('setZIndex', zIndex);
|
|
}
|
|
return this;
|
|
},
|
|
|
|
// re-compute window border size
|
|
computeBorderSize: function() {
|
|
if (this.element) {
|
|
if (e107API.Browser.IE >= 7)
|
|
this.content.style.width = "100%";
|
|
|
|
var dim = this.element.getDimensions(),
|
|
pos = this.content.positionedOffset();
|
|
|
|
this.borderSize = {
|
|
top: pos[1],
|
|
bottom: dim.height - pos[1] - this.content.getHeight(),
|
|
left: pos[0],
|
|
right: dim.width - pos[0] - this.content.getWidth()
|
|
};
|
|
this.borderSize.width = this.borderSize.left
|
|
+ this.borderSize.right;
|
|
this.borderSize.height = this.borderSize.top
|
|
+ this.borderSize.bottom;
|
|
if (e107API.Browser.IE >= 7)
|
|
this.content.style.width = "auto";
|
|
}
|
|
},
|
|
|
|
computeSize: function(width, height, innerSize) {
|
|
var innerWidth, innerHeight, outerWidth, outerHeight;
|
|
if (innerSize) {
|
|
outerWidth = width + this.borderSize.width;
|
|
outerHeight = height + this.borderSize.height;
|
|
} else {
|
|
outerWidth = width;
|
|
outerHeight = height;
|
|
}
|
|
// Check grid value
|
|
if (!this.animating) {
|
|
outerWidth = outerWidth.snap(this.options.gridX);
|
|
outerHeight = outerHeight.snap(this.options.gridY);
|
|
|
|
// Check min size
|
|
if (outerWidth < this.options.minWidth)
|
|
outerWidth = this.options.minWidth;
|
|
if (outerHeight < this.options.minHeight)
|
|
outerHeight = this.options.minHeight;
|
|
|
|
// Check max size
|
|
if (this.options.maxWidth && outerWidth > this.options.maxWidth)
|
|
outerWidth = this.options.maxWidth;
|
|
|
|
if (this.options.maxHeight && outerHeight > this.options.maxHeight)
|
|
outerHeight = this.options.maxHeight;
|
|
}
|
|
|
|
if (this.centerOptions && this.centerOptions.auto)
|
|
this.recenter();
|
|
|
|
innerWidth = outerWidth - this.borderSize.width;
|
|
innerHeight = outerHeight - this.borderSize.height;
|
|
return {
|
|
innerWidth: innerWidth,
|
|
innerHeight: innerHeight,
|
|
outerWidth: outerWidth,
|
|
outerHeight: outerHeight
|
|
};
|
|
},
|
|
|
|
computePosition: function(top, left) {
|
|
if (this.modal && this.centerOptions && this.centerOptions.auto)
|
|
return this.computeRecenter(this.getSize());
|
|
|
|
return {
|
|
top: this.animating ? top : top.snap(this.options.gridY),
|
|
left: this.animating ? left : left.snap(this.options.gridX)
|
|
};
|
|
},
|
|
|
|
computeRecenter: function(size) {
|
|
var viewport = this.dialogManager.viewport, area = viewport.getDimensions(), offset = viewport.getScrollOffset(), center = {
|
|
top: Object.isUndefined(this.centerOptions.top) ? (area.height - size.height) / 2 : this.centerOptions.top,
|
|
left: Object.isUndefined(this.centerOptions.left) ? (area.width - size.width) / 2 : this.centerOptions.left
|
|
};
|
|
|
|
return {
|
|
top: parseInt(center.top + offset.top),
|
|
left: parseInt(center.left + offset.left)
|
|
};
|
|
},
|
|
|
|
recenter: function(event) {
|
|
var pos = this.computeRecenter(this.getSize());
|
|
this.setPosition(pos.top, pos.left);
|
|
}
|
|
});
|
|
|
|
e107Widgets.URLDialog = Class.create(e107Widgets.Dialog, {
|
|
|
|
setAjaxContent: function() {
|
|
return this;
|
|
},
|
|
|
|
initialize: function($super, url, options) {
|
|
$super(options);
|
|
this.options.url = url || this.options.url;
|
|
this.createIFrame();
|
|
},
|
|
|
|
destroy: function($super) {
|
|
this.iframe.src = null;
|
|
$super();
|
|
},
|
|
|
|
getUrl: function() {
|
|
return this.iframe.src;
|
|
},
|
|
|
|
setUrl: function(url) {
|
|
this.iframe.src = url;
|
|
return this;
|
|
},
|
|
|
|
createIFrame: function($super) {
|
|
this.iframe = new Element('iframe', {
|
|
style: this.style,
|
|
frameborder: 0,
|
|
src: this.options.url,
|
|
name: this.element.id + "_frame",
|
|
id: this.element.id + "_frame"
|
|
});
|
|
|
|
this.content.insert(this.iframe);
|
|
}
|
|
});
|
|
|
|
e107Base.setPrefs('core-confirm-dialog', {
|
|
buttons: null, // default = ok/cancel button
|
|
beforeSelect: function() {
|
|
return true;
|
|
},
|
|
close: false,
|
|
resizable: false,
|
|
activeOnClick: false
|
|
});
|
|
|
|
e107Widgets.ConfirmDialog = Class.create(e107Widgets.Dialog, {
|
|
|
|
initialize: function($super, options) {
|
|
options = Object.extend(e107Base.getPrefs('core-confirm-dialog'), options || {});
|
|
$super(options);
|
|
|
|
},
|
|
|
|
disableDialogButton: function(index) {
|
|
var button = this.getDialogButton(index);
|
|
if (button)
|
|
button.addClassName("disabled");
|
|
return this;
|
|
},
|
|
|
|
enableDialogButton: function(index) {
|
|
var button = this.getDialogButton(index);
|
|
if (button)
|
|
button.removeClassName("disabled");
|
|
return this;
|
|
},
|
|
|
|
getDialogButton: function(index) {
|
|
var buttons = this.buttonContainer.childElements();
|
|
if (index >= 0 && index < buttons.length)
|
|
return buttons[index];
|
|
else
|
|
return null;
|
|
},
|
|
|
|
// Override create to add dialog buttons
|
|
create: function($super) {
|
|
$super();
|
|
|
|
// Create buttons
|
|
this.buttonContainer = this.createButtons();
|
|
// Add a new content for dialog content
|
|
this.dialogContent = new Element('div', {
|
|
className: 'ui-dialog-confirm-content'
|
|
});
|
|
|
|
this.content.update(this.dialogContent);
|
|
this.content.insert(this.buttonContainer);
|
|
},
|
|
|
|
addElements: function($super) {
|
|
$super();
|
|
// Pre compute buttons height
|
|
this.buttonsHeight = this.buttonContainer.getHeight() || this.buttonsHeight;
|
|
this.setDialogSize();
|
|
},
|
|
|
|
setContent: function(content, withoutButton) {
|
|
this.dialogContent.update(content);
|
|
|
|
// Remove button if need be
|
|
if (withoutButton && this.buttonContainer.parentNode)
|
|
this.buttonContainer.remove();
|
|
else
|
|
this.content.insert(this.buttonContainer);
|
|
|
|
// Update dialog size
|
|
this.setDialogSize();
|
|
return this;
|
|
},
|
|
|
|
onSelect: function(e) {
|
|
var element = e.element();
|
|
|
|
if (element.callback && !element.hasClassName('disabled')) {
|
|
if (this.options.beforeSelect(element))
|
|
element.callback(this);
|
|
}
|
|
},
|
|
|
|
createButtons: function(dialogButtons) {
|
|
var buttonContainer = new Element('div', {
|
|
className: 'ui-dialog-confirm-buttons'
|
|
});
|
|
|
|
(this.options.buttons || e107Widgets.ConfirmDialog.okCancelButtons).each(function(item) {
|
|
var button;
|
|
if (item.separator)
|
|
button = new Element('span', {
|
|
className: 'separator'
|
|
});
|
|
else
|
|
button = new Element('button', {
|
|
title: item.title,
|
|
className: (item.className || '') + (item.disabled ? ' disabled' : '')
|
|
}).observe('click', this.onSelect.bind(this)).update(item.title);
|
|
|
|
buttonContainer.insert(button);
|
|
button.callback = item.callback;
|
|
}.bind(this));
|
|
return buttonContainer;
|
|
},
|
|
|
|
setDialogSize: function() {
|
|
// Do not compute dialog size if window is not completly ready
|
|
if (!this.borderSize)
|
|
return;
|
|
|
|
this.buttonsHeight = this.buttonContainer.getHeight() || this.buttonsHeight;
|
|
var style = this.dialogContent.style, size = this.getSize(true);
|
|
style.width = size.width + "px", style.height = size.height - this.buttonsHeight + "px";
|
|
},
|
|
|
|
setSize: function($super, width, height, innerSize) {
|
|
$super(width, height, innerSize);
|
|
this.setDialogSize();
|
|
return this;
|
|
}
|
|
});
|
|
|
|
e107Widgets.ConfirmDialog = Object.extend(e107Widgets.ConfirmDialog, {
|
|
okButton : [{title: 'Ok', className: 'ok', callback: function(win) { win.destroy(); }}],
|
|
okCancelButtons : [{title: 'Ok', className: 'ok', callback: function(win) { win.destroy(); }},
|
|
{title: 'Cancel', className: 'cancel', callback: function(win) { win.destroy(); }}]
|
|
});
|
|
|
|
if (!Object.isUndefined(window.Effect)) {
|
|
e107Widgets.Dialog.Effects = e107Widgets.Dialog.Effects || {};
|
|
e107Widgets.Dialog.Effects.Morph = Class.create(Effect.Base, {
|
|
initialize: function(window, bounds) {
|
|
this.window = window;
|
|
var options = Object.extend( {
|
|
fromBounds: this.window.getBounds(),
|
|
toBounds: bounds,
|
|
from: 0,
|
|
to: 1
|
|
}, arguments[2] || {});
|
|
this.start(options);
|
|
},
|
|
|
|
update: function(position) {
|
|
var t = this.options.fromBounds.top + (this.options.toBounds.top - this.options.fromBounds.top) * position;
|
|
var l = this.options.fromBounds.left + (this.options.toBounds.left - this.options.fromBounds.left) * position;
|
|
|
|
var ow = this.options.fromBounds.width + (this.options.toBounds.width - this.options.fromBounds.width) * position;
|
|
var oh = this.options.fromBounds.height + (this.options.toBounds.height - this.options.fromBounds.height) * position;
|
|
|
|
this.window.setBounds( {
|
|
top: t,
|
|
left: l,
|
|
width: ow,
|
|
height: oh
|
|
})
|
|
}
|
|
});
|
|
}
|
|
|
|
e107Widgets.Dialog.addMethods( {
|
|
|
|
startDrag: function(handle) {
|
|
this.initBounds = this.getBounds();
|
|
this.activate();
|
|
|
|
if (this.options.wired) {
|
|
this.createWiredElement();
|
|
this.wiredElement.style.cssText = this.element.style.cssText;
|
|
this.element.hide();
|
|
if(this.shadow) this.shadow.hide();
|
|
this.savedElement = this.element;
|
|
this.dialogManager.container.appendChild(this.wiredElement);
|
|
this.element = this.wiredElement;
|
|
}
|
|
|
|
handle.hasClassName('resize_handle') ? this.startResize(handle) : this.startMove();
|
|
},
|
|
|
|
endDrag: function() {
|
|
this.element.hasClassName('resized') ? this.endResize() : this.endMove();
|
|
|
|
if (this.options.wired) {
|
|
this.savedElement.style.cssText = this.wiredElement.style.cssText;
|
|
this.wiredElement.remove();
|
|
this.element = this.savedElement;
|
|
if(this.shadow) this.shadow.show();
|
|
this.savedElement = false;
|
|
}
|
|
},
|
|
|
|
startMove: function() {
|
|
// method used to drag
|
|
this.drag = this.moveDrag;
|
|
this.element.addClassName('moved');
|
|
this.fire('move:started');
|
|
},
|
|
|
|
endMove: function() {
|
|
this.element.removeClassName('moved');
|
|
this.fire('move:ended');
|
|
},
|
|
|
|
startResize: function(handle) {
|
|
this.drag = this[handle.readAttribute('drag_prefix') + 'Drag'];
|
|
this.element.addClassName('resized');
|
|
this.fire('resize:started');
|
|
},
|
|
|
|
endResize: function() {
|
|
this.element.removeClassName('resized');
|
|
this.fire('resize:ended');
|
|
},
|
|
|
|
moveDrag: function(dx, dy) {
|
|
var top = this.initBounds.top + dy, left = this.initBounds.left + dx;
|
|
if(this.options.noPositionConstrain)
|
|
this.setPosition(top, left);
|
|
else
|
|
this.setPosition(top < 0 ? 0 : top, left < 0 ? 0 : left);
|
|
},
|
|
|
|
swDrag: function(dx, dy) {
|
|
var initBounds = this.initBounds;
|
|
this.setSize(initBounds.width - dx, initBounds.height + dy).setPosition(initBounds.top, initBounds.left + (initBounds.width - this.getSize().width));
|
|
},
|
|
|
|
seDrag: function(dx, dy) {
|
|
this.setSize(this.initBounds.width + dx, this.initBounds.height + dy);
|
|
},
|
|
|
|
nwDrag: function(dx, dy) {
|
|
var initBounds = this.initBounds;
|
|
this.setSize(initBounds.width - dx, initBounds.height - dy).setPosition(initBounds.top + (initBounds.height - this.getSize().height), initBounds.left + (initBounds.width - this.getSize().width));
|
|
},
|
|
|
|
neDrag: function(dx, dy) {
|
|
var initBounds = this.initBounds;
|
|
this.setSize(initBounds.width + dx, initBounds.height - dy).setPosition(initBounds.top + (initBounds.height - this.getSize().height), initBounds.left);
|
|
},
|
|
|
|
wDrag: function(dx, dy) {
|
|
var initBounds = this.initBounds;
|
|
this.setSize(initBounds.width - dx, initBounds.height).setPosition(initBounds.top, initBounds.left + (initBounds.width - this.getSize().width));
|
|
},
|
|
|
|
eDrag: function(dx, dy) {
|
|
this.setSize(this.initBounds.width + dx, this.initBounds.height);
|
|
},
|
|
|
|
nDrag: function(dx, dy) {
|
|
var initBounds = this.initBounds;
|
|
this.setSize(initBounds.width, initBounds.height - dy).setPosition(initBounds.top + (initBounds.height - this.getSize().height), initBounds.left);
|
|
},
|
|
|
|
sDrag: function(dx, dy) {
|
|
this.setSize(this.initBounds.width, this.initBounds.height + dy);
|
|
}
|
|
});
|
|
|
|
e107Widgets.Dialog.addMethods( {
|
|
|
|
createButtons: function() {
|
|
this.buttons = new Element("div", {
|
|
className: "buttons"
|
|
}).observe('click', this.onButtonsClick.bind(this))
|
|
.observe('mouseover', this.onButtonsHover.bind(this))
|
|
.observe('mouseout', this.onButtonsOut.bind(this));
|
|
|
|
this.element.insert(this.buttons);
|
|
|
|
this.defaultButtons.each(function(button) {
|
|
if (this.options[button] !== false)
|
|
this.addButton(button);
|
|
}, this);
|
|
},
|
|
|
|
destroyButtons: function() {
|
|
if(this.buttons)
|
|
this.buttons.stopObserving();
|
|
},
|
|
|
|
defaultButtons: $w('maximize close'),
|
|
|
|
getButtonElement: function(buttonName) {
|
|
return this.buttons.down("." + buttonName);
|
|
},
|
|
|
|
// Controls close, minimize, maximize, etc.
|
|
// action can be either a string or a function
|
|
// if action is a string, it is the method name that will be called
|
|
// else the function will take the window as first parameter.
|
|
// if not given action will be taken in window's options
|
|
addButton: function(buttonName, action) {
|
|
this.buttons.insert(new Element("a", {
|
|
className: buttonName,
|
|
href: "#"
|
|
}));
|
|
|
|
if (action)
|
|
this.options[buttonName] = action;
|
|
|
|
return this;
|
|
},
|
|
|
|
removeButton: function(buttonName) {
|
|
var b = this.getButtonElement(buttonName);
|
|
if(b) b.remove();
|
|
return this;
|
|
},
|
|
|
|
disableButton: function(buttonName) {
|
|
var b = this.getButtonElement(buttonName);
|
|
if(b) b.addClassName("disabled");
|
|
return this;
|
|
},
|
|
|
|
enableButton: function(buttonName) {
|
|
var b = this.getButtonElement(buttonName);
|
|
if(b) b.removeClassName("disabled");
|
|
return this;
|
|
},
|
|
|
|
onButtonsClick: function(event) {
|
|
var element = event.findElement('a:not(.disabled)');
|
|
|
|
if (element)
|
|
this.action(element.className);
|
|
event.stop();
|
|
},
|
|
|
|
onButtonsHover: function(event) {
|
|
this.buttons.addClassName("over");
|
|
},
|
|
|
|
onButtonsOut: function(event) {
|
|
this.buttons.removeClassName("over");
|
|
},
|
|
|
|
updateButtonsOrder: function() {
|
|
if(!this.buttons) return;
|
|
var buttons = this.buttons.childElements();
|
|
|
|
buttons.inject(new Array(buttons.length), function(array, button) {
|
|
array[parseInt(button.getStyle("padding-top"))] = button.setStyle("padding: 0");
|
|
return array;
|
|
}).each(function(button) {
|
|
this.buttons.insert(button)
|
|
}, this);
|
|
}
|
|
});
|
|
|
|
e107Widgets.Dialog.addMethods( {
|
|
|
|
showShadow: function() {
|
|
if (this.shadow) {
|
|
this.shadow.hide();
|
|
this.effect('show', this.shadow.shadow);
|
|
}
|
|
},
|
|
|
|
hideShadow: function() {
|
|
if (this.shadow)
|
|
this.effect('hide', this.shadow.shadow, this.options['hideShadowOptions']);
|
|
},
|
|
|
|
removeShadow: function() {
|
|
if (this.shadow)
|
|
this.shadow.remove();
|
|
},
|
|
|
|
focusShadow: function() {
|
|
if (this.shadow)
|
|
this.shadow.focus();
|
|
},
|
|
|
|
blurShadow: function() {
|
|
if (this.shadow)
|
|
this.shadow.blur();
|
|
},
|
|
|
|
// Private Functions
|
|
createShadow: function() {
|
|
if (!this.options.shadow || Object.isUndefined(e107Widgets.Shadow)) return;
|
|
|
|
this.observe('showing', this.showShadow)
|
|
.observe('hiding', this.hideShadow)
|
|
.observe('hidden', this.removeShadow)
|
|
.observe('focused', this.focusShadow)
|
|
.observe('blurred', this.blurShadow);
|
|
|
|
this.shadow = new e107Widgets.Shadow(this.element, {
|
|
theme: this.getShadowTheme()
|
|
});
|
|
},
|
|
|
|
addElementsShadow: function() {
|
|
if (this.shadow) {
|
|
this.shadow.setBounds(this.options).render();
|
|
}
|
|
},
|
|
|
|
setZIndexShadow: function(zIndex) {
|
|
if (this.zIndex != zIndex) {
|
|
if (this.shadow)
|
|
this.shadow.setZIndex(zIndex - 1);
|
|
|
|
this.zIndex = zIndex;
|
|
}
|
|
return this;
|
|
},
|
|
|
|
setPositionShadow: function(top, left) {
|
|
if (this.shadow) {
|
|
var pos = this.getPosition();
|
|
this.shadow.setPosition(pos.top, pos.left);
|
|
}
|
|
return this;
|
|
},
|
|
|
|
setSizeShadow: function(width, height, innerSize) {
|
|
if (this.shadow) {
|
|
var size = this.getSize();
|
|
this.shadow.setSize(size.width, size.height);
|
|
}
|
|
return this;
|
|
},
|
|
|
|
setBoundsShadow: function(bounds, innerSize) {
|
|
if (this.shadow)
|
|
this.shadow.setBounds(this.getBounds());
|
|
}
|
|
});
|
|
|
|
|
|
e107Base.setPrefs('core-dialogmanager', {
|
|
className : 'e-dialog',
|
|
container: null, // will default to document.body
|
|
zIndex: 2000,
|
|
theme: "e107",
|
|
shadowTheme: "e107_shadow",
|
|
showOverlay: Element.show,
|
|
hideOverlay: Element.hide,
|
|
positionningStrategyOffset: null,
|
|
positionningStrategy: function(win, area, winoffset) {
|
|
e107Widgets.DialogManager.DefPositionningStrategy(win, area, winoffset);
|
|
}
|
|
});
|
|
|
|
e107Widgets.DialogManager = Class.create(e107WidgetAbstract, {
|
|
|
|
initialize: function(options) {
|
|
|
|
this.initMod('core-dialogmanager', options);
|
|
|
|
this.container = $(this.options.container || document.body);
|
|
|
|
if (this.container === $(document.body)) {
|
|
this.viewport = document.viewport;
|
|
this.scrollContainer = window;
|
|
} else {
|
|
this.viewport = this.scrollContainer = this.container;
|
|
}
|
|
|
|
this.container.observe('drag:started', this.onStartDrag.bind(this))
|
|
.observe('drag:updated', this.onDrag.bind(this))
|
|
.observe('drag:ended', this.onEndDrag.bind(this));
|
|
|
|
this.stack = new e107Widgets.DialogManager.Stack();
|
|
this.modalSessions = 0;
|
|
|
|
this.createOverlays();
|
|
this.resizeEvent = this.resize.bind(this);
|
|
|
|
Event.observe(window, "resize", this.resizeEvent);
|
|
},
|
|
|
|
destroy: function() {
|
|
this.windows().invoke('destroy');
|
|
this.stack.destroy();
|
|
Event.stopObserving(window, "resize", this.resizeEvent);
|
|
},
|
|
|
|
/*
|
|
* Method: setTheme Changes window manager's theme, all windows that
|
|
* don't have a own theme will have this new theme.
|
|
*
|
|
* Parameters: theme - theme name
|
|
*
|
|
* Example: e107Widgets.DialogManagerDefault.setTheme('bluelighting');
|
|
*/
|
|
setTheme: function(theme) {
|
|
this.stack.windows.select(function(w) {
|
|
return !w.options.theme;
|
|
}).invoke('setTheme', theme, true);
|
|
this.options.theme = theme;
|
|
return this;
|
|
},
|
|
|
|
getTheme: function() {
|
|
return this.options.theme;
|
|
},
|
|
|
|
//shadow under construction
|
|
getShadowTheme: function() {
|
|
return this.options.shadowTheme;
|
|
},
|
|
|
|
register: function(win) {
|
|
if (this.getWindow(win.id))
|
|
return;
|
|
|
|
this.handlePosition(win);
|
|
this.stack.add(win);
|
|
this.restartZIndexes();
|
|
},
|
|
|
|
unregister: function(win) {
|
|
this.stack.remove(win);
|
|
|
|
if (win == this.focusedWindow)
|
|
this.focusedWindow = null;
|
|
},
|
|
|
|
/*
|
|
* Method: getWindow Find the window containing a given element.
|
|
*
|
|
* Example: $$('.e-dialog a.close').invoke('observe', 'click',
|
|
* function() { e107Widgets.DialogManagerDefault.getWindow(this).close(); });
|
|
*
|
|
* Parameters: element - element or element identifier
|
|
*
|
|
* Returns: containing window or null
|
|
*/
|
|
getWindow: function(element) {
|
|
element = $(element);
|
|
|
|
if (!element)
|
|
return;
|
|
|
|
if (!element.hasClassName(this.options.className))
|
|
element = element.up('.' + this.options.className);
|
|
|
|
var id = element.id;
|
|
return this.stack.windows.find(function(win) {
|
|
return win.id == id
|
|
});
|
|
},
|
|
|
|
/*
|
|
* Method: windows Returns an array of all windows handled by this
|
|
* window manager. First one is the back window, last one is the front
|
|
* window.
|
|
*
|
|
* Example: e107Widgets.DialogManagerDefault.windows().invoke('destroy');
|
|
*/
|
|
windows: function() {
|
|
return this.stack.windows.clone();
|
|
},
|
|
|
|
/*
|
|
* Method: getFocusedWindow Returns the focused window
|
|
*/
|
|
getFocusedWindow: function() {
|
|
return this.focusedWindow;
|
|
},
|
|
|
|
// INTERNAL
|
|
|
|
// Modal mode
|
|
startModalSession: function(win) {
|
|
if (!this.modalSessions) {
|
|
this.removeOverflow();
|
|
this.modalOverlay.className = win.getTheme() + "_overlay";
|
|
this.container.appendChild(this.modalOverlay);
|
|
|
|
if (!this.modalOverlay.opacity)
|
|
this.modalOverlay.opacity = this.modalOverlay.getOpacity();
|
|
this.modalOverlay.setStyle("height: " + this.viewport.getHeight() + "px");
|
|
|
|
this.options.showOverlay(this.modalOverlay, {
|
|
from: 0,
|
|
to: this.modalOverlay.opacity
|
|
});
|
|
}
|
|
this.modalOverlay.setStyle( {
|
|
zIndex: win.zIndex - 1
|
|
});
|
|
this.modalSessions++;
|
|
},
|
|
|
|
endModalSession: function(win) {
|
|
this.modalSessions--;
|
|
if (this.modalSessions) {
|
|
this.modalOverlay.setStyle( {
|
|
zIndex: this.stack.getPreviousWindow(win).zIndex - 1
|
|
});
|
|
} else {
|
|
this.resetOverflow();
|
|
this.options.hideOverlay(this.modalOverlay, {
|
|
from: this.modalOverlay.opacity,
|
|
to: 0
|
|
});
|
|
}
|
|
},
|
|
|
|
// not sure this should stay so, too slow?
|
|
moveHandleSelector: '.#{className}.draggable .move_handle',
|
|
resizeHandleSelector: '.#{className}.resizable .resize_handle',
|
|
|
|
onStartDrag: function(event) {
|
|
var handle = event.element(),
|
|
isMoveHandle = handle.match(this.moveHandleSelector.interpolate(this.options)),
|
|
isResizeHandle = handle.match(this.resizeHandleSelector.interpolate(this.options));
|
|
|
|
// ensure dragged element is a window handle !
|
|
if (isResizeHandle || isMoveHandle) {
|
|
event.stop();
|
|
|
|
// find the corresponding window
|
|
var win = this.getWindow(event.findElement('.' + this.options.className));
|
|
|
|
// render drag overlay
|
|
this.container.insert(this.dragOverlay.setStyle( {
|
|
zIndex: this.getLastZIndex()
|
|
}));
|
|
|
|
win.startDrag(handle);
|
|
this.draggedWindow = win;
|
|
}
|
|
},
|
|
|
|
onDrag: function(event) {
|
|
if (this.draggedWindow) {
|
|
event.stop();
|
|
this.draggedWindow.drag(event.memo.dx, event.memo.dy);
|
|
}
|
|
},
|
|
|
|
onEndDrag: function(event) {
|
|
if (this.draggedWindow) {
|
|
event.stop();
|
|
this.dragOverlay.remove();
|
|
this.draggedWindow.endDrag();
|
|
this.draggedWindow = null;
|
|
}
|
|
},
|
|
|
|
maximize: function(win) {
|
|
this.removeOverflow();
|
|
this.maximizedWindow = win;
|
|
return true;
|
|
},
|
|
|
|
restore: function(win) {
|
|
if (this.maximizedWindow) {
|
|
this.resetOverflow();
|
|
this.maximizedWindow = false;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
removeOverflow: function() {
|
|
var container = this.container;
|
|
// Remove overflow, save overflow and scrolloffset values to restore
|
|
// them when restore window
|
|
container.savedOverflow = container.style.overflow || "auto";
|
|
container.savedOffset = this.viewport.getScrollOffset();
|
|
container.style.overflow = "hidden";
|
|
|
|
this.viewport.setScrollOffset( {
|
|
top: 0,
|
|
left: 0
|
|
});
|
|
|
|
if (this.container == document.body && Prototype.Browser.IE)
|
|
this.cssRule = CSS.addRule("html { overflow: hidden }");
|
|
},
|
|
|
|
resetOverflow: function() {
|
|
var container = this.container;
|
|
// Restore overflow ans scrolloffset
|
|
if (container.savedOverflow) {
|
|
if (this.container == document.body && Prototype.Browser.IE)
|
|
this.cssRule.remove();
|
|
|
|
container.style.overflow = container.savedOverflow;
|
|
this.viewport.setScrollOffset(container.savedOffset);
|
|
|
|
container.savedOffset = container.savedOverflow = null;
|
|
}
|
|
},
|
|
|
|
hide: function(win) {
|
|
var previous = this.stack.getPreviousWindow(win);
|
|
if (previous)
|
|
previous.focus();
|
|
},
|
|
|
|
getZIndex: function() {
|
|
return this.options.zIndex;
|
|
},
|
|
|
|
restartZIndexes: function() {
|
|
// Reset zIndex
|
|
var zIndex = this.getZIndex() + 1; // keep a zIndex free for
|
|
// overlay divs
|
|
this.stack.windows.each(function(w) {
|
|
w.setZIndex(zIndex);
|
|
zIndex = w.lastZIndex + 1;
|
|
});
|
|
},
|
|
|
|
getLastZIndex: function() {
|
|
return this.stack.getFrontWindow().lastZIndex + 1;
|
|
},
|
|
|
|
overlayStyle: "position: absolute; top: 0; left: 0; display: none; width: 100%;",
|
|
|
|
createOverlays: function() {
|
|
this.modalOverlay = new Element("div", {
|
|
style: this.overlayStyle
|
|
});
|
|
this.dragOverlay = new Element("div", {
|
|
style: this.overlayStyle + "height: 100%"
|
|
});
|
|
},
|
|
|
|
focus: function(win) {
|
|
// Blur the previous focused window
|
|
if (this.focusedWindow)
|
|
this.focusedWindow.blur();
|
|
this.focusedWindow = win;
|
|
},
|
|
|
|
blur: function(win) {
|
|
if (win == this.focusedWindow)
|
|
this.focusedWindow = null;
|
|
},
|
|
|
|
setAltitude: function(win, altitude) {
|
|
var stack = this.stack;
|
|
|
|
if (altitude === "front") {
|
|
if (stack.getFrontWindow() === win)
|
|
return;
|
|
stack.bringToFront(win);
|
|
} else if (altitude === "back") {
|
|
if (stack.getBackWindow() === win)
|
|
return;
|
|
stack.sendToBack(win);
|
|
} else {
|
|
if (stack.getPosition(win) == altitude)
|
|
return;
|
|
stack.setPosition(win, altitude);
|
|
}
|
|
|
|
this.restartZIndexes();
|
|
return true;
|
|
},
|
|
|
|
getAltitude: function(win) {
|
|
return this.stack.getPosition(win);
|
|
},
|
|
|
|
resize: function(event) {
|
|
var area = this.viewport.getDimensions();
|
|
|
|
if (this.maximizedWindow)
|
|
this.maximizedWindow.setSize(area.width, area.height);
|
|
|
|
if (this.modalOverlay.visible())
|
|
this.modalOverlay.setStyle("height:" + area.height + "px");
|
|
},
|
|
|
|
handlePosition: function(win) {
|
|
// window has its own position, nothing needs to be done
|
|
if (Object.isNumber(win.options.top) && Object.isNumber(win.options.left))
|
|
return;
|
|
|
|
// default values
|
|
//win.options.top = win.options.left = 0;
|
|
var strategy = this.options.positionningStrategy,
|
|
area = this.viewport.getDimensions(),
|
|
winoffset = win.options.positionningStrategyOffset || win.options.positionningStrategyOffset === false ? win.options.positionningStrategyOffset : this.options.positionningStrategyOffset;
|
|
|
|
Object.isFunction(strategy) ? strategy(win, area, winoffset) : strategy.position(win, area, winoffset);
|
|
}
|
|
});
|
|
|
|
e107Widgets.DialogManager.DefPositionningStrategy = function(win, area, winoffset) {
|
|
|
|
var manager = win.dialogManager,
|
|
last = manager.stack.getFrontWindow(),
|
|
size = win.getSize(),
|
|
offset = manager.viewport.getScrollOffset(),
|
|
maxtop = area.height - size.height,
|
|
maxleft = area.width - size.width,
|
|
poffset = winoffset === false ? 0 : (winoffset || 20),
|
|
start = { left: offset[0] + poffset, top: offset[1] + poffset },
|
|
left, top;
|
|
|
|
if(last) {
|
|
start = last.getPosition();
|
|
start.left = (start.left < offset[0] ? offset[0] : start.left) + poffset;
|
|
start.top = (start.top < offset[1] ? offset[1] : start.top) + poffset;
|
|
}
|
|
|
|
left = start.left < maxleft ? start.left : start.left - (poffset * 2);
|
|
top = start.top < maxtop ? start.top : start.top - (poffset * 2);
|
|
win.setPosition(top, left);
|
|
};
|
|
|
|
e107Widgets.DialogManager.Stack = Class.create(Enumerable, {
|
|
initialize: function() {
|
|
this.windows = [];
|
|
},
|
|
|
|
each: function(iterator) {
|
|
this.windows.each(iterator);
|
|
},
|
|
|
|
add: function(win, position) {
|
|
this.windows.splice(position || this.windows.length, 0, win);
|
|
},
|
|
|
|
remove: function(win) {
|
|
this.windows = this.windows.without(win);
|
|
},
|
|
|
|
sendToBack: function(win) {
|
|
this.remove(win);
|
|
this.windows.unshift(win);
|
|
},
|
|
|
|
bringToFront: function(win) {
|
|
this.remove(win);
|
|
this.windows.push(win);
|
|
},
|
|
|
|
getPosition: function(win) {
|
|
return this.windows.indexOf(win);
|
|
},
|
|
|
|
setPosition: function(win, position) {
|
|
this.remove(win);
|
|
this.windows.splice(position, 0, win);
|
|
},
|
|
|
|
getFrontWindow: function() {
|
|
return this.windows.last();
|
|
},
|
|
|
|
getBackWindow: function() {
|
|
return this.windows.first();
|
|
},
|
|
|
|
getPreviousWindow: function(win) {
|
|
return (win == this.windows.first()) ? null : this.windows[this.windows.indexOf(win) - 1];
|
|
}
|
|
});
|
|
|
|
/*
|
|
Utility functions for CSS/StyleSheet files access
|
|
|
|
Authors:
|
|
- Sébastien Gruhier, <http://www.xilinus.com>
|
|
- Samuel Lebeau, <http://gotfresh.info>
|
|
*/
|
|
|
|
var CSS = (function() {
|
|
// Code based on:
|
|
// - IE5.5+ PNG Alpha Fix v1.0RC4 (c) 2004-2005 Angus Turnbull http://www.twinhelix.com
|
|
// - Whatever:hover - V2.02.060206 - hover, active & focus (c) 2005 - Peter Nederlof * Peterned - http://www.xs4all.nl/~peterned/
|
|
function fixPNG() {
|
|
parseStylesheet.apply(this, $A(arguments).concat(fixRule));
|
|
};
|
|
|
|
function parseStylesheet() {
|
|
var patterns = $A(arguments);
|
|
var method = patterns.pop();
|
|
|
|
// To avoid flicking background
|
|
//document.execCommand("BackgroundImageCache", false, true);
|
|
// Parse all document stylesheets
|
|
var styleSheets = $A(document.styleSheets);
|
|
if (patterns.length > 1) {
|
|
styleSheets = styleSheets.select(function(css) {
|
|
return patterns.any(function(pattern) {
|
|
return css.href && css.href.match(pattern)
|
|
});
|
|
});
|
|
}
|
|
styleSheets.each(function(styleSheet) {fixStylesheet.call(this, styleSheet, method)});
|
|
};
|
|
|
|
// Fixes a stylesheet
|
|
function fixStylesheet(stylesheet, method) {
|
|
// Parse import files
|
|
if (stylesheet.imports)
|
|
$A(stylesheet.imports).each(fixStylesheet);
|
|
|
|
var href = stylesheet.href || document.location.href;
|
|
var docPath = href.substr(0, href.lastIndexOf('/'));
|
|
// Parse all CSS Rules
|
|
$A(stylesheet.rules || stylesheet.cssRules).each(function(rule) { method.call(this, rule, docPath) });
|
|
};
|
|
|
|
var filterPattern = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="#{src}",sizingMethod="#{method}")';
|
|
|
|
// Fixes a rule if it has a PNG background
|
|
function fixRule(rule, docPath) {
|
|
var bgImg = rule.style.backgroundImage;
|
|
// Rule with PNG background image
|
|
if (bgImg && bgImg != 'none' && bgImg.match(/^url[("']+(.*\.png)[)"']+$/i)) {
|
|
var src = RegExp.$1;
|
|
var bgRepeat = rule.style.backgroundRepeat;
|
|
// Relative path
|
|
if (src[0] != '/')
|
|
src = docPath + "/" + src;
|
|
// Apply filter
|
|
rule.style.filter = filterPattern.interpolate({
|
|
src: src,
|
|
method: bgRepeat == "no-repeat" ? "crop" : "scale" });
|
|
rule.style.backgroundImage = "none";
|
|
}
|
|
};
|
|
|
|
var preloadedImages = new Hash();
|
|
|
|
function preloadRule(rule, docPath) {
|
|
var bgImg = rule.style.backgroundImage;
|
|
if (bgImg && bgImg != 'none' && bgImg != 'initial' ) {
|
|
if (!preloadedImages.get(bgImg)) {
|
|
bgImg.match(/^url[("']+(.*)[)"']+$/i);
|
|
var src = RegExp.$1;
|
|
// Relative path
|
|
if (!(src[0] == '/' || src.match(/^file:/) || src.match(/^https?:/)))
|
|
src = docPath + "/" + src;
|
|
preloadedImages.set(bgImg, true);
|
|
var image = new Image();
|
|
image.src = src;
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
/*
|
|
Method: fixPNG
|
|
Fix transparency of PNG background of document stylesheets.
|
|
(only on IE version<7, otherwise does nothing)
|
|
|
|
Warning: All png background will not work as IE filter use for handling transparency in PNG
|
|
is not compatible with all background. It does not support top/left position (so no CSS sprite)
|
|
|
|
I recommend to create a special CSS file with png that needs to be fixed and call CSS.fixPNG on this CSS
|
|
|
|
Examples:
|
|
> CSS.fixPNG() // To fix all css
|
|
>
|
|
> CSS.fixPNG("mac_shadow.css") // to fix all css files with mac_shadow.css so mainly only on file
|
|
>
|
|
> CSS.fixPNG("shadow", "vista"); // To fix all css files with shadow or vista in their names
|
|
|
|
Parameters
|
|
patterns: (optional) list of pattern to filter css files
|
|
*/
|
|
fixPNG: (Prototype.Browser.IE && Prototype.Browser.IEVersion < 7) ? fixPNG : Prototype.emptyFunction,
|
|
|
|
// By Tobie Langel (http://tobielangel.com)
|
|
// inspired by http://yuiblog.com/blog/2007/06/07/style/
|
|
addRule: function(css, backwardCompatibility) {
|
|
if (backwardCompatibility) css = css + '{' + backwardCompatibility + '}';
|
|
var style = new Element('style', { type: 'text/css', media: 'screen' });
|
|
$(document.getElementsByTagName('head')[0]).insert(style);
|
|
if (style.styleSheet) style.styleSheet.cssText = css;
|
|
else style.appendText(css);
|
|
return style;
|
|
},
|
|
|
|
preloadImages: function() {
|
|
parseStylesheet.apply(this, $A(arguments).concat(preloadRule));
|
|
}
|
|
};
|
|
})();
|
|
|
|
/**
|
|
* String extension
|
|
*/
|
|
Object.extend(Number.prototype, {
|
|
// Snap a number to a grid
|
|
snap: function(round) {
|
|
return parseInt(round == 1 ? this : (this / round).floor() * round);
|
|
}
|
|
});
|
|
|
|
document.observe('dom:loaded', function() {
|
|
if(typeof e107Widgets['DialogManagerDefault'] == 'undefined')
|
|
e107Widgets.DialogManagerDefault = new e107Widgets.DialogManager();
|
|
});
|
|
|