/* * Copyright (C) 2005 - 2011 Jaspersoft Corporation. All rights reserved. * http://www.jaspersoft.com. * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ /** * @author Angus Croll */ var layoutModule = { ELEMENT_CONTEXTMENU: "element:contextmenu", //predefine CSS patterns for element sifting SIZEABLE_PATTERN: '.sizeable', SIZER_PATTERN: '.sizer', RESIZE_OVERLAY_PATTERN: '.resizeOverlay', MOVEABLE_PATTERN: '.moveable', MOVER_PATTERN: '.mover', MINIMIZER_PATTERN: '.maximized .minimize', MINIMIZED_PATTERN: '.minimized .minimize', TRUNCATE_PATTERN: '.trunc', TREE_LEAF_PATTERN: 'a.>node', TREE_CONTAINER_PATTERN: '.collapsible', TOOLBAR_CAPSULE_PATTERN: '#toolbar .capsule', NAVIGATION_MUTTON_PATTERN: 'li.mutton', NAVIGATION_PATTERN: '#navigationOptions li', NAVIGATION_HOVER_PATTERN: '#navigationOptions li.over', META_LINKS_PATTERN: '#metaLinks #main_logOut_link', BUTTON_SET_BUTTON: '.buttonSet > .', TABSET_TAB_PATTERN: '.tab', BUTTON_PATTERN: '.button', PRESSED_PATTERN: '.pressed', SELECTED_PATTERN: '.selected', LIST_ITEM_PATTERN: '.list.responsive > li', LIST_ITEM_WRAP_PATTERN: '.wrap', DISCLOSURE_BUTTON_PATTERN: ".disclosure", MENU_LIST_PATTERN: '#menu li', SEPARATOR_PATTERN: '.separator', MESSAGE_WARNING_PATTERN: '.message.warning', COLUMN_NODE_WRAPPER_PATTERN: ".node > .wrap > .column", COLUMN_LEAF_WRAPPER_PATTERN: ".leaf > .wrap > .column", SEARCH_LOCKUP_PATTERN: ".searchLockup", DIALOG_PATTERN: ".dialog", DIALOG_LOADING_PATTERN: ".dialog.loading", SWIPE_SCROLL_PATTERN: ".swipeScroll", SCROLL_WRAPPER_PATTERN: ".scrollWrapper", //classes ADHOC_MODE_OPTION_CLASS: 'tab mode horizontal', //not used? DRAGGING_CLASS: 'dragging', COPY_CLASS: 'copy', PRESSED_CLASS : 'pressed', SELECTED_CLASS : 'selected', DISABLED_CLASS : 'disabled', HOVERED_CLASS : 'over', ERROR_CLASS : 'error', UP_CLASS : 'up', LAST_CLASS : 'last', FIRST_CLASS : 'first', SCHEDULED_CLASS: 'scheduled', NODE_CLASS: 'node', LEAF_CLASS: 'leaf', ICON_CLASS: 'icon', OPEN_CLASS: 'open', CLOSED_CLASS: 'closed', LOADING_CLASS: 'loading', NOTHING_TO_DISPLAY_CLASS: 'nothingToDisplay', COLLAPSIBLE_CLASS: "collapsible", RESPONSIVE_CLASS: "responsive", HIDDEN_CLASS: "hidden", EMPHASIS_CLASS: "emphasis", ASCENDING_CLASS: "ascending", DESCENDING_CLASS: "descending", CANCELLABLE_CLASS: "cancellable", DROP_TARGET_CLASS: "dropTarget", BUTTON_CLASS: "button", ONE_COLUMN_CLASS: "oneColumn", CONTROL_PAGE_CLASS: "controlPage", //attributes DISABLED_ATTR_NAME: "disabled", SELECTED_ATTR_NAME: "selected", OPEN_ATTR_NAME: "open", CLOSED_ATTR_NAME: "closed", READONLY_ATTR_NAME: "readonly", // Predefined DOM elements IDs. DIMMER_ID: "pageDimmer", PAGE_BODY_ID: "display", MENU_ID: "menu", MAIN_NAVIGATION_ID: "mainNavigation", MAIN_NAVIGATION_HOME_ITEM_ID: "main_home", MAIN_NAVIGATION_LIBRARY_ITEM_ID: "main_library", META_LINK_LOGOUT_ID : "main_logOut_link", // DnD SCROLL_SENSITIVITY: 50, //dimmer DIMMER_Z_INDEX: 900, //Resizable folders/filters/properties/fields panels FOLDERS_RESIZABLE_PANEL_ID: 'folders', FILTERS_RESIZABLE_PANEL_ID: 'filters', PROPERTIES_RESIZABLE_PANEL_ID: 'properties', FIELDS_RESIZABLE_PANEL_ID: 'fields', FOLDERS_RESIZABLE_PANEL_COOKIE_NAME: 'foldersPanelWidth', FOLDERS_MINIMIZED_PANEL_COOKIE_NAME: 'foldersMinimized', FILTERS_RESIZABLE_PANEL_COOKIE_NAME: 'filtersPanelWidth', FILTERS_MINIMIZED_PANEL_COOKIE_NAME: 'filtersMinimized', PROPERTIES_RESIZABLE_PANEL_COOKIE_NAME: 'propertiesPanelWidth', PROPERTIES_MINIMIZED_PANEL_COOKIE_NAME: 'propertiesMinimized', FIELDS_RESIZABLE_PANEL_COOKIE_NAME: 'fieldsPanelWidth', FIELDS_MINIMIZED_PANEL_COOKIE_NAME: 'fieldsMinimized', PANEL_WIDTH: 'PanelWidth', MINIMIZED: 'Minimized', // swipe scroll scrolls: $H(), ////////////////////////////////////////////////////////////////////// // Initialize: Programmatically modifies the DOM objects upfront ////////////////////////////////////////////////////////////////////// initialize: function(container){ container = $(container) || $(document.body); var helpLink = $('helpLink'); if (helpLink) { helpLink.observe('click',webHelpModule.displayWebHelp); } //truncate matching patterns new Truncator(container.select(layoutModule.TRUNCATE_PATTERN)); //IE7 needs explicit style set (no sensible alternative to browser sniffing here) isIE7() && this.fixIE7Sizes(); container.select(this.SIZEABLE_PATTERN).each(this.createSizer.bind(this)); //NW.Dom.select(this.SIZEABLE_PATTERN, container, layoutModule.createSizer); //init moveables (note: DOM elements created after page load will need to be initialized for move after creation) container.select(this.MOVEABLE_PATTERN).each(this.createMover.bind(this)); //NW.Dom.select(this.MOVEABLE_PATTERN, container, layoutModule.createMover); //elements for centering (note: DOM elements created after page load will need to be initialized for center after creation) container.select('.centered_horz,.centered_vert').each(function(elem){ var fn = parseFunc(elem, 'centered_fn_'); fn || (fn = centerElement); fn(elem, { horz: elem.match('.centered_horz'), vert: elem.match('.centered_vert') }); }); //page dimmer init if ($(layoutModule.DIMMER_ID) != null) { $(layoutModule.DIMMER_ID).style.zIndex = layoutModule.DIMMER_Z_INDEX; } // in case of ajaxClobberedUpdate we have to reinitialize datepicker if (jQuery.datepicker && jQuery.datepicker.initialized) jQuery.datepicker.initialized = false; jQuery(window).resize(function(){ if(this.resizeTo) clearTimeout(this.resizeTo); this.resizeTo = setTimeout(function(){ jQuery(this).trigger('resizeEnd'); }, 500); }); }, updateOnOrientation: function(){ }, ////////////////////////////////////////////////////////////////////// // visibility ////////////////////////////////////////////////////////////////////// isVisible : function(element) { return element && !$(element).hasClassName(layoutModule.HIDDEN_CLASS); }, ////////////////////////////////////////////////////////////////////// // panel scrolling ////////////////////////////////////////////////////////////////////// createScroller : function(scrollContainer, options){ if (scrollContainer) { var existingScroll = layoutModule.scrolls.get(scrollContainer.identify()); existingScroll && existingScroll.destroy(); var disableTransformFor = ["mainTableContainer", "resultsContainer", "filtersPanel", "foldersPodContent"]; scrollContainer.identify().startsWith("iframeScroll_") && disableTransformFor.push(scrollContainer.identify()); options = Object.extend({ hideScrollbar: false, useTransform: !disableTransformFor.include(scrollContainer.identify()), bounce: ["resultsContainer"].include(scrollContainer.identify()) //checkDOMChanges: true }, options || {}); var scroll = new iScroll(scrollContainer, options); layoutModule.scrolls.set(scrollContainer.identify(), scroll); return scroll; } return null; }, ////////////////////////////////////////////////////////////////////// // panel resizing ////////////////////////////////////////////////////////////////////// createSizer : function(sizeable, options){ sizeable = $(sizeable); // Prototype and jQuery compatibilu //sizeable is the element we will resize //sizer is the handle we drag to resize it var sizer = options && options.sizer ? $(options.sizer) : sizeable.down(this.SIZER_PATTERN); //get first descendant with class sizer if (!sizer || matchMeOrUp(sizeable,"." + layoutModule.HIDDEN_CLASS)) {return;} var sizerType = this.getSizerType(sizer); var sizerAlign = this.alignmentModule.getSizerAlignment(sizer, sizerType); var dragger = new Draggable(sizer); dragger.resizeablePanel = sizeable; dragger.primaryPanel = $(sizeable).siblings().find(function(s){ return s.match('.primary') }); if (options && options.fillerPattern) { dragger.filler = $(jQuery(sizeable).find(options.fillerPattern)[0]); } var sizerMousedownCallback = function() { return function(evt) { //set co-ords now - if we wait until drag start it is too late - mouse already moved a bit dragger.pointerX = evt.pointerX(); dragger.pointerY = evt.pointerY(); } }(); //have to observer at this level - otherwise draggable has already swallowed up event sizer.observe('mousedown', sizerMousedownCallback); jQuery(sizer).bind({ 'touchstart':function(e){ sizerMousedownCallback(e.originalEvent); this.style.background = '#666'; this.style.zIndex = 9; }, 'touchend':function(){ this.style.background = 'transparent'; } }) dragger.sizerType = sizerType; dragger.alignment = sizerAlign; dragger.options = { constraint: ((sizerType === 'diagonal') ? '' : sizerType), onStart: layoutModule.beginSizerDragging.bind(layoutModule), onDrag: !isIPad() ? layoutModule.respondToDrag.bind(layoutModule) : doNothing, onEnd: layoutModule.endSizerDragging.bind(layoutModule) } }, getSizerType: function(sizer) { return (sizer.match('.horizontal') && 'horizontal') || (sizer.match('.vertical') && 'vertical') || (sizer.match('.diagonal') && 'diagonal'); }, alignmentModule: { alignments: [ ['left','right'], ['top','bottom'] ], alignmentIndexes: { 'horizontal':0, 'vertical':1 }, dimensions: ['width','height'], /** * which edge(s) of the sizeable object is the sizer aligned with * @param {Object} sizer * @param {Object} sizerType * @return (Array) ['left', 'right' or '']['top', 'bottom' or ''] */ getSizerAlignment: function(sizer, sizerType){ var result = ['','']; if (sizerType==='diagonal') { //diagonals sizer always the same alignment return ['right','bottom']; } var alignmentIndex = this.alignmentIndexes[sizerType]; //0 or 1 var alignmentStyles = this.alignments[alignmentIndex]; //['left','right'] or ['top','bottom'] var alignmentOffsets = [0,1].map( function(al) { return parseInt(sizer.getStyle(alignmentStyles[al])) }); //calculate sizer anchorage by testing which offset is smaller (NaN mean not anchored - therefore not aligned) var alignment = (isNaN(alignmentOffsets[0]) || (alignmentOffsets[0] > alignmentOffsets[1])) ? alignmentStyles[1] : alignmentStyles[0]; //now set the appropriate element result[alignmentIndex] = alignment; //e.g. for horizontal: ['right','']; return result; } }, beginSizerDragging : function(dragger, event) { var sizer = dragger.element; dragger.parentOffset = [sizer.getStyle(dragger.alignment[0]), sizer.getStyle(dragger.alignment[1])]; dragger.offsetUnit = 'px'; //TODO: fix me dragger.pointerX = dragger.pointerX || event.pointerX(); dragger.pointerY = dragger.pointerY || event.pointerY(); dragger.element.addClassName(layoutModule.DRAGGING_CLASS); $$(layoutModule.RESIZE_OVERLAY_PATTERN).each(function(overlay){ overlay.removeClassName(layoutModule.HIDDEN_CLASS); }); }, endSizerDragging : function(dragger, event){ layoutModule.respondToDrag(dragger, event); dragger.element.removeClassName(layoutModule.DRAGGING_CLASS); $$(layoutModule.RESIZE_OVERLAY_PATTERN).each(function (overlay) { overlay.addClassName(layoutModule.HIDDEN_CLASS); }); //fire custom event so that we can know when we have finished sizing document.fire("dragger:sizer", {targetEvent:event, element: dragger.element}); }, respondToDrag : function(dragger, event) { //no else stmt - diagonal sizer will do both if (dragger.sizerType !== 'vertical') { //includes diagonal this.resizeOnDrag(dragger, event, 'horizontal'); } if (dragger.sizerType !== 'horizontal') { //includes diagonal this.resizeOnDrag(dragger, event, 'vertical'); } }, resizeOnDrag : function(dragger, event, orientation) { //set vars based on dragger orientation var dragData = {}; dragData.axis = (orientation == 'horizontal') ? 0 : 1; dragData.myAlignments = this.alignmentModule.alignments[dragData.axis]; dragData.dimension = this.alignmentModule.dimensions[dragData.axis]; dragData.sizeProperty = dragData.axis ? 'offsetHeight' : 'offsetWidth'; var pointerName = dragData.axis ? 'pointerY' : 'pointerX'; var c = { pointerY: 'clientY', pointerX: 'clientX' } //generic code starts here var sizer = dragger.element; dragData.sizeableAnchorage = (dragger.alignment[dragData.axis] === dragData.myAlignments[0]) ? dragData.myAlignments[1] : dragData.myAlignments[0]; var p = event.changedTouches ? event.changedTouches[0][c[pointerName]] : event[pointerName](); var dragDelta = dragger[pointerName] ? p - dragger[pointerName] : 0; dragDelta = (dragger.alignment[dragData.axis] === dragData.myAlignments[1]) ? dragDelta : 0 - dragDelta; //directional correction dragData.dragDelta = dragDelta; dragger[pointerName] = event[pointerName](); this.resizePanelsOnDrag(dragger, dragData); }, resizePanelsOnDrag : function(dragger, dragData) { var sizeTracker = this.getSizeTracker(); sizeTracker.checkpoint(dragger.resizeablePanel[dragData.sizeProperty]); if (dragger.filler && !dragger['fillerDelta'+dragData.dimension]){ dragger['fillerDelta'+dragData.dimension] = dragger.resizeablePanel[dragData.sizeProperty] - dragger.filler[dragData.sizeProperty]; } //size the panel var panelSize = getDimensionInPx(dragger.resizeablePanel, dragData.dimension); //worsk for % or px if (this.isInBounds(dragger, dragData) || (!this.isInBounds(dragger, dragData) && dragData.dragDelta < 0)) { dragger.resizeablePanel.setStyle(dragData.dimension + ':' + (panelSize + dragData.dragDelta) + 'px'); //size filling element if any if (dragger.filler) { dragger.filler.setStyle(dragData.dimension + ':' + (panelSize + dragData.dragDelta - dragger['fillerDelta' + dragData.dimension]) + 'px'); } } new JSCookie(dragger.resizeablePanel.identify() + layoutModule.PANEL_WIDTH, dragger.resizeablePanel.getWidth()); // //if resizeablePanel is folders panel then put resizeablePanel.width into cookie // if (dragger.resizeablePanel.id == this.FOLDERS_RESIZABLE_PANEL_ID) { // new JSCookie(this.FOLDERS_RESIZABLE_PANEL_COOKIE_NAME, dragger.resizeablePanel.getWidth()); // } // //if resizeablePanel is filters panel then put resizeablePanel.width into cookie // if (dragger.resizeablePanel.id == this.FILTERS_RESIZABLE_PANEL_ID) { // new JSCookie(this.FILTERS_RESIZABLE_PANEL_COOKIE_NAME, dragger.resizeablePanel.getWidth()); // } // //if resizeablePanel is properties panel then put resizeablePanel.width into cookie // if (dragger.resizeablePanel.id == this.PROPERTIES_RESIZABLE_PANEL_ID) { // new JSCookie(this.PROPERTIES_RESIZABLE_PANEL_COOKIE_NAME, dragger.resizeablePanel.getWidth()); // } // //if resizeablePanel is fields panel then put resizeablePanel.width into cookie // if (dragger.resizeablePanel.id == this.FIELDS_RESIZABLE_PANEL_ID) { // new JSCookie(this.FIELDS_RESIZABLE_PANEL_COOKIE_NAME, dragger.resizeablePanel.getWidth()); // } //could not size the panel? restore position of sizer and style of panel if (!sizeTracker.changed(dragger.resizeablePanel[dragData.sizeProperty])) { var actualSize = getActualDimension(dragger.resizeablePanel, dragData.dimension); if (dragger.alignment[dragData.axis] != dragData.myAlignments[0]) { //if sizer not naturally left/top aligned, remove left/top styling added by scriptaculous dragger dragger.element.style[dragData.myAlignments[0]] = ""; } dragger.element.setStyle(dragger.alignment[dragData.axis] + ':' + dragger.parentOffset[dragData.axis]); dragger.resizeablePanel.setStyle(dragData.dimension + ':' + actualSize + 'px'); if (dragger.primaryPanel && (dragger.primaryPanel.style.zIndex == dragger.resizeablePanel.style.zIndex)) { dragger.primaryPanel.setStyle(dragData.sizeableAnchorage + ':' + (actualSize) + 'px'); } if (dragger.filler) { dragger.filler.setStyle(dragData.dimension + ':' + (actualSize - dragger['fillerDelta'+dragData.dimension]) + 'px'); } return; } var minWidth; if (dragger.resizeablePanel.currentStyle){ minWidth = dragger.resizeablePanel.currentStyle.minWidth; } else{ minWidth = document.defaultView.getComputedStyle(dragger.resizeablePanel,null); minWidth = minWidth['min-width'] ? minWidth['min-width'] : minWidth['minWidth']; } minWidth = minWidth.substring(0,minWidth.indexOf('px')); //size primary panel if any (and in same layer) if (dragger.primaryPanel && (dragger.primaryPanel.style.zIndex == dragger.resizeablePanel.style.zIndex)) { var primaryOffset = getDimensionInPx(dragger.primaryPanel, dragData.sizeableAnchorage) + dragData.dragDelta; var newOffset = primaryOffset < minWidth ? minWidth : primaryOffset; dragger.primaryPanel.setStyle(dragData.sizeableAnchorage + ':' + newOffset + 'px'); //resize main (middle) panel if any } //finally restore sizer`s alignment w/ respect to its parent if (dragger.alignment[dragData.axis] != dragData.myAlignments[0]) { dragger.element.style[dragData.myAlignments[0]] = ""; } dragger.element.setStyle(dragger.alignment[dragData.axis] + ':' + dragger.parentOffset[dragData.axis]); jQuery.event.trigger('layout_update'); }, isInBounds: function(dragger, dragData) { //just init variables var primaryMinMeasurement,sizeableAnchorageMeasurement, avaliableParentMeasurement,pimaryPanelMarginMeasurement, outerDimentionFunc, primaryPanel = jQuery(dragger.primaryPanel), primaryPanelParent = primaryPanel.parent(), dimention = dragData.dimension; if (dragger.primaryPanel) { //uppercase first charter dimention = dimention.replace(dimention.charAt(0), dimention.charAt(0).toUpperCase()); //chose function to get current dimmention outerDimentionFunc = jQuery.fn['outer'+dimention]; //calculate measurement pimaryPanelMarginMeasurement = outerDimentionFunc.call(primaryPanel, true) - outerDimentionFunc.call(primaryPanel); primaryMinMeasurement = parseInt(primaryPanel.css("min-" + dragData.dimension)); if (isNaN(primaryMinMeasurement)) { primaryMinMeasurement = 0; } sizeableAnchorageMeasurement = parseInt(primaryPanel.css(dragData.sizeableAnchorage)); avaliableParentMeasurement = parseInt(primaryPanelParent.css(dragData.dimension)); //if parent container has other divs then include their distentions in bound validation var panels = primaryPanelParent.children('div:visible:not(.minimized)'); jQuery.each(panels, function() { var elem = jQuery(this), isTemplatable = elem.width() === 0 || elem.height() === 0; if (dragger.resizeablePanel != this && dragger.primaryPanel != this && !isTemplatable) { avaliableParentMeasurement -= outerDimentionFunc.call(elem, true); } }); return avaliableParentMeasurement - sizeableAnchorageMeasurement - dragData.dragDelta > primaryMinMeasurement + pimaryPanelMarginMeasurement; } else { return true; } }, getSizeTracker: function() { lastSize = -1; return { checkpoint: function(size){ lastSize = size; }, changed: function(size){ return size != lastSize; } } }, /////////////////////////////////////////////////////////////////////////////////// // Make moveable /////////////////////////////////////////////////////////////////////////////////// createMover : function(movable){ //movable is the element we will move //mover is the handle we drag to move it var mover = movable.down(this.MOVER_PATTERN); //get first descendant with class mover if (!mover || matchMeOrUp(movable,"." + layoutModule.HIDDEN_CLASS)) {return;} var dragger = new Draggable(movable, {handle: mover}); }, /////////////////////////////////////////////////////////////////////////////////// // Minimizer / Maximizer /////////////////////////////////////////////////////////////////////////////////// maximize : function(elem, noEffects){ noEffects = true; var element = elem.hasClassName ? elem : $(elem); var toMaximize = element.hasClassName('column') ? element : element.up('.column'); /* * Special case for Adhoc Designer on iPad. */ if( window.orientation === 0){ toMaximize.id == 'filters' && layoutModule.minimize(document.getElementById('fields')); toMaximize.id == 'fields' && layoutModule.minimize(document.getElementById('filters')); } var aligments = layoutModule.alignmentModule.alignments[0]; var offsets = aligments.map(function(al) { return parseInt(toMaximize.getStyle(al)); }); var thisAlignment = aligments[offsets[0] === 0 ? 0 : 1]; //left at 0, right at 1 var primaryPanel = toMaximize.siblings().find(function(s) { return s.match('.primary') }); var ppOffset; if (primaryPanel) { ppOffset = new JSCookie(toMaximize.identify() + layoutModule.PANEL_WIDTH).value; } if (ppOffset && !isNaN(ppOffset)) { ppOffset += 'px'; toMaximize.setStyle({width: ppOffset}); if (noEffects) { primaryPanel.style[thisAlignment] = ppOffset; toMaximize.removeClassName('minimized_if_vertical_orientation'); toMaximize.removeClassName('minimized'); toMaximize.addClassName("maximized"); new JSCookie(toMaximize.identify() + layoutModule.MINIMIZED, false); jQuery('div.content',toMaximize).show(); jQuery('div.vtitle',toMaximize).hide(); } else { function saveState() { toMaximize.removeClassName('minimized_if_vertical_orientation'); toMaximize.removeClassName('minimized'); toMaximize.addClassName("maximized"); new JSCookie(toMaximize.identify() + layoutModule.MINIMIZED, false); jQuery('div.content',toMaximize).show(); } //This... new Effect.Morph(primaryPanel, {style: thisAlignment + ":" + ppOffset, duration: 0.6, afterFinish: function(){jQuery.event.trigger('layout_update');}}); //...runs parallel to these two... new Effect.Opacity(toMaximize, {to: 0, from: 1, duration: 0.3, queue: {position: 'front', scope: 'sidePanel'}, afterFinish: saveState}); new Effect.Opacity(toMaximize, {to: 1, from: 0, duration: 0.3, queue: {position: 'end', scope: 'sidePanel'}}); } } jQuery(toMaximize).find(".sizer").show(); jQuery.event.trigger('layout_update',{elem: elem.parentNode, type: 'panel-maximize'}); jQuery('.column.secondary > div.content > .body').show().height(); }, minimize : function(elem, noEffects){ var primaryPanel, ppOffset; noEffects = true; var element = elem.hasClassName ? elem : $(elem); var toMinimize = element.hasClassName('column') ? element : element.up('.column'); var isMinimized = new JSCookie(toMinimize.identify() + layoutModule.MINIMIZED).value == 'true'; !isMinimized && new JSCookie(toMinimize.identify() + layoutModule.PANEL_WIDTH, toMinimize.getWidth()); //figure out alignment (left or right) var aligments = layoutModule.alignmentModule.alignments[0]; var offsets = aligments.map(function(al){ return parseInt(toMinimize.getStyle(al)); }); var thisAlignment = aligments[offsets[0] === 0 ? 0 : 1]; //left at 0, right at 1 primaryPanel = toMinimize.siblings().find(function(s) {return s.match('.primary')}); if (primaryPanel) { ppOffset = primaryPanel.getStyle(thisAlignment); if (noEffects) { var title = jQuery('div.title',toMinimize).eq(0); var vTitle = jQuery('div.vtitle',toMinimize); var headerText = title.html(); var w = title.width(); w = jQuery.trim(title.text()).length * 7; primaryPanel.style[thisAlignment] = '12px'; toMinimize.addClassName("minimized"); toMinimize.removeClassName("maximized"); toMinimize.removeClassName('minimized_if_vertical_orientation'); new JSCookie(toMinimize.identify() + layoutModule.MINIMIZED, true); if(!vTitle.length) { vTitle = jQuery('
').appendTo(toMinimize); vTitle.on('mouseup touchend',function(evt){ layoutModule.maximize(toMinimize); evt.preventDefault(); }); vTitle.html(jQuery.trim(headerText)).width(w+24); } if(document.attachEvent){ vTitle.css({ top:0, left:0 }); } else { vTitle.css('top',w+24+'px'); } if(location.href.indexOf('nui=1') > 0) { vTitle.hide(); } else { vTitle.show(); } jQuery('div.content',toMinimize).hide(); } else { function saveState() { toMinimize.addClassName("minimized"); toMinimize.removeClassName("maximized"); toMinimize.removeClassName('minimized_if_vertical_orientation'); new JSCookie(toMinimize.identify() + layoutModule.MINIMIZED, true); jQuery('div.content',toMinimize).hide(); } //This... new Effect.Morph(primaryPanel, {style: thisAlignment + ':0px', duration: 0.6, afterFinish: function(){jQuery.event.trigger('layout_update');}}); //...runs parallel to these two... new Effect.Opacity(toMinimize, {to: 0, from: 1, duration: 0.3, queue: {position: 'front', scope: 'sidePanel'}, afterFinish: saveState}); new Effect.Opacity(toMinimize, {to: 1, from: 0, duration: 0.3, queue: {position: 'end', scope: 'sidePanel'}}); } } jQuery(toMinimize).find(".sizer").hide(); jQuery.event.trigger('layout_update',{elem: elem.parentNode, type: 'panel-minimize'}); }, resizeOnClient: function(leftPanelID, mainPanelID, rightPanelID) { var panels = []; var jMainPanelElement = jQuery('#'+mainPanelID); var diff = jQuery('#display').width() - 20 - parseInt(jMainPanelElement.width()); var minWidth; /* * Get panel state and dimensions */ jQuery.each([leftPanelID,rightPanelID],function(i,v){ if(v) { panels.push({id: v, isLeft: i == 0 ? true : false, jo: jQuery('#'+v), width: parseInt(new JSCookie(v + layoutModule.PANEL_WIDTH).value)}); panels[i].minimized = new JSCookie(v + layoutModule.MINIMIZED).value; panels[i].minimized = !Object.isUndefined(panels[i].minimized) ? (panels[i].minimized == "true") : panels[i].jo.hasClass("minimized"); minWidth = panels[i].jo[0].currentStyle ? panels[i].jo[0].currentStyle.minWidth : document.defaultView.getComputedStyle(panels[i].jo[0],null)['minWidth']; panels[i].minWidth = (minWidth && minWidth.indexOf('px')) > 0 ? minWidth.substring(0,minWidth.indexOf('px')) : 200; panels[i].width = panels[i].width ? panels[i].width : panels[i].jo.width(); diff -= panels[i].width; } }); var offset = diff < 0 ? Math.abs(diff) : 0; diff = 0; jQuery.each(panels,function(i,panel) { if (panel.jo.length && panel.jo.is(":visible")) { if (panel.minimized) { panel.jo.removeClass("maximized").addClass("minimized"); layoutModule.minimize(panel.jo[0], true); } else { if(i == 1 && !panels[0].minimized) { panel.width -= offset; if(panel.width < panel.minWidth) { diff = panel.width - panel.minWidth; panel.width = panel.minWidth; } } panel.jo.removeClass("minimized").addClass("maximized"); jMainPanelElement.css(panel.isLeft ? 'left' : 'right', panel.width + 'px'); panel.jo.css('width', panel.width + 'px'); } } }); if(diff != 0) { panels[0].width += diff; panels[0].width = panels[0].width < panels[0].minWidth ? panels[0].minWidth : panels[0].width; jMainPanelElement.css('left', panels[0].width + 'px'); panels[0].jo.css('width', panels[0].width + 'px'); } }, autoMaximize: function(element) { var minimized = new JSCookie(element.identify() + layoutModule.MINIMIZED).value; if (minimized == 'true') { element.hasClassName('minimized') && layoutModule.maximize(element, true); } else { !element.hasClassName('minimized') && layoutModule.minimize(element, true); } }, autoMinimize: function(element) { var minimized = new JSCookie(element.identify() + layoutModule.MINIMIZED).value; if (minimized == 'false') { layoutModule.minimize(element, true); } else { element.removeClassName('minimized'); } }, fixIE7Sizes: function() { $$(".control.tabSet.buttons.vertical").each(function(elem) { elem.immediateDescendants().each(function(child) { child.style.width = elem.clientWidth || elem.offsetWidth; }); }); } };