diff --git a/phpgwapi/js/framework/fw_base.js b/phpgwapi/js/framework/fw_base.js new file mode 100644 index 0000000000..cb39a394c0 --- /dev/null +++ b/phpgwapi/js/framework/fw_base.js @@ -0,0 +1,128 @@ +/** + * eGroupware Framework base object + * @package framework + * @author Hadi Nategh + * @copyright Stylite AG 2014 + * @description Framework base module which creates fw_base object and includes basic framework functionallity + */ + +"use strict"; +/*egw:uses + jquery.jquery; + egw_inheritance.js; +*/ + +var fw_base = Class.extend({ + + /** + * Framework base class constructor sets up basic initialization + */ + init: function (){ + + }, + + alertHandler: function (_message, _details) + { + if (_details) + { + alert('Error:\n ' + _message + '\n\nDetails:\n ' + _details); + } + else + { + alert(_message); + } + }, + + /** + * Call online manual + * + * @param {string} referer optional referer, default use activeApp + */ + callManual: function(referer) + { + if (typeof referer == 'undefined' && this.activeApp && this.activeApp.appName != 'manual') + { + referer = this.activeApp.indexUrl; + if (this.activeApp.browser.iframe && this.activeApp.browser.iframe.contentWindow.location) + { + //this.activeApp.browser.iframe.contentWindow.callManual(); + referer = this.activeApp.browser.iframe.contentWindow.location.href; + } + } + if (typeof referer != 'undefined') + { + this.linkHandler(egw.link('/index.php', { + menuaction: 'manual.uimanual.view', + referer: referer + }), 'manual', true); + } + }, + + /** + * Redirect window to the URL + * @param {string} _url + */ + redirect: function(_url) + { + window.location = _url; + }, + + /** + * Sets the active framework application to the application specified by _app + * + * @param {egw_fw_class_application} _app application object + */ + setActiveApp: function(_app) + { + //Only perform the following commands if a new application is activated + if (_app != this.activeApp) + { + // tab not yet loaded, load it now + if (!_app.browser.currentLocation && !_app.browser.iframe) + { + this.applicationTabNavigate(_app, _app.indexUrl); + return; + } + this.activeApp = _app; + + //Set the sidebox width if a application specific sidebox width is set + if (_app.sideboxWidth !== false) + { + this.sideboxSizeCallback(_app.sideboxWidth); + this.splitterUi.constraints[0].size = _app.sideboxWidth; + } + + //Open the sidemenuUi that belongs to the app, if no sidemenu is attached + //to the app, close the sidemenuUi + if (_app.sidemenuEntry) + { + if (_app.hasSideboxMenuContent) + { + this.sidemenuUi.open(_app.sidemenuEntry); + } + } + else + { + this.sidemenuUi.open(null); + } + + //Set the website title + this.refreshAppTitle(); + + //Show the application tab + if (_app.tab) + { + this.tabsUi.showTab(_app.tab); + + //Going to a new tab changes the tab state + this.notifyTabChange(_app.tab); + } + + //Resize the scroll area... + this.scrollAreaUi.update(); + + //...and scroll to the top + this.scrollAreaUi.setScrollPos(0); + } + } +}); diff --git a/phpgwapi/js/framework/fw_browser.js b/phpgwapi/js/framework/fw_browser.js new file mode 100644 index 0000000000..446ec8f7ef --- /dev/null +++ b/phpgwapi/js/framework/fw_browser.js @@ -0,0 +1,327 @@ +/** + * eGroupware Framework browser object + * @package framework + * @author Hadi Nategh + * @copyright Stylite AG 2014 + * @description Framework browser object, is implementation of browser class in order to display application content + */ + +/*egw:uses + jquery.jquery; + egw_inheritance.js; +*/ + +/** + * Constants definition + */ +EGW_BROWSER_TYPE_NONE = 0; +EGW_BROWSER_TYPE_IFRAME = 1; +EGW_BROWSER_TYPE_DIV = 2; +"use strict"; +var fw_browser = Class.extend({ + + + + /** + * @param {string} _app + * @param {function} _heightCallback + * Framework browser class constructor + */ + init: function (_app, _heightCallback){ + //Create a div which contains both, the legacy iframe and the contentDiv + this.baseDiv = document.createElement('div'); + this.type = EGW_BROWSER_TYPE_NONE; + this.iframe = null; + this.contentDiv = null; + this.heightCallback = _heightCallback; + this.app = _app; + this.currentLocation = ''; + }, + + /** + * Triggers resize event on window + */ + callResizeHandler: function() + { + var wnd = window; + if (this.iframe) + { + wnd = this.iframe.contentWindow; + } + + // Call the resize handler (we have to use the jquery object of the iframe!) + if (wnd && typeof wnd.$j != "undefined") + { + wnd.$j(wnd).trigger("resize"); + } + }, + + /** + * Resizes both, the contentDiv and the iframe to the size returned from the heightCallback + */ + resize: function() + { + var height = this.heightCallback.call(this.iframe) + 'px'; + + //Set the height of the content div or the iframe + if (this.contentDiv) + { + this.contentDiv.style.height = height; + } + if (this.iframe) + { + this.iframe.style.height = height; + } + }, + + /** + * Sets browser type either DIV or IFRAME + * + * @param {int} _type + */ + setBrowserType: function(_type) + { + //Only do anything if the browser type has changed + if (_type != this.type) + { + //Destroy the iframe and/or the contentDiv + $j(this.baseDiv).empty(); + this.iframe = null; + this.contentDiv = null; + this.ajaxLoaderDiv = null; + + switch (_type) + { + //Create the div for displaying the content + case EGW_BROWSER_TYPE_DIV: + this.contentDiv = document.createElement('div'); + $j(this.contentDiv).addClass('egw_fw_content_browser_div'); + $j(this.baseDiv).append(this.contentDiv); + + break; + + case EGW_BROWSER_TYPE_IFRAME: + //Create the iframe + this.iframe = document.createElement('iframe'); + this.iframe.style.width = "100%"; + this.iframe.style.borderWidth = 0; + this.iframe.frameBorder = 0; + this.iframe.name = 'egw_app_iframe_' + this.app.appName; + $j(this.iframe).addClass('egw_fw_content_browser_iframe'); + $j(this.baseDiv).append(this.iframe); + + break; + } + + this.resize(); + this.type = _type; + } + }, + + /** + * Sets url to browse and load the content in proper content browser + * @param {string} _url + */ + browse: function(_url) + { + // check if app has its own linkHandler and it accepts the link (returns true), or returns different url instead + if (typeof window.app == 'object' && typeof window.app[this.app.appName] == 'object' && + typeof window.app[this.app.appName].linkHandler == 'function') + { + var ret = window.app[this.app.appName].linkHandler.call(window.app[this.app.appName], _url); + { + if (ret === true) return; + if (typeof ret === 'string') + { + _url = ret; + } + } + } + var useIframe = true; + var targetUrl = _url; + + // Check whether the given url is a pseudo url which should be executed + // by calling the ajax_exec function + // we now send whole url back to server, so apps can use $_GET['ajax']==='true' + // to detect app-icon was clicked and eg. further reset filters + var matches = _url.match(/\/index.php\?menuaction=([A-Za-z0-9_\.]*.*&ajax=true.*)$/); + if (matches) { + // Matches[1] contains the menuaction which should be executed - replace + // the given url with the following line. This will be evaluated by the + // jdots_framework ajax_exec function which will be called by the code + // below as we set useIframe to false. + targetUrl = "index.php?menuaction=" + matches[1]; + useIframe = false; + } + + // Destroy application js + if(window.app[this.app.appName] && window.app[this.app.appName].destroy) + { + window.app[this.app.appName].destroy(); + } + + // Unload etemplate2, if there + if(typeof etemplate2 == "function") + { + // Clear all etemplates on this tab, regardless of application, by using DOM nodes + $j('.et2_container',this.contentDiv||this.baseDiv).each(function() { + var et = etemplate2.getById(this.id); + if(et !== null) + { + et.clear(); + } + }); + } + else if(this.iframe && typeof this.iframe.contentWindow.etemplate2 == "function") + { + try + { + if(typeof this.iframe.contentWindow.etemplate2 == "function") + { + // Clear all etemplates on this tab, regardless of application, by using DOM nodes + var content = this.iframe.contentWindow; + $j('.et2_container',this.iframe.contentWindow).each(function() { + var et = content.etemplate2.getById(this.id); + if(et !== null) + { + et.clear(); + } + }); + } + } + catch(e) {} // catch error if eg. SiteMgr runs a different origin, otherwise tab cant be closed + } + + //Set the browser type + if (useIframe) + { + this.setBrowserType(EGW_BROWSER_TYPE_IFRAME); + + //Postpone the actual "navigation" - gives some speedup with internet explorer + //as it does no longer blocks the complete page until all frames have loaded. + var self = this; + window.setTimeout(function() { + //Load the iframe content + self.iframe.src = _url; + + //Set the "_legacy_iframe" flag to allow link handlers to easily determine + //the type of the link source + if (self.iframe && self.iframe.contentWindow) { + try { + self.iframe.contentWindow._legacy_iframe = true; + + // Focus the iframe of the current application + if (self.app == framework.activeApp) + { + self.iframe.contentWindow.focus(); + } + } + catch (e) { + // ignoer SecurityError: Blocked a frame ..., caused by different origin + } + } + }, 1); + } + else + { + this.setBrowserType(EGW_BROWSER_TYPE_DIV); + + // Save the actual url which has been passed as parameter + this.currentLocation = _url; + + //Special treatement of "about:blank" + if (targetUrl == "about:blank") + { + if (this.app.sidemenuEntry) + this.app.sidemenuEntry.hideAjaxLoader(); + + egw_widgetReplace(this.app.appName, this.contentDiv, ''); + } + else + { + //Perform an AJAX request loading application output + if (this.app.sidemenuEntry) + this.app.sidemenuEntry.showAjaxLoader(); + this.data = ""; + $j(this.contentDiv).empty(); + var self_egw = egw(this.app.appName); + var req = self_egw.json( + this.app.getMenuaction('ajax_exec'), + [targetUrl], this.browse_callback,this, true, this + ); + req.sendRequest(); + } + } + }, + + /** + * + * @param {type} _data + * @return {undefined} return undefined if data is not from the right response + */ + browse_callback: function(_data) + { + // Abort if data is from wrong kind of response - only 'data' + if(!_data || _data.type != undefined) return; + + this.data = _data[0]; + this.browse_finished(); + }, + + /** + * Get call via browse_callback in order to attaching nodes to the DOM + */ + browse_finished: function() + { + if (this.app.sidemenuEntry) + this.app.sidemenuEntry.hideAjaxLoader(); + // egw_widgetReplace(this.app.appName, this.contentDiv, this.data); + content = { + html: this.data, + js: '' + }; + + if (this.app == framework.activeApp) + { + window.focus(); + } + + egw_seperateJavaScript(content); + + // Insert the content + $j(this.contentDiv).append(content.html); + + // Run the javascript code + //console.log(content.js); + $j(this.contentDiv).append(content.js); + }, + + /** + * REload the content of the browser object + */ + reload: function() + { + switch (this.type) + { + case EGW_BROWSER_TYPE_DIV: + this.browse(this.currentLocation); + break; + + case EGW_BROWSER_TYPE_IFRAME: + //Do a simple reload in the iframe case + this.iframe.contentWindow.location.reload(); + break; + } + }, + + /** + * + */ + blank: function() + { + this.browse('about:blank', this.type == EGW_BROWSER_TYPE_IFRAME); + } + + + +});