// Licensed Materials - Property of IBM // // IBM Cognos Products: cpscrn // // (C) Copyright IBM Corp. 2005, 2011 // // US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. // // // Copyright (C) 2008 Cognos ULC, an IBM Company. All rights reserved. // Cognos (R) is a trademark of Cognos ULC, (formerly Cognos Incorporated). //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // PageLayout /* Classes defined in this files: CPage - application level API, owns everything CLayout - holds an object hierachy that represents a layout, serializable in multiple formats CRow - a simple holder of columns, serializable CColumn - contain rows or is a valid dropzone for portlets CZone - hold the portlets for a dropzone column and manages all interactions CPortlet - represents the portlet properties and proxies for a CPanel CPanel - handles all interactions with the moveable portlets */ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Utility function _F_getElementLeft(eElement) { var nLeftPos = eElement.offsetLeft; // initialize var to store calculations var eParElement = eElement.offsetParent; // identify first offset parent element while (eParElement != null) { // move up through element hierarchy nLeftPos += eParElement.offsetLeft - eParElement.scrollLeft; // appending left offset of each parent eParElement = eParElement.offsetParent; // until no more offset parents exist } return nLeftPos; // return the number calculated } function _F_getElementTop(eElement) { var nTopPos = eElement.offsetTop; var eParElement = eElement.offsetParent; while (eParElement != null) { nTopPos += eParElement.offsetTop - eParElement.scrollTop; eParElement = eParElement.offsetParent; } return nTopPos; } function _F_serializeObject(obj, sName) { var s = ''; sName = sName != undefined ? sName : ""; if (typeof(obj) == "object" && sName != "") { // create element s += '<' + sName; // output attributes for (var sProp in obj) if (typeof(obj[sProp]) != "object" && sProp != "_text_") s += _F_serializeObject(obj[sProp], sProp); if (typeof(obj[sProp]) == "object" || sProp == "_text_") { s += '>'; // output contents for (var sProp in obj) if (typeof(obj[sProp]) == "object" || sProp == "_text_") s += _F_serializeObject(obj[sProp], sProp); s += ''; } else s += '/>'; } else if (typeof(obj) == "object") { // output contents for (var sProp in obj) s += _F_serializeObject(obj[sProp], sProp); } else if (sName == "_text_") { // create text node s += _F_Strings.xmlEncode(obj); } else if (sName != "") { // create attribute s += ' ' + sName + '="' + _F_Strings.xmlEncode(obj) + '"'; } return s; } //------------------------------------------------------------- //-- class CColumn //- Class CColumn(int width, CRow[] rows) function CColumn(width, rows) { this.parent = null; this.width = width ? width : "100"; this.rows = rows ? rows : []; var i, l = this.rows.length; for (i = 0; i < l; i++) this.rows[i].parent = this; this.id = CColumn.prototype.idCount++; } CColumn.prototype = { idCount: 0, //- string getBaseId() getBaseId: function() { if (this.parent) return this.parent.getBaseId(); return ""; }, //- Boolean isLast() isLast: function() { if (!this.parent) return true; return this.parent.columns[this.parent.columns.length - 1] === this; }, //- Object findColumnById(string id) findColumnById: function(id) { if (this.id == id) return this; var obj = null; if (this.rows.length) { var i, l = this.rows.length; for (i = 0; i < l; i++) { if (obj = this.rows[i].findColumnById(id)) break; } } return obj; }, //- void setWidth(int w) setWidth: function(w) { this.width = w; }, //- void getColumns(CColumn[] columns) getColumns: function(columns) { if (this.rows.length) for (var i = 0; i < this.rows.length; i++) this.rows[i].getColumns(columns); else columns.push(this); }, //- HTMLElementImage getSpacer() getSpacer: function() { return $(this.getBaseId() + "zone" + this.id); }, //- HTMLElementDiv getResizeBar() getResizeBar: function() { return $(this.getBaseId() + "resizebar" + this.id); }, //- void setSpacerHeight(int h) setSpacerHeight: function(h) { var img = this.getSpacer(); if (img) img.height = h; var resizeBar = this.getResizeBar(); if (resizeBar) xHeight(resizeBar, h); }, //- HTMLElementDiv getDiv() getDiv: function() { return xParent(this.getSpacer(), true); }, //- Object getRect() getRect: function() { var div = this.getDiv(); return { left: xPageX(div), top: xPageY(div), width: xWidth(div), height: xHeight(div) }; }, //- Object getGlobalRect() getGlobalRect: function() { var div = this.getDiv(); return { left: _F_getElementLeft(div), top: _F_getElementTop(div), width: xWidth(div), height: xHeight(div) }; }, //- HTMLElementImage getSpacer() addRow: function(row) { this.rows.push(row); }, // - string render() render: function() { var s = ''; if (this.rows.length) { s += ''; for (var i = 0; i < this.rows.length; i++) s += this.rows[i].render(); s += '
'; } else { // border:1px solid gray; s += '
'; s += ''; s += '
'; } s += ''; if (!this.isLast()) { s += '
'; s += '
'; } return s; }, //- string serialize() serialize: function() { var s = ''; if (this.rows.length) { for (var i = 0; i < this.rows.length; i++) s += this.rows[i].serialize(); } else s += this.zone.serialize(); s += ''; return s; } } //------------------------------------------------------------ //-- class CRow //- Class CRow(CColumn[] columns) function CRow(columns) { this.parent = null; // this.height = "100%"; this.columns = columns ? columns : []; for (var i = 0; i < this.columns.length; i++) this.columns[i].parent = this; } CRow.prototype = { //- string getBaseId() getBaseId: function() { if (this.parent) return this.parent.getBaseId(); return ""; }, //- Object findColumnById(string id) findColumnById: function(id) { var obj = null; var i, l = this.columns.length; for (i = 0; i < l; i++) { if (obj = this.columns[i].findColumnById(id)) break; } return obj; }, //- void getColumns(CColumn[] columns) getColumns: function(columns) { for (var i = 0; i < this.columns.length; i++) this.columns[i].getColumns(columns); }, //- void addColumn(CColumn column) addColumn: function(column) { this.columns.push(column); column.parent = this; }, //- string render() render: function() { var s = ' 1) { s += ''; s += ''; s += ' 1) { s += ''; s += '
'; s += ''; } s += ''; return s; }, //- string serialize() serialize: function() { var s = ''; var i, l = this.columns.length; for (i = 0; i < l; i++) s += this.columns[i].serialize(); s += ''; return s; } } //------------------------------------------------------------- //-- class CLayout /* init() startSelection() moveSelection(x, y) endSelection(context) reflow hittest */ //- Class CLayout(CRow[] rows, Object properties) function CLayout(rows, properties) { this.parent = null; this.properties = properties ? properties : null; this.rows = rows ? rows : []; var i, l = this.rows.length; for (i = 0; i < l; i++) this.rows[i].parent = this; } CLayout.prototype = { //- string getBaseId() getBaseId: function() { if (this.parent) return this.parent.getBaseId(); return ""; }, //- void addRow(CRow row) addRow: function(row) { this.rows.push(row); row.parent = this; }, //- string render() render: function() { var s = ''; for (var i = 0; i < this.rows.length; i++) s += this.rows[i].render(); s += '
'; return s; }, //- void getColumns(CColumn[] columns) getColumns: function(columns) { for (var i = 0; i < this.rows.length; i++) this.rows[i].getColumns(columns); }, //- Object findColumnById(string id) findColumnById: function(id) { var obj = null; var i, l = this.rows.length; for (i = 0; i < l; i++) { if (obj = this.rows[i].findColumnById(id)) break; } return obj; }, //- void setWidth(int w) setWidth: function(w) { }, //- string serialize() serialize: function() { var s = ""; s += ''; s += _F_serializeObject(this.properties); var i, l = this.rows.length; for (i = 0; i < l; i++) s += this.rows[i].serialize(); s += ''; return s; } } //------------------------------------------------------------- //-- class CPanel //- Class Cpanel(string sId) function CPanel(sId) { // Private Properties this.id = sId; this.parent = null; var self = this; var panel = $(sId + "panel"); var caption = $(sId + "caption"); var closebtn = $(sId + "caption_close"); var editbtn = $(sId + "caption_edit"); var x, y, w, h = false; //- CPage getPage() this.getPage = function() { return this.parent.getPage(); } //- string getBaseId() this.getBaseId = function() { return this.getPage().getBaseId(); } //- HTMLElementDiv getParentDiv() this.getParentDiv = function() { return this.getPage().getParentDiv(); } // Public Methods //- void onunload() this.onunload = function() { if (xIE4Up) // clear cir refs { xDisableDrag(caption); } this.getParentDiv().removeChild(panel); if (closebtn != null) closebtn.onclick = null; self = panel = null; } //- void paint() this.paint = function() { if (fragments[sId] && fragments[sId].onresize) fragments[sId].onresize(); } //- void position(int x, int y, int width) this.position = function(x, y, width) { var cx = xOffsetLeft(this.getParentDiv()); var cy = xOffsetTop(this.getParentDiv()); xMoveTo(panel, x - cx, y - cy); var content = $(this.id + "content"); xWidth(content, width - 12); xWidth(panel, width - 8); } //- int getHeight() this.getHeight = function() { return xHeight(panel); } //- int getTop() this.getTop = function() { return xPageY(panel); } //- int getGlobalTop() this.getGlobalTop = function() { return _F_getElementTop(panel); } // Private Event Listeners var offset = { left: 0, top: 0 }; function panelDragStart(e, x, y) { panel.style.backgroundColor="#eeeeee"; panel.style.filter="alpha(opacity=50)"; panel.style.opacity="0.3"; offset.left = x - xLeft(panel); offset.top = y - xTop(panel); var div = $( self.getBaseId() + "shadow"); xMoveTo(div, xLeft(panel), xTop(panel)); xResizeTo(div, xWidth(panel), xHeight(panel)); xShow(div); self.getPage().startSelection(x, y, self.parent); } function panelDragMove(e, dx, dy) { xMoveTo(panel, e.xDPX - offset.left, e.xDPY - offset.top); self.getPage().moveSelection(e.xDPX, e.xDPY); } function panelDragEnd(e, x, y) { panel.style.backgroundColor=""; panel.style.filter=""; panel.style.opacity=""; var div = $(self.getBaseId() + "shadow"); xHide(div); if (self.getPage().hasSelection()) { self.getPage().movePortlet(self.parent); } else { xSlideTo(panel, xLeft(div), xTop(div), 500); } self.getPage().endSelection(); } function panelMousedown() { xZIndex(panel, CPanel.z++); } // Constructor Code xZIndex(panel, CPanel.z++); this.paint(); xEnableDrag(caption, panelDragStart, panelDragMove, panelDragEnd); panel.onmousedown = panelMousedown; if (closebtn != null) closebtn.onclick = function(evt) { if (self.parent) self.parent.notifyClose(self); }; xShow(panel); } // end Panel object prototype CPanel.z = 0; // panel static property function panelMarkup(parentDiv, sId, sTitle, readOnly) { var panel = document.createElement("DIV"); panel.className = "cogstyle-portlet-frame"; panel.style.position = "absolute"; panel.id = sId + "panel"; parentDiv.appendChild(panel); var s = '' + '' + '' + '' + '' + '' + '' + '
' + '
' + '' + '' + '' + '' + '' + '
' + '
' + sTitle + '
' + '
'; if (!readOnly){ s+= '' + '' + '' + '' + '
' + 'Close' + '
'; } s+= '
' + '
' + '
' + '
' + '


' + '
' + 'Loading' + '
' + '


' + '
' + '
'; panel.innerHTML = s; return panel; } //------------------------------------------------------------- //-- CPortlet Class /** retrieve() position(x, y, w) getHeight() getTop() getGlobalTop() render() notifyClose() destroy() */ //- Class CPortlet(string sId, string sLayoutId, string sPortletId, string sTitle) //- Class CPortlet(Object sId) function CPortlet(sId, sLayoutId, sPortletId, sTitle) { this.parent = null; this.div = null; this.frag = null; if (typeof(sId) == 'object') { for (var sProp in sId) this[sProp] = sId[sProp]; } else { this.id = sId; this.layoutId = sLayoutId ? sLayoutId : ""; this.portletId = sPortletId ? sPortletId : ""; this.title = sTitle ? sTitle : ""; this.isNew = true; } } CPortlet.prototype = { //- CPage getPage() getPage: function() { return this.parent.getPage(); }, //- string getBaseId() getBaseId: function() { return this.getPage().getBaseId(); }, //- HTMLElementDiv getParentDiv() getParentDiv: function() { return this.getPage().getParentDiv(); }, //- void init(CZone zone) init: function(zone) { this.parent = zone; if (!this.div) { this.div = panelMarkup(this.getParentDiv(), this.id, this.title, this.getPage().isReadOnly); this.panel = new CPanel(this.id); this.panel.parent = this; } var page = this.getPage(); if (page != null && page.storeId != null ) if(this.isNew) this.path = "/cm/" + encodeURIComponent(page.storeId) +"?add=" + encodeURIComponent(this.portletId); else this.path = "/cm/" + encodeURIComponent(page.storeId) +"?query=" + encodeURIComponent(this.portletId); else this.path = "/cm/" + this.portletId; this.retrieve(); }, //- void retrieve() retrieve: function() { if (this.frag == null) { this.frag = new fragment(this.path, this.id); this.frag.mode = "preview"; var _self = this; var _hook = this.frag.oncompleted; var _frag = this.frag this.frag.oncompleted = function(bComplete) { if (typeof(_hook) == "function") _hook.call(_frag, bComplete); _self.panel.paint(); _self.parent.dirty = true; _self.parent.parent.reflow(); }; this.frag.retrieve(); this.panel.paint(); } }, //- void position(int x, int y, int w) position: function(x, y, w) { this.panel.position(x, y, w); }, //- int getHeight() getHeight: function() { return this.panel.getHeight(); }, //- int getTop() getTop: function() { return this.panel.getTop(); }, //- int getGlobalTop() getGlobalTop: function() { return this.panel.getGlobalTop(); }, //- string render() notifyClose: function(panel) { if (this.parent) this.parent.notifyClose(this); }, //- string serialize() serialize: function() { var s = '' + '' + this.layoutId + '' + '' + this.portletId + ''; if (this.context) { s += '' + '' + this.context.portletHandle + '' + '' + this.context.portletState + ''; if (this.context.portletType) { s += '' + '' + '' + this.context.portletType + '' + '' + ''; } s += ''; } s += ''; return s; }, //- void destroy() destroy: function() { this.panel.onunload(); } } //------------------------------------------------------------- // column resize handler singleton var CResizer = { td1: null, td2: null, region: null, range: 0, min: 0, max: 0, baseId: "", columnId1: "", columnId2: "", mouseDown: function(evt) { xPreventDefault(evt); var e = new xEvent(evt); this.funcMove = function(e) { CResizer.mouseMove(e) }; this.funcUp = function(e) { CResizer.mouseUp(e) }; xAddEventListener(document, "mousemove", this.funcMove, true); xAddEventListener(document, "mouseup", this.funcUp, true); var div = e.target; this.baseId = div.getAttributeNode("baseId").nodeValue; var parentDiv = $(this.baseId + "content"); var tdSizer = xParent(div, true); var tr = xParent(tdSizer, true); var tbody = xParent(tr, true); var table = xParent(tbody, true); var td1 = xPrevSib(tdSizer, "TD"); var td2 = xNextSib(tdSizer, "TD"); var sLabel = "column_"; this.columnId1 = td1.id.substring(td1.id.indexOf(sLabel) + sLabel.length); this.columnId2 = td2.id.substring(td2.id.indexOf(sLabel) + sLabel.length); var cx = xOffsetLeft(parentDiv); var cy = xOffsetTop(parentDiv); var boxX = xPageX(table) - cx; var boxY = xPageY(table) - cy; var boxW = xWidth(table); var boxH = xHeight(table); var box = $(this.baseId + "resizeBox"); var bar = $(this.baseId + "resizeBar"); var info = $(this.baseId + "resizeInfo"); var infoLeft = $(this.baseId + "resizeLeft"); var infoRight = $(this.baseId + "resizeRight"); xMoveTo(box, boxX, boxY); xResizeTo(box, boxW, boxH); var x = xPageX(div) - cx; var y = (xPageY(div) - cy) + 2; xMoveTo(bar, x, boxY); xResizeTo(bar, 4, boxH); xMoveTo(info, x - 30, Math.max(cy, boxY) + 20); infoLeft.innerHTML = td1.width; infoRight.innerHTML = td2.width; this.td1 = td1; this.td2 = td2; this.range = parseInt(td1.width) + parseInt(td2.width); this.region = { left: xPageX(td1) - cx, width: xWidth(td1) + xWidth(td2) }; var pixelRange = this.region.width * 100 / this.range; this.min = this.region.left + (pixelRange / 10); this.max = this.region.left + this.region.width - (pixelRange / 10); xShow(box); xShow(bar); xShow(info); }, mouseMove: function(evt) { xPreventDefault(evt); var e = new xEvent(evt); var div = e.target; var parentDiv = $(this.baseId + "content"); var bar = $(this.baseId + "resizeBar"); var info = $(this.baseId + "resizeInfo"); var infoLeft = $(this.baseId + "resizeLeft"); var infoRight = $(this.baseId + "resizeRight"); var cx = xOffsetLeft(parentDiv) - xScrollLeft(parentDiv); var x = Math.min(Math.max(e.pageX - cx, this.min), this.max); var sizeLeft = x - this.region.left; var sizeRight = this.region.width - sizeLeft; xLeft(bar, x); xLeft(info, x - 30); infoLeft.innerHTML = Math.round(sizeLeft * this.range / this.region.width) + "%"; infoRight.innerHTML = Math.round(sizeRight * this.range / this.region.width) + "%"; }, mouseUp: function(evt) { xPreventDefault(evt); var e = new xEvent(evt); var parentDiv = $(this.baseId + "content"); xRemoveEventListener(document, "mousemove", this.funcMove, true); xRemoveEventListener(document, "mouseup", this.funcUp, true); var x = Math.min(Math.max(e.pageX - xOffsetLeft(parentDiv), this.min), this.max); var sizeLeft = x - this.region.left; var sizeRight = this.region.width - sizeLeft; var W1 = Math.round(sizeLeft * this.range / this.region.width); var W2 = Math.round(sizeRight * this.range / this.region.width); this.td1.width = W1 + "%"; this.td2.width = W2 + "%"; var box = $(this.baseId + "resizeBox"); var bar = $(this.baseId + "resizeBar"); var info = $(this.baseId + "resizeInfo"); xHide(box); xHide(bar); xHide(info); this.td1 = null; this.td2 = null; var page = eval(this.baseId + "page"); if (page) { page.setColumnWidths(this.columnId1, W1, this.columnId2, W2); page.reflow(); } } } //------------------------------------------------------------- // CZone Class /** setColumn(column) destroy() getRect() hittest(x, y) insertHittest(x, y) appendPortlet(portlet) insertPortlet(index, portlet) reflow() notifyClose() */ //- class CZone(CPortlet[] portlets) function CZone(portlets) { this.parent = null; this.column = null; this.portlets = portlets ? portlets : []; var i, l = this.portlets.length; for (i = 0; i < l; i++) this.portlets[i].parent = this; // reflow logic this.rows = []; this.lastRect = { }; this.lastHeight = 0; this.dirty = true; } CZone.prototype = { //- void init() init: function() { var i, l = this.portlets.length; for (i = 0; i < l; i++) this.portlets[i].init(this); }, //- void setDirty(Boolean bDirty) setDirty: function(bDirty) { this.dirty = bDirty == undefined ? true : bDirty; }, // void appendPortlet(portlet) appendPortlet: function(portlet) { this.portlets.push(portlet); portlet.init(this); this.setDirty(); this.reflow(); }, //- void insertPortlet(int index, CPortlet portlet) insertPortlet: function(index, portlet) { if (index > -1) _F_Array.insert(this.portlets, index, portlet); else this.portlets.push(portlet); portlet.init(this); this.setDirty(); this.reflow(); }, //- void insertPortlet(int index, CPortlet portlet) removePortlet: function(portlet) { _F_Array.remove(this.portlets, portlet); this.setDirty(); }, //- CPage getPage() getPage: function() { return this.parent; }, //- string getBaseId() getBaseId: function() { return this.getPage().getBaseId(); }, //- HTMLElementDiv getParentDiv() getParentDiv: function() { return this.getPage().getParentDiv(); }, //- void setBackground(string color) setBackground: function(color) { this.column.getDiv().style.backgroundColor = color; }, //- void setColumn(CColumn column) setColumn: function(column) { this.column = column; column.zone = this; this.lastHeight = 0; this.setDirty(); }, //- void destroy() //-- destroy all of the portlets destroy: function() { for (var i = 0; i < this.portlets.length; i++) this.portlets[i].destroy(); }, //- rect getRect() getRect: function() { return this.column.getRect(); }, //- Boolean hittest(int x, int y) hittest: function(x, y) { var rc = this.column.getGlobalRect(); return (x >= rc.left && x < rc.left + rc.width && y >= rc.top && y < rc.top + rc.height); }, //- int insertHittest(int y) insertHittest: function(y) { var index = -1; var closest = 10000000; var rc = this.column.getGlobalRect(); var top = rc.top; for (var i = 0; i < this.rows.length; i++) { var diff = Math.abs(y - (top + this.rows[i])); if (diff < closest) { closest = diff; index = i; } } return index; }, //- void reflow() reflow: function() { var rc = this.column.getRect(); // if dirty or we added portlets or the column rect has changed if (this.dirty || (rc.left != this.lastRect.left || rc.top != this.lastRect.top || rc.width != this.lastRect.width || rc.height != this.lastRect.height)) { this.lastRect = rc; if (this.portlets.length) { this.rows.length = this.portlets.length + 1; var i, totalHeight = 0, l = this.portlets.length; for (i = 0; i < l; i++) { this.portlets[i].position(rc.left + 2, rc.top + totalHeight, rc.width - 4); this.rows[i] = totalHeight; totalHeight += this.portlets[i].getHeight(); } this.rows[i] = totalHeight; } else { this.rows.length = 0; totalHeight = 72; } if (this.lastHeight != totalHeight) { this.lastHeight = totalHeight; this.column.setSpacerHeight(totalHeight); this.setDirty(); } else this.setDirty(false); } return this.dirty; }, //- void notifyClose(CPortlet portlet) notifyClose: function(portlet) { // remove portlet var oldportlet = this.portlets.remove(portlet); portlet.destroy(); this.setDirty(); this.reflow(); // reflow parent this.parent.reflow(); }, //- string serialize() serialize: function() { var s = ""; var i, l = this.portlets.length; for (i = 0; i < l; i++) s += ''; return s; } } //------------------------------------------------------------- // CPage Class /* render() setLayout(layout) getLayout() hittest(x, y) insertPortlet(portlet) movePortlet(portlet) selectZone(zone) hasSelection() startSelection() moveSelection(x, y) endSelection() reflow hittest */ //- Class CPage(string baseId, string storeid, HTMLElementDiv parentDiv, CZone[] zones, Object properties) function CPage(baseId, storeId, parentDiv, zones, properties) { this.isReadOnly = false; this.baseId = baseId; this.parentDiv = $(parentDiv); this.layout = null; this.storeId = storeId; this.zones = zones ? zones : []; var i, l = this.zones.length; for (i = 0; i < l; i++) this.zones[i].parent = this; if (properties) for (var sProp in properties) this[sProp] = properties[sProp]; this.currentZone = -1; this.currentInsert = -1; //Reflow the page twice a second. This is allows the layout to deal with portlets whose size changes after the initial retrieve. var _self = this; this.funcForceReflow = function() { _self.reflow(true); }; this.reflowTimer = setInterval(this.funcForceReflow, 500); } CPage.prototype = { //- string getBaseId() getBaseId: function() { return this.baseId; }, //- HTMLElementDiv getParentDiv() getParentDiv: function() { return this.parentDiv; }, //- void initZones(HTMLElementDiv div, CLayout layout) initZones: function(div, layout) { this.layout = layout; layout.parent = this; $(div).innerHTML = layout.render(); columns = []; layout.getColumns(columns); // bind zone to column var i, l = columns.length; for (i = 0; i < l; i++) this.zones[i].setColumn(columns[i]); var i, l = this.zones.length; for (i = 0; i < l; i++) this.zones[i].init(this); this.reflow(); }, //- void setLayout(HTMLElementDiv div, CLayout layout) setLayout: function(div, layout) { this.layout = layout; layout.parent = this; $(div).innerHTML = layout.render(); columns = []; layout.getColumns(columns); // if there are more columns than zones, create extra zones if (columns.length > this.zones.length) { for (var i = this.zones.length; i < columns.length; i++) { var zone = new CZone(); this.zones.push(zone); zone.parent = this; } } // if less, copy portlets to last zone and remove extra zones else if (columns.length < this.zones.length) { var lastZone = this.zones[columns.length - 1]; var len = this.zones.length; for (var i = columns.length; i < len; i++) { var zone = this.zones.pop(); for (var j = 0; j < zone.portlets.length; j++) { var portlet = zone.portlets[j]; lastZone.portlets.push(portlet); portlet.parent = lastZone; } } } // bind zone to column for (var i = 0; i < columns.length; i++) this.zones[i].setColumn(columns[i]); this.reflow(); }, //- CLayout getLayout() getLayout: function() { return this.layout; }, //- int hittest(int x, int y) hittest: function(x, y) { var cx = xOffsetLeft(this.parentDiv); var cy = xOffsetTop(this.parentDiv); for (var i = 0; i < this.zones.length; i++) if (this.zones[i].hittest(x, y)) return i; return -1; }, //- void insertPortlet(CPortlet portlet) insertPortlet: function(portlet) { if (this.currentZone > -1) this.zones[this.currentZone].insertPortlet( this.currentInsert, portlet); this.reflow(); }, //- void movePortlet(CPortlet portlet) movePortlet: function(portlet) { // requires selection point if (this.currentZone == -1) return; var zoneTo = this.zones[this.currentZone]; // find portlet's zone and remove it var zoneFrom = portlet.parent; zoneFrom.removePortlet(portlet); // insert portlet at insertion point zoneTo.insertPortlet( this.currentInsert, portlet); this.reflow(); }, //- void reflow(Boolean bForce) reflow: function(bForce) { if (bForce) for (var i = 0; i < this.zones.length; i++) this.zones[i].setDirty(); var dirty = false; do { dirty = false; for (var i = 0; i < this.zones.length; i++) { if (dirty = this.zones[i].reflow()) break; } } while (dirty); }, //- void selectZone(CZone zone, int insert) selectedZone: -1, selectZone: function(zone, insert) { var div = $(this.getBaseId() + "selector"); if (zone > -1) { var rc = this.zones[zone].getRect(); var parentDiv = this.getParentDiv(); var cx = xOffsetLeft(parentDiv); var cy = xOffsetTop(parentDiv); var top = rc.top; if (insert > -1) top += this.zones[zone].rows[insert]; xMoveTo(div, (rc.left + 2) - cx, (top - 2) - cy); xResizeTo(div, rc.width - 4, 6); xShow(div); } else { xHide(div); } if (this.selectedZone != zone) { if (this.selectedZone > -1) this.zones[this.selectedZone].setBackground("white"); if (zone > -1) this.zones[zone].setBackground("#f0f0f0"); this.selectedZone = zone; } }, //- void startSelection(int x, int y, Cportlet portlet) startSelection: function(x, y, portlet) { clearInterval(this.reflowTimer); this.sourceZone = portlet ? _F_Array.indexOf(this.zones, portlet.parent) : -1; this.sourceIndex = portlet ? _F_Array.indexOf(this.zones[this.sourceZone].portlets, portlet) : -1; this.currentZone = -1; }, //- void moveSelection(int x, int y) moveSelection: function(x, y) { var zone = this.hittest(x, y); var insert = -1; if (zone > -1) insert = this.zones[zone].insertHittest(y); if (this.sourceZone != -1 && zone == this.sourceZone && (insert == this.sourceIndex || insert == this.sourceIndex + 1)) { zone = -1; } if (!this.isReadOnly && (zone != this.currentZone || insert != this.currentInsert)) { this.currentZone = zone; this.currentInsert = insert; this.selectZone(zone, insert); } }, //- void endSelection() endSelection: function() { this.selectZone(-1); this.reflowTimer = setInterval(this.funcForceReflow, 500); }, //- void hasSelection() hasSelection: function() { return this.currentZone > -1; }, //- void setColumnWidths(string id1, int w1, string id2, int w2) setColumnWidths: function( id1, w1, id2, w2) { var c1 = this.layout.findColumnById(id1); var c2 = this.layout.findColumnById(id2); if (c1 && c2) { c1.setWidth(w1); c2.setWidth(w2); } }, //- string serialize() serialize: function() { var s = '' + '' + this.id + '' + '' + this.name + '' + '' + this.description + '' + '' + this.screenTip + '' + '' + this.layout.serialize() + ''; var i , l = this.zones.length; for (i = 0; i < l; i++) { var j, lz = this.zones[i].portlets.length; for (j = 0; j < lz; j++) s += this.zones[i].portlets[j].serialize(); } s += ''; return s; } }