jetspeed.ui._loadPortletWindowsから・・・
jetspeed.ui._loadPortletWindows = function( /* Portlet[] */ portletArray, windowsToRender, portletWindowFactory ) { if ( portletArray ) { for ( var i = 0; i < portletArray.length; i++ ) { var portlet = portletArray[i]; if ( jetspeed.debugPortletEntityIdFilter ) { if ( ! dojo.lang.inArray( jetspeed.debugPortletEntityIdFilter, portlet.entityId ) ) portlet = null; } if ( portlet ) { windowsToRender.push( portlet ); portlet.createPortletWindow( portletWindowFactory, null ); } } } };
デバッグの部分は気にしないで進むと、ポートレット配列があれば、ポートレットを順にwindowsToRender配列に入れて、createPortletWindowを呼び出していく。そのcreatePortletWindowは
createPortletWindow: function( portletWindowFactory, portletContentListener ) { jetspeed.ui.createPortletWindow( this, portletWindowFactory, portletContentListener ); },
だから、jetspeed.ui.createPortletWindowに行き、
jetspeed.ui.createPortletWindow = function( windowConfigObject, portletWindowFactory, portletContentListener ) { if ( portletWindowFactory == null ) { var winPositionStatic = windowConfigObject.getProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC ); if ( winPositionStatic == null ) winPositionStatic = ( jetspeed.prefs.windowTiling ? true : false ); // BOZO: what to do about setting the value here ( putProperty ) if ( ! winPositionStatic ) portletWindowFactory = new jetspeed.om.PortletWindowFactory() ; else portletWindowFactory = new jetspeed.om.PortletTilingWindowFactory() ; } var windowWidget = dojo.widget.byId( windowConfigObject.getProperty( jetspeed.id.PORTLET_PROP_WIDGET_ID ) ); // get existing window widget if ( windowWidget ) { portletWindowFactory.reset( windowConfigObject, windowWidget ) ; } else { windowWidget = portletWindowFactory.create( windowConfigObject ) ; } if ( windowWidget ) { portletWindowFactory.layout( windowConfigObject, windowWidget ); } };
ここで、引数を確認すると、windowConfigObjectはポートレットで、 portletWindowFactoryとportletContentListenerはnullと思われる。というわけで、始めのif文には入るわけだな。っで、winPositionStaticは true と思われるから、jetspeed.om.PortletTilingWindowFactoryの方になるのかね。そのコンストラクタでは何もしないようだ。
jetspeed.om.PortletTilingWindowFactory = function() { };
というわけで、次に進み、windowConfigObject.getProperty( jetspeed.id.PORTLET_PROP_WIDGET_ID )は、jetspeed.om.Portletのinitializeで、jetspeed.id.PORTLET_WINDOW_ID_PREFIX + this.entityIdを入れている。まぁ、この段階では、windowWidgetはnullだろうから、portletWindowFactory.createの方に入って、
create: function( windowConfigObject ) { return jetspeed.ui.createPortletWindowWidget( windowConfigObject ); },
っで、
jetspeed.ui.createPortletWindowWidget = function( windowConfigObject, createWidgetParams ) { if ( ! createWidgetParams ) createWidgetParams = {}; if ( windowConfigObject instanceof jetspeed.om.Portlet ) { createWidgetParams.portlet = windowConfigObject; } else { jetspeed.ui.widget.PortletWindow.prototype.staticDefineAsAltInitParameters( createWidgetParams, windowConfigObject ); } // NOTE: other parameters, such as widgetId could be set here (to override what PortletWindow does) var nWidget = dojo.widget.createWidget( 'PortletWindow', createWidgetParams ); return nWidget; };
createWidgetParamsはnullだろうから、始めのif文に入り、windowConfigObjectはjetspeed.om.Portletだから、createWidgetParams.portletにセットされ、dojo.widget.createWidgetが実行される。createWidgetについて、たいした情報はないけど、http://dojo.jot.com/WidgetExamples あたりだろうか。
PortletWindow については、src/webapp/javascript/desktop/widget/PortletWindow.jsに定義してあるみたい。そのコンストラクタは、
jetspeed.ui.widget.PortletWindow = function() { jetspeed.ui.widget.BaseFloatingPane.call( this ); this.widgetType = "PortletWindow"; this.portletInitialized = false; };
っで、親がBaseFloatingPaneなので、
jetspeed.ui.widget.BaseFloatingPane = function(){ dojo.widget.html.ContentPane.call(this); }
その親がdojoのContentPaneなわけね。こんな感じで、ウィジェットが作られて、jetspeed.ui.createPortletWindowに戻る。
次に
if ( windowWidget ) { portletWindowFactory.layout( windowConfigObject, windowWidget ); }
だから、そのlayoutは
layout: function( windowConfigObject, /* PortletWindow */ portletWindowWidget ) { var windowPositionStatic = windowConfigObject.getProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC ); if ( ! windowPositionStatic ) { portletWindowWidget.domNode.style.position = "absolute"; var addToElmt = document.getElementById( jetspeed.id.DESKTOP ); addToElmt.appendChild( portletWindowWidget.domNode ); } else { var useColumnElmt = null; var useColumnIndex = -1; var preferredColumn = windowConfigObject.getProperty( jetspeed.id.PORTLET_PROP_COLUMN ); if ( preferredColumn >= 0 && preferredColumn < jetspeed.columns.length ) { useColumnIndex = preferredColumn; useColumnElmt = jetspeed.columns[ useColumnIndex ]; } if ( useColumnIndex == -1 ) { // select a column based on least populated (least number of child nodes) for ( var i = 0 ; i < jetspeed.columns.length ; i++ ) { var columnElmt = jetspeed.columns[i]; if ( ! columnElmt.hasChildNodes() ) { useColumnElmt = columnElmt; useColumnIndex = i; break; } if ( useColumnElmt == null || useColumnElmt.childNodes.length > columnElmt.childNodes.length ) { useColumnElmt = columnElmt; useColumnIndex = i; } } } if ( useColumnElmt ) { useColumnElmt.appendChild( portletWindowWidget.domNode ); } } } }
位置が固定じゃないなら、if文に入り、jetspeed.id.DESKTOP属性を持つdivタグにdomNodeを貼り付けて、位置が固定なら、列のdivタグを見つけて、それに貼り付ける。はて、domNodeはどの段階で作られたのだろうか・・・。
この謎を解くためには、http://manual.dojotoolkit.org/widget/Widget.html にあるように、いくつか上書きするメソッド見たいのがあるみたい。PortletWindowを見てみると、postCreate がある。つまり、ウィジェットを作ると、こいつが呼ばれると思われる。というわけで、見ていこう。
postCreate: function( args, fragment, parentComp ) { jetspeed.ui.widget.PortletWindow.superclass.postCreate.call( this ); this.dragSource = new jetspeed.ui.widget.PortletWindowDragMoveSource( this ); if ( this.constrainToContainer ) { this.dragSource.constrainTo(); } this.dragSource.setDragHandle( this.titleBar ); this.domNode.id = this.widgetId; // BOZO: must set the id here - it gets defensively cleared by dojo this.portletPostCreate(); this.createTitleBarContextMenu(); if ( jetspeed.debug.createWindow ) dojo.debug( "createdWindow [" + ( this.portlet ? this.portlet.entityId : this.widgetId ) + "]" + " width=" + this.domNode.style.width + " height=" + this.domNode.style.height + " left=" + this.domNode.style.left + " top=" + this.domNode.style.top ) ; this.portletInitialized = true; var initWindowState = this.getInitProperty( jetspeed.id.PORTLET_PROP_WINDOW_STATE ); if ( initWindowState == "minimized" ) this.minimizeWindow(); },
まぁ、始めの~superclass.postCreateは、BaseFloatingPaneが持っていないので、その親に行くのかな。BaseFloatingPaneの親はdojoのウィジェットだから、そこまでは追うのはやめておこ。っで次には、ドラッグアンドドロップ関連のウィジェットを作るみたいだな。
jetspeed.ui.widget.PortletWindowDragMoveSource = function( /* jetspeed.ui.widget.PortletWindow */ portletWindow, type) { this.portletWindow = portletWindow; dojo.dnd.HtmlDragMoveSource.call(this, portletWindow.domNode, type); }; dojo.inherits( jetspeed.ui.widget.PortletWindowDragMoveSource, dojo.dnd.HtmlDragMoveSource ); dojo.lang.extend( jetspeed.ui.widget.PortletWindowDragMoveSource, { onDragStart: function() { // BOZO: code copied from dojo.dnd.HtmlDragMoveSource.onDragStart to change dragObject var dragObj = new jetspeed.ui.widget.PortletWindowDragMoveObject( this.portletWindow, this.dragObject, this.type ); if ( this.constrainToContainer ) { dragObj.constrainTo( this.constrainingContainer ); } return dragObj; }, onDragEnd: function() { } });
まぁ、以上のような感じで、親がdojo.dnd.HtmlDragMoveSourceということで、ここではこんな感じかとわかれば、深追いする必要はないだろう。this.dragSource.setDragHandle( this.titleBar );では、たぶん、タイトルバーでのドラッグアンドドロップを有効にするのだろう(推測)。次に、this.domNode.id = this.widgetId;としているが、つまり、この段階で、既に、domNodeが生成されていると言うことになる。なんだかわかりにくいので、ちょっと、dojoのウィジェット処理について、確認しよう。現在のPortletWindowの継承図は以下のようになる。
dojo.widget.Widget ↑ dojo.widget.DomWidget ↑ dojo.widget.HtmlWidget ↑ dojo.widget.html.ContentPane ↑ jetspeed.ui.widget.BaseFloatingPane ↑ jetspeed.ui.widget.PortletWindow
では、ウィジェットはどう作られるのだろうか。現状の情報から推測すると、createで作成されると思われる。これらのウィジェットを確認すると、dojo.widget.Widgetしかcreateを持っていないので、それが呼ばれているみたい。createは、
create: function(args, fragment, parentComp){ // dojo.debug(this.widgetType, "create"); this.satisfyPropertySets(args, fragment, parentComp); // dojo.debug(this.widgetType, "-> mixInProperties"); this.mixInProperties(args, fragment, parentComp); // dojo.debug(this.widgetType, "-> postMixInProperties"); this.postMixInProperties(args, fragment, parentComp); // dojo.debug(this.widgetType, "-> dojo.widget.manager.add"); dojo.widget.manager.add(this); // dojo.debug(this.widgetType, "-> buildRendering"); this.buildRendering(args, fragment, parentComp); // dojo.debug(this.widgetType, "-> initialize"); this.initialize(args, fragment, parentComp); // dojo.debug(this.widgetType, "-> postInitialize"); this.postInitialize(args, fragment, parentComp); // dojo.debug(this.widgetType, "-> postCreate"); this.postCreate(args, fragment, parentComp); // dojo.debug(this.widgetType, "done!"); return this; },
ふむ、なるほど、こういう順番で呼ばれるのね。postCreateは本当に最後だな。どうやら見てみると、domNodeはbuildRenderingのところで作られているっぽい。一連のウィジェットの中では、dojo.widget.DomWidgetがそれを持つ。それは、以下のようなもの。
buildRendering: function(args, frag){ // DOM widgets construct themselves from a template var ts = dojo.widget._templateCache[this.widgetType]; if( (!this.preventClobber)&&( (this.templatePath)|| (this.templateNode)|| ( (this["templateString"])&&(this.templateString.length) )|| ( (typeof ts != "undefined")&&( (ts["string"])||(ts["node"]) ) ) ) ){ // if it looks like we can build the thing from a template, do it! this.buildFromTemplate(args, frag); }else{ // otherwise, assign the DOM node that was the source of the widget // parsing to be the root node this.domNode = this.getFragNodeRef(frag); } this.fillInTemplate(args, frag); // this is where individual widgets // will handle population of data // from properties, remote data // sets, etc. },
たぶん、buildFromtemplate で domNodeがテンプレートから作成されると思われる。ここで、最後のfillInTemplateとあるが、このメソッドは、PortletWindowにも定義されているので、それが呼び出されるだろう。
fillInTemplate: function( args, frag ) { this.portletFillInTemplate(); //dojo.debug( "fillInTemplate-a [" + this.widgetId + "] containerNode-outerwidth: " + dojo.style.getOuterWidth( this.containerNode ) + " containerNode-contentwidth: " + dojo.style.getContentWidth( this.containerNode ) + " domNode-outerwidth: " + dojo.style.getOuterWidth( this.domNode ) ); jetspeed.ui.widget.PortletWindow.superclass.fillInTemplate.call( this, args, frag ); //dojo.debug( "fillInTemplate-b [" + this.widgetId + "] containerNode-outerwidth: " + dojo.style.getOuterWidth( this.containerNode ) + " containerNode-contentwidth: " + dojo.style.getContentWidth( this.containerNode ) + " domNode-outerwidth: " + dojo.style.getOuterWidth( this.domNode ) ); },
デバッグの部分を無視すると、portletFillInTemplateだから、
portletFillInTemplate: function() { var isResizable = this.resizable; if ( isResizable ) { this.resizeBar.style.display = "block"; var rh = null; var rhWidgetId = this.widgetId + "_resize"; if ( ! this.portletInitialized ) rh = dojo.widget.createWidget( "PortletWindowResizeHandle", { targetElmId: this.widgetId, id: rhWidgetId, portletWindow: this } ); else rh = dojo.widget.byId( rhWidgetId ); if ( rh ) { if ( this.windowPositionStatic && dojo.render.html.mozilla ) // dojo.render.html.ie rh.domNode.style.position = "static"; else rh.domNode.style.position = "absolute"; if ( ! this.portletInitialized ) this.resizeBar.appendChild( rh.domNode ); } } },
ざっとみると、リサイズが起きたときのハンドラが貼り付けられたように見える。まぁ、これ以上ここでは追わなくても大丈夫だろう。
あと、dojo.widget.Widgetのcreateで気になるのは、postMixInPropertiesかね。これまた、PortletWindowにある。
postMixInProperties: function( args, fragment, parentComp ) { jetspeed.ui.widget.PortletWindow.superclass.postMixInProperties.call( this ); this.portletIndex = this._getNextIndex(); var initWidgetId = this.getInitProperty( jetspeed.id.PORTLET_PROP_WIDGET_ID ); if ( this.portlet ) { if ( this.widgetId ) { dojo.raise( "PortletWindow.widgetId (" + this.widgetId + ") should not be assigned directly" ); } if ( ! initWidgetId ) { dojo.raise( "PortletWindow.widgetId is not defined for portlet [" + this.portlet.entityId + "] - Portlet.initialize may not have been called" ); } this.widgetId = initWidgetId; } else { if ( initWidgetId ) this.widgetId = initWidgetId; else if ( ! this.widgetId ) this.widgetId = jetspeed.id.PORTLET_WINDOW_ID_PREFIX + this.portletIndex; } this._incrementNextIndex(); this.templatePath = jetspeed.ui.getDefaultFloatingPaneTemplate(); this.portletMixinProperties( fragment ); //dojo.debug("PortletWindow widgetId=" + this.widgetId + " windowtheme=" + windowtheme + " templateCssPath=" + this.templateCssPath); },
this.portletIndexをセットして、idがおかしければ、dojo.raiseでエラーをあげる。dojo.raiseについては、http://manual.dojotoolkit.org/dojo.html を参照。そんで、インデックスをインクリメントしておき、templatePathを取得。jetspeed.ui.getDefaultFloatingPaneTemplateは、
jetspeed.ui.getDefaultFloatingPaneTemplate = function() { return new dojo.uri.Uri(jetspeed.url.basePortalDesktopUrl() + "/javascript/desktop/widget/HtmlFloatingPane.html"); // BOZO: improve this junk };
一応、HtmlFloatingPane.htmlも見てみると、
<div id="${this.widgetId}" class="dojoFloatingPane" > <!-- dojoAttachEvent="onMouseDown" --> <div id="${this.widgetId}_titleBar" dojoAttachPoint="titleBar" class="dojoFloatingPaneTitleBar" dojoAttachEvent="onMouseDown;onMouseOver:titleMouseOver;onMouseOut:titleMouseOut" style="display:none"> <img dojoAttachPoint="titleBarIcon" class="dojoFloatingPaneTitleBarIcon"> <div dojoAttachPoint="closeAction" dojoAttachEvent="onClick:closeWindow" class="dojoFloatingPaneCloseIcon"></div> <div dojoAttachPoint="maximizeAction" dojoAttachEvent="onClick:maximizeWindow" class="dojoFloatingPaneMaximizeIcon"></div> <div dojoAttachPoint="restoreAction" dojoAttachEvent="onClick:restoreWindow" class="dojoFloatingPaneRestoreIcon"></div> <div dojoAttachPoint="minimizeAction" dojoAttachEvent="onClick:minimizeWindow" class="dojoFloatingPaneMinimizeIcon"></div> <div dojoAttachPoint="titleBarText" class="dojoFloatingPaneTitleText">${this.title}</div> </div> <div dojoAttachPoint="containerNode" class="dojoFloatingPaneClient"></div> <div dojoAttachPoint="resizeBar" class="dojoFloatingPaneResizebar"></div> </div>
と言う感じ。つまり、これにあわせてスタイルシートを書けば、そのデザインになるのね。
っで、戻って、this.portletMixinPropertiesだね。
portletMixinProperties: function( fragment ) { this.setWindowTheme( fragment ); this.setWindowTitle( fragment ); this.setWindowIcon( fragment ); if ( dojo.render.html.mozilla ) // dojo.render.html.ie { //this.hasShadow = "true"; // dojo.debug( "nWidget.domNode.cssText: " + //nWidget.domNode.style = "overflow: visible;"; // so that drop shadow is displayed } this.setWindowDimensions( fragment ); },
ここで、fragmentも少々気になるが、「Object. A subtree section from the return of the dojo.xml.Parser system.」とあるけど、実際にはどんなものかわからん(まぁ、fragmentを使って、何かしているわけではないみたいなので、次へ進もう)。まず、setWindowThemeは、
setWindowTheme: function( fragment ) { var windowtheme = this.getInitProperty( jetspeed.id.PORTLET_PROP_WINDOW_THEME ); if ( ! windowtheme ) { if ( this.portletWindowTheme ) windowtheme = this.portletWindowTheme; else windowtheme = jetspeed.page.getWindowThemeDefault(); } this.portletWindowTheme = windowtheme ; var prevCssPath = ( this.templateCssPath == null ? null : this.templateCssPath.toString() ); this.templateCssPath = new dojo.uri.Uri( jetspeed.url.basePortalWindowThemeUrl( windowtheme ) + "/css/styles.css" ); if ( this.portletInitialized ) { // load new stylesheet // BOZO: it would be nice to check if this were necessary if ( prevCssPath == null || prevCssPath != this.templateCssPath.toString() ) dojo.style.insertCssFile( this.templateCssPath, null, true ); } },
ここでは、テーマのtemplateCssPathをセットするのが目的みたいだな。確認しておくべきところは、
jetspeed.url.basePortalWindowThemeUrl = function( windowtheme ) { return jetspeed.url.basePortalDesktopUrl() + "/javascript/desktop/windowthemes/" + windowtheme; };
だな。ポートレットウィンドウのテーマは、/javascript/desktop/windowthemes/以下に置かれると言うことだ。なるほどね~。ここにおかんといかんのね。
次は、setWindowTitleで、
setWindowTitle: function( fragment ) { var windowtitle = this.getInitProperty( jetspeed.id.PORTLET_PROP_WINDOW_TITLE ); if ( windowtitle ) this.title = windowtitle; else if ( this.title == null ) this.title = ""; if ( this.portletInitialized ) { // BOZO: update title } },
やっぱり、タイトルは、現状、PSMLのIDが入るような気が・・・。
っで、setWindowIconは、
setWindowIcon: function( fragment ) { var windowicon = this.getInitProperty( jetspeed.id.PORTLET_PROP_WINDOW_ICON ); if ( ! windowicon ) { if ( jetspeed.debugPortletWindowIcons ) { windowicon = jetspeed.debugPortletWindowIcons[Math.floor(Math.random()*jetspeed.debugPortletWindowIcons.length)]; } } if ( windowicon ) this.iconSrc = new dojo.uri.Uri(jetspeed.url.basePortalDesktopUrl() + "/javascript/desktop/windowicons/" + windowicon ) ; else this.iconSrc = new dojo.uri.Uri(jetspeed.url.basePortalDesktopUrl() + "/javascript/desktop/windowicons/document.gif" ) ; if ( this.portletInitialized ) { if ( this.titleBarIcon ) this.titleBarIcon.src = this.iconSrc.toString(); } },
か。PSMLにアイコン情報まで置いておかんといかんのかね。これも、置く場所は、/javascript/desktop/windowicons/だね。
次はsetWindowDimensionsは、
setWindowDimensions: function( fragment ) { this.windowPositionStatic = this.getInitProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC ); this.windowColumnSpan = this.getInitProperty( jetspeed.id.PORTLET_PROP_COLUMN_SPAN ); if ( this.windowColumnSpan != null || this.windowPositionStatic ) this.windowIsColumnBound = true; this.constrainToContainer = 0; var portletWidth = null, portletHeight = null, portletLeft = null, portletTop = null; if ( this.portlet ) { var portletWindowState = this.portlet.getLastSavedWindowState(); portletWidth = portletWindowState.width; portletHeight = portletWindowState.height; portletLeft = portletWindowState.left; portletTop = portletWindowState.top; // NOTE: portletWindowState.zIndex; - should be dealt with in the creation order } else { portletWidth = this.getInitProperty( jetspeed.id.PORTLET_PROP_WIDTH ); portletHeight = this.getInitProperty( jetspeed.id.PORTLET_PROP_HEIGHT ); portletLeft = this.getInitProperty( jetspeed.id.PORTLET_PROP_LEFT ); portletTop = this.getInitProperty( jetspeed.id.PORTLET_PROP_TOP ); } if ( portletWidth != null && portletWidth > 0 ) portletWidth = Math.floor(portletWidth) + "px"; else portletWidth = jetspeed.prefs.defaultPortletWidth; if ( portletHeight != null && portletHeight > 0 ) portletHeight = Math.floor(portletHeight) + "px"; else portletHeight = jetspeed.prefs.defaultPortletHeight; if ( portletLeft != null && portletLeft >= 0 ) portletLeft = Math.floor(portletLeft) + "px"; else portletLeft = (((this.portletIndex -2) * 30 ) + 200) + "px"; if ( portletTop != null && portletTop >= 0 ) portletTop = Math.floor(portletTop) + "px"; else portletTop = (((this.portletIndex -2) * 30 ) + 170) + "px"; if ( ! this.portletInitialized ) { var source = this.getFragNodeRef( fragment ); var dimensionsCss = "width: " + portletWidth + ( ( portletHeight != null && portletHeight.length > 0 ) ? ( "; height: " + portletHeight ) : ""); if ( ! this.windowPositionStatic ) dimensionsCss += "; left: " + portletLeft + "; top: " + portletTop + ";"; source.style.cssText = dimensionsCss; //dojo.debug( "PortletWindow.setWindowDimensions: " + dimensionsCss ); } else { // update dimensions this.domNode.style.position = "absolute"; this.domNode.style.width = portletWidth; this.domNode.style.height = portletHeight; if ( ! this.windowPositionStatic ) { this.domNode.style.left = portletLeft; this.domNode.style.top = portletTop; } } },
長い・・・。でも、やっていることは、場所情報の設定だね。
一通り、見たところで、話をpostCreateに戻そう。this.domNode.id = this.widgetIdとした後は、portletPostCreateなので、
portletPostCreate: function() { if ( this.windowPositionStatic ) { this.domNode.style.position = "static"; // can't be done earlier this.domNode.style.left = "auto"; this.domNode.style.top = "auto"; } if ( this.windowPositionStatic && ! jetspeed.prefs.windowTilingVariableHeight ) { this.domNode.style.overflow = "visible"; this.domNode.style.height = ""; } else this.domNode.style.overflow = "hidden"; if ( this.windowPositionStatic && ! jetspeed.prefs.windowTilingVariableWidth ) { this.domNode.style.width = ""; if ( this.titleBar ) this.titleBar.style.width = ""; if ( this.resizeBar ) this.resizeBar.style.width = ""; } if ( ! this.templateDomNodeClassName ) this.templateDomNodeClassName = this.domNode.className; var domNodeClassName = this.templateDomNodeClassName; if ( this.portletWindowTheme ) { domNodeClassName = this.portletWindowTheme + ( domNodeClassName ? ( " " + domNodeClassName ) : "" ); } this.domNode.className = jetspeed.id.PORTLET_STYLE_CLASS + ( domNodeClassName ? ( " " + domNodeClassName ) : "" ); if ( this.containerNode ) { if ( ! this.templateContainerNodeClassName ) this.templateContainerNodeClassName = this.containerNode.className; var containerNodeClassName = this.templateContainerNodeClassName; if ( this.portletWindowTheme ) { containerNodeClassName = this.portletWindowTheme + ( containerNodeClassName ? ( " " + containerNodeClassName ) : "" ); } this.containerNode.className = jetspeed.id.PORTLET_STYLE_CLASS + ( containerNodeClassName ? ( " " + containerNodeClassName ) : "" ); if ( this.windowPositionStatic && ! jetspeed.prefs.windowTilingVariableHeight ) { this.containerNode.style.overflow = "visible"; this.containerNode.style.height = ""; } else this.containerNode.style.overflow = "auto"; if ( this.windowPositionStatic && ! jetspeed.prefs.windowTilingVariableWidth ) { //this.containerNode.style.width = ""; // commented-out with change to ie width 100% in resizeTo //dojo.debug( "portletPostCreate containerNode-width: " + dojo.style.getOuterWidth( this.containerNode ) + " domNode-width: " + this.domNode.style.width ); } } //dojo.debug( "PortletWindow.portletPostCreate [" + this.portlet.entityId + "] setting domNode.className=" + this.domNode.className + " containerNode.className=" + this.containerNode.className ); this.width = dojo.style.getOuterWidth( this.domNode ); this.height = dojo.style.getOuterHeight( this.domNode ); this.resetLostHeightWidth(); this.titleDim( true ); },
これまた、長いな・・・。なるほど、前半部分でスタイルを設定している。おもしろいのは、ポートレットのスタイルの書き換えだ。どうやって、ポートレットのテーマを設定するのかと思ったら、ここで、差し替えていたのね。始めは、this.domNode.classNameはdojoFloatingPaneだと思われるけど、それにテーマをくっつけているのだね。そんで、コンテンツ部分についても同様にスタイルを設定するのだね。そして、高さと幅を与えて、resetLostHeightWidthは、BaseFloatingPane.jsにあるから、
resetLostHeightWidth: function() { // figure out how much space is used for padding/borders etc. this.lostHeight= (dojo.style.getOuterHeight(this.domNode)-dojo.style.getContentHeight(this.domNode)) +dojo.style.getOuterHeight(this.titleBar) +dojo.style.getOuterHeight(this.resizeBar); this.lostWidth= dojo.style.getOuterWidth(this.domNode)-dojo.style.getContentWidth(this.domNode); },
これをみると、コンテンツ部分以外の高さと幅みたいだな。
次に、titleDimは、
titleDim: function( immediateForce ) { var mightBeExtinguished = [ this.restoreAction, this.maximizeAction, this.minimizeAction, this.closeAction ] ; var toBeExtinguished = [] ; for ( var i = 0 ; i < mightBeExtinguished.length ; i++ ) { var btn = mightBeExtinguished[i]; if ( immediateForce ) btn.style.visibility = "hidden" ; else if ( btn.style.visibility != "hidden" ) toBeExtinguished.push( btn ); } for ( var i = 0 ; i < toBeExtinguished.length ; i++ ) { toBeExtinguished[i].style.visibility = "hidden" ; } this.restoreAction.style.display = "none"; //jetspeed.ui.fadeOut( toBeExtinguished, 280, [ this.restoreAction ] ); // nodes in 3rd arg will be set to display=none this.titleLit = false ; },
ここでは、アクションボタンにhiddenを設定して見えなくしているのかね。titleLitをfalseにしているけど、何の値かね。
っで、postCreateに戻り、this.createTitleBarContextMenu();だな。
createTitleBarContextMenu: function() { var portletWindow = this; var titleBarContextMenu = dojo.widget.createWidget( "PopupMenu2", { id: this.widgetId + "_ctxmenu", targetNodeIds: [ this.titleBar.id ], contextMenuForWindow: false }, null ); var dumpPosMenuItem = dojo.widget.createWidget( "MenuItem2", { caption: "Dump Position"} ); var makeFreeFloating = dojo.widget.createWidget( "MenuItem2", { caption: "Make Free Floating"} ); //var twoColummLayoutMenuItem = dojo.widget.createWidget( "MenuItem2", { id: "jstb_menu_item3", caption: "Two Column Layout"} ); //var threeColummLayoutMenuItem = dojo.widget.createWidget( "MenuItem2", { id: "jstb_menu_item4", caption: "Three Column Layout"} ); dojo.event.connect( dumpPosMenuItem, "onClick", function(e) { portletWindow.dumpPostionInfo(); } ); dojo.event.connect( makeFreeFloating, "onClick", function(e) { portletWindow.makeFreeFloating(); } ); //dojo.event.connect( freeFormLayoutMenuItem, "onClick", function(e) { jetspeed.prefs.windowTiling = false; jetspeed.page.resetWindowLayout(); jetspeed.page.reload(); } ); //dojo.event.connect( twoColummLayoutMenuItem, "onClick", function(e) { jetspeed.prefs.windowTiling = 2; jetspeed.page.reload(); } ); //dojo.event.connect( threeColummLayoutMenuItem, "onClick", function(e) { jetspeed.prefs.windowTiling = 3; jetspeed.page.reload(); } ); titleBarContextMenu.addChild( dumpPosMenuItem ); titleBarContextMenu.addChild( makeFreeFloating ); //titleBarContextMenu.addChild( twoColummLayoutMenuItem ); //titleBarContextMenu.addChild( threeColummLayoutMenuItem ); document.body.appendChild( titleBarContextMenu.domNode ); },
タイトルのポップアップメニューを作るみたい。ポートレットウィンドウのタイトルバーを右クリックしてポップアップメニューが出てきたからな。
っで、postCreateの残りの部分は、
if ( jetspeed.debug.createWindow ) dojo.debug( "createdWindow [" + ( this.portlet ? this.portlet.entityId : this.widgetId ) + "]" + " width=" + this.domNode.style.width + " height=" + this.domNode.style.height + " left=" + this.domNode.style.left + " top=" + this.domNode.style.top ) ; this.portletInitialized = true; var initWindowState = this.getInitProperty( jetspeed.id.PORTLET_PROP_WINDOW_STATE ); if ( initWindowState == "minimized" ) this.minimizeWindow();
というわけで、デバッグはいいとして、初期化を判定する値のportletInitializedをtrueにして、最小化されているなら、minimizeWindowを実行するみたいだね。
だいぶ、離れたところで、戻るとjetspeed.loadPortletWindowsまで戻り、続きを見ると、
portletArray = jetspeed.page.getPortletArrayByZIndex(); jetspeed.ui._loadPortletWindows( portletArray, windowsToRender, portletWindowFactory ); if ( windowsToRender && windowsToRender.length > 0 ) { jetspeed.doRenderAll( null, windowsToRender, true ); } jetspeed.page.retrieveAllMenus(); // BOZO: should not be happening here!
からかな。getPortletArrayByZIndexは、
getPortletArrayByZIndex: function() { var portletArray = this.getPortletArray(); if ( ! portletArray ) return portletArray; var filteredPortletArray = []; for ( var i = 0 ; i < portletArray.length; i++ ) { if ( ! portletArray[i].getProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC ) ) filteredPortletArray.push( portletArray[i] ); } filteredPortletArray.sort( this._portletZIndexCompare ); return filteredPortletArray; },
だね。今度は、場所が固定じゃないやつを配列にして、ソートして返すと言うことだね。ソートの方法は、
_portletZIndexCompare: function( portletA, portletB ) { // uses saved state only - does not check with window widget var aZIndex = null; var bZIndex = null; var windowState = null; windowState = portletA.getLastSavedWindowState(); aZIndex = windowState.zIndex; windowState = portletB.getLastSavedWindowState(); bZIndex = windowState.zIndex; if ( aZIndex && ! bZIndex ) return -1; else if ( bZIndex && ! aZIndex ) return 1; else if ( aZIndex == bZIndex ) return 0; return ( aZIndex - bZIndex ); },
だな。つまり、z方向でソートすると言うことだな。っで、配列ができたら、また、jetspeed.ui._loadPortletWindowsを実行。まぁ、また、追う必要はないだろう。でも、さっきと違って、今度は場所が固定じゃない処理が実行されることになるのだろう。
そしたら、今まで処理したポートレットの配列windowsToRenderに対して、jetspeed.doRenderAllを実行。
jetspeed.doRenderAll = function( url, windowArray, isPageLoad ) { var debugMsg = jetspeed.debug.doRenderDoAction; var debugPageLoad = jetspeed.debug.pageLoad && isPageLoad; if ( ! windowArray ) windowArray = jetspeed.page.getPortletArray(); var renderMsg = ""; for ( var i = 0; i < windowArray.length; i++ ) { var renderObj = windowArray[i]; if ( (debugMsg || debugPageLoad) ) { if ( i > 0 ) renderMsg = renderMsg + ", "; if ( renderObj.entityId ) { renderMsg = renderMsg + renderObj.entityId; if ( debugPageLoad && renderObj.getProperty( jetspeed.id.PORTLET_PROP_WINDOW_TITLE ) ) renderMsg = renderMsg + " " + renderObj.getProperty( jetspeed.id.PORTLET_PROP_WINDOW_TITLE ); } else { var widgetId = null; if ( renderObj.getProperty != null ) widgetId = renderObj.getProperty( jetspeed.id.PORTLET_PROP_WIDGET_ID ); if ( ! widgetId ) widgetId = renderObj.widgetId; if ( ! widgetId ) widgetId = renderObj.toString(); renderMsg = renderMsg + widgetId; } } renderObj.retrieveContent( null, url ); } if ( debugMsg ) dojo.debug( "doRenderAll [" + renderMsg + "] url: " + url ); else if ( debugPageLoad ) // this.getPsmlUrl() ; dojo.debug( "doRenderAll page-url: " + jetspeed.page.getPsmlUrl() + " portlets: [" + renderMsg + "]" + ( url ? ( " url: " + url ) : "" ) ); };
何かいろいろと書いてあるけど、デバッグコードを無視すると、表示するためのポートレット配列に対して、renderObj.retrieveContentを実行しているだけっぽいな。urlはここでは、nullなので、retrieveContentには、null,nullを渡すことになるな。
retrieveContent: function( contentListener, renderOrActionUrl, actionForm ) { if ( contentListener == null ) contentListener = new jetspeed.om.PortletContentListener() ; var portlet = this ; var requestUrl = portlet.getPortletUrl( renderOrActionUrl ) ; this.contentRetriever.getContent( requestUrl, contentListener, actionForm, null, portlet, jetspeed.debugContentDumpIds ); },
contentListernerはnullだから、PortletContentListenerを作成する。
jetspeed.om.PortletContentListener = function() { };
コンストラクタでは何もしていない模様。っで、次に進み、getPortletUrlでurlを取得する。引数にはnullを渡すことになるな。
getPortletUrl: function( renderUrl ) { var queryString = "?entity=" + this.entityId + "&portlet=" + this.name + "&encoder=desktop"; if (renderUrl) return renderUrl + queryString; return jetspeed.url.basePortalUrl() + jetspeed.url.path.PORTLET + queryString; },
作成されるURLは、http://localhost:8080/palportal/portlet?entity=<Entity ID>&portlet=<Portlet Name>&encoder=desktop といった感じだろうか。そして、this.contentRetriever.getContentを呼び出し。contentRetrieverについては、既に確認したけど、jetspeed.om.PortletContentRetrieverである。それで、getContentは、
jetspeed.om.PortletContentRetriever.prototype = { // /* Portlet */ portlet, /* String */ requestUrl, /* PortletContentListener */ portletContentListener getContent: function( /* String */ requestUrl, contentListener, /* DOM Form */ formObject, /* String */ mimeType, domainModelObject, /* String[] */ debugContentDumpIds ) { jetspeed.url.retrieveContent( requestUrl, contentListener, formObject, mimeType, domainModelObject, debugContentDumpIds ); } };
jetspeed.url.retrieveContentを呼び出し。このメソッドは、既に PSML の取得で見たやつだな。
今日はここまで・・・