/** * WJAeroplane is the main Aeroplane Javascript, this should be used to access Aeroplane functions * * @since Fri Jul 04 2008 * @author Ron Rademaker **/ var WJAeroplane = Class.create({ /** * initialize * * Creates a new WJAeroplane * * @since Fri Jul 04 2008 * @access public * @return WJAeroplane **/ initialize: function() { this.menu = null; this.contextmenu = null; this.spinErrorHandlers = {}; this.windowmanager = new WJWindowManager(); if (window.WJProgressNotifier) { this.progressnotifier = new WJProgressNotifier(); } this.unloadmanager = new WJUnloadManager(this.allowUnload.bind(this) ); this.topbarId = "aeroplane_topbar"; this.contentId = "aeroplane_main"; this.contentClass = "aeroplane_sitemaincontent"; this.contentBlockContainers = {}; this.dbtables = {}; this.layers = []; this.translateGui = WJAeroplane.translate.bind(this); new WJImageloader(); }, /** * aeroplaneSpinError * * Fallback function to handle unhandled spin (ajax) errors * * @since Wed Jan 07 2009 * @access public * @param response response * @return void **/ aeroplaneSpinError: function(response, lastSpin) { for (code in this.spinErrorHandlers) { if (code == response.status && typeof(this.spinErrorHandlers[code])=="function") { this.spinErrorHandlers[code](response, lastSpin); return; } } if (document.location.pathname == "/aeroplaneapplication") { var reload = function() { this.unloadmanager.suspend(); document.location.reload(); }.bind(this); WJWindow.alert("Er heeft zich een fout voorgedaan, Windmill CMS zal automatisch worden herladen. Neem contact op met Connectholland wanneer dit probleem zich blijft voordoen.", reload, aeroplane.translateGui); } }, /** * selectLanguage * * Sets Aeroplane to the given language * * @since Fri May 15 2009 * @access public * @param string language * @return void **/ selectLanguage: function(language, force) { var force = !!force; if (this.allowUnload() || force) { this.unloadmanager.suspend(true); var href = document.location.href.replace(document.location.hash, "").replace(/#$/, ""); if (href.match(/uilanguage=/) ) { href = href.replace(/(uilanguage=)[^&]*/, "$1" + language); } else if (href.match(/\?/) ) { href = href + "&uilanguage=" + language; } else { href = href + "?uilanguage=" + language; } document.location.href = href; } else { WJWindow.booleanConfirm("Mogelijk zijn er nog niet opgeslagen gegevens."+ "\n" + "Wanneer de taalinstelling gewijzigd wordt zullen alle applicaties gesloten worden."+ "\n\n" + "Weet je zeker dat je de taalinstelling wilt wijzigen?", this.selectLanguage.bind(this, language, true), aeroplane.translateGui); } }, /** * registerSpinErrorHandler * * Registers a callback to the error status * * @since Thu Feb 12 2009 * @access public * @param integer code * @param Function callback * @return void **/ registerSpinErrorHandler: function(code, callback) { this.spinErrorHandlers[code] = callback; }, /** * addMainMenuItem * * Adds an item to the main menu, these are used only to access the submenu's * * @since Fri Jul 04 2008 * @access public * @param string id * @param WJMenu menu **/ addMainMenuItem: function(id, menu) { if (this.menu == null) { this.menu = new WJMenu("main", -1); } this.menu.addItem(id, menu); }, /** * addMenuItem * * Adds a menu item to a main menu item, these contain the actual actions * * @since Fri Jul 04 2008 * @access public * @param string mainid * @param string id * @param WJMenu menu **/ addMenuItem: function(mainid, id, menu) { this.menu.getItem(mainid).addItem(id, menu); }, /** * openApplication * * Creates an application interface and lets the window manager run the application * * @since Fri Jul 04 2008 * @access public * @param string application * @param mixed applicationargs (not in declaration) * @return WJApplicationInterface **/ openApplication: function(application) { var applicationInterface = window["WJ" + application + "Interface"].construct(arguments); this.windowmanager.startApplication(applicationInterface); if (applicationInterface.showProgress() ) { this.progressnotifier.show(applicationInterface, "Applicatie wordt opgestart"); } return applicationInterface; }, /** * closeMotd * * Closes the current motd and makes sure it won't be back * * @since Tue Sep 22 2009 * @access public * @return void **/ closeMotd: function() { if ($("motd") ) { $("motd").hide(); var spin = new WJSpin(); spin.update(new WJUrl({"ct": "wmdynamic", "module": "Wmcb"}), "Wmcb", "readMotd", {}, []); } }, /** * createTopBar * * Creates the html elements for the topbar * Uses dom manipulation to keep references made by other scripts intact * * @since Mon Jul 07 2008 * @access public * @return void **/ createTopBar: function() { var bodyChildren = Element.extend(document.body).childElements(); var topbarDiv = document.body.appendChild(new Element("div", {id: this.topbarId} ) ); var mainDiv = document.body.appendChild(new Element("div", {"class": this.contentClass, id: this.contentId} ) ); for (i=0; i < bodyChildren.length; i++) { if (bodyChildren[i].tagName != "script") { mainDiv.appendChild(bodyChildren[i] ); } } }, /** * printPage * * Interface to native window print because 'Nightmare from Redmond 7' can't bind natives * * @since Fri Feb 27 2009 * @access public * @return void **/ printPage: function() { window.print(); }, /** * showTopBar * * Fills the topbar element from the temporary topbar and shows it * * @since Mon Jul 07 2008 * @access public * @param string temporaryid * @return void **/ showTopBar: function(temporaryid) { // remove empty menus $(temporaryid).select(".aeroplane_mainmenu").each(function(s) { if ( (s.select("li").length == 0) && (!s.hasClassName("aeroplane_mainmenu_singleclick") ) ) { s.remove(); } }); // prevent a scrollbars on the page when in CMS mode, if needed it should be in the div document.body.setStyle({"overflow": "hidden"}); Element.extend(document.documentElement).setStyle({"overflow": "hidden"}); var tempTop = $(temporaryid); var topbar = $(this.topbarId); topbar.innerHTML = tempTop.innerHTML; topbar.className = tempTop.className; tempTop.remove(); var fixMainDivHeight = function(mainDiv, topbar) { $(mainDiv).setStyle({"height": ($(document).viewport.getHeight() - $(topbar).getHeight() ) + "px"}); }.bind(window, this.getContentElement(), this.getTopbar() ); Event.observe(window, "resize", fixMainDivHeight); fixMainDivHeight(); }, /** * getContentElement * * Gets the main content element * * @since Mon Jul 07 2008 * @access public * @return DOMElement **/ getContentElement: function() { return document.getElementById(this.contentId); }, /** * getTopbar * * Gets the topbar element * * @since Mon Jul 07 2008 * @access public * @return DOMElement **/ getTopbar: function() { return document.getElementById(this.topbarId); }, /** * registerContentBlock * * Registers a content block on the page * * @since Mon Aug 04 2008 * @access public * @param string id * @param string identifier * @param string module * @param string basemodule * @param object properties * @return void **/ registerContentBlock: function(id, cbcid, identifier, module, basemodule, properties) { var properties = properties || {}; var cblock = new WJContentBlock(id, module, properties); cblock.setIdentifier(identifier); this.contentBlockContainers[cbcid].registerContentBlock(cblock); }, /** * registerDBTable * * Registers a dbtable record (with contentblocks) on the page * * @since Tue Mar 31 2009 * @access public * @param string htmlid * @param string module * @param string collection * @return void **/ registerDBTable: function(htmlid, module, collection, saveAndLogout) { if (!(htmlid in this.dbtables) ) { this.dbtables[htmlid] = new WJDBTable(htmlid, module, collection, saveAndLogout); } }, /** * registerContentBlockContainer * * Registers a content block container, a cbc contains (or is able to contain) content blocks * * @since Mon Sep 22 2008 * @access public * @param string id * @param string identifier * @param string module * @param string basemodule * @param object properties * @return void **/ registerContentBlockContainer: function(id, identifier, module, basemodule, properties) { var properties = properties || {}; var cbc = new WJContentBlockContainer(id, identifier, module, properties); this.contentBlockContainers[identifier] = cbc; }, /** * editContentBlock * * Opens an editor to edit the content block in the html element with id * * @since Mon Aug 04 2008 * @access public * @param string cbcid * @param string blockid * @return void **/ editContentBlock: function(cbcid, blockid) { WJDebugger.log(WJDebugger.NOTICE, "Edit content block", cbcid, blockid); var contentBlock = this.getContentBlock(cbcid, blockid); if (contentBlock) { var application = this.openApplication(contentBlock.getApplicationName(), contentBlock.getModule(), contentBlock.getIdentifier(), contentBlock.getProperties() ); application.setCBC(this.contentBlockContainers[cbcid]); } }, /** * getCBCs * * Gets all active cbcs for module * * @since Tue Sep 23 2008 * @access public * @param string module * @return void **/ getCBCs: function(module) { var cbcs = new Array(); for (var key in this.contentBlockContainers) { if (this.contentBlockContainers[key].getModule() == module) { cbcs.push(this.contentBlockContainers[key]); } } return cbcs; }, /** * getContentBlock * * Returns the block identified by id * * @since Wed Aug 6 2008 * @access public * @param string cbcid * @param string blockid * @return WJContentBlock **/ getContentBlock: function(cbcid, blockid) { return (this.contentBlockContainers[cbcid]) ? this.contentBlockContainers[cbcid].getContentBlock(blockid) : false; }, /** * isContentBlock * * Tells if the given id identifies a contentBlock * * @since Mon Sep 8 2008 * @access public * @param string cbcid * @param string blockid * @return boolean **/ isContentBlock: function(cbcid, blockid) { return (this.contentBlockContainers[cbcid] && this.contentBlockContainers[cbcid].getContentBlock(blockid) ); }, /** * openDatabaseContentEditor * * Opens the content editor identified by cbcid * * @since Wed May 20 2009 * @access public * @param string cbcid * @return void **/ openDatabaseContentEditor: function(cbcid) { this.dbtables[cbcid].openContentEditor(); }, /** * contextMenu * * Handles the case a contextmenu fires an event * * @since Fri Aug 8 2008 * @access public * @param Event event * @param string blockid * @return void **/ contextMenu: function(cbcid, blockid, action) { if (blockid == "dbtable") { switch (action) { case "update": this.openDatabaseContentEditor(cbcid); break; case "delete": this.dbtables[cbcid].deleteRecord(); break; case "moveUp": case "moveDown": this.dbtables[cbcid].dbTableFunction(action); break; } } else { switch (action) { case "update": this.editContentBlock(cbcid, blockid); break; case "delete": this.deleteContentBlock(cbcid, blockid); break; case "online": this.setContentBlockOnline(true, cbcid, blockid); break; case "offline": this.setContentBlockOnline(false, cbcid, blockid); break; case "moveUp": case "moveDown": this.contentBlockFunction(action, cbcid, blockid); break; } } }, /** * contentBlockFunction * * Calls action on the contentblock with blockid in cbcid * * @since Mon Feb 16 2009 * @access public * @param string action * @param string cbcid * @param string blockid * @return void **/ contentBlockFunction: function(action, cbcid, blockid) { var spin = new WJSpin(); var contentBlock = this.getContentBlock(cbcid, blockid); var contentBlockContainer = this.contentBlockContainers[cbcid]; spin.update(new WJUrl({"ct": "wmdynamic", "module": "Wmcb", "collections": contentBlock.properties.collection}), "Wmcb", action, {objid: contentBlock.getIdentifier()}, [contentBlock.postActionHandler.bind(contentBlock, action), contentBlockContainer.postActionHandler.bind(contentBlockContainer, contentBlock, action)]); }, /** * deleteContentBlock * * Deletes a contentblock (used from the context menu * todo: dry this with WJContentEditorInterface's delete contentblock * * @since Fri Jan 09 2009 * @access public * @param string cbcid * @param string blockid * @return void **/ deleteContentBlock: function(cbcid, blockid) { WJWindow.booleanConfirm("Weet je zeker dat je dit contentblok wilt verwijderen?", function(cbcid, blockid, window, e, confirm) { if (!confirm) { return; } var spin = new WJSpin(); var contentBlock = this.getContentBlock(cbcid, blockid); var cbcon = this.contentBlockContainers[cbcid]; spin.update(new WJUrl({"ct": "wmdynamic", "module": "Wmcb", "collections": contentBlock.properties.collection}), "Wmcb", "delete", {objid: contentBlock.getIdentifier() }, [contentBlock.removeContextMenu.bind(contentBlock), contentBlock.getElement().remove.bind(contentBlock.getElement() ), cbcon.refreshContextMenuButtons.bind(cbcon)]); }.bind(this, cbcid, blockid), aeroplane.translateGui); }, /** * setContentBlockOnline * * Sets a contentBlock online / offline * * @since Fri Jan 09 2009 * @access public * @param boolean online * @param string cbcid * @param string blockid * @return void **/ setContentBlockOnline: function(online, cbcid, blockid) { var spin = new WJSpin(); var contentBlock = this.getContentBlock(cbcid, blockid); var func = online ? "online" : "offline"; var message = online ? "Het contentblok staat nu online": "Het contentblok staat nu offline"; var updateClassname = online ? function() { this.removeClassName("offline"); }.bind(contentBlock.getElement() ) : function() { this.addClassName("offline"); }.bind(contentBlock.getElement() ); spin.update(new WJUrl({"ct": "wmdynamic", "module": "Wmcb", "collections": contentBlock.properties.collection}), "Wmcb", func, {objid: contentBlock.getIdentifier() }, [WJWindow.notice.bind(WJWindow, message, null, aeroplane.translateGui), updateClassname]); }, /** * registerContextMenu * * Binds a listener to the contextmenu * * @since Fri Aug 8 2008 * @access public * @param string menuid * @param string cbcid * @param string blockid * @return void **/ registerContextMenu: function(menuid, cbcid, blockid) { if (!this.contextmenu) { this.contextmenu = new WJContextMenu(); } this.contextmenu.register(menuid, cbcid, blockid); }, /** * registerDBTableContextMenu * * Binds a listener to the contextmenu * * @since Tue Mar 31 2009 * @access public * @param string menuid * @param string htmlid * @param string id * @return void **/ registerDBTableContextMenu: function(menuid, htmlid, id) { if (!this.contextmenu) { this.contextmenu = new WJContextMenu(); } this.contextmenu.registerDBTable(menuid, htmlid, id); }, /** * hideAllContextMenus * * Calls the hideAll method on the contextmenu handler * * @since Fri Aug 8 2008 * @access public * @return void **/ hideAllContextMenus: function() { this.contextmenu.hideAll(); }, /** * logout * * Logs the user out * * @since Fri Jul 04 2008 * @access public * @param string logouturl * @return void **/ logout: function(logouturl) { if (logouturl == null) { document.location.href = "/?useraction=logout"; } else { document.location.href = logouturl; } }, /** * loadingCursor * * Changes the current cursor to a loader or back to normal * * @since Thu Sep 25 2008 * @access public * @param boolean loading * @param wjwindow wjwindow * @param function callback * @return void **/ loadingCursor: function(loading, wjwindow, callback) { var wjwindow = wjwindow || false; var callback = callback || false; if (wjwindow) { wjwindow.setLoading(loading, callback); } if (loading) { this.layers.push(new WJModalLayer() ); $(document.body).setStyle({"cursor": "wait"}); $$(".aeroplane_button").each(function(s) { $(s).setStyle({"cursor": "wait"}); } ); $$(".dijitTab").each(function(s) { $(s).setStyle({"cursor": "wait"}); } ); } else { this.layers.each(function(l) { l.destroy(); }); this.layers = []; $(document.body).setStyle({"cursor": "auto"}); $$(".aeroplane_button").each(function(s) { $(s).setStyle({"cursor": "default"}); } ); $$(".dijitTab").each(function(s) { $(s).setStyle({"cursor": "pointer"}); } ); } }, /** * respinMain * * Executes a spin request to replace the entire main div with the latest info from the database (use this when local ajax updates can't be used to show updated information) * * @since Wed Feb 25 2009 * @access public * @return void **/ respinMain: function(callback) { var callback = Object.isFunction(callback) ? callback : function() {}; var baseUrl = document.location.href.replace("#", ""); var url = (baseUrl.indexOf("?") == -1) ? baseUrl + "?wmtrigger[]=requestufts&wmtrigger[]=spin" : baseUrl + "&wmtrigger[]=requestufts&wmtrigger[]=spin"; url = (url.indexOf("dt=") == -1) ? url + "&dt=default" : url; var spin = new WJSpin(); if (!$("aeroplane_main") ) { aeroplane.loadingCursor(false); return; } spin.content(new WJUrl({}, url), [function(response) { if (!response.documentElement) { return; } var newcontent = response.documentElement.getElementsByTagName("body")[0]; if (document.importNode) { var stub = new Element("div"); stub.appendChild($("aeroplane_main").ownerDocument.importNode(newcontent, true) ); stub.innerHTML += ""; var newdoc = stub.firstDescendant(); var origdoc = $("aeroplane_main"); for (var i = 0; i < origdoc.childNodes.length; i++) { if ( (origdoc.childNodes[i].nodeName == newdoc.nodeName) && (origdoc.childNodes[i].className == newdoc.className) ) { $(origdoc.childNodes[i]).update(newdoc); } } } else { var origdoc = $("aeroplane_main"); for (var i = 0; i < origdoc.childNodes.length; i++) { if ( (origdoc.childNodes[i].nodeName == newcontent.nodeName) && (origdoc.childNodes[i].className == newcontent.className) ) { $(origdoc.childNodes[i]).update(newcontent); } } origdoc.innerHTML = origdoc.innerHTML; } aeroplane.loadingCursor(false); }, callback]); }, /** * allowUnload * * Does a check to tell if an unload is allowed (says it is not allowed if any application that is not readonly is open) * * @since Tue Feb 17 2009 * @access public * @return boolean **/ allowUnload: function() { var apps = this.windowmanager.getRunningApplication(); for (var i = 0; i < apps.length; i++) { if (!apps[i].readonly && (apps[i].state != "closed") ) { return false; } } return true; } }); /** * Aeroplane translations * * @since Thu Jun 18 2009 * @access public * @param string key * @return string **/ WJAeroplane._translations = {OK: "Ok", CANCEL: "Annuleren", YES: "Ja", NO: "Nee", CLOSE_WINDOW: "Venster sluiten"}; WJAeroplane.translate = function(key) { if (WJAeroplane._translations[key] ) { return WJAeroplane._translations[key]; } return key.charAt(0).toUpperCase() + key.replace("_", " ").substr(1).toLowerCase(); }; /** * WJWindowManager manages all windows (javascript WJWindows) for Aeroplane * * @since Fri Jul 04 2008 * @author Ron Rademaker **/ var WJWindowManager = Class.create({ /** * initialize * * Creates a new WJWindowManager * * @since Fri Jul 04 2008 * @access public * @return void **/ initialize: function() { this.applications = new Array(); // Currently running applications (javascript interfaces to the application) this.windows = {}; // Current windows, showing or hidden. Each window must be associated with an application this.applicationRunner.bind(this).repeat(0.25); this.applicationRun = false; this.pid = 0; // give all running applications a unique process id dojo.require("dojo.parser"); Event.observe(document, "keydown", this.observeKey.bindAsEventListener(this) ); }, /** * getByPid * * Gets a running application by pid * * @since Tue May 12 2009 * @access public * @param integer pid * @return WJApplicationInterface **/ getByPid: function(pid) { for (var i = 0; i < this.applications.length; i++) { if (this.applications[i].getPid() == pid) { return this.applications[i]; } } }, /** * observeKey * * Passes the key event to the currently open application (ie. the last application) * * @since Wed Apr 22 2009 * @access public * @param event e * @return void **/ observeKey: function(e) { if (this.applications.length > 0) { this.applications[this.applications.length - 1].handleKeyEvent(e); } }, /** * getMaxZIndex * * Gets the highest used z-index is the current dom * * @since Wed Nov 19 2008 * @access public * @return int **/ getMaxZIndex: function() { var nodes = $$("."); var lenght = nodes.lenght; var z = 0; for (var i = 0; i < lenght; i++) { z = Math.max(z, nodes[i].getStyle("z-index") ); } return z; }, /** * startApplication * * Starts an application from the application interfaces * * @since Fri Jul 04 2008 * @access public * @param WJApplicationInterface application * @return void **/ startApplication: function(application) { if ($("motd") ) { $("motd").hide(); } this.pid++; application.setPid(this.pid); var pid = application.getPid(); this.windows["application" + pid] = {}; this.applications.push(application); application.wakeUp(); }, /** * applicationRunner * * Wakes all running applications up and lets the do something (if they need to do something) * * @since Fri Jul 04 2008 * @access public * @return void **/ applicationRunner: function() { if (!this.applicationRun) { this.applicationRun = true; for (var i = 0; i < this.applications.length; i++) { this.applications[i].wakeUp(); } for (var i = 0; i < this.applications.length; i++) { if (this.applications[i].closed() ) { this.closeApplication(this.applications[i], i); } } this.applicationRun = false; } }, /** * getRunningApplication * * Returns the running applications * * @since Wed Feb 18 2009 * @access public * @return Array **/ getRunningApplication: function() { return this.applications; }, /** * cleanUpDijitWidgets * * Destroys all dijit widgets that are no longer in the dom * * @since Tue Nov 04 2008 * @access public * @return void **/ cleanUpDijitWidgets: function() { dijit.registry.forEach(function(widget) { if (!$(widget.domNode).descendantOf(widget.domNode.ownerDocument.documentElement) ) { WJDebugger.log(WJDebugger.INFO, "Destroying dijit widget", widget); widget.destroyRecursive(false); } }); }, /** * closeApplication * * Closes the main window of this application and removes the application from the applications array * * @since Wed Jul 16 2008 * @access public * @param WJApplicationInterface application * @param integer index * @return void **/ closeApplication: function(application, index) { var wjwindow = this.getMainWindow(application); wjwindow.hide(); this.applications.splice(index, 1); }, /** * destroyMainWindow * * Destroy the main window of the given application * * @since Tue Aug 19 2008 * @access public * @param WJApplicationInterface application * @return void **/ destroyMainWindow: function(application) { WJDebugger.log(WJDebugger.INFO, "Destroy main window", this); this.getMainWindow(application).destroy(); }, /** * getMainWindow * * Gets the main window for application * Creates a window if there is no window * * @since Mon Jul 07 2008 * @access public * @param WJApplicationInterface application * @return DOMElement **/ getMainWindow: function(application) { return this.getWindow(application, "main"); }, /** * applicationResponse * * Handles according to the response inside the application * * @since Tue Aug 19 2008 * @access public * @param WJApplicationInterface application * @param WJWindow wjwindow * @param Event event * @return void **/ applicationResponse: function(application, wjwindow, event) { WJDebugger.log(WJDebugger.NOTICE, "Application response", application, wjwindow, event); switch (event.eventName) { case "wjgui:save": application.save(); break; case "wjgui:close": case "wjgui:false": case "wjgui:cancel": application.close(); break; default: var eventName = event.eventName.sub("wjgui:", ""); application.handleWindowEvent(eventName); break; } }, /** * getWindow * * Gets a window of tyoe for application * Creates a window if there is no window * * @since Mon Jul 28 2008 * @access public * @param WJApplicationInterface application * @param string type * @return DOMElement **/ getWindow: function(application, type) { var pid = application.getPid(); if (this.windows["application" + pid]) { if (this.windows["application" + pid][type]) { return this.windows["application" + pid][type]; } } if (type == "main") { this.windows["application" + pid][type] = application.createMainWindow(); } else { this.windows["application" + pid][type] = application.createWindow(type); } return this.windows["application" + pid][type]; }, /** * destroyWindow * * Destroys the type window for application * * @since Wed May 27 2009 * @access public * @param WJApplicationInterface application * @param string type * @return void **/ destroyWindow: function(application, type) { var pid = application.getPid(); if (this.windows["application" + pid]) { if (this.windows["application" + pid][type]) { delete this.windows["application" + pid][type]; } } }, /** * getMainWindowWidth * * Gets the width for main windows (ie. full apps) * * @since Mon Jul 07 2008 * @access public * @return integer **/ getMainWindowWidth: function() { return (document.viewport.getWidth() - (this.getMainWindowLeft() + this.getMainWindowRight() ) ); }, /** * getMainWindowHeight * * Gets the height for main windows (ie. full apps) * * @since Mon Jul 07 2008 * @access public * @return integer **/ getMainWindowHeight: function() { return (document.viewport.getHeight() - (this.getMainWindowTop() + this.getMainWindowBottom() ) ); }, /** * getMainWindowTop * * Gets the Y position for main windows (ie. full apps) * * @since Mon Jul 07 2008 * @access public * @return integer **/ getMainWindowTop: function() { return 2; if (aeroplane.menu) { return 42; } else { return 2; } }, /** * getMainWindowBottom * * Gets the Y position for the bottom of main windows (ie. full apps) * * @since Fri Aug 08 2008 * @access public * @return integer **/ getMainWindowBottom: function() { return 2; }, /** * getMainWindowLeft * * Gets the X position for main windows (ie. full apps) * * @since Mon Jul 07 2008 * @access public * @return integer **/ getMainWindowLeft: function() { return 5; }, /** * getMainWindowRight * * Gets the X position for the right of main windows (ie. full apps) * * @since Fri Aug 08 2008 * @access public * @return integer **/ getMainWindowRight: function() { return 5; }, /** * maximize * * Maximizes the given window according to the padding set in this manager * * @since Fri Aug 8 2008 * @access public * @param WJWindow window * @return void **/ maximize: function(window) { window.maximize(this.getMainWindowTop(), this.getMainWindowRight(), this.getMainWindowBottom(), this.getMainWindowLeft() ); } }); /** * WJApplicationInterface is the base interface to applications. Manages communication with the server through WJSpin * * @since Fri Jul 04 2008 * @author Ron Rademaker **/ var WJApplicationInterface = Class.create({ /** * WJApplicationInterface keeps track of the current state of the running application. Possible states are: * starting: the application is starting up * running: the application is running fine * waiting: the application is waiting for a server response or for user input * busy: the application is running slowly * crashed: the application has crashed (of course, being able to determine this is rare) * closing: the application is closing down * closed: the application has been closed and others may forget about it **/ /** * initialize * * Creates a new WJApplicationInterface * * @since Fri Jul 04 2008 * @access public * @param string appname * @return void **/ initialize: function(appname) { this.appname = appname; this.state = "starting"; this.pid = null; this.readonly = false; this._showprogress = false; this._closeurl = null; // URL to return to when the app closes }, /** * setCloseUrl * * Sets the apps close url * * @since Fri Jan 29 2010 * @access public * @param string url * @return void **/ setCloseUrl: function(url) { this._closeurl = url; }, /** * callCMSFunction * * Calls a CMS function and then calls the cmsCallback * * @since Mon Jun 08 2009 * @access public * @param string func * @param string module * @param object data * @return void **/ callCMSFunction: function(func, module, data) { var spin = new WJSpin(); var url = new WJUrl(); url.setCt("wmdynamic"); url.addParameter("module", module); url.addParameter("type", "xml"); url.addParameter("wmtrigger[]", ["requestufts"]); spin.update(url, module, func, data, [this.cmsCallback.bind(this, func)]); aeroplane.loadingCursor(true); }, /** * cmsCallback * * Callback function called after executing cmsfunction * * @since Mon Jun 08 2009 * @access public * @param string cmsfunction * @param object response * @return void **/ cmsCallback: function(cmsfunction, response) { aeroplane.loadingCursor(false); }, /** * setReloadCallback * * Sets a reload callback, reloads the page part with the content being edited in this application * * @since Mon Aug 04 2008 * @access public * @param function callback * @return void **/ setReloadCallback: function(callback) { this.reloadCallback = callback; }, /** * buildGui * * Creates a WJGui for this application * * @since Tue Jul 15 2008 * @access public * @return WJGui **/ buildGui: function() { return new WJGui(this); // easy to extend to e.g. WJEditorGui }, /** * closed * * Returns true if this application is closed * * @since Mon Jul 07 2008 * @access public * @return boolean **/ closed: function() { return (this.state == "closed"); }, /** * wakeUp * * Gives the application the chance to do whatever it is they want to do * * @since Mon Jul 07 2008 * @access public * @return void **/ wakeUp: function() { WJDebugger.log(WJDebugger.DEBUG, "Application wakeup", this, this.state); switch (this.state) { case "starting": this.startApplication(); break; case "running": this.pingApplication(); break; case "waiting": this.testTimeout(); break; case "busy": this.handleBusy(); break; case "crashed": this.reportCrash(); break; case "closing": WJDebugger.log(WJDebugger.DEBUG, "Go cleanup application", this); this.cleanUp(); break; case "closed": break; } }, /** * setPid * * Sets a PID for this application * * @since Mon Jul 07 2008 * @access public * @param integer pid * @return void **/ setPid: function(pid) { this.pid = pid; }, /** * getPid * * Gets the PID for this application * * @since Mon Jul 07 2008 * @access public * @return integer **/ getPid: function() { return this.pid; }, /** * createMainWindow * * Creates the main WJWindow for this application * * @since Mon Jul 07 2008 * @access public * @return WJWindow **/ createMainWindow: function() { var window = new WJWindow(aeroplane.windowmanager.applicationResponse.bind(aeroplane.windowmanager, this), aeroplane.getTopbar(), aeroplane.translateGui); window.getWindowElement().addClassName("aeroplane_window_applicationwindow").addClassName("aeroplane_window_applicationwindow_" + this.appname.toLowerCase() ).addClassName("aeroplane_reset"); window.setTitle(this.getWindowTitle() ); aeroplane.windowmanager.maximize(window); window.hide(); return window; }, /** * getWindowTitle * * Tells what title to put on the window * * @since Mon Sep 22 2008 * @access public * @return string **/ getWindowTitle: function() { return ""; }, /** * closeMainWindow * * Callback for closing the main window (ie. sets the state to closing) * * @since Mon Jul 07 2008 * @access public * @return void **/ close: function() { WJDebugger.log(WJDebugger.NOTICE, "Requesting application close", this); // allow a last processing of normal operations this.wakeUp(); // make sure the app will close down on next wakeup this.state = "closing"; }, /** * startApplication * * Starts this application, should end up with a state different from starting * * @since Mon Jul 07 2008 * @access public * @return void **/ startApplication: function() { if (this.pid == null) { throw "Trying to start an application without a pid"; } this.currentComponent = aeroplane.windowmanager.getMainWindow(this).getContentElement("main"); this.gui = this.buildGui(); this.gui.show(aeroplane.windowmanager.getMainWindow(this), this.currentComponent, new WJSpin(), this.contentUpdated.bind(this) ); }, /** * createWindow * * Creates a helper window for type * * @since Mon Jul 28 2008 * @access public * @param string type * @return WJWindow **/ createWindow: function(type) { var wjwindow = new WJWindow(null, aeroplane.getTopbar(), aeroplane.translateGui); wjwindow.setWidth(aeroplane.windowmanager.getMainWindowWidth() ); wjwindow.setHeight(aeroplane.windowmanager.getMainWindowHeight() ); wjwindow.setX(aeroplane.windowmanager.getMainWindowLeft() ); wjwindow.setY(aeroplane.windowmanager.getMainWindowTop() ); return wjwindow; }, /** * contentUpdated * * Callback to notify the editor interface that the content has been updated * * @since Mon Jul 07 2008 * @access public * @return void **/ contentUpdated: function() { WJDebugger.log(WJDebugger.INFO, "Content updated", this); this.state = "running"; var loaderWnd = aeroplane.windowmanager.getWindow(this, "Loader"); loaderWnd.destroy.bind(loaderWnd).delay(2.1); // should be ready in 2 sec so 2.1 is 0.1 sec. safe aeroplane.windowmanager.getMainWindow(this).evalContentElement("main"); if (this.showProgress() ) { aeroplane.progressnotifier.hide(this, "Applicatie wordt opgestart"); aeroplane.progressnotifier.hide(this, "De inhoud van de applicatie is aan het laden"); } }, /** * pingApplication * * Gives this application the chance to do /something/, should end up with a state different from starting * * @since Mon Jul 07 2008 * @access public * @return void **/ pingApplication: function() { }, /** * testTimeout * * The application is currently waiting for something, this function gives the possibility to detect a timeout and deal with it * * @since Mon Jul 07 2008 * @access public * @return void **/ testTimeout: function() { }, /** * handleBusy * * The application is currently not keeping up, this function can be used to close non essential stuff and get the application out of the busy state * * @since Mon Jul 07 2008 * @access public * @return void **/ handleBusy: function() { }, /** * reportCrash * * The application has actually told us it has crashed (:D), this function deals with the crash (ie. report it per mail to the windmill maintainer) * * @since Mon Jul 07 2008 * @access public * @return void **/ reportCrash: function() { }, /** * cleanUp * * The application wants to stop running, clean up anything open and move state to closed * * @since Mon Jul 07 2008 * @access public * @return void **/ cleanUp: function() { WJDebugger.log(WJDebugger.NOTICE, "Cleaning up application", this); aeroplane.windowmanager.destroyMainWindow(this); aeroplane.loadingCursor(false); this.state = "closed"; if (this._closeurl) { document.location.href = this._closeurl; } }, /** * handleKeyEvent * * Function stub to overwrite to implement key events * * @since Wed Apr 22 2009 * @access public * @param event e * @return void **/ handleKeyEvent: function(e) { }, /** * handleWindowEvent * * Get's called by the windowmanager if an event occured in the window that has no default call to the application * * @since Thu Aug 21 2008 * @access public * @param string eventName * @return void **/ handleWindowEvent: function(eventName) { }, /** * showProgress * * * * @since Mon Apr 27 2009 * @access public * @return boolean **/ showProgress: function() { return this._showprogress; }, /** * getApplicationState * * Reads the current app state from the location hash * * @since Wed Mar 17 2010 * @access public * @return object **/ getApplicationState: function() { var state = {}; document.location.hash.replace(/#/, "").split("&").invoke("split", "=").each(function(s) { this[s[0] ] = s[1]; }.bind(state) ); return state; }, /** * toString * * Gives a string representation of this application * * @since Wed Apr 22 2009 * @access public * @return string **/ toString: function() { if (this.appname === null) { return "Uninitialized WJApplicationInterface"; } return this.appname + " instance '" + this.pid + "'"; } }); /** * Base GUI class (fallback / defaults for everything not configured / overwritten) * * @since Tue Jul 15 2008 * @author Ron Rademaker **/ var WJGui = Class.create({ /** * __construct * * Creates a new WJGui * * @since Tue Jul 15 2008 * @access public * @return WJGui **/ initialize: function(application) { WJDebugger.log(WJDebugger.INFO, "create gui"); this.application = application; this.loadingCallback = false; this.componentCache = {}; // quick access object for all components, speeds stuff up WJDebugger.log(WJDebugger.INFO, "finished creating gui", this); }, /** * getComponentForField * * Gets the WJComponent in this gui for a field with the name name * * @since Tue Aug 05 2008 * @access public * @param string name * @param object component * @return WJComponent **/ getComponentForField: function(name, component) { return this.componentCache[name]; }, /** * show * * Loads this GUI into wnd * * @since Tue Jul 15 2008 * @access public * @param WJWindow wjwindow * @param DomNode elem * @param WJSpin spin * @param function finished * @param WJUrl url - optional * @return void **/ show: function(wjwindow, elem, spin, finished, url) { if (!url) { var url = this._getUrl(); } this.addButtons(wjwindow); wjwindow.show(); this.updateContent(wjwindow, elem, spin, finished, url); this.application.state = "waiting"; }, /** * updateContent * * Updates the content of elem and calls gui parsing functions * * @since Tue May 12 2009 * @access public * @param wjwindow wjwindow * @param DomNode elem * @param WJSpin spin * @param function finished * @param WJUrl url **/ updateContent: function(wjwindow, elem, spin, finished, url) { this.preCleanUp(elem); if (dijit.byNode(elem) ) { this._updateContentTab(wjwindow, dijit.byNode(elem), spin, finished, url); } else { this.parseDojo = true; spin.content(url, [elem, finished, this.parseGUI.bind(this, elem, wjwindow) ]); } }, /** * updateContentCMS * * Update content function that includes a CMS call * * @since Thu Sep 03 2009 * @access public * @param wjwindow wjwindow * @param DomNode elem * @param WJSpin spin * @param function finished * @param WJUrl url * @param string module * @param string function * @param object data **/ updateContentCMS: function(wjwindow, elem, spin, finished, url, module, func, data) { var parameters = {}; Object.extend(parameters, url.getParameters() || { }); var _url = new WJUrl(parameters, url.getUrl() ); _url.addParameter("__cms_" + module, "true"); _url.addParameter("__function_" + module, func); for (var key in data) { _url.addParameter(key, data[key]); } this.updateContent(wjwindow, elem, spin, finished, _url); }, /** * _updateContentTab * * Updates the content of a dijit tab by setting its href attribute * * @since Wed Sep 02 2009 * @access public * @param wjwindow wjwindow * @param DijitTab elem * @param WJSpin spin * @param function finished * @param WJUrl url * @return void **/ _updateContentTab: function(wjwindow, tab, spin, finished, url) { var href = url.getUrl() + "?" + Object.toQueryString(url.getParameters() ); if (tab.attr("href") != href) { this.parseDojo = false; tab.attr("onDownloadEnd", function(elem, wjwindow, finished) { this.parseGUI(elem, wjwindow); finished(); }.bind(this, tab.domNode, wjwindow, finished) ); tab.attr("href", href); aeroplane.windowmanager.cleanUpDijitWidgets(); } else { aeroplane.loadingCursor(false, wjwindow, this.loadingCallback); } }, /** * _getUrl * * Gets the WJUrl to get the GUI * * @since Tue May 12 2009 * @access protected * @return WJUrl **/ _getUrl: function() { var url = new WJUrl({}, "/index.php"); url.setCt("wmdynamic"); url.setDt(this.getDt() ); url.addParameter("mode", "datacollector"); url.addParameter("state", this.application.state); url.addParameter("uft[]", this.getUfts() ); url.addParameter("wmtrigger[]", ["requestufts"]); url.addParameter("module", this.application.module); url.addParameter("pid", this.application.getPid() ); return url; }, /** * preCleanUp * * Cleans up the gui before spinning for content * * @since Tue Dec 16 2008 * @access public * @param DomNode elem * @return void **/ preCleanUp: function(elem) { var tinyMCELoaded = (typeof(tinyMCE) != "undefined") ? true : false; if (tinyMCELoaded) { $H(tinyMCE.editors).keys().each(function(id) { if (!$(id) || $(id).descendantOf(this) ) { WJDebugger.log(WJDebugger.NOTICE, "Removing tinyMCE editor: ", id); tinymce.EditorManager.execCommand("mceRemoveControl", false, id) } }.bind(elem) ); } }, /** * parseGUI * * Parses the GUI * * @since Wed Sep 3 2008 * @access public * @param Element context * @return void **/ parseGUI: function(context, wjwindow) { WJDebugger.log(WJDebugger.DEBUG, "Parse GUI", context, wjwindow); if (dojo && dojo.parser) { WJDebugger.log(WJDebugger.DEBUG, "Ready to parse GUI"); this._parseGUI(context, wjwindow); this.application.state = "running"; } else { arguments.callee.bind(this, context, wjwindow).delay(0.5); // try it later, because the content is not ready yet } }, /** * _parseGui * * Parses and handles the GUI * * @since Fri Sep 12 2008 * @access protected * @param Element context * @return array **/ _parseGUI: function(context, wjwindow) { WJDebugger.log(WJDebugger.INFO, "Dojo parsing new Gui", context, wjwindow); try { if (this.parseDojo) { aeroplane.windowmanager.cleanUpDijitWidgets(); var widgets = dojo.parser.parse(context); } else { context.innerHTML.evalScripts(); } } catch (e) { WJDebugger.log(WJDebugger.ERROR, "Dojo parsing new Gui failed", e); WJWindow.alert("De grafische gebruikersinterface kon niet correct worden opgebouwd."+ "\n" + "Neem contact op met Connectholland."+ "\n" + "De applicatie zal worden gesloten.", this.application.close.bind(this.application), aeroplane.translateGui); } this._handleGUILoad(context, wjwindow); return widgets; }, /** * handleGUILoad * * Does actions after the gui is loaded and parsed * * @since Thu Sep 4 2008 * @access protected * @param Element context * @param WJWindow wjwindow * @return void **/ _handleGUILoad: function(context, wjwindow) { this.focusElement(context); aeroplane.loadingCursor(false, wjwindow, this.loadingCallback); }, /** * focusElement * * Gives the possibility to focus a preferred element (as default tries to find a first element) * * @since Wed Sep 3 2008 * @access public * @param context * @return void **/ focusElement: function(context) { if (!context) { return; } var element = context.select("input:not([type=hidden])").first(); if (Object.isElement(element) ) { try { (function() { element.focus(); element.focus(); // doing it twice helps IE8 }).defer(); } catch (err) { // ie gets here... don't crash } } }, /** * getDt * * Returns the dt for gui-building - makes it possible to use another dt in a subclass * * @since Fri Aug 22 2008 * @access public * @return string **/ getDt: function() { return "gui"; }, /** * getUfts * * Returns the ufts for gui-building - makes it possible to use other uft's in a subclass * * @since Fri Aug 22 2008 * @access public * @return Array **/ getUfts: function() { return ["components"]; }, /** * addButtons * * Gives the possibility to add buttons to the window * * @since Thu Aug 14 2008 * @access public * @param WJWindow window * @return void **/ addButtons: function(window) { // here for extending purposes only }, /** * getComponentId * * Gets the html id of a component with id id (actual id depends on pid to avoid double ids) * * @since Tue Dec 30 2008 * @access public * @param string id * @return string **/ getComponentId: function(id) { if ($(id + "_" + this.application.pid) ) { return id + "_" + this.application.pid; } else { return id; } }, /** * setComponents * * Sets the WJ Components and couples them to input elements (if any) * * @since Tue May 12 2009 * @access public * @param array components * @return void **/ setComponents: function(components) { this.components = components; this._coupleComponents(this.components); }, /** * getData * * Retrieves an object with all key - value pairs for this gui's components * * @since Wed Feb 17 2010 * @access public * @param string prefix * @param object components * @return object **/ getData: function(prefix, data, component, noIdForGroups) { var prefix = prefix || ""; var component = component || this.components; var data = data || {}; var noIdForGroups = !!noIdForGroups; for (var cmp in component) { if (cmp == "id") { var value = component.getValue(); if (component.componentType == "WJExtendibleGroup") { for (var key in value) { propname = key; if (propname.match(/([^\[]*)(\[.*)/) ) { propname = propname.replace(/([^\[]*)(\[.*)/, "[$1]$2"); } else { propname = "_" + propname; } data[prefix + component[cmp] + propname] = value[key]; } return data; } else if (Object.isArray(value) ) { var length = value.length; if (length === 0) { data[prefix + component[cmp] + "[]" ] = ""; } else { for (var i = 0; i < length; i++) { data[prefix + component[cmp] + "[" + i + "]" ] = value[i]; } } } else if (typeof(value) == "object") { for (var key in value) { data[prefix + component[cmp] + "[" + key + "]" ] = value[key]; } } else { data[prefix + component[cmp] ] = component.getValue(); } } if (cmp == "component") { data = this.getData(prefix, data, component[cmp], noIdForGroups); } if (cmp == "components" && component.componentType != "WJExtendibleGroup") { if (component[cmp].each) { $A(component[cmp]).each(function(comp) { if (component["id"] && !noIdForGroups) { var id = component["id"].replace(/\[.*$/, ""); data = this.getData(prefix + id + "_", data, comp, noIdForGroups); } else { data = this.getData(prefix, data, comp, noIdForGroups); } }.bind(this) ); } } } return data; }, /** * _coupleComponents * * Couples the javascript components with HTML form elements (the visual representations of the components) * By now there should be input elements for all components * * @since Mon Jul 21 2008 * @access protected * @param object component * @return void **/ _coupleComponents: function(component) { WJDebugger.log(WJDebugger.INFO, "coupling", component); for (var cmp in component) { if (cmp == "id") { this.componentCache[component[cmp] ] = component; if ($(this.getComponentId(component[cmp]) ) ) { component.setHtmlelement($(this.getComponentId(component[cmp]) ), this); } else { var possibles = document.getElementsByName(component[cmp]); $A(possibles).each(component.setHtmlelement.bind(component) ); } } if (cmp == "component") { this._coupleComponents(component[cmp]); } if (cmp == "components") { if (component[cmp].each) { $A(component[cmp]).each(this._coupleComponents.bind(this) ); } } } }, /** * toString * * Gives a string representation of this gui * * @since Wed Apr 22 2009 * @access public * @return string **/ toString: function() { if (this.application === null) { return "Uninitialized WJGui"; } return "WJGui for \"" + this.application + "\""; } }); /** * WJLoginInterface is the interface to the user module for the login process. * * @since Tue Aug 12 2008 * @author Giso Stallenberg **/ WJLoginInterface = Class.create(WJApplicationInterface, { /** * initialize * * Initializes a WJLoginInterface * * @since Tue Aug 12 2008 * @access public * @param string appname * @return WJLoginInterface **/ initialize: function($super, appname, module, loggedIn, uiLanguage) { $super(appname); this.module = module; this.readonly = true; this.loggedIn = loggedIn; this.uiLanguage = uiLanguage || "nl_NL"; this.state = "background"; this.spinQueue = []; aeroplane.registerSpinErrorHandler(403, this.handleAccessDenied.bind(this) ); }, /** * handleKeyEvent * * Listens for CTRL+L to open its gui * * @since Wed Apr 22 2009 * @access public * @param event e * @return void **/ handleKeyEvent: function($super, e) { $super(e); if (!this.loggedIn) { if ( (this.state == "background") && (e.keyCode == 76) ) { // L if (e.ctrlKey && !e.shiftKey) { Event.stop(e); // Somehow Event.stop(event) doesn't work full in FF if (e.preventDefault) { e.preventDefault(); } this.state = "starting"; } } } }, /** * cleanUp * * Starts a new Login app after closing this one * * @since Wed May 13 2009 * @access public * @return void **/ cleanUp: function($super) { $super(); aeroplane.openApplication("Login", this.module, this.loggedIn, this.uiLanguage); }, /** * handleAccessDenied * * Hanles an AD spin response * * @since Thu Feb 12 2009 * @access * @param * @return **/ handleAccessDenied: function(response, spinCall) { if (typeof(spinCall) == "function") { this.spinQueue.push(spinCall); } this.state = "starting"; this.setLoginCorrectHandler(this.invokeSpinQueue.bind(this) ); }, /** * invokeSpinQueue * * Invokes all stacked spins * * @since Thu Feb 12 2009 * @access public * @return void **/ invokeSpinQueue: function(response) { if (typeof(this.spinQueue[0] ) == "function") { this.spinQueue[0](); delete this.spinQueue[0]; this.invokeSpinQueue(response); } }, /** * buildGui * * Creates a WJLoginGui for the app * * @since Tue Aug 12 2008 * @access public * @return WJLoginGui **/ buildGui: function() { return new WJLoginGui(this); }, /** * closeMainWindow * * * * @since Thu Aug 14 2008 * @access * @param * @return **/ handleWindowEvent: function(eventName) { if (eventName == "true") { this.login(); } else { aeroplane.windowmanager.getMainWindow(this).hide(); } }, /** * login * * Attempts a login at windmill CMS * * @since Mon Aug 11 2008 * @access public * @return void **/ login: function() { var wjwindow = aeroplane.windowmanager.getMainWindow(this); aeroplane.loadingCursor(true); var spin = new WJSpin(); var url = new WJUrl({}, "/index.php"); url.setCt("wmdynamic"); url.addParameter("application", this.appname); url.addParameter("module", this.module); var loginData = this.gui.getData(); url.addParameter("username", loginData.loginfields_username); url.addParameter("password", loginData.loginfields_password); spin.content(url, [this.loginCorrect.bind(this)], {"401": this.loginIncorrect.bind(this), "403": this.accessDenied.bind(this) }); }, /** * loginCorrect * * Handles the case a login was succesful * * @since Wed Aug 13 2008 * @access public * @param XMLHTTPRequest response * @return void **/ loginCorrect: function(response) { if (typeof(this.loginCorrectHandler) == "function") { this.loginCorrectHandler(response); aeroplane.windowmanager.destroyMainWindow(this); } else { if (response.loginforward) { this._forward(response.loginforward); } else if (response.xmlVersion && response.getElementsByTagName(this.module.toLowerCase() )[0] && response.getElementsByTagName(this.module.toLowerCase() )[0].getElementsByTagName("loginforward")[0] && (response.getElementsByTagName(this.module.toLowerCase() )[0].getElementsByTagName("loginforward")[0].textContent || response.getElementsByTagName(this.module.toLowerCase() )[0].getElementsByTagName("loginforward")[0].innerHTML) ) { if (response.getElementsByTagName(this.module.toLowerCase() )[0].getElementsByTagName("loginforward")[0].textContent) { var url = response.getElementsByTagName(this.module.toLowerCase() )[0].getElementsByTagName("loginforward")[0].textContent; } else { var url = response.getElementsByTagName(this.module.toLowerCase() )[0].getElementsByTagName("loginforward")[0].innerHTML; } this._forward(url); } else { this._reload(); } } }, /** * setLoginCorrectHandler * * Sets the handler to use for a correct login * * @since Thu Feb 12 2009 * @access public * @param Function callback * @return void **/ setLoginCorrectHandler: function(callback) { this.loginCorrectHandler = callback; }, /** * _forward * * Forwards to the given url * * @since Thu Aug 14 2008 * @access protected * @param string url * @return void **/ _forward: function(url) { document.location.href = url; }, /** * _reload * * Reloads the document (but makes sure there's no useraction=logout, otherwise uses _forward to the stripped url) * * @since Thu Aug 14 2008 * @access protected * @return void **/ _reload: function() { var loc = document.location; if (loc.href.indexOf("useraction=logout") != -1) { var url = loc.href.replace("useraction=logout&", ""); url = url.replace("useraction=logout", ""); if (url.endsWith("?") ) { url = url.replace("?", ""); } this._forward(url); } else { document.location.reload(); } }, /** * loginIncorrect * * Handles the case a login was incorrect * * @since Wed Aug 13 2008 * @access public * @param XMLHTTPRequest response * @return void **/ loginIncorrect: function(response) { aeroplane.loadingCursor(false); WJWindow.alert("De door u opgegeven gebruikersnaam/wachtwoord combinatie is onbekend", this.showWindow.bind(this), aeroplane.translateGui); }, /** * showWindow * * Shows the window * * @since Thu Aug 14 2008 * @access public * @return void **/ showWindow: function() { var win = aeroplane.windowmanager.getMainWindow(this); win.show(); }, /** * accessDenied * * Handles the case a login was not ok for aeroplane * * @since Wed Aug 13 2008 * @access public * @param XMLHTTPRequest response * @return void **/ accessDenied: function(response) { var win = aeroplane.windowmanager.getMainWindow(this); aeroplane.loadingCursor(false); WJWindow.alert("U heeft geen toegang tot dit deel van het systeem, maar bent wel succesvol aangemeld.", this._reload.bind(this), aeroplane.translateGui); } }); /** * GUI class for the paragraph editor * * @since Wed Aug 13 2008 * @author Giso Stallenberg **/ var WJLoginGui = Class.create(WJGui, { /** * show * * Loads this GUI into wnd * * @since Tue Jul 15 2008 * @access public * @param WJWindow wnd * @param WJSpin spin * @param function finished * @return void **/ show: function($super, wjwindow, spin, finished) { $super(wjwindow, spin, finished); wjwindow.getWindowElement().addClassName("aeroplane_reset"); wjwindow.insertWindowRowBefore("main", "intro"); wjwindow.setWidth(400); wjwindow.setHeight(510, wjwindow.getContentElement("main"), false); wjwindow.setZ(1000); wjwindow.center(); wjwindow.keepCentered(); }, /** * addButtons * * Adds buttons to the window * * @since Thu Aug 14 2008 * @access public * @param WJWindow window * @return void **/ addButtons: function(wjwindow) { wjwindow.addButton("Aanmelden", "true", true); }, /** * _parseGui * * Parses and handles the GUI * * @since Wed Feb 18 2009 * @access protected * @param Element context * @return array **/ _parseGUI: function($super, context, wjwindow) { var widgets = $super(context, wjwindow); wjwindow.getContentElement("intro").appendChild(wjwindow.getContentElement("main").down(".aeroplane_wjhtml") ); return widgets; }, /** * _handleGUILoad * * Scrolls the window into view if it's not * * @since Mon Mar 15 2010 * @access protected * @param Element context * @param WJWindow wjwindow * @return void **/ _handleGUILoad: function($super, context, wjwindow) { if (document.viewport.getScrollOffsets().top > wjwindow.getY() ) { wjwindow.getWindowElement().scrollTo(); } return $super(context, wjwindow); }, /** * getDt * * Returns the dt for login application gui-building. Specific dt to disable content panes * * @since Tue Feb 02 2010 * @access public * @return string **/ getDt: function() { return "logingui"; }, /** * _getUrl * * Gets the WJUrl to get the GUI * * @since Tue May 12 2009 * @access protected * @return WJUrl **/ _getUrl: function($super) { var url = $super(); url.addParameter("uilanguage", this.application.uiLanguage); return url; } }); /** * WJUnloadManager makes sure no data get lost when an unload takes place * * @since Tue Feb 17 2009 * @revision $Revision$ * @author Giso Stallenberg * @package Windmill.Aeroplane.Javascript **/ var WJUnloadManager = Class.create({ /** * initialize * * Creates a new WJUnloadManager * * @since Tue Feb 17 2009 * @access public * @return WJUnloadManager **/ initialize: function(checker) { this._checker = checker || function() {return false;}; this.suspend(false); this._asking = false; Event.observe(window, "keydown", this.handleKeyUnload.bindAsEventListener(this) ); Event.observe(window, "beforeunload", this.handleUnload.bindAsEventListener(this) ); }, /** * handleUnload * * Handles the case where no keys were detected, but the page is about to unload * * @since Tue Feb 17 2009 * @access public * @param Event event * @return void **/ handleUnload: function(event) { if (!this._checker() && !this.isSuspended() ) { event.returnValue = this._getMessage(true); } }, /** * handleKeyUnload * * Handles the case where a user might unload the page because of a key (combination) * * @since Tue Feb 17 2009 * @access public * @param Event event * @return void **/ handleKeyUnload: function(event) { var modKs = (event.altKey ? 1 : 0) + (event.shiftKey ? 2 : 0) + (event.ctrlKey ? 4 : 0); var key = event.keyCode; if (!this._checker() && !this.isSuspended() ) { if ((modKs==4 || modKs==6) && key == 82) { // CTRL+R this._showMessage(this.doReload.bind(this) ); } if (modKs==1 && (key == Event.KEY_LEFT || key == Event.KEY_RIGHT) ) { // ALT + (LEFT|RIGHT) this._showMessage(this.doHistory.bind(this, ( (key == Event.KEY_LEFT) ? -1 : +1) ) ); } if ((modKs==0 || modKs==4) && key == 116) { // (CTRL+)F5 this._showMessage(this.doReload.bind(this) ); } /** * Other options might be * - CTRL+F4 * - ALT+F4 * - CTRL+W * - CTRL+SHIFT+W * * But it needs to be possible to reproduce them through script. For now they're handled by handleUnload **/ } if (this._asking) { return this._stop(event); } }, /** * _stop * * Stops the event * * @since Tue Feb 17 2009 * @access protected * @param Event event * @return boolean **/ _stop: function(event) { if (event.stopPropagation) { event.stopPropagation(); } event.stop(); event.returnValue = false; return false; }, /** * doReload * * Performs the actual reload (as requested by the user) * * @since Tue Feb 17 2009 * @access public * @param WJWindow wjwindow * @param Event event * @param boolean doReload * @return void **/ doReload: function(wjwindow, event, doReload) { if (doReload) { this.suspend(); document.location.reload(); } else { this._asking = false; } }, /** * doHistory * * Performs the actual history change (as requested by the user) * * @since Tue Feb 17 2009 * @access public * @param WJWindow wjwindow * @param Event event * @param integer direction * @param boolean doHistory * @return void **/ doHistory: function(direction, wjwindow, event, doHistory) { if (doHistory) { this.suspend(); window.history.go(direction); } else { this._asking = false; } }, /** * suspend * * Makes this class skip the observers * * @since Mon Feb 23 2009 * @access public * @param boolean doSuspend * @return void **/ suspend: function(doSuspend) { var doSuspend = (doSuspend != false); this._suspended = doSuspend; }, /** * isSuspended * * Tells if this class is suspended * * @since Mon Feb 23 2009 * @access public * @return boolean **/ isSuspended: function() { return this._suspended; }, /** * _showMessage * * Shows the message * * @since Tue Feb 17 2009 * @access protected * @param Function callback * @return void **/ _showMessage: function(callback) { if (!this._asking) { WJWindow.booleanConfirm(this._getMessage(false, true), callback, aeroplane.translateGui); this._asking = true; } }, /** * getMessage * * Returns the message to show to the user * * @since Tue Feb 17 2009 * @access protected * @param boolean useBrowserLang * @return string **/ _getMessage: function(useBrowserLang, full) { var useBrowserLang = (useBrowserLang === true); var full = (full === true); if (useBrowserLang) { var lang = this._getBrowserLanguage(); if (full) { return this._messages.body[lang] + "\n\n" + this._messages.question[lang]; } else { return this._messages.body[lang]; } } else { if (full) { // for now we use "might be" because this is not verified in any way return "Mogelijk zijn er nog niet opgeslagen gegevens."+ "\n\n" + "Weet je zeker dat u deze pagina wilt verlaten?"; } else { // for now we use "might be" because this is not verified in any way return "Mogelijk zijn er nog niet opgeslagen gegevens."; } return ; } }, /** * _getBrowserLanguage * * Returns the language used in this browser * * @since Tue Feb 17 2009 * @access protected * @return string **/ _getBrowserLanguage: function() { var lang = window.navigator["language"] || window.navigator["browserLanguage"]; switch (lang) { case "nl": case "nl-NL": case "nl_NL": case "nl-be": case "nl-BE": case "nl_BE": return "nl_NL"; default: return "default"; } }, /** * The various messages * * @since Tue Feb 17 2009 * @access protected * @var Object **/ _messages: { body: { // for now we use "might be" because this is not verified in any way nl_NL: "Mogelijk zijn er nog niet opgeslagen gegevens.", "default": "There might be unsaved data." }, question: { nl_NL: "Weet u zeker dat u deze pagina wilt verlaten?", "default": "Are you sure you want to navigate away?" } } });/** * WJImageloader loads any non existing image from the mediamanager * Allows creating images on a need-for-usage base, which is especially useful when using aeroplane in the cloud * Known NOT to work with Opera (tested working in IE6, IE7, IE8, FF3.5, FF3.6, Chrome) * * @since Fri Mar 19 2010 * @author Ron Rademaker **/ var WJImageloader = Class.create({ /** * initialize * * Creates a new WJImageloader and starts checking * * @since Fri Mar 19 2010 * @access public * @return WJImageloader **/ initialize: function() { this.images = $A(document.images); this.checkImages(); }, /** * checkImages * * Checks all images and loads any empty image from the mediamanager (empty means width and height are both 0) * Only attempts to load /images/thumbs images * Stops checking if all images are succesfully loaded * * @since Fri Mar 19 2010 * @access public * @return void **/ checkImages: function() { this.images.each(this._checkImage.bind(this, 10) ); // try max 10 times per image }, /** * checkImage * * Checks an individual image * * @since Fri Apr 2 2010 * @access protected * @param Image img * @return void **/ _checkImage: function(loop, img) { if (loop < 1) { return; } var done = true; if (!img.complete) { done = false; } if ( ( ("naturalHeight" in img) && (img.naturalHeight == 0) ) || ( (img.fileSize == -1) && (img.height > 0) ) ) { if (img.src.match(/\/images\/thumbs\//) && !(img.src.match(/orig_uri/) ) ) { img.src = "/index.php?ct=wmdynamic&module=Wmmediamanager&mode=thumbnail&orig_uri=" + img.src.replace(/https?:\/\/[^\/]*\//, "/"); } } if (!done) { loop = loop-1; this._checkImage.bind(this, loop, img).delay(0.5); } } }); /** * WJComponent * * Base Component class * * @since Wed Jul 16 2008 * @revision $Revision$ * @author Ron Rademaker * @package Windmill.Javascript.Component **/ var WJComponent = Class.create({ /** * Properties of WJComponent * * string id * string value * boolean disabled * boolean readonly * event focusEvent * event blurEvent * event changeEvent **/ /** * initialize * * Creates a new WJComponent * * @since * @access public * @param string id * @return **/ initialize: function(id) { this.id = id; this.value = null; this.componentType = "WJComponent"; this.components = new Array(); this.label = null; this.group = false; }, /** * setHtmlelement * * Sets the html element for this component * * @since Mon Jul 21 2008 * @access public * @param htmlelement element * @return void **/ setHtmlelement: function(element) { this.htmlelement = element; if (this.htmlelement.value) { this.value = this.htmlelement.value; } else if ($("hidden_" + this.htmlelement.id) ) { this.value = $("hidden_" + this.htmlelement.id).value; } }, /** * observe * * Adds an observer to this component's htmlelement * * @since Fri Nov 06 2009 * @access public * @param string event * @param function callback * @return void **/ observe: function(event, callback) { if (Object.isArray(this.htmlelement) ) { this.htmlelement.each(function(s) { s.observe(event, callback); }); } else if (this.htmlelement) { this.htmlelement.observe(event, callback); } }, /** * addComponent * * Adds a component to this component group * * @since Tue Aug 19 2008 * @access public * @param WJComponent comp * @return void **/ addComponent: function(comp) { WJDebugger.log(WJDebugger.DEBUG, "Adding component to " + this.componentType + " " + this.id, comp); this.components.push(comp); }, /** * getComponents * * Gets the components in this group * * @since Tue Aug 19 2008 * @access public * @return Array **/ getComponents: function() { return this.components; }, /** * valueChanged * * Returns true if the value of this component has changed * * @since Tue May 19 2009 * @access public * @return boolean **/ valueChanged: function() { var oldValue = this.value; this.getValue(); var changed = (oldValue == null && this.value == null) ? false : (oldValue != this.getValue() ); // extra null check is because null != null is true since null means unknown (and it is more likely that two unknowns would differ than that two unknowns are equal) this.value = oldValue; return changed; }, /** * getValue * * Gets the value of this component * * @since * @access public * @param boolean nochange * @return **/ getValue: function(nochange) { var usesDijit = (typeof(dijit) != "undefined") ? true : false; var nochange = nochange || false; var oldvalue = this.value; if (this.htmlelement && usesDijit && dijit.byId(this.htmlelement.id) && dijit.byId(this.htmlelement.id).getValue) { this.value = dijit.byId(this.htmlelement.id).attr("value"); // IE doesn't support getValue, FF doesn't (fully) support .value } else if (this.htmlelement && (this.htmlelement.value != null) ) { this.value = this.htmlelement.value; } if (nochange) { var newval = this.value; this.value = oldvalue; return newval; } else { return this.value; } }, /** * setValue * * Sets the value of this component * * @since Tue Nov 04 2008 * @access public * @return void **/ setValue: function(value) { var usesDijit = (typeof(dijit) != "undefined") ? true : false; this.value = value; if (this.htmlelement && usesDijit && dijit.byId(this.htmlelement.id) && dijit.byId(this.htmlelement.id).setValue) { dijit.byId(this.htmlelement.id).setValue(this.value); } else if (this.htmlelement && this.htmlelement.value) { this.htmlelement.value = this.value; } }, /** * getId * * Gets this component's id * * @since * @access public * @return **/ getId: function() { return this.id; }, /** * toString * * Gives a string representation of this component * * @since Tue Apr 14 2009 * @access public * @return string **/ toString: function() { if (this.componentType === null) { return "Uninitialized WJComponent"; } return this.componentType + " instance '" + this.id + "'"; } }); /** * WJText * * Textbox input component * * @since Wed Jul 16 2008 * @revision $Revision$ * @author Ron Rademaker * @package Windmill.Javascript.Component **/ var WJText = Class.create(WJComponent, { /** * initialize * * Initialize this WJText * * @since Mon Jul 28 2008 * @access public * @return void **/ initialize: function($super, id) { $super(id); this.componentType = "WJText"; } }); /** * WJPassword * * Textbox for password input * * @since Wed Jul 16 2008 * @revision $Revision$ * @author Ron Rademaker * @package Windmill.Javascript.Component **/ var WJPassword = Class.create(WJText, { /** * initialize * * Initialize this WJPassword * * @since Fri Aug 22 2008 * @access public * @return void **/ initialize: function($super, id) { $super(id); this.componentType = "WJPassword"; } }); /** * WJLabel * * A label, the text that is usually found near an input component. * * @since Wed Jul 16 2008 * @revision $Revision$ * @author Ron Rademaker * @package Windmill.Javascript.Component **/ WJLabel = Class.create(WJComponent, { /** * initialize * * Creates a new Label * * @since * @access public * @param string id * @param string text (default: null) * @param string image (default: null) * @return **/ initialize: function($super, id, text, image) { $super(id); this.componentType = "WJLabel", this.text = text; this.image = image; } }); /** * WJGroup * * A group of components * * @since Wed Jul 16 2008 * @revision $Revision$ * @author Ron Rademaker * @package Windmill.Javascript.Component **/ WJGroup = Class.create(WJComponent, { /** * initialize * * Initializes a new WJGroup * * @since Tue Aug 19 2008 * @access public * @param string id * @return void **/ initialize: function($super, id) { $super(id); this.componentType = "WJGroup"; this.region = "center"; this.group = true; }, /** * setRegion * * Sets the region where to show this group * * @since Wed Nov 12 2008 * @access public * @param string region * @return void **/ setRegion: function(region) { this.region = region; } }); /** * WJHtml * * A html component, used to be able to use contentblocks with components without contentpanes * * @since Mon Jan 19 2009 * @revision $Revision$ * @author Ron Rademaker * @package Windmill.Javascript.Component **/ var WJHtml = Class.create(WJGroup, { /** * initialize * * Initialize this WJHtml * * @since Mon Jan 19 2009 * @access public * @return WJHtml **/ initialize: function($super, id) { $super(id); this.componentType = "WJHtml"; this.group = 0; // WJHtml has a lot of group properties but it isn't really a group (like WJLink). This makes sure it isn't treated as a group on the XSL level. } }); /** * class WJWindow * * The base window class * * @since Fri Jun 27 2008 * @revision $Revision$ * @author Giso Stallenberg * @package Windmill.Javascript.Aeroplane **/ var WJWindow = Class.create({ /** * Properties of Window * * string _title * string _type * DOMElement _content * mixed _contenttype * Function _callbackFunction * boolean _visible * integer _x * integer _y * integer _z * integer _w * integer _h **/ DEFAULT_PARENT: document.body, /** * initialize * * Creates a new WJWindow * * @since Fri Jun 27 2008 * @access public * @param Function callback * @param DOMElement parent (default: document.body) * @return WJWindow **/ initialize: function(callback, parent, translate) { this._loading = false; this._basetitle = this._title = ""; this._theme = "default"; this._parent = parent || WJWindow.DEFAULT_PARENT || document.body; this._listeners = new Hash(); this.translate = translate || this.translate; this._createWindow(); this._addDefaultListeners(); this._addCloseButton(); this.setCallback(callback); this.setBaseTitle(WJGuiSettings.windowBaseTitle); }, /** * _createWindow * * Creates a new window DOMElement * * @since Fri Jun 27 2008 * @access protected * @return void **/ _createWindow: function() { var classname = this._getBaseClassname(); this._windowElement = new Element("div"); this._windowElement.addClassName(classname); this._windowElement.setStyle({"display": "none"}); this._createWindowRows(["title", "main", "buttons", "bottom"], classname); this._windowElementId = this._windowElement.identify(); this._parent.insert(this._windowElement); this._absolutizeTopLeft(); this.hide(); this._outerElement = this._windowElement; this.setTheme(); }, /** * insertWindowRowBefore * * Inserts a new row before given rowname with name newrowname * * @since Tue Sep 23 2008 * @access public * @param string rowname * @param string newrowname * @return DOMElement **/ insertWindowRowBefore: function(rowname, newrowname) { if (rowname === "title") { return; } var classname = this._getBaseClassname(); var row = this._windowElement.select("." + classname + "_" + rowname) row = row.first(); var newrowhtml = this._createRow(newrowname, classname, " " + classname + "_body"); var div = new Element("div"); div.update(newrowhtml); var toprow = row.parentNode; var newrow = toprow.insertBefore(div.firstChild, row ); newrow = Element.extend(newrow); newrow = newrow.select("." + classname + "_content"); this._contentElements[newrowname] = newrow.first(); return newrow; }, /** * replaceWindowRow * * Replaces windowrow old with new, keeps references to old alive (they'll return the new rows) * Returns the removed row * * @since Thu Feb 12 2009 * @access public * @param string oldrow * @param string newrow * @return htmlelement **/ replaceWindowRow: function(oldrow, newrow) { var inserted = this.insertWindowRowBefore(oldrow, newrow); var toremove = this.getContentElement(oldrow); this._contentElements[oldrow] = this._contentElements[newrow]; return toremove.remove(); }, /** * removeWindowRow * * Removes windowrow * Returns the removed row * * @since Tue Dec 8 2009 * @access public * @param string oldrow * @return htmlelement **/ removeWindowRow: function(oldrow) { var toremove = this.getContentElement(oldrow); delete(this._contentElements[oldrow]); return toremove.remove(); }, /** * _addCloseButton * * Adds a button to close the window * * @since Mon Jul 7 2008 * @access protected * @return void **/ _addCloseButton: function() { var title = this.getContentElement("title"); var titlediv = new Element("div", {"onclick": "this.parentNode.getWJWindowObject().fireClose(this)", "title": this.translate("CLOSE_WINDOW") } ); titlediv.addClassName(this._getBaseClassname() + "_closebutton"); title.insert(titlediv); }, /** * fireClose * * Fires the close event from the given element * * @since Thu Oct 16 2008 * @access public * @param Element element * @return void **/ fireClose: function(element) { element = $(element); /* Observe once function */ var func = function() { this.destroy(); Event.stopObserving(document, "wjgui:close", arguments.callee.observerFunction); } var bound = func.bindAsEventListener(this); func.observerFunction = bound; /* End observe once function */ Event.observe(document, "wjgui:close", bound); element.fire("wjgui:close"); Event.stopObserving.defer(document, "wjgui:close", bound); }, /** * _addDefaultListeners * * Adds custom event listeners to the window * * @since Mon Jul 7 2008 * @access protected * @return void **/ _addDefaultListeners: function(element) { this.addListener("true", this.windowResult.bindAsEventListener(this, true) ); this.addListener("false", this.windowResult.bindAsEventListener(this, false) ); this.addListener("close", this.windowResult.bindAsEventListener(this, false) ); this.addListener("save", this.windowResult.bindAsEventListener(this) ); this.addListener("delete", this.windowResult.bindAsEventListener(this) ); this.addListener("cancel", this.windowResult.bindAsEventListener(this) ); this._addDefaultKeyListener(); }, /** * _addDefaultKeyListener * * Adds a listener for key's like return and esc * * @since Fri Sep 5 2008 * @access protected * @return void **/ _addDefaultKeyListener: function() { // here for extending purposes only var element = element || this._windowElement; Event.observe(element, "keydown", this.keyHandle.bindAsEventListener(this) ); }, /** * keyHandle * * Handles pressing enter or esc * * @since Fri Sep 5 2008 * @access public * @param Event event * @return void **/ keyHandle: function(event) { var element = event.element(); if (Object.isElement(element.up(".wjgui_window") ) ) { switch (event.keyCode) { case Event.KEY_RETURN: if (this.isVisible() ) { element.fire("wjgui:true"); } break; case Event.KEY_ESC: if (this.isVisible() ) { element.fire("wjgui:close"); } break; default: return; } } }, /** * addListener * * Adds a listener for a custom event that calls the given callback or the default callback of this window * * @since Tue Aug 12 2008 * @access * @param * @return WJWindow **/ addListener: function(eventName, callback, element) { WJDebugger.log(WJDebugger.INFO, "Adding listener in WJWindow", eventName, callback); var callback = callback || this.windowResult.bindAsEventListener(this); var element = element || this._windowElement; Event.observe(element, "wjgui:" + eventName, callback); this._setListener(eventName, {"element": element, "callback": callback} ); return this; }, /** * _setListener * * Registers a listener function * * @since Wed Jul 9 2008 * @access public * @param string key * @param Object elementAndCallback * @return void **/ _setListener: function(key, elementAndCallback) { this._listeners.set(key, elementAndCallback); }, /** * removeListener * * Removes the listener set for key * * @since Tue Aug 12 2008 * @access * @param * @return WJWindow **/ removeListener: function(key) { var listener = this.getListener(key); Event.stopObserving(listener.element, "wjgui:" + key, listener.callback); this._listeners.unset(key); return this; }, /** * removeListeners * * Removes all listeners * * @since Tue Aug 12 2008 * @access public * @return WJWindow **/ removeListeners: function() { this._listeners.each(function(info) { this.removeListener(info.key); }.bind(this) ); return this; }, /** * windowResult * * Handles the window result event * * @since Wed Jul 9 2008 * @access protected * @param Event event * @return void **/ windowResult: function(event) { this._callback.apply(this, arguments); }, /** * getListeners * * Returns the listeners hash * * @since Mon Jul 7 2008 * @access public * @return Hash **/ getListeners: function() { return this._listeners; }, /** * getListener * * Returns the listener info set for key * * @since Tue Aug 12 2008 * @access * @param * @return **/ getListener: function(key) { return this._listeners.get(key); }, /** * _getBaseClassname * * Returns the base classname used for windows * * @since Fri Jun 27 2008 * @access protected * @return string **/ _getBaseClassname: function() { return "wjgui_window"; }, /** * _getWindowRowTemplate * * Returns a template that can be used to create rows in windows * * @since Fri Jun 27 2008 * @access protected * @return Template **/ _getWindowRowTemplate: function() { return new Template("
 
"); }, /** * _createWindowRows * * Creates rows with names in the rows argument, appends them to windowElement and prefixes all classes with classprefix * * @since Fri Jun 27 2008 * @access protected * @param Array rows * @param string classprefix * @param Element windowElement * @return array **/ _createWindowRows: function(rows, classprefix, windowElement) { var windowElement = windowElement || this._windowElement; rows.each(function(windowElement, classprefix, rowname, index) { var body = " " + classprefix + "_body"; if (index == 0 || index == (rows.length - 1) ) { body = ""; } windowElement.innerHTML += this._createRow(rowname, classprefix, body); }.bind(this, windowElement, classprefix)); this._saveRows(rows, classprefix, windowElement); this._addWindowObjectGetters(); }, /** * _addWindowObjectGetters * * Adds a getWJWindowObject getter to all content elements and the main window element * * @since Thu Oct 16 2008 * @access protected * @return Array **/ _addWindowObjectGetters: function() { var test = [$H(this._contentElements).values(), this._windowElement].flatten(); test.each(function(el) { el.getWJWindowObject = function() { return this; }.bind(this); }, this); return test; }, /** * _saveRows * * Saves all rows in this._contentElements * * @since Tue Sep 23 2008 * @access protected * @param Array rows * @param string classprefix * @param Element windowElement * @return WJWindow **/ _saveRows: function(rows, classprefix, windowElement) { var windowElement = windowElement || this._windowElement; this._contentElements = {}; rows.each(function(windowElements, rowname, index) { this._contentElements[rowname] = windowElements[index]; }.bind(this, windowElement.select("." + classprefix + "_content") ) ); return this; }, /** * _createRow * * Creates the HTML of a row * * @since Tue Sep 23 2008 * @access protected * @param string rowname * @param string classprefix * @param string body * @return string **/ _createRow: function(rowname, classprefix, body) { var row = this._getWindowRowTemplate(); return row.evaluate({"rowname": rowname, "classprefix": classprefix, "body": body}); }, /** * getContentElement * * Returns the content element identified by rowname * * @since Mon Jul 7 2008 * @access public * @param string rowname * @return DOMElement **/ getContentElement: function(rowname) { return this._contentElements[rowname]; }, /** * evalContentElement * * Evaluates the script parts in the content element identified by rowname * * @since Wed Jul 30 2008 * @access public * @param string rowname * @return WJWindow **/ evalContentElement: function(rowname) { var element = this.getContentElement(rowname); element.innerHTML.evalScripts(); return this; }, /** * _absolutizeTopLeft * * Puts the window in the top left corner of the viewport * * @since Fri Jun 27 2008 * @access protected * @param Element element * @return void **/ _absolutizeTopLeft: function(element) { var element = element || this._windowElement; element.absolutize(); element.setStyle({height: "", width: ""}); this.setX(0, element); this.setY(0, element); }, /** * _checkMaxHeight * * Checks the window wo be inside the viewport * * @since Mon Jul 7 2008 * @access protected * @param DOMElement element * @return void **/ _checkMaxHeight: function(element) { var element = element || this.getContentElement("main"); if (this.getY() + this.getHeight() > document.viewport.getHeight() ) { this.setHeight(document.viewport.getHeight() - this.getY(), element, false); } else { element.setStyle({"maxHeight": ""}); } }, /** * show * * Shows the window * * @since Fri Jun 27 2008 * @access public * @return WJWindow **/ show: function(element) { var element = element || this._outerElement || this._windowElement; element.style.display = "block"; try { element.focus() } catch(e) {} // TODO think of something better to get focus in browsers and a window in IE6 return this; }, /** * hide * * Hides the window * * @since Fri Jun 27 2008 * @access public * @return WJWindow **/ hide: function(element) { var element = element || this._outerElement || this._windowElement; element.style.display = "none"; return this; }, /** * destroy * * Destroys the window * * @since Mon Jul 28 2008 * @access public * @return WJWindow **/ destroy: function(element) { var element = element || this._outerElement || this._windowElement; if (element.parentNode) { element.remove(); } return this; }, /** * _callback * * Does the callback that this window should do * * @since Fri Jun 27 2008 * @access protected * @return mixed **/ _callback: function() { if (Object.isFunction(this._callbackFunction) ) { var args = $A(arguments); args.unshift(this); return this._callbackFunction.apply(this._callbackFunction, args); } }, /** * _close * * Closes the window * * @since Fri Jun 27 2008 * @access protected * @return mixed **/ _close: function(event) { this.hide(); }, /** * setBaseTitle * * Changes the base title * * @since Wed Sep 10 2008 * @access public * @param string title * @return WJWindow **/ setBaseTitle: function(title) { this._basetitle = title; this.setTitle(this.getTitle() ); return this; }, /** * setTitle * * Changes the title * * @since Fri Jun 27 2008 * @access public * @return WJWindow **/ setTitle: function(title) { this._title = title; var headers = this.getContentElement("title").getElementsByTagName("h1"); if (headers.length < 1) { this.getContentElement("title").innerHTML = "

 

" + this.getContentElement("title").innerHTML; return this.setTitle(this._title); } headers[0].innerHTML = this._getComposedTitle(); return this; }, /** * _getComposedTitle * * Creates a nice looking title * * @since Wed Sep 10 2008 * @access protected * @return string **/ _getComposedTitle: function() { return this._title + ( (this._basetitle != "" && this._basetitle != this._title) ? ( (this._title != "") ? " - " : "") + this._basetitle : ""); }, /** * setContent * * Changes the content * * @since Fri Jun 27 2008 * @access public * @param mixed content * @return WJWindow **/ setContent: function(content) { if (Object.isString(content) ) { this.getContentElement("main").innerHTML = content; } if (Object.isElement(content) ) { this.getContentElement("main").appendChild(content); } this._content = content; return this; }, /** * addButton * * Adds a button to the window * * @since Tue Aug 12 2008 * @access public * @param string caption * @param mixed callback * @param boolean defaultButton * @return DOMElement **/ addButton: function(caption, eventHandler, defaultButton) { WJDebugger.log(WJDebugger.INFO, "Adding button to window", caption, eventHandler, this); var button = WJButton.create(caption, eventHandler, defaultButton, this.getContentElement("buttons") ); this._checkMaxHeight(); // this function is likely to change the height of the bottom row return button; }, /** * addStatusbar * * Adds a statusbar to the window * * @since Mon Feb 02 2009 * @access public * @return void **/ addStatusbar: function() { WJDebugger.log(WJDebugger.INFO, "Adding statusbar to window", this); this._statusbar = new Element("div"); this._statusbar.addClassName("wjgui_statusbar"); this.getContentElement("buttons").insert(this._statusbar); this._checkMaxHeight(); }, /** * setStatusbar * * Sets the content of the statusbar * * @since Mon Feb 02 2009 * @access public * @param string content * @param integer fade * @return void **/ setStatusbar: function(content, fade) { var fade = fade || -1; if (this._statusbar) { this._statusbar.update(content); if (fade > 0) { this.hideStatusbar.bind(this).delay(fade); } } }, /** * hideStatusbar * * Hides the contents of the statusbar, and then clears its contents * * @since Mon Feb 02 2009 * @access public * @return void **/ hideStatusbar: function() { Effect.Fade(this._statusbar, {duration: 3.0}); this.clearAndShowStatusbar.bind(this).delay(3.5); }, /** * clearAndShowStatusbar * * Clears and shows the statusbar * * @since Mon Feb 02 2009 * @access public * @return void **/ clearAndShowStatusbar: function() { this._statusbar.update(""); this._statusbar.show(); }, /** * setCallback * * Changes the callback function * * @since Fri Jun 27 2008 * @access public * @param Function callback * @return WJWindow **/ setCallback: function(callback) { if (Object.isFunction(callback) ) { this._callbackFunction = callback; } return this; }, /** * setX * * Changes the x position of this window * * @since Fri Jun 27 2008 * @access public * @param integer x * @return WJWindow **/ setX: function(x, element) { this._x = x || 0; var element = element || this._windowElement; element.style.left = x + "px"; return this; }, /** * setY * * Changes the y position of this window * * @since Fri Jun 27 2008 * @access public * @param integer y * @return WJWindow **/ setY: function(y, element) { this._y = y || 0; var element = element || this._windowElement; element.style.top = y + "px"; this._checkMaxHeight(element); return this; }, /** * setZ * * Changes the z-index of this window * * @since Fri Jun 27 2008 * @access public * @param integer z * @return WJWindow **/ setZ: function(z, element) { this._z = z || 10000; var element = element || this._windowElement; element.style.zIndex = z; return this; }, /** * setWidth * * Changes the width of this window * * @since Fri Jun 27 2008 * @access public * @param integer width * @return WJWindow **/ setWidth: function(width, element) { this._width = width; var element = element || this._windowElement; element.setStyle({"width": width + "px"}); element.fire("wjgui:resize"); return this; }, /** * setHeight * * Changes the height of this window * * @since Fri Jun 27 2008 * @access public * @param integer height * @return WJWindow **/ setHeight: function(height, element, checkHeight) { this._height = height; var element = element || this.getContentElement("main"); var wasVisible = this.isVisible(); var origX = this.getX(); var origY = this.getY(); if (!wasVisible) { this.setX(-10000); this.setY(-10000); this.show(); } var otherRowsHeight = 0; for (var key in this._contentElements) { if (key != "main") { otherRowsHeight += this._contentElements[key].getHeight(); } } var height = (Object.isNumber(height) == false) ? height : (height - otherRowsHeight) + "px"; element.setStyle({"height": height}); if (!wasVisible) { this.hide(); this.setX(origX); this.setY(origY); } if (checkHeight != false) { this._checkMaxHeight(element); } if (!checkHeight) { element.fire("wjgui:resize"); } return this; }, /** * getBaseTitle * * Returns the title of this window * * @since Fri Jun 27 2008 * @access public * @return string **/ getBaseTitle: function() { return this._basetitle; }, /** * getTitle * * Returns the title of this window * * @since Fri Jun 27 2008 * @access public * @return string **/ getTitle: function() { return this._title; }, /** * getType * * Tells what window type this window is * * @since Fri Jun 27 2008 * @access public * @return string **/ getType: function() { return this._type; }, /** * getContent * * Returns the content of this window * * @since Fri Jun 27 2008 * @access public * @return mixed **/ getContent: function() { return this._content; }, /** * getContenttype * * Returns the type of the content * * @since Fri Jun 27 2008 * @access public * @return mixed **/ getContenttype: function() { }, /** * getCallback * * Returns the callback function * * @since Fri Jun 27 2008 * @access public * @return Function **/ getCallback: function() { return this._callbackFunction; }, /** * isVisible * * Tells if this window can be seen * * @since Fri Jun 27 2008 * @access public * @return boolean **/ isVisible: function() { var xInLow = (this.getX() < 0 && (this.getX() + this.getWidth() ) > 0); var xInHigh = (this.getX() >= 0 && this.getX() < document.viewport.getWidth() ); var yInLow = (this.getY() < 0 && (this.getY() + this.getHeight() ) > 0); var yInHigh = (this.getY() >= 0 && this.getY() < document.viewport.getHeight() ); if ( (xInLow || xInHigh) && (yInLow || yInHigh) && this._windowElement.visible() ) { return true; } return false; }, /** * getX * * Tells the x position of this window * * @since Fri Jun 27 2008 * @access public * @return integer **/ getX: function(element) { var element = element || this._windowElement; return parseInt(element.style.left); }, /** * getY * * Tells the y position of this window * * @since Fri Jun 27 2008 * @access public * @return integer **/ getY: function(element) { var element = element || this._windowElement; return parseInt(element.style.top); }, /** * getZ * * Tells the zIndex of this window * * @since Fri Jun 27 2008 * @access public * @return integer **/ getZ: function() { var element = element || this._windowElement; return element.style.zIndex; }, /** * getWidth * * Tells the width of this window * * @since Fri Jun 27 2008 * @access public * @return integer **/ getWidth: function(element) { var element = element || this._windowElement; return element.getWidth(); }, /** * getHeight * * Tells the height of this window * * @since Fri Jun 27 2008 * @access public * @return integer **/ getHeight: function(element) { var element = element || this._windowElement; return element.getHeight(); }, /** * getContentHeight * * Tells what's the height of the content element * * @since Tue Sep 16 2008 * @access public * @return integer **/ getContentHeight: function() { return this.getContentElement("main").getHeight(); }, /** * getContentWidth * * Tells what's the width of the content element * * @since Tue Sep 16 2008 * @access public * @return integer **/ getContentWidth: function() { return this.getContentElement("main").getWidth(); }, /** * getWindowElement * * Returns the windowElement * * @since Mon Jul 7 2008 * @access public * @return DOMElement **/ getWindowElement: function() { return this._windowElement; }, /** * center * * centers the given element * * @since Mon Jul 7 2008 * @access public * @param DOMElement element * @return WJWindow **/ center: function(element) { var element = element || this._windowElement; var remainsX = document.viewport.getWidth() - this.getWidth(element); var remainsY = document.viewport.getHeight() - this.getHeight(element); this.setX(remainsX / 2, element).setY(remainsY / 2, element); return this; }, /** * keepCentered * * Makes sure the window stays centered * * @since Mon Jul 7 2008 * @access public * @param DOMElement element * @return void **/ keepCentered: function(element) { if (!this._centerObserver) { var element = element || this._windowElement; this._centerObserver = this.center.bind(this, element); Event.observe(window, "resize", this._centerObserver); } }, /** * stopCentered * * Stops centering the window * * @since Mon Jul 7 2008 * @access public * @return void **/ stopCentered: function() { Event.stopObserving(window, "resize", this._centerObserver); this._centerObserver = null; }, /** * maximize * * Maximizes the window * * @since Fri Aug 8 2008 * @access public * @return WJWindow **/ maximize: function(paddingTop, paddingRight, paddingBottom, paddingLeft, noScroll) { var paddingTop = paddingTop || 0; var paddingRight = paddingRight || paddingTop; var paddingBottom = paddingBottom || paddingTop; var paddingLeft = paddingLeft || paddingTop; var noScroll = noScroll || false; this.setX(paddingLeft).setY(paddingTop); if (noScroll) { this.setWidth(0).setHeight(0); } this.setWidth(document.viewport.getWidth() - (paddingLeft + paddingRight) ).setHeight(document.viewport.getHeight() - (paddingTop + paddingBottom) ); return this; }, /** * keepMaximized * * Makes sure the window stays maximized * * @since Tue Sep 9 2008 * @access public * @return void **/ keepMaximized: function() { if (!this._maximizedObserver) { var paddingTop = this.getY(); var paddingLeft = this.getX(); var paddingRight = document.viewport.getWidth() - this.getWidth() - paddingLeft; var paddingBottom = document.viewport.getHeight() - this.getHeight() - paddingTop; this._maximizedObserver = this.maximize.bind(this, paddingTop, paddingRight, paddingBottom, paddingLeft, true); Event.observe(window, "resize", this._maximizedObserver); } }, /** * stopMaximized * * Stops maximizing the window * * @since Tue Sep 9 2008 * @access public * @return void **/ stopMaximized: function() { Event.stopObserving(window, "resize", this._maximizedObserver); this._maximizedObserver = null; }, /** * setLoading * * Mark this window as loading (or not) * * @since Wed Sep 3 2008 * @access public * @param boolean loading * @param function loadCallback; * @return WJWindow **/ setLoading: function(loading, loadCallback) { var loadCallback = loadCallback || false; if (loading && !this.getLoading() ) { this.getWindowElement().addClassName("wjgui_window_loading"); if (!loadCallback) { this.getContentElement("main").setStyle({"visibility": "hidden"}); } else { loadCallback(this, loading); } } else if (!loading && this.getLoading() ) { this.getWindowElement().removeClassName("wjgui_window_loading"); if (!loadCallback) { this.getContentElement("main").setStyle({"visibility": "visible"}); } else { loadCallback(this, loading); } } this._loading = loading; return this; }, /** * getLoading * * Tells if this window is marked as loading * * @since Wed Sep 3 2008 * @access public * @return boolean **/ getLoading: function() { return this._loading; }, /** * setTheme * * Sets the theme for the window * * @since Fri Dec 5 2008 * @access public * @param string theme * @return void **/ setTheme: function(theme) { if (theme == this.getTheme() ) { return; } this._removeOldTheme(); this._setTheme(theme); this._addNewTheme(); }, /** * _setTheme * * Sets the value of the _theme property * * @since Fri Dec 5 2008 * @access protected * @param string theme * @return void **/ _setTheme: function(theme) { this._theme = theme || "default"; }, /** * _removeOldTheme * * Removes the previously set theme class from the window * * @since Fri Dec 5 2008 * @access * @param * @return **/ _removeOldTheme: function() { this.getWindowElement().removeClassName(this._getBaseClassname() + "theme_" + this.getTheme() ); }, /** * _addNewTheme * * Adds the new theme class to the window * * @since Fri Dec 5 2008 * @access protected * @return void **/ _addNewTheme: function() { this.getWindowElement().addClassName(this._getBaseClassname() + "theme_" + this.getTheme() ); }, /** * getTheme * * Returns the value of the _theme property * * @since Fri Dec 5 2008 * @access public * @return string **/ getTheme: function() { return this._theme; }, /** * translate * * Translates strings * * @since Thu Jun 18 2009 * @access public * @param string key * @return string **/ translate: function(key) { if (this._translations[key] ) { return this._translations[key]; } return key.charAt(0).toUpperCase() + key.replace("_", " ").substr(1).toLowerCase(); }, /** * The translations table * * @since Thu Jun 18 2009 * @access protected * @var Object **/ _translations: {OK: "Ok", CANCEL: "Annuleren", YES: "Ja", NO: "Nee", CLOSE_WINDOW: "Venster sluiten"} }); WJWindow._messagedialog = function(type, message, callback, show, translate, allowHTML) { var win = new WJWindow(callback, null, translate); var mwin = new window[type](win); mwin.setMessage(message, allowHTML); if (show) { mwin.show(); } return mwin; }; WJWindow.alert = function(message, callback, translate, allowHTML) { return WJWindow._messagedialog("WJWindowAlert", message, callback, true, translate, allowHTML); }; WJWindow.notice = function(message, callback, translate, allowHTML) { return WJWindow._messagedialog("WJWindowNotice", message, callback, true, translate, allowHTML); }; WJWindow.confirm = function(message, callback, translate, allowHTML) { return WJWindow._messagedialog("WJWindowConfirm", message, callback, true, translate, allowHTML); }; WJWindow.booleanConfirm = function(message, callback, translate, allowHTML) { return WJWindow._messagedialog("WJWindowBooleanConfirm", message, callback, true, translate, allowHTML); }; WJWindow.prompt = function(message, callback, translate, allowHTML) { return WJWindow._messagedialog("WJWindowPrompt", message, callback, true, translate, allowHTML); }; /** * WJWindowModal * * The base class to decorate a window with modal properties * * @since Fri Jun 27 2008 * @revision $Revision$ * @author Giso Stallenberg * @package Windmill.Javascript.Aeroplane **/ var WJWindowModal = Class.create({ /** * initialize * * Creates a new instanceof WJWindowModal * * @since Fri Jul 4 2008 * @access public * @param WJWindow wjwindow * @return WJWindowModal **/ initialize: function(toDecorate) { this._decorate(toDecorate); this._createModalLayer(); this._maxblink = 6; this._addBlinkListener(); this._rebindListeners(); this._rebindWindowObjectGetters(); this.setZ(2147483647); this.showOnInit(); }, /** * showOnInit * * BC solution to be able to not show a window on initialize * * @since Fri Oct 16 2009 * @access public * @return void **/ showOnInit: function() { this.show(); }, /** * _decorate * * Decorates the given object * * @since Tue Jul 8 2008 * @access protected * @param WJWindow toDecorate * @return void **/ _decorate: function(toDecorate) { this._decorated = toDecorate; for (property in this._decorated) { // Add all methods not defined in this if (!Object.isFunction(this[property]) ) { this[property] = this._decorated[property]; } } }, /** * _rebindListeners * * Stops the listeners observing and rebinds 'this' to the listeners * * @since Mon Jul 7 2008 * @access protected * @return void **/ _rebindListeners: function() { this.removeListeners(); this._addDefaultListeners(); }, /** * _createModalLayer * * Creates a layer to simulate modality * * @since Mon Jul 7 2008 * @access protected * @return void **/ _createModalLayer: function() { var windowElement = this._decorated.getWindowElement(); this._modalLayer = new WJModalLayer(); this._modalLayer.getLayer().insert(windowElement); this._outerElement = this._modalLayer.getLayer(); }, /** * show * * Shows the window * * @since Mon Jul 7 2008 * @access public * @return void **/ show: function(element) { var element = element || this._outerElement || this._modalLayer.getLayer(); element.style.display = "block"; this._setBodyOverflow("hidden"); this._decorated.show(); }, /** * hide * * Hides the window * * @since Mon Jul 7 2008 * @access public * @return void **/ hide: function(element) { var element = element || this._outerElement || this._modalLayer.getLayer(); element.style.display = "none"; this._setBodyOverflow(); this._decorated.hide(); }, /** * _setBodyOverflow * * Set's the overflow property of body (and html for IE7) * * @since Mon Jul 7 2008 * @access protected * @param string value * @return void **/ _setBodyOverflow: function(value) { var value = value || ""; $(document.body).setStyle({overflow: value}); $(document.getElementsByTagName("html")[0]).setStyle({overflow: value}); }, /** * * * * * @since Thu Jul 10 2008 * @access * @param * @return **/ _addBlinkListener: function() { Event.observe(this._modalLayer.getLayer(), "click", this.blink.bindAsEventListener(this) ); }, /** * * * * * @since Thu Jul 10 2008 * @access * @param * @return **/ blink: function(event, doBlink, count) { var count = count || 0; if (Event.element(event).className == this._getBaseClassname() + "_modality") { if (doBlink) { this.getWindowElement().addClassName(this._getBaseClassname() + "_blink"); doBlink = false; } else { this.getWindowElement().removeClassName(this._getBaseClassname() + "_blink"); doBlink = true; } if (count < this._maxblink) { count++ this.blink.bind(this, event, doBlink, count).delay(0.05); } } }, /** * _rebindWindowObjectGetters * * Adds a getWJWindowObject getter to all content elements and the main window element and binds it to this not the decorated window * * @since Fri Feb 13 2009 * @access protected * @return void **/ _rebindWindowObjectGetters: function() { var els = this._decorated._addWindowObjectGetters(); els.each(function(el) { el.getWJWindowObject = el.getWJWindowObject.bind(this); }, this); return els; } }); /** * WJModalLayer is a class to create a modal layer on the page to disallow any user interaction other that on things on top op the layer **/ var WJModalLayer = Class.create({ /** * initialize * * Creates and applies a WJModalLayer * * @since Tue Jan 06 2009 * @access public * @param Element parent * @param Element modalLayer * @return void **/ initialize: function(parent, modalLayer) { var parent = parent || document.body; this._modalLayer = (modalLayer || new Element("div") ); Element.extend(this._modalLayer).addClassName("wjgui_window_modality"); parent.appendChild(this._modalLayer); this._removed = false; this._absolutizeTopLeft(); this._fillViewport(); Event.observe(window, "resize", this._fillViewport.bind(this, this._modalLayer) ); // on purpose, no need to bind as event listener }, /** * _absolutizeTopLeft * * Puts the window in the top left corner of the viewport * * @since Fri Jun 27 2008 * @access protected * @param Element element * @return void **/ _absolutizeTopLeft: function(element) { var element = this._modalLayer; element.absolutize(); element.setStyle({left: 0, top: 0, zIndex: 2147483647}); }, /** * _fillViewport * * Stretches the given element to fill the viewport * * @since Mon Jul 7 2008 * @access protected * @param DOMElement element * @return void **/ _fillViewport: function() { var element = $(this._modalLayer); if ($(element.parentNode) && $(element.parentNode).getHeight) { element.setStyle( {width: $(element.parentNode).getWidth() + "px", height: $(element.parentNode).getHeight() + "px"} ); } else { element.setStyle( {width: document.viewport.getWidth() + "px", height: document.viewport.getHeight() + "px"} ); } }, /** * getLayer * * Gets the layer element * * @since Tue Jan 06 2009 * @access public * @return htmlelement **/ getLayer: function() { return this._modalLayer; }, /** * destroy * * Destroys this modal layer * * @since Tue Jan 06 2009 * @access public * @return void **/ destroy: function() { if (!this._removed) { this._modalLayer.remove(); this._removed = true; } } }); /** * WJWindowMessageDialog * * A class handling modal alert messages * * @since Fri Jun 27 2008 * @revision $Revision$ * @author Giso Stallenberg * @package Windmill.Javascript.Aeroplane **/ var WJWindowMessageDialog = Class.create(WJWindowModal, { /** * initialize * * Creates a new WJWindowMessageDialog * * @since Mon Jul 7 2008 * @access public * @param Class $super * @param Function callback * @param string type * @return WJWindowMessageDialog **/ initialize: function($super, toDecorate) { $super(toDecorate); this.center(); this.keepCentered(); this._drawDefaultContent(); this._buttons = null; this._addButtons(); }, /** * _drawDefaultContent * * Draws the default alert content * * @since Tue Jul 8 2008 * @access protected * @return void **/ _drawDefaultContent: function() { var content = this.getContentElement("main"); var replaces = this._getTemplateValues(); var template = this._getTemplate(); content.innerHTML = template.evaluate(replaces); this._contentElements["message"] = content.down("." + replaces.classprefix+"_message"); }, /** * * * * * @since Wed Jul 9 2008 * @access * @param * @return **/ _getTemplateValues: function() { return {"classprefix": this._getBaseClassname(), "windowtype": this._type}; }, /** * _addButtons * * Adds the right buttons * * @since Wed Jul 9 2008 * @access protected * @return void **/ _addButtons: function() { if (this._buttons == null) { this._buttons = new Hash(); this._buttons.set("ok", WJButton.create(this._decorated.translate("OK"), "true", true, this.getContentElement("buttons") ) ).focus(); } return this._buttons; }, /** * _getMainTemplate * * * * @since Tue Jul 8 2008 * @access protected * @return Template **/ _getTemplate: function() { return new Template("
 
 
"); }, /** * setMessage * * Sets the message for this window * * @since Tue Jul 8 2008 * @access public * @param string message * @return void **/ setMessage: function(message, allowHTML) { var allowHTML = !!allowHTML; if (!allowHTML) { message = message.stripTags(); } this.message = message.stripScripts().split("\n").join("
"); this.getContentElement("message").innerHTML = this.message; }, /** * _callback * * Does the callback that this window should do (and hides the message) * * @since Fri Jun 27 2008 * @access protected * @return mixed **/ _callback: function() { this.hide(); return this._decorated._callback.apply(this._decorated, $A(arguments) ); } }); /** * WJWindowAlert * * A class handling modal alert messages * * @since Fri Jun 27 2008 * @revision $Revision$ * @author Giso Stallenberg * @package Windmill.Javascript.Aeroplane **/ var WJWindowAlert = Class.create(WJWindowMessageDialog, { /** * initialize * * Creates a new WJWindowAlert * * @since Wed Jul 9 2008 * @access public * @param WJWindow toDecorate * @return WJWindowAlert **/ initialize: function($super, toDecorate) { if (!this._type) { this._type = "alert"; } $super(toDecorate); this.getListener("close").callback.setArgument(0, true); // closing an alert means ok this.removeListener("false");// an alert can only be true this.removeListener("save"); this.removeListener("cancel"); } }); /** * WJWindowNotice * * A class handling modal notice (friendly alert) messages * * @since Mon Jul 07 2008 * @revision $Revision$ * @author Giso Stallenberg * @package Windmill.Javascript.Aeroplane **/ var WJWindowNotice = Class.create(WJWindowAlert, { /** * initialize * * Creates a new WJWindowNotice * * @since Mon Jul 07 2008 * @access public * @param Class $super * @param Function callback * @param string type * @return WJWindowNotice **/ initialize: function($super, toDecorate) { this._type = "notice"; $super(toDecorate); } }); /** * WJButton * * A class handling the creation of buttons * * @since Wed Jul 09 2008 * @revision $Revision$ * @author Giso Stallenberg * @package Windmill.Javascript.Aeroplane **/ var WJButton = Class.create({ /** * initialize * * Creates a new WJButton * * @since Wed Jul 9 2008 * @access public * @param string caption * @param Function|string event * @param string type * @return WJButton **/ initialize: function(caption, eventHandler, defaultButton, parentElement) { WJDebugger.log(WJDebugger.INFO, "Create new button", caption, eventHandler, defaultButton, parentElement); this._caption = caption; this._eventHandler = eventHandler; this._defaultButton = (defaultButton === true) ? true : false; this._parentElement = $(parentElement); this._buildEventHandler(); this._createButton(); this._addButtonMethods(); this._addObserver(); if (Object.isElement(this._parentElement) ) { this._parentElement.appendChild(this.getButton() ); } this.updateCaption(this._caption); }, /** * _addButtonMethods * * Adds methods to the element to easy update the caption and enable or disable the button * * @since Thu Jul 10 2008 * @access protected * @return void **/ _addButtonMethods: function() { this.getButton().updateCaption = this.updateCaption.bind(this); this.getButton().setCaption = this.getButton().updateCaption; this.getButton().getCaption = this.getCaption.bind(this); this.getButton().enable = this.enable.bind(this); this.getButton().disable = this.disable.bind(this); }, /** * updateCaption * * A method that updates the caption content of the button (and resizes the button if needed) * * @since Thu Jul 10 2008 * @access public * @param string caption * @return Element **/ updateCaption: function(caption) { this._caption = caption.stripTags().stripScripts(); return this._setCaption.bind(this).defer(); }, /** * setCaption * * Changes the caption of this button * * @since Mon Feb 16 2009 * @access public * @param string caption * @return Element **/ setCaption: function(caption) { this.updateCaption(caption); }, /** * _setCaption * * Performs the real setting of the caption (it used to be called with a defer from initialize, now it's deferred always (@see updateCaption), to avoid it being updated later by old calls) * * @since Fri Feb 13 2009 * @access protected * @return void **/ _setCaption: function() { var contentElement = this.getContentElement(); contentElement.update(this._caption); this.setWidth(this._getNewButtonWidth(this._caption, contentElement) ); return this.getButton(); }, /** * enable * * Enables the button * * @since Mon Nov 10 2008 * @access public * @return this **/ enable: function() { this.getButton().removeAttribute("disabled"); this.getButton().removeClassName("wjgui_button_disabled"); return this; }, /** * disable * * Disables the button * * @since Mon Nov 10 2008 * @access public * @return this **/ disable: function() { this.getButton().disabled = "disabled"; this.getButton().addClassName("wjgui_button_disabled"); return this; }, /** * getContentElement * * Returns the container of the content * * @since Tue Aug 19 2008 * @access public * @return Element **/ getContentElement: function() { return this.getButton().down("." + this._getBaseClassName() + "_content"); }, /** * getNewButtonWidth * * Returns the width needed to fit the content on the button * * @since Tue Aug 19 2008 * @access protected * @param string text * @param Element element * @return integer **/ _getNewButtonWidth: function(text, element) { var fontfamily = element.getStyle("fontFamily"); var fontsize = element.getStyle("fontSize"); var fontweight = element.getStyle("fontWeight"); WJButton.measureElement.setStyle({"fontFamily": fontfamily, "fontSize": fontsize, "fontWeight": fontweight}).update(text); var width = document.body.appendChild(WJButton.measureElement).getWidth(); WJButton.measureElement.remove(); width += this.getWidth() - element.getWidth(); return (width > 100 || this.getButton().up("div.autowidth", 0) ) ? width : 100; }, /** * getWidth * * Tells the width of the button * * @since Mon Aug 18 2008 * @access public * @return integer **/ getWidth: function() { return this.getButton().getWidth(); }, /** * setWidth * * Sets the width of the button * * @since Mon Aug 18 2008 * @access public * @param integer width * @return void **/ setWidth: function(width) { this.getButton().setStyle({"width": width + "px"}); }, /** * _buildEventHandler * * Creates a function to use as click event handler * * @since Wed Jul 9 2008 * @access protected * @return void **/ _buildEventHandler: function() { if (!Object.isFunction(this._eventHandler) ) { if (this._eventHandler.indexOf(":") == -1) { this._eventHandler = this._getEventPrefix() + ":" + this._eventHandler; WJDebugger.log(WJDebugger.INFO, "Build event handler for this, create event " + this._eventHandler); var func = function(event, eventHandler) { WJDebugger.log(WJDebugger.INFO, "Fire event in WJButton", event, eventHandler); Event.element(event).fire(eventHandler); }.bindAsEventListener(this.getButton(), this._eventHandler); this._eventHandler = func; } } }, /** * _getEventPrefix * * Returns the namespacing prefix for the event to fire * * @since Wed Jul 9 2008 * @access protected * @return string **/ _getEventPrefix: function() { return "wjgui"; }, /** * _createButton * * Creates the button element * * @since Wed Jul 9 2008 * @access protected * @return void **/ _createButton: function() { this._buttonElement = new Element("button"); var template = this._getTemplate(); var replaces = {}; replaces.classprefix = this._getBaseClassName(); this._buttonElement.addClassName(replaces.classprefix + " " + replaces.classprefix + "_" + ((this._defaultButton) ? "" : "no") + "default"); this._buttonElement.innerHTML = template.evaluate(replaces); }, /** * _getBaseClassName * * Returns the base className for buttons * * @since Wed Jul 9 2008 * @access protected * @return string **/ _getBaseClassName: function() { return "wjgui_button"; }, /** * _getTemplate * * Returns a template element on which the button innerHTML is based * * @since Wed Jul 9 2008 * @access protected * @return Template **/ _getTemplate: function() { return new Template("
 
"); }, /** * getButton * * Returns the created button * * @since Wed Jul 9 2008 * @access public * @return DOMElement **/ getButton: function() { return this._buttonElement; }, /** * _addObserver * * Adds an observer function to the button's click event * * @since Wed Jul 9 2008 * @access protected * @return void **/ _addObserver: function() { WJDebugger.log(WJDebugger.INFO, "_addObserver in WJButton", this._eventHandler); WJDebugger.log(WJDebugger.DEBUG, "WJButton observer code", this._eventHandler.toString() ); Event.observe(this.getButton(), "click", this._eventHandler); }, /** * setObserver * * Sets the current click observer for this button to eventHandler * * @since Tue Sep 16 2008 * @access public * @param function eventHandler * @return void **/ setObserver: function(eventHandler) { Event.stopObserving(this.getButton(), "click", this._eventHandler); this._eventHandler = eventHandler; this._addObserver(); }, /** * getCaption * * Returns the value of teh caption * * @since Tue Feb 10 2009 * @access public * @return string **/ getCaption: function() { return this._caption; }, /** * recalculateWidth * * Recalculates the width by updating the caption with the current caption * * @since Tue Feb 10 2009 * @access public * @return void **/ recalculateWidth: function() { this.updateCaption(this.getCaption() ); } }); /** * an element to measure string length in context * * @since Tue Aug 19 2008 * @access public **/ WJButton.measureElement = new Element("div", {"style": "position: absolute; left: -1000px;"}); /** * create * * Static method to create a single button * * @since Wed Jul 9 2008 * @access public * @param string caption * @param Function|string eventHandler * @param boolean defaultButton * @param DOMElement element * @return DOMElement **/ WJButton.create = function(caption, eventHandler, defaultButton, parentElement) { var button = new WJButton(caption, eventHandler, defaultButton, parentElement); return button.getButton(); } /** * toWJButtonStyle * * Styles a given button as a WJButton (NOTE: does not create a WJButton instance and does not attach methods and so on) * * @since Fri Mar 20 2009 * @access public * @param Element element * @param boolean defaultButton * @return Element **/ WJButton.toWJButtonStyle = function(element, defaultButton) { if (element.tagName.toLowerCase() == "button") { var element = $(element); var caption = element.getTextContent(); var template = WJButton.prototype._getTemplate(); var replaces = {classprefix: WJButton.prototype._getBaseClassName()}; element.className = replaces.classprefix + " " + replaces.classprefix + "_" + ((defaultButton) ? "" : "no") + "default"; element.update(template.evaluate(replaces) ); element.down("." + replaces.classprefix + "_content").update(caption); } return element; } /** * WJGuiSettings * * Mixes existing WJGuiSettings with default values * * @since Fri Oct 3 2008 * @revision $Revision$ * @author Giso Stallenberg * @package Windmill.WJGui.Javascript **/ var WJGuiSettings = Object.extend({ windowBaseTitle: "Windmill CMS" }, WJGuiSettings || {});