/ * *
* Roundcube functions for default skin interface
*
* Copyright ( c ) 2011 , The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution - ShareAlike
* License . It is allowed to copy , distribute , transmit and to adapt the work
* by keeping credits to the original autors in the README file .
* See http : //creativecommons.org/licenses/by-sa/3.0/ for details.
*
* $Id$
* /
function rcube _mail _ui ( )
{
var env = { } ;
var popups = { } ;
var popupconfig = {
forwardmenu : { editable : 1 } ,
searchmenu : { editable : 1 , callback : searchmenu } ,
listoptions : { editable : 1 } ,
dragmessagemenu : { sticky : 1 } ,
groupmenu : { above : 1 } ,
mailboxmenu : { above : 1 } ,
composeoptionsmenu : { editable : 1 , overlap : 1 } ,
// toggle: #1486823, #1486930
'attachment-form' : { editable : 1 , above : 1 , toggle : ! bw . ie && ! bw . linux } ,
'upload-form' : { editable : 1 , toggle : ! bw . ie && ! bw . linux }
} ;
var me = this ;
var mailviewsplit ;
var compose _headers = { } ;
// export public methods
this . set = setenv ;
this . init = init ;
this . init _tabs = init _tabs ;
this . show _about = show _about ;
this . show _popup = show _popup ;
this . set _searchmod = set _searchmod ;
this . show _uploadform = show _uploadform ;
this . show _header _row = show _header _row ;
this . hide _header _row = hide _header _row ;
/ * *
*
* /
function setenv ( key , val )
{
env [ key ] = val ;
}
/ * *
*
* /
function init ( )
{
rcmail . addEventListener ( 'message' , message _displayed ) ;
if ( rcmail . env . task == 'mail' ) {
rcmail . addEventListener ( 'menu-open' , show _listoptions ) ;
rcmail . addEventListener ( 'menu-save' , save _listoptions ) ;
rcmail . addEventListener ( 'responseafterlist' , function ( e ) { switch _view _mode ( rcmail . env . threading ? 'thread' : 'list' ) } ) ;
var dragmenu = $ ( '#dragmessagemenu' ) ;
if ( dragmenu . length ) {
rcmail . gui _object ( 'message_dragmenu' , 'dragmessagemenu' ) ;
popups . dragmessagemenu = dragmenu ;
}
var previewframe = $ ( '#mailpreviewframe' ) . is ( ':visible' ) ;
$ ( '#mailpreviewtoggle' ) . addClass ( previewframe ? 'enabled' : 'closed' ) . click ( function ( e ) { toggle _preview _pane ( e ) ; return false } ) ;
$ ( '#maillistmode' ) . addClass ( rcmail . env . threading ? '' : 'selected' ) . click ( function ( e ) { switch _view _mode ( 'list' ) ; return false } ) ;
$ ( '#mailthreadmode' ) . addClass ( rcmail . env . threading ? 'selected' : '' ) . click ( function ( e ) { switch _view _mode ( 'thread' ) ; return false } ) ;
if ( rcmail . env . action == 'show' || rcmail . env . action == 'preview' ) {
layout _messageview ( ) ;
$ ( "#all-headers" ) . resizable ( { handles : 's' , minHeight : 50 } ) ;
$ ( '#previewheaderstoggle' ) . click ( function ( e ) { toggle _preview _headers ( this ) ; return false } ) ;
}
else if ( rcmail . env . action == 'compose' ) {
rcmail . addEventListener ( 'aftertoggle-editor' , function ( ) { window . setTimeout ( function ( ) { layout _composeview ( ) } , 200 ) ; } ) ;
rcmail . addEventListener ( 'aftersend-attachment' , show _uploadform ) ;
rcmail . addEventListener ( 'add-recipient' , function ( p ) { show _header _row ( p . field , true ) ; } ) ;
layout _composeview ( ) ;
$ ( '#composeoptionstoggle' ) . parent ( ) . click ( function ( ) {
$ ( '#composeoptionstoggle' ) . toggleClass ( 'enabled' ) ;
$ ( '#composeoptions' ) . toggle ( ) ;
layout _composeview ( ) ;
return false ;
} ) . css ( 'cursor' , 'pointer' ) ;
new rcube _splitter ( { id : 'composesplitterv' , p1 : '#composeview-left' , p2 : '#composeview-right' ,
orientation : 'v' , relative : true , start : 248 , min : 170 , size : 12 , render : layout _composeview } ) . init ( ) ;
}
else if ( rcmail . env . action == 'list' || ! rcmail . env . action ) {
mailviewsplit = new rcube _splitter ( { id : 'mailviewsplitter' , p1 : '#mailview-top' , p2 : '#mailview-bottom' ,
orientation : 'h' , relative : true , start : 310 , min : 150 , size : 0 , offset : - 22 } ) ;
if ( previewframe )
mailviewsplit . init ( ) ;
rcmail . addEventListener ( 'setquota' , update _quota ) ;
}
if ( $ ( '#mailview-left' ) . length ) {
new rcube _splitter ( { id : 'mailviewsplitterv' , p1 : '#mailview-left' , p2 : '#mailview-right' ,
orientation : 'v' , relative : true , start : 248 , min : 150 , size : 12 , callback : render _mailboxlist , render : resize _leftcol } ) . init ( ) ;
}
}
else if ( rcmail . env . task == 'settings' ) {
rcmail . addEventListener ( 'init' , function ( ) {
var tab = '#settingstabpreferences' ;
if ( rcmail . env . action )
tab = '#settingstab' + ( rcmail . env . action . indexOf ( 'identity' ) > 0 ? 'identities' : rcmail . env . action . replace ( /\./g , '' ) ) ;
$ ( tab ) . addClass ( 'selected' )
. children ( ) . first ( ) . removeAttr ( 'onclick' ) . click ( function ( ) { return false ; } ) ;
} ) ;
if ( rcmail . env . action == 'folders' ) {
new rcube _splitter ( { id : 'folderviewsplitter' , p1 : '#folderslist' , p2 : '#folder-details' ,
orientation : 'v' , relative : true , start : 305 , min : 150 , size : 12 } ) . init ( ) ;
}
else if ( rcmail . env . action == 'identities' ) {
new rcube _splitter ( { id : 'identviewsplitter' , p1 : '#identitieslist' , p2 : '#identity-details' ,
orientation : 'v' , relative : true , start : 305 , min : 150 , size : 12 } ) . init ( ) ;
}
}
else if ( rcmail . env . task == 'addressbook' ) {
rcmail . addEventListener ( 'afterupload-photo' , show _uploadform ) ;
if ( rcmail . env . action == '' ) {
new rcube _splitter ( { id : 'addressviewsplitterd' , p1 : '#addressview-left' , p2 : '#addressview-right' ,
orientation : 'v' , relative : true , start : 226 , min : 150 , size : 12 , render : resize _leftcol } ) . init ( ) ;
new rcube _splitter ( { id : 'addressviewsplitter' , p1 : '#addresslist' , p2 : '#contacts-box' ,
orientation : 'v' , relative : true , start : 296 , min : 220 , size : 12 } ) . init ( ) ;
}
}
else if ( rcmail . env . task == 'login' ) {
if ( bw . ie && bw . vendver < 9 ) {
var popup = $ ( '<div>' )
. addClass ( 'readtext' )
. html ( "Roundcube will not work well with the crappy browser ya' using. Get yourself a new internet browsing software and don't come back without!<p>Sincerly,<br/>the Roundcube Dev Team</p>" )
. appendTo ( document . body )
. dialog ( {
dialogClass : 'alert' ,
closeOnEscape : true ,
title : "No way, are you serious?" ,
close : function ( ) {
popup . dialog ( 'destroy' ) . remove ( ) ;
} ,
width : 450
} ) ;
}
}
// turn a group of fieldsets into tabs
$ ( '.tabbed' ) . each ( function ( idx , elem ) { init _tabs ( elem ) ; } )
$ ( document . body ) . bind ( 'mouseup' , function ( e ) {
var config , obj , target = e . target ;
for ( var id in popups ) {
obj = popups [ id ] ;
config = popupconfig [ id ] ;
if ( obj . is ( ':visible' )
&& target . id != id + 'link'
&& ! config . toggle
&& ( ! config . editable || ! target _overlaps ( target , obj . get ( 0 ) ) )
&& ( ! config . sticky || ! rcube _mouse _is _over ( e , obj . get ( 0 ) ) )
) {
var myid = id + '' ;
window . setTimeout ( function ( ) { show _popupmenu ( myid , false ) } , 10 ) ;
}
}
} )
. bind ( 'keyup' , function ( e ) {
if ( e . keyCode == 27 ) {
for ( var id in popups ) {
if ( popups [ id ] . is ( ':visible' ) )
show _popup ( id , false ) ;
}
}
} ) ;
$ ( window ) . resize ( function ( e ) {
// check target due to bugs in jquery
// http://bugs.jqueryui.com/ticket/7514
// http://bugs.jquery.com/ticket/9841
if ( e . target == window ) resize ( ) ;
} ) ;
}
/ * *
* Update UI on window resize
* /
function resize ( )
{
if ( rcmail . env . task == 'mail' && ( rcmail . env . action == 'show' || rcmail . env . action == 'preview' ) ) {
layout _messageview ( ) ;
}
if ( rcmail . env . task == 'mail' && rcmail . env . action == 'compose' ) {
layout _composeview ( ) ;
}
}
/ * *
* Triggered when a new user message is displayed
* /
function message _displayed ( p )
{
// show a popup dialog on errors
if ( p . type == 'error' ) {
if ( ! me . messagedialog ) {
me . messagedialog = $ ( '<div>' ) . addClass ( 'popupdialog' ) ;
}
var pos = $ ( p . object ) . offset ( ) ;
me . messagedialog . dialog ( 'close' ) ;
me . messagedialog . html ( p . message )
. dialog ( {
resizable : false ,
closeOnEscape : true ,
dialogClass : 'popupmessage ' + p . type ,
title : null ,
close : function ( ) {
me . messagedialog . dialog ( 'destroy' ) . hide ( ) ;
} ,
position : [ 'center' , pos . top - 160 ] ,
hide : { effect : 'drop' , direction : 'down' } ,
width : 420 ,
minHeight : 90
} ) . show ( ) ;
window . setTimeout ( function ( ) { me . messagedialog . dialog ( 'close' ) ; } , Math . max ( 2000 , p . timeout / 2 ) ) ;
}
}
/ * *
* Adjust UI objects of the mail view screen
* /
function layout _messageview ( )
{
$ ( '#messagecontent' ) . css ( 'top' , ( $ ( '#messageheader' ) . outerHeight ( ) + 10 ) + 'px' ) ;
$ ( '#message-objects div a' ) . addClass ( 'button' ) ;
if ( ! $ ( '#attachment-list li' ) . length ) {
$ ( 'div.rightcol' ) . hide ( ) ;
$ ( 'div.leftcol' ) . css ( 'margin-right' , '0' ) ;
}
}
function render _mailboxlist ( splitter )
{
// TODO: implement smart shortening of long folder names
}
function resize _leftcol ( splitter )
{
if ( splitter )
$ ( '#quicksearchbar input' ) . css ( 'width' , ( splitter . pos - 70 ) + 'px' ) ;
}
function layout _composeview ( )
{
var body = $ ( '#composebody' ) ,
form = $ ( '#compose-content' ) ,
bottom = $ ( '#composeview-bottom' ) ,
w , h ;
bottom . css ( 'height' , ( form . height ( ) - bottom . position ( ) . top ) + 'px' ) ;
w = body . parent ( ) . width ( ) - 6 ;
h = body . parent ( ) . height ( ) - 36 ;
body . width ( w ) . height ( h ) ;
if ( window . tinyMCE && tinyMCE . get ( 'composebody' ) ) {
$ ( '#composebody_tbl' ) . width ( ( w + 10 ) + 'px' ) . height ( '' ) . css ( 'margin-top' , '1px' ) ;
$ ( '#composebody_ifr' ) . width ( ( w + 10 ) + 'px' ) . height ( ( h - 22 ) + 'px' ) ;
}
else {
$ ( '#googie_edit_layer' ) . height ( h + 'px' ) ;
}
var abooks = $ ( '#directorylist' ) ;
$ ( '#compose-contacts .scroller' ) . css ( 'top' , abooks . position ( ) . top + abooks . outerHeight ( ) ) ;
}
function update _quota ( p )
{
var y = p . total ? Math . ceil ( p . percent / 100 * 20 ) * 24 : 0 ;
$ ( '#quotadisplay' ) . css ( 'background-position' , '0 -' + y + 'px' ) ;
}
/ * *
* Trigger for popup menus
* /
function show _popup ( popup , show , config )
{
// auto-register menu object
if ( config || ! popupconfig [ popup ] )
popupconfig [ popup ] = $ . extend ( popupconfig [ popup ] || { } , config ) ;
var visible = show _popupmenu ( popup , show ) ,
config = popupconfig [ popup ] ;
if ( typeof config . callback == 'function' )
config . callback ( visible ) ;
}
/ * *
* Show / hide a specific popup menu
* /
function show _popupmenu ( popup , show )
{
var obj = popups [ popup ] ,
config = popupconfig [ popup ] ,
ref = $ ( '#' + popup + 'link' ) ,
above = config . above ;
if ( ! obj ) {
obj = popups [ popup ] = $ ( '#' + popup ) ;
obj . appendTo ( document . body ) ; // move them to top for proper absolute positioning
}
if ( ! obj || ! obj . length )
return false ;
if ( typeof show == 'undefined' )
show = obj . is ( ':visible' ) ? false : true ;
else if ( config . toggle && show && obj . is ( ':visible' ) )
show = false ;
if ( show && ref ) {
var parent = ref . parent ( ) ,
win = $ ( window ) ,
pos ;
if ( parent . hasClass ( 'dropbutton' ) )
ref = parent ;
pos = ref . offset ( ) ;
ref . offsetHeight = ref . outerHeight ( ) ;
if ( ! above && pos . top + ref . offsetHeight + obj . height ( ) > win . height ( ) )
above = true ;
if ( pos . left + obj . width ( ) > win . width ( ) )
pos . left = win . width ( ) - obj . width ( ) - 12 ;
obj . css ( { left : pos . left , top : ( pos . top + ( above ? - obj . height ( ) : ref . offsetHeight ) ) } ) ;
}
obj [ show ? 'show' : 'hide' ] ( ) ;
// hide drop-down elements on buggy browsers
if ( bw . ie6 && config . overlap ) {
$ ( 'select' ) . css ( 'visibility' , show ? 'hidden' : 'inherit' ) ;
$ ( 'select' , obj ) . css ( 'visibility' , 'inherit' ) ;
}
return show ;
}
/ * *
*
* /
function target _overlaps ( target , elem )
{
while ( target . parentNode ) {
if ( target . parentNode == elem )
return true ;
target = target . parentNode ;
}
return false ;
}
/ * *
* Show / hide the preview pane
* /
function toggle _preview _pane ( e )
{
var button = $ ( e . target ) ,
frame = $ ( '#mailpreviewframe' ) ,
visible = ! frame . is ( ':visible' ) ,
splitter = mailviewsplit . pos || parseInt ( bw . get _cookie ( 'mailviewsplitter' ) || 320 ) ,
topstyles , bottomstyles , uid ;
frame . toggle ( ) ;
button . removeClass ( ) . addClass ( visible ? 'enabled' : 'closed' ) ;
if ( visible ) {
$ ( '#mailview-top' ) . css ( { bottom : 'auto' } ) ;
$ ( '#mailview-bottom' ) . css ( { height : 'auto' } ) ;
rcmail . env . contentframe = 'messagecontframe' ;
if ( uid = rcmail . message _list . get _single _selection ( ) )
rcmail . show _message ( uid , false , true ) ;
// let the splitter set the correct size and position
if ( mailviewsplit . handle ) {
mailviewsplit . handle . show ( ) ;
mailviewsplit . resize ( ) ;
}
else
mailviewsplit . init ( ) ;
}
else {
rcmail . env . contentframe = null ;
rcmail . show _contentframe ( false ) ;
$ ( '#mailview-top' ) . css ( { height : 'auto' , bottom : '28px' } ) ;
$ ( '#mailview-bottom' ) . css ( { top : 'auto' , height : '26px' } ) ;
if ( mailviewsplit . handle )
mailviewsplit . handle . hide ( ) ;
}
if ( visible && uid && rcmail . message _list )
rcmail . message _list . scrollto ( uid ) ;
rcmail . command ( 'save-pref' , { name : 'preview_pane' , value : ( visible ? 1 : 0 ) } ) ;
}
/ * *
* Switch between short and full headers display in message preview
* /
function toggle _preview _headers ( button )
{
$ ( '#preview-shortheaders' ) . toggle ( ) ;
var full = $ ( '#preview-allheaders' ) . toggle ( ) ;
// add toggle button to full headers table
if ( ! full . data ( 'mod' ) ) {
$ ( '<a>' ) . attr ( 'href' , '#hide' )
. addClass ( 'iconlink remove' )
. html ( 'Hide' )
. appendTo ( $ ( '<td>' ) . appendTo ( $ ( 'tr:first' , full ) ) )
. click ( function ( ) { toggle _preview _headers ( this ) ; return false } ) ;
full . data ( 'mod' , true ) ;
}
}
/ * *
*
* /
function switch _view _mode ( mode )
{
if ( rcmail . env . threading != ( mode == 'thread' ) )
rcmail . set _list _options ( null , undefined , undefined , mode == 'thread' ? 1 : 0 ) ;
$ ( '#maillistmode, #mailthreadmode' ) . removeClass ( 'selected' ) ;
$ ( '#mail' + mode + 'mode' ) . addClass ( 'selected' ) ;
}
/**** popup callbacks ****/
function searchmenu ( show )
{
if ( show && rcmail . env . search _mods ) {
var n , all ,
obj = popups [ 'searchmenu' ] ,
list = $ ( 'input:checkbox[name="s_mods[]"]' , obj ) ,
mbox = rcmail . env . mailbox ,
mods = rcmail . env . search _mods ;
if ( rcmail . env . task == 'mail' ) {
mods = mods [ mbox ] ? mods [ mbox ] : mods [ '*' ] ;
all = 'text' ;
}
else {
all = '*' ;
}
if ( mods [ all ] )
list . map ( function ( ) {
this . checked = true ;
this . disabled = this . value != all ;
} ) ;
else {
list . prop ( 'disabled' , false ) . prop ( 'checked' , false ) ;
for ( n in mods )
$ ( '#s_mod_' + n ) . prop ( 'checked' , true ) ;
}
}
}
/ * *
*
* /
function show _listoptions ( )
{
var $dialog = $ ( '#listoptions' ) ;
// close the dialog
if ( $dialog . is ( ':visible' ) ) {
$dialog . dialog ( 'close' ) ;
return ;
}
// set form values
$ ( 'input[name="sort_col"][value="' + rcmail . env . sort _col + '"]' ) . prop ( 'checked' , true ) ;
$ ( 'input[name="sort_ord"][value="DESC"]' ) . prop ( 'checked' , rcmail . env . sort _order == 'DESC' ) ;
$ ( 'input[name="sort_ord"][value="ASC"]' ) . prop ( 'checked' , rcmail . env . sort _order != 'DESC' ) ;
$ ( 'input[name="view"][value="thread"]' ) . prop ( 'checked' , rcmail . env . threading ? true : false ) ;
$ ( 'input[name="view"][value="list"]' ) . prop ( 'checked' , rcmail . env . threading ? false : true ) ;
// list columns
var found , cols = $ ( 'input[name="list_col[]"]' ) ;
for ( var i = 0 ; i < cols . length ; i ++ ) {
if ( cols [ i ] . value != 'from' ) {
found = $ . inArray ( cols [ i ] . value , rcmail . env . coltypes ) != - 1 ;
}
else {
found = ( $ . inArray ( 'from' , rcmail . env . coltypes ) != - 1
|| $ . inArray ( 'to' , rcmail . env . coltypes ) != - 1 ) ;
}
$ ( cols [ i ] ) . prop ( 'checked' , found ) ;
}
$dialog . dialog ( {
modal : true ,
resizable : false ,
closeOnEscape : true ,
title : null ,
close : function ( ) {
$dialog . dialog ( 'destroy' ) . hide ( ) ;
} ,
width : 650
} ) . show ( ) ;
}
/ * *
*
* /
function save _listoptions ( )
{
$ ( '#listoptions' ) . dialog ( 'close' ) ;
var sort = $ ( 'input[name="sort_col"]:checked' ) . val ( ) ,
ord = $ ( 'input[name="sort_ord"]:checked' ) . val ( ) ,
thread = $ ( 'input[name="view"]:checked' ) . val ( ) ,
cols = $ ( 'input[name="list_col[]"]:checked' )
. map ( function ( ) { return this . value ; } ) . get ( ) ;
rcmail . set _list _options ( cols , sort , ord , thread == 'thread' ? 1 : 0 ) ;
}
/ * *
*
* /
function set _searchmod ( elem )
{
var all , m , task = rcmail . env . task ,
mods = rcmail . env . search _mods ,
mbox = rcmail . env . mailbox ;
if ( ! mods )
mods = { } ;
if ( task == 'mail' ) {
if ( ! mods [ mbox ] )
mods [ mbox ] = rcube _clone _object ( mods [ '*' ] ) ;
m = mods [ mbox ] ;
all = 'text' ;
}
else { //addressbook
m = mods ;
all = '*' ;
}
if ( ! elem . checked )
delete ( m [ elem . value ] ) ;
else
m [ elem . value ] = 1 ;
// mark all fields
if ( elem . value != all )
return ;
$ ( 'input:checkbox[name="s_mods[]"]' ) . map ( function ( ) {
if ( this == elem )
return ;
this . checked = true ;
if ( elem . checked ) {
this . disabled = true ;
delete m [ this . value ] ;
}
else {
this . disabled = false ;
m [ this . value ] = 1 ;
}
} ) ;
}
function show _uploadform ( )
{
var $dialog = $ ( '#upload-dialog' ) ;
// close the dialog
if ( $dialog . is ( ':visible' ) ) {
$dialog . dialog ( 'close' ) ;
return ;
}
// add icons to clone file input field
if ( rcmail . env . action == 'compose' && ! $dialog . data ( 'extended' ) ) {
$ ( '<a>' )
. addClass ( 'iconlink add' )
. attr ( 'href' , '#add' )
. html ( 'Add' )
. appendTo ( $ ( 'input[type="file"]' , $dialog ) . parent ( ) )
. click ( add _uploadfile ) ;
$dialog . data ( 'extended' , true ) ;
}
$dialog . dialog ( {
modal : true ,
resizable : false ,
closeOnEscape : true ,
title : $dialog . attr ( 'title' ) ,
close : function ( ) {
try { $ ( '#upload-dialog form' ) . get ( 0 ) . reset ( ) ; }
catch ( e ) { } // ignore errors
$dialog . dialog ( 'destroy' ) . hide ( ) ;
$ ( 'div.addline' , $dialog ) . remove ( ) ;
} ,
width : 480
} ) . show ( ) ;
if ( ! document . all )
$ ( 'input[type=file]' , $dialog ) . first ( ) . click ( ) ;
}
function add _uploadfile ( e )
{
var div = $ ( this ) . parent ( ) ;
var clone = div . clone ( ) . addClass ( 'addline' ) . insertAfter ( div ) ;
clone . children ( '.iconlink' ) . click ( add _uploadfile ) ;
clone . children ( 'input' ) . val ( '' ) ;
if ( ! document . all )
$ ( 'input[type=file]' , clone ) . click ( ) ;
}
/ * *
*
* /
function show _header _row ( which , updated )
{
var row = $ ( '#compose-' + which ) ;
if ( row . is ( ':visible' ) )
return ; // nothing to be done here
if ( compose _headers [ which ] && ! updated )
$ ( '#_' + which ) . val ( compose _headers [ which ] ) ;
row . show ( ) ;
$ ( '#' + which + '-link' ) . hide ( ) ;
layout _composeview ( ) ;
return false ;
}
/ * *
*
* /
function hide _header _row ( which )
{
// copy and clear field value
var field = $ ( '#_' + which ) ;
compose _headers [ which ] = field . val ( ) ;
field . val ( '' ) ;
$ ( '#compose-' + which ) . hide ( ) ;
$ ( '#' + which + '-link' ) . show ( ) ;
layout _composeview ( ) ;
return false ;
}
/ * *
* Fieldsets - to - tabs converter
* /
function init _tabs ( elem , current )
{
var id = elem . id ,
content = $ ( elem ) ,
fs = content . children ( 'fieldset' ) ;
if ( ! fs . length )
return ;
if ( ! id ) {
id = 'rcmtabcontainer' ;
elem . attr ( 'id' , id ) ;
}
// first hide not selected tabs
current = current || 0 ;
fs . each ( function ( idx ) { if ( idx != current ) $ ( this ) . hide ( ) ; } ) ;
// create tabs container
var tabs = $ ( '<div>' ) . addClass ( 'tabsbar' ) . prependTo ( content ) ;
// convert fildsets into tabs
fs . each ( function ( idx ) {
var tab , a , elm = $ ( this ) , legend = elm . children ( 'legend' ) ;
// create a tab
a = $ ( '<a>' ) . text ( legend . text ( ) ) . attr ( 'href' , '#' ) ;
tab = $ ( '<span>' ) . attr ( { 'id' : 'tab' + idx , 'class' : 'tablink' } )
. click ( function ( ) { show _tab ( id , idx ) ; return false } )
// remove legend
legend . remove ( ) ;
// style fieldset
elm . addClass ( 'tab' ) ;
// style selected tab
if ( idx == current )
tab . addClass ( 'selected' ) ;
// add the tab to container
tab . append ( a ) . appendTo ( tabs ) ;
} ) ;
}
function show _tab ( id , index )
{
var fs = $ ( '#' + id ) . children ( 'fieldset' ) ;
fs . each ( function ( idx ) {
// Show/hide fieldset (tab content)
$ ( this ) [ index == idx ? 'show' : 'hide' ] ( ) ;
// Select/unselect tab
$ ( '#tab' + idx ) . toggleClass ( 'selected' , idx == index ) ;
} ) ;
}
/ * *
* Show about page as jquery UI dialog
* /
function show _about ( elem )
{
var frame = $ ( '<iframe>' ) . attr ( 'id' , 'aboutframe' )
. attr ( 'src' , rcmail . url ( 'settings/about' ) )
. appendTo ( document . body ) ;
var h = Math . floor ( $ ( window ) . height ( ) * 0.75 ) ;
var buttons = { } ;
var supportln = $ ( '#supportlink' ) ;
if ( supportln . length && ( env . supporturl = supportln . attr ( 'href' ) ) )
buttons [ supportln . html ( ) ] = function ( e ) { env . supporturl . indexOf ( 'mailto:' ) < 0 ? window . open ( env . supporturl ) : location . href = env . supporturl } ;
frame . dialog ( {
modal : true ,
resizable : false ,
closeOnEscape : true ,
title : elem ? elem . title || elem . innerHTML : null ,
close : function ( ) {
frame . dialog ( 'destroy' ) . remove ( ) ;
} ,
buttons : buttons ,
width : 640 ,
height : h
} ) . width ( 640 ) ;
}
}
/ * *
* Roundcube splitter GUI class
*
* @ constructor
* /
function rcube _splitter ( p )
{
this . p = p ;
this . id = p . id ;
this . horizontal = ( p . orientation == 'horizontal' || p . orientation == 'h' ) ;
this . halfsize = ( p . size !== undefined ? p . size : 10 ) / 2 ;
this . pos = p . start || 0 ;
this . min = p . min || 20 ;
this . offset = p . offset || 0 ;
this . relative = p . relative ? true : false ;
this . drag _active = false ;
this . render = p . render ;
this . callback = p . callback ;
var me = this ;
this . init = function ( )
{
this . p1 = $ ( this . p . p1 ) ;
this . p2 = $ ( this . p . p2 ) ;
// create and position the handle for this splitter
this . p1pos = this . relative ? this . p1 . position ( ) : this . p1 . offset ( ) ;
this . p2pos = this . relative ? this . p2 . position ( ) : this . p2 . offset ( ) ;
this . handle = $ ( '<div>' )
. attr ( 'id' , this . id )
. attr ( 'unselectable' , 'on' )
. addClass ( 'splitter ' + ( this . horizontal ? 'splitter-h' : 'splitter-v' ) )
. appendTo ( this . p1 . parent ( ) )
. bind ( 'mousedown' , onDragStart ) ;
if ( this . horizontal ) {
var top = this . p1pos . top + this . p1 . outerHeight ( ) ;
this . handle . css ( { left : '0px' , top : top + 'px' } ) ;
}
else {
var left = this . p1pos . left + this . p1 . outerWidth ( ) ;
this . handle . css ( { left : left + 'px' , top : '0px' } ) ;
}
this . elm = this . handle . get ( 0 ) ;
// listen to window resize on IE
if ( bw . ie )
$ ( window ) . resize ( function ( e ) { onResize ( e ) } ) ;
// read saved position from cookie
var cookie = bw . get _cookie ( this . id ) ;
if ( cookie && ! isNaN ( cookie ) ) {
this . pos = parseFloat ( cookie ) ;
this . resize ( ) ;
}
else if ( this . pos ) {
this . resize ( ) ;
this . set _cookie ( ) ;
}
} ;
/ * *
* Set size and position of all DOM objects
* according to the saved splitter position
* /
this . resize = function ( )
{
if ( this . horizontal ) {
this . p1 . css ( 'height' , Math . floor ( this . pos - this . p1pos . top - this . halfsize ) + 'px' ) ;
this . p2 . css ( 'top' , Math . ceil ( this . pos + this . halfsize + 2 ) + 'px' ) ;
this . handle . css ( 'top' , Math . round ( this . pos - this . halfsize + this . offset ) + 'px' ) ;
if ( bw . ie ) {
var new _height = parseInt ( this . p2 . parent ( ) . outerHeight ( ) , 10 ) - parseInt ( this . p2 . css ( 'top' ) , 10 ) - ( bw . ie8 ? 2 : 0 ) ;
this . p2 . css ( 'height' , ( new _height > 0 ? new _height : 0 ) + 'px' ) ;
}
}
else {
this . p1 . css ( 'width' , Math . floor ( this . pos - this . p1pos . left - this . halfsize ) + 'px' ) ;
this . p2 . css ( 'left' , Math . ceil ( this . pos + this . halfsize ) + 'px' ) ;
this . handle . css ( 'left' , Math . round ( this . pos - this . halfsize + this . offset + 3 ) + 'px' ) ;
if ( bw . ie ) {
var new _width = parseInt ( this . p2 . parent ( ) . outerWidth ( ) , 10 ) - parseInt ( this . p2 . css ( 'left' ) , 10 ) ;
this . p2 . css ( 'width' , ( new _width > 0 ? new _width : 0 ) + 'px' ) ;
}
}
this . p2 . resize ( ) ;
this . p1 . resize ( ) ;
// also resize iframe covers
if ( this . drag _active ) {
$ ( 'iframe' ) . each ( function ( i , elem ) {
var pos = $ ( this ) . offset ( ) ;
$ ( '#iframe-splitter-fix-' + i ) . css ( { top : pos . top + 'px' , left : pos . left + 'px' , width : elem . offsetWidth + 'px' , height : elem . offsetHeight + 'px' } ) ;
} ) ;
}
if ( typeof this . render == 'function' )
this . render ( this ) ;
} ;
/ * *
* Handler for mousedown events
* /
function onDragStart ( e )
{
// disable text selection while dragging the splitter
if ( bw . konq || bw . chrome || bw . safari )
document . body . style . webkitUserSelect = 'none' ;
me . p1pos = me . relative ? me . p1 . position ( ) : me . p1 . offset ( ) ;
me . p2pos = me . relative ? me . p2 . position ( ) : me . p2 . offset ( ) ;
me . drag _active = true ;
// start listening to mousemove events
$ ( document ) . bind ( 'mousemove.' + this . id , onDrag ) . bind ( 'mouseup.' + this . id , onDragStop ) ;
// enable dragging above iframes
$ ( 'iframe' ) . each ( function ( i , elem ) {
$ ( '<div>' )
. attr ( 'id' , 'iframe-splitter-fix-' + i )
. addClass ( 'iframe-splitter-fix' )
. css ( { background : '#fff' ,
width : elem . offsetWidth + 'px' , height : elem . offsetHeight + 'px' ,
position : 'absolute' , opacity : '0.001' , zIndex : 1000
} )
. css ( $ ( this ) . offset ( ) )
. appendTo ( 'body' ) ;
} ) ;
} ;
/ * *
* Handler for mousemove events
* /
function onDrag ( e )
{
if ( ! me . drag _active )
return false ;
var pos = rcube _event . get _mouse _pos ( e ) ;
if ( me . relative ) {
var parent = me . p1 . parent ( ) . offset ( ) ;
pos . x -= parent . left ;
pos . y -= parent . top ;
}
if ( me . horizontal ) {
if ( ( ( pos . y - me . halfsize ) > me . p1pos . top ) && ( ( pos . y + me . halfsize ) < ( me . p2pos . top + me . p2 . outerHeight ( ) ) ) ) {
me . pos = Math . max ( me . min , pos . y - me . offset ) ;
me . resize ( ) ;
}
}
else {
if ( ( ( pos . x - me . halfsize ) > me . p1pos . left ) && ( ( pos . x + me . halfsize ) < ( me . p2pos . left + me . p2 . outerWidth ( ) ) ) ) {
me . pos = Math . max ( me . min , pos . x - me . offset ) ;
me . resize ( ) ;
}
}
me . p1pos = me . relative ? me . p1 . position ( ) : me . p1 . offset ( ) ;
me . p2pos = me . relative ? me . p2 . position ( ) : me . p2 . offset ( ) ;
return false ;
} ;
/ * *
* Handler for mouseup events
* /
function onDragStop ( e )
{
// resume the ability to highlight text
if ( bw . konq || bw . chrome || bw . safari )
document . body . style . webkitUserSelect = 'auto' ;
// cancel the listening for drag events
$ ( document ) . unbind ( '.' + me . id ) ;
me . drag _active = false ;
// remove temp divs
$ ( 'div.iframe-splitter-fix' ) . remove ( ) ;
me . set _cookie ( ) ;
if ( typeof me . callback == 'function' )
me . callback ( me ) ;
return bw . safari ? true : rcube _event . cancel ( e ) ;
} ;
/ * *
* Handler for window resize events
* /
function onResize ( e )
{
if ( me . horizontal ) {
var new _height = parseInt ( me . p2 . parent ( ) . outerHeight ( ) , 10 ) - parseInt ( me . p2 [ 0 ] . style . top , 10 ) - ( bw . ie8 ? 2 : 0 ) ;
me . p2 . css ( 'height' , ( new _height > 0 ? new _height : 0 ) + 'px' ) ;
}
else {
var new _width = parseInt ( me . p2 . parent ( ) . outerWidth ( ) , 10 ) - parseInt ( me . p2 [ 0 ] . style . left , 10 ) ;
me . p2 . css ( 'width' , ( new _width > 0 ? new _width : 0 ) + 'px' ) ;
}
} ;
/ * *
* Saves splitter position in cookie
* /
this . set _cookie = function ( )
{
var exp = new Date ( ) ;
exp . setYear ( exp . getFullYear ( ) + 1 ) ;
bw . set _cookie ( this . id , this . pos , exp ) ;
} ;
} // end class rcube_splitter