2013-02-22 01:25:41 +01:00
/ * *
2013-04-13 21:00:13 +02:00
* EGroupware eTemplate2 - Split panel
2013-02-22 01:25:41 +01:00
*
* @ license http : //opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @ package etemplate
* @ subpackage api
* @ link http : //www.egroupware.org
* @ author Nathan Gray
* @ copyright Nathan Gray 2013
* @ version $Id$
* /
"use strict" ;
/ * e g w : u s e s
jquery . jquery ;
jquery . splitter ;
et2 _core _baseWidget ;
* /
/ * *
* A container widget that accepts 2 children , and puts a resize bar between them .
*
* This is the etemplate2 implementation of the traditional split pane / split panel .
* The split can be horizontal or vertical , and can be limited in size . You can also
* turn on double - click docking to minimize one of the children .
*
* @ see http : //methvin.com/splitter/ Uses Splitter
2013-04-13 21:00:13 +02:00
* @ augments et2 _DOMWidget
2013-02-22 01:25:41 +01:00
* /
2013-04-13 21:00:13 +02:00
var et2 _split = et2 _DOMWidget . extend ( [ et2 _IResizeable ] ,
{
2013-02-22 01:25:41 +01:00
attributes : {
"orientation" : {
"name" : "Orientation" ,
"description" : "Horizontal or vertical (v or h)" ,
"default" : "v" ,
"type" : "string"
} ,
"outline" : {
"name" : "Outline" ,
"description" : "Use a 'ghosted' copy of the splitbar and does not resize the panes until the mouse button is released. Reduces flickering or unwanted re-layout during resize" ,
"default" : false ,
"type" : "boolean"
} ,
"dock_side" : {
"name" : "Dock" ,
"description" : "Allow the user to 'Dock' the splitbar to one side of the splitter, essentially hiding one pane and using the entire splitter area for the other pane. One of leftDock, rightDock, topDock, bottomDock." ,
"default" : et2 _no _init ,
"type" : "string"
} ,
"width" : {
"default" : "100%"
} ,
// Not needed
"overflow" : { "ignore" : true } ,
"no_lang" : { "ignore" : true } ,
"rows" : { "ignore" : true } ,
"cols" : { "ignore" : true }
} ,
2013-04-13 21:00:13 +02:00
/ * *
* Constructor
*
* @ memberOf et2 _split
* /
2013-02-22 01:25:41 +01:00
init : function ( ) {
this . _super . apply ( this , arguments ) ;
this . div = $j ( document . createElement ( "div" ) ) ;
// Create the dynheight component which dynamically scales the inner
2013-07-20 15:45:22 +02:00
// container.
2013-10-03 14:56:29 +02:00
this . dynheight = new et2 _dynheight (
this . getParent ( ) . getDOMNode ( ) || this . getInstanceManager ( ) . DOMContainer ,
this . div , 100
) ;
2013-02-22 01:25:41 +01:00
// Add something so we can see it - will be replaced if there's children
this . left = $j ( "<div>Top / Left</div>" ) . appendTo ( this . div ) ;
this . right = $j ( "<div>Bottom / Right</div>" ) . appendTo ( this . div ) ;
} ,
destroy : function ( ) {
2013-04-10 11:25:05 +02:00
// Stop listening
this . left . next ( ) . off ( "mouseup" ) ;
2013-02-22 17:02:47 +01:00
// Destroy splitter, restore children
2013-02-22 01:25:41 +01:00
this . div . trigger ( "destroy" ) ;
2013-02-22 17:02:47 +01:00
// Destroy dynamic full-height
2013-02-22 01:25:41 +01:00
this . dynheight . free ( ) ;
// Remove placeholder children
if ( this . _children . length == 0 )
{
this . div . empty ( ) ;
}
this . div . remove ( ) ;
} ,
/ * *
* Tap in here to check if we have real children , because all children should be created
2013-02-22 17:02:47 +01:00
* by this point . If there are , replace the placeholders .
2013-02-22 01:25:41 +01:00
* /
loadFromXML : function ( ) {
this . _super . apply ( this , arguments ) ;
if ( this . _children . length > 0 )
{
if ( this . _children [ 0 ] )
{
this . left . detach ( ) ;
this . left = $j ( this . _children [ 0 ] . getDOMNode ( this . _children [ 0 ] ) )
. appendTo ( this . div ) ;
}
if ( this . _children [ 1 ] )
{
this . right . detach ( ) ;
this . right = $j ( this . _children [ 1 ] . getDOMNode ( this . _children [ 1 ] ) )
. appendTo ( this . div ) ;
}
}
2013-02-22 17:02:47 +01:00
// Nextmatches (and possibly other "full height" widgets) need to be adjusted
// Trigger the dynamic height thing to re-initialize
for ( var i = 0 ; i < this . _children . length ; i ++ )
{
if ( this . _children [ i ] . dynheight )
{
this . _children [ i ] . dynheight . outerNode = ( i == 0 ? this . left : this . right ) ;
this . _children [ i ] . dynheight . initialized = false ;
}
}
2013-02-22 01:25:41 +01:00
} ,
doLoadingFinished : function ( ) {
this . _super . apply ( this , arguments ) ;
// Use a timeout to give the children a chance to finish
var self = this ;
window . setTimeout ( function ( ) {
self . _init _splitter ( ) ;
} , 1 ) ;
return true ;
} ,
/ * *
2013-02-22 17:02:47 +01:00
* Initialize the splitter UI
2013-02-22 01:25:41 +01:00
* Internal .
* /
_init _splitter : function ( ) {
if ( ! this . isAttached ( ) ) return ;
var options = {
type : this . orientation ,
dock : this . dock _side ,
splitterClass : "et2_split"
} ;
2013-02-22 17:02:47 +01:00
// Check for position preference, load it in
2013-02-22 01:25:41 +01:00
if ( this . id )
{
var pref = this . egw ( ) . preference ( 'splitter-size-' + this . id , this . egw ( ) . getAppName ( ) ) ;
if ( pref )
{
options = $j . extend ( options , pref ) ;
}
}
// Avoid double init
if ( this . div . hasClass ( options . splitterClass ) )
{
this . div . trigger ( "destroy" ) ;
}
2013-02-22 17:02:47 +01:00
// Initialize splitter
2013-02-22 01:25:41 +01:00
this . div . splitter ( options ) ;
// Add icon to splitter bar
var icon = "ui-icon-grip-"
+ ( this . dock _side ? "solid" : "dotted" ) + "-"
+ ( this . orientation == "h" ? "horizontal" : "vertical" ) ;
$j ( document . createElement ( "div" ) )
. addClass ( "ui-icon" )
. addClass ( icon )
. appendTo ( this . left . next ( ) ) ;
2013-04-10 11:25:05 +02:00
// Save preference when size changed
if ( this . id && this . egw ( ) . getAppName ( ) )
{
self = this ;
this . left . next ( ) . on ( "mouseup" , function ( ) {
// Store current position in preferences
var size = self . orientation == "v" ? { sizeLeft : self . left . width ( ) } : { sizeTop : self . left . height ( ) } ;
self . egw ( ) . set _preference ( self . egw ( ) . getAppName ( ) , 'splitter-size-' + self . id , size ) ;
} ) ;
}
2013-02-22 01:25:41 +01:00
} ,
/ * *
* Implement the et2 _IResizable interface to resize
* /
resize : function ( ) {
if ( this . dynheight )
{
2013-10-03 14:56:29 +02:00
this . dynheight . update ( function ( w , h ) {
if ( this . orientation == "v" )
{
this . left . height ( h ) ;
this . right . height ( h ) ;
}
if ( this . orientation == "h" )
{
this . left . width ( w ) ;
this . right . width ( w ) ;
}
} , this ) ;
2013-02-22 01:25:41 +01:00
}
} ,
getDOMNode : function ( ) {
return this . div [ 0 ] ;
} ,
/ * *
* Set splitter orientation
*
* @ param orient String "v" or "h"
* /
set _orientation : function ( orient ) {
this . orientation = orient ;
this . _init _splitter ( ) ;
} ,
/ * *
* Set the side for docking
*
* @ param dock String One of leftDock , rightDock , topDock , bottomDock
* /
set _dock _side : function ( dock ) {
this . dock _side = dock ;
this . _init _splitter ( ) ;
} ,
/ * *
* Turn on or off resizing while dragging
*
* @ param outline boolean
* /
set _outline : function ( outline ) {
this . outline = outline ;
this . _init _splitter ( ) ;
} ,
/ * *
* If the splitter has a dock direction set , dock it .
* Docking requires the dock attribute to be set .
* /
dock : function ( ) {
this . div . trigger ( "dock" ) ;
} ,
/ * *
* If the splitter is docked , restore it to previous size
* Docking requires the dock attribute to be set .
* /
undock : function ( ) {
this . div . trigger ( "undock" ) ;
} ,
/ * *
* Toggle the splitter ' s docked state .
* Docking requires the dock attribute to be set .
* /
toggleDock : function ( ) {
this . div . trigger ( "toggleDock" ) ;
}
} ) ;
et2 _register _widget ( et2 _split , [ "split" ] ) ;