Widgets Lifecycle
Widgets are small - non re sizable - pure javascripts components to be deployed in the eXo portal. They can be added in the left column (and sorted there) or inside the WebOS layout.Init Phase
Widgets are bundled - like portlets - inside dedicated WARs and hence initialized thanks to a ServletListener. Hence each portlet is referenced inside the WebAppController object.public class ApplicationRegister implements ServletContextListener { protected static Log log = ExoLogger.getLogger("widget:ApplicationRegister"); /** * Each time a new widget application war is deployed then widgets are registered into the * WebAppController */ public void contextInitialized(ServletContextEvent event) { try { String applications = event.getServletContext().getInitParameter("exo.application"); String[] classes = applications.split(",") ; RootContainer root = RootContainer.getInstance() ; PortalContainer pcontainer = root.getPortalContainer("portal") ; WebAppController controller = (WebAppController)pcontainer.getComponentInstanceOfType(WebAppController.class) ; ClassLoader loader = Thread.currentThread().getContextClassLoader() ; for(String className : classes) { className = className.trim() ; log.info("Deploy Widget class name: " + className); Class type = loader.loadClass(className) ; Application application = (Application)type.newInstance() ; controller.addApplication(application) ; } } catch(Exception ex) { log.error("Error while deploying a widget", ex); } }
abstract public class WidgetApplication<T> extends Application { public String getApplicationType() { return "eXoWidget" ; } abstract public void processRender(T uiWidget, Writer w) throws Exception ; public ResourceBundle getOwnerResourceBundle(String username, Locale locale) throws Exception { throw new Exception("This method is not supported") ; } public ResourceBundle getResourceBundle(Locale locale) throws Exception { throw new Exception("This method is not supported") ; } }
Render Phase
When the Portal is built, UIWidget components are bound to the UI component tree. The UIWidget class extends the UIComponent but it is a simple wrapper that does not contain any business logic as it is delegated to the UIWidgetLifecycle./** * The processRender method of the UIWidget component is implemented in its bound Lifecycle object. * * The Lifecycle itself simply delegates the call to the WidgetApplication stored in the IoC WebAppController * component */ @SuppressWarnings("unchecked") public void processRender(UIComponent uicomponent , WebuiRequestContext context) throws Exception { UIWidget uiWidget = (UIWidget) uicomponent ; PortalContainer container = PortalContainer.getInstance() ; WebAppController controller = (WebAppController)container.getComponentInstanceOfType(WebAppController.class) ; WidgetApplication application = (WidgetApplication) controller.getApplication(uiWidget.getApplicationId()) ; if(application != null) application.processRender(uiWidget, context.getWriter()) ; }
public class InfoWidget extends WidgetApplication<UIWidget> { public String getApplicationId() { return "eXoWidgetWeb/InfoWidget"; } public String getApplicationName() { return "InfoWidget"; } public String getApplicationGroup() { return "eXoWidgetWeb"; } public void processRender(UIWidget uiWidget, Writer w) throws Exception { PortalRequestContext pContext = Util.getPortalRequestContext(); MVCRequestContext appReqContext = new MVCRequestContext(this, pContext) ; int instanceId = uiWidget.getApplicationInstanceId().hashCode() ; int posX = uiWidget.getProperties().getIntValue("locationX") ; int posY = uiWidget.getProperties().getIntValue("locationY") ; int zIndex = uiWidget.getProperties().getIntValue("zIndex") ; w.write("<div id = 'UIInfoWidget' applicationId = '"+instanceId+"' posX = '"+posX+"' posY = '"+posY+"' zIndex = '"+zIndex+"'><span></span></div>") ; String script = "eXo.portal.UIPortal.createJSApplication('eXo.widget.web.info.UIInfoWidget','UIInfoWidget','"+instanceId+"','/eXoWidgetWeb/javascript/');"; appReqContext.getJavascriptManager().addCustomizedOnLoadScript(script) ; } }
<script type="text/javascript">
<%=rcontext.getJavascriptManager().getJavascript()%>
eXo.core.Browser.onLoad();
<%=rcontext.getJavascriptManager().getCustomizedOnLoadScript();%>
</script>eXo.core.Browser.onLoad();
eXo.portal.UIPortal.createJSApplication('eXo.widget.web.welcome.UIWelcomeWidget','UIWelcomeWidget','1292191470','/eXoWidgetWeb/javascript/');Javascript Phase
Once the HTML is returned to the client and hence the server phase is over, the browser still needs to load the javascript scripts on the client. Some of them are dynamically loaded and cached The UIPortal.js script contains the createJSApplication() application as shown in the following js code fragment/* * This method will start the creation of a new javascript application such as a widget * * - The application parameter is the full javascript class for the application (for example "eXo.widget.web.info.UIInfoWidget") * - The application id is an id shared among all the application instance * - The instance id is unique among all the javascript application deployed in the layout * - The appLocation is the root path location of the jstmpl file on the server (for example /eXoWidgetWeb/javascript/) * * If the application class name is not null, the associated .js file on the server is loaded using the eXo.require() method * * Once loaded the initApplication() method is called; in other words, the application is lazy instantiated and initialized * on the client browser */ UIPortal.prototype.createJSApplication = function(application, applicationId, instanceId, appLocation) { if(application) { eXo.require(application, appLocation); var createApplication = application + '.initApplication(\''+applicationId+'\',\''+instanceId+'\');' ; eval(createApplication); } } ;
/* * This method will : * 1) dynamically load a javascript module from the server (if no root location is set * then use '/eXoResources/javascript/', aka files * located in the eXoResources WAR in the application server). * The method used underneath is a XMLHttpRequest * 2) Evaluate the returned script * 3) Cache the script on the client * */ eXo.require = function(module, jsLocation) { try { if(eval(module + ' != null')) return ; } catch(err) { //alert(err + " : " + module); } window.status = "Loading Javascript Module " + module ; if(jsLocation == null) jsLocation = '/eXoResources/javascript/' ; var path = jsLocation + module.replace(/\./g, '/') + '.js' ; var request = eXo.core.Browser.createHttpRequest() ; request.open('GET', path, false) ; request.setRequestHeader("Cache-Control", "max-age=86400") ; request.send(null) ; try { eval(request.responseText) ; } catch(err) { alert(err + " : " + request.responseText) ; } } ;
eXo.require('eXo.widget.UIExoWidget');
UIInfoWidget.prototype = eXo.widget.UIExoWidget;
UIInfoWidget.prototype.constructor = UIInfoWidget;
function UIInfoWidget() {
this.init("UIInfoWidget", "info");
}
if(eXo.widget.web == null) eXo.widget.web = {} ;
if(eXo.widget.web.info == null) eXo.widget.web.info = {};
eXo.widget.web.info.UIInfoWidget = new UIInfoWidget() ;/* * This method is used by any user widget to init itself * * - The widget name is is extracted from the full class name * - A widget can have an icon to be then used in several locations like the application registry * - A widget must have a width of maximum 220px to fit in the left column of eXo Portal * - A widget can provide different skins but only a default is mandatory * */ UIExoWidget.prototype.init = function(appName, appFolder, attrsWidget) { this.appCategory = "eXoWidgetWeb" ; this.appName = appName ; this.attrsWidget = attrsWidget; this.appFolder = appFolder; var nameWidget = eXo.widget.UIExoWidget.getNameWidget(appName); this.appIcon = "/eXoResources/skin/DefaultSkin/portal/webui/component/view/UIPageDesktop/icons/80x80/"+nameWidget+".png" ; this.skin = { Default: "/eXoWidgetWeb/skin/"+appFolder+"/DefaultStylesheet.css", Mac: "/eXoWidgetWeb/skin/"+appFolder+"/MacStylesheet.css", Vista: "/eXoWidgetWeb/skin/"+appFolder+"/VistaStylesheet.css" } ; this.width = "220px" ; this.height = "auto" ; };
on 21/08/2007 at 06:31