2011-04-27 18:53:06 +02:00
/ * *
2013-10-31 15:51:19 +01:00
* EGroupware - Calendar - Javascript UI
2011-04-27 18:53:06 +02:00
*
* @ link http : //www.egroupware.org
* @ package calendar
2013-10-31 15:51:19 +01:00
* @ author Hadi Nategh < hn - AT - stylite . de >
* @ copyright ( c ) 2008 - 13 by Ralf Becker < RalfBecker - AT - outdoor - training . de >
2011-04-27 18:53:06 +02:00
* @ license http : //opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @ version $Id$
* /
2013-11-05 19:08:07 +01:00
/ * e g w : u s e s
/ e t e m p l a t e / j s / e t e m p l a t e 2 . j s
* /
2011-04-27 18:53:06 +02:00
/ * *
2013-10-31 15:51:19 +01:00
* UI for calendar
*
* @ augments AppJS
2011-04-27 18:53:06 +02:00
* /
2013-11-04 21:54:23 +01:00
app . classes . calendar = AppJS . extend (
2011-04-27 18:53:06 +02:00
{
2013-10-31 15:51:19 +01:00
/ * *
* application name
* /
appname : 'calendar' ,
2013-11-05 19:08:07 +01:00
2013-10-31 15:51:19 +01:00
/ * *
* Constructor
*
* @ memberOf app . calendar
* /
init : function ( )
2011-04-27 18:53:06 +02:00
{
2013-12-12 00:51:35 +01:00
// make calendar object available, even if not running in top window, as sidebox does
2014-11-27 18:37:18 +01:00
if ( window . top !== window && ! egw ( window ) . is _popup ( ) )
2013-12-12 00:51:35 +01:00
{
2014-08-26 18:29:12 +02:00
// we have to explicitly delete old object or IE11 complains about accessing an already freed script
delete window . top . app . calendar ;
2013-12-12 00:51:35 +01:00
window . top . app . calendar = this ;
}
2014-08-26 18:29:12 +02:00
// call parent
this . _super . apply ( this , arguments ) ;
2014-08-21 16:12:07 +02:00
//Drag_n_Drop (need to wait for DOM ready to init dnd)
jQuery ( jQuery . proxy ( this . drag _n _drop , this ) ) ;
2013-10-31 15:51:19 +01:00
} ,
/ * *
* Destructor
* /
destroy : function ( )
2011-04-27 18:53:06 +02:00
{
2013-10-31 15:51:19 +01:00
// call parent
this . _super . apply ( this , arguments ) ;
2013-12-12 00:51:35 +01:00
// remove top window reference
if ( window . top !== window && window . top . app . calendar === this )
{
2014-02-19 16:20:19 +01:00
delete window . top . app . calendar ;
2013-12-12 00:51:35 +01:00
}
2013-10-31 15:51:19 +01:00
} ,
2011-04-27 18:53:06 +02:00
2013-10-31 15:51:19 +01:00
/ * *
* This function is called when the etemplate2 object is loaded
* and ready . If you must store a reference to the et2 object ,
* make sure to clean it up in destroy ( ) .
*
2014-02-19 16:20:19 +01:00
* @ param { etemplate2 } _et2 newly ready et2 object
* @ param { string } _name name of template
2013-10-31 15:51:19 +01:00
* /
2014-02-19 16:20:19 +01:00
et2 _ready : function ( _et2 , _name )
2013-10-31 15:51:19 +01:00
{
// call parent
this . _super . apply ( this , arguments ) ;
2014-02-12 18:36:20 +01:00
// Re-init sidebox, since it was probably initialized too soon
var sidebox = jQuery ( '#favorite_sidebox_' + this . appname ) ;
if ( sidebox . length == 0 && egw _getFramework ( ) != null )
{
var egw _fw = egw _getFramework ( ) ;
sidebox = $j ( '#favorite_sidebox_' + this . appname , egw _fw . sidemenuDiv ) ;
}
this . _init _sidebox ( sidebox ) ;
2013-10-31 15:51:19 +01:00
var content = this . et2 . getArrayMgr ( 'content' ) ;
2014-10-30 11:24:11 +01:00
2014-02-19 16:20:19 +01:00
switch ( _name )
2013-10-31 15:51:19 +01:00
{
2014-02-19 16:20:19 +01:00
case 'calendar.list' :
this . filter _change ( ) ;
break ;
case 'calendar.edit' :
if ( typeof content . data [ 'conflicts' ] == 'undefined' )
2014-01-24 16:50:17 +01:00
{
2014-02-19 16:20:19 +01:00
$j ( document . getElementById ( 'calendar-edit_calendar-delete_series' ) ) . hide ( ) ;
//Check if it's fallback from conflict window or it's from edit window
if ( content . data [ 'button_was' ] != 'freetime' )
{
this . set _enddate _visibility ( ) ;
this . check _recur _type ( ) ;
2014-10-30 11:24:11 +01:00
this . et2 . getWidgetById ( 'recur_exception' ) . set _disabled ( ! content . data . recur _exception ||
typeof content . data . recur _exception [ 0 ] == 'undefined' ) ;
2014-02-19 16:20:19 +01:00
}
else
{
this . freetime _search ( ) ;
}
//send Syncronus ajax request to the server to unlock the on close entry
//set onbeforeunload with json request to send request when the window gets close by X button
2015-08-31 12:49:17 +02:00
if ( content . data . lock _token )
{
window . onbeforeunload = function ( ) {
this . egw . json ( 'calendar.calendar_uiforms.ajax_unlock' ,
[ content . data . id , content . data . lock _token ] , null , true , null , null ) . sendRequest ( true ) ;
} ;
}
2014-01-24 16:50:17 +01:00
}
2014-05-27 17:02:56 +02:00
this . alarm _custom _date ( ) ;
2014-02-19 16:20:19 +01:00
break ;
case 'calendar.freetimesearch' :
2013-10-31 15:51:19 +01:00
this . set _enddate _visibility ( ) ;
2014-02-19 16:20:19 +01:00
break ;
2013-10-31 15:51:19 +01:00
}
} ,
2014-08-21 14:43:14 +02:00
2014-06-25 17:39:58 +02:00
/ * *
* Observer method receives update notifications from all applications
*
* App is responsible for only reacting to "messages" it is interested in !
*
* @ param { string } _msg message ( already translated ) to show , eg . 'Entry deleted'
* @ param { string } _app application name
* @ param { ( string | number ) } _id id of entry to refresh or null
* @ param { string } _type either 'update' , 'edit' , 'delete' , 'add' or null
* - update : request just modified data from given rows . Sorting is not considered ,
* so if the sort field is changed , the row will not be moved .
* - edit : rows changed , but sorting may be affected . Requires full reload .
* - delete : just delete the given rows clientside ( no server interaction neccessary )
* - add : requires full reload for proper sorting
* @ param { string } _msg _type 'error' , 'warning' or 'success' ( default )
* @ param { object | null } _links app => array of ids of linked entries
* or null , if not triggered on server - side , which adds that info
* @ return { false | * } false to stop regular refresh , thought all observers are run
* /
observer : function ( _msg , _app , _id , _type , _msg _type , _links )
{
2014-06-26 14:39:20 +02:00
var do _refresh = false ;
switch ( _app )
2014-06-25 17:39:58 +02:00
{
2014-06-26 14:39:20 +02:00
case 'infolog' :
2014-06-25 17:39:58 +02:00
{
2014-06-26 14:39:20 +02:00
jQuery ( '.calendar_calDayTodos' )
. find ( 'a' )
. each ( function ( i , a ) {
var match = a . href . split ( /&info_id=/ ) ;
if ( match && typeof match [ 1 ] != "undefined" )
2014-06-25 17:39:58 +02:00
{
2014-06-26 14:39:20 +02:00
if ( match [ 1 ] == _id ) do _refresh = true ;
2014-06-25 17:39:58 +02:00
}
2014-06-26 14:39:20 +02:00
} ) ;
2014-08-21 15:31:10 +02:00
if ( jQuery ( 'div [id^="infolog' + _id + '"],div [id^="drag_infolog' + _id + '"]' ) . length > 0 ) do _refresh = true ;
2014-06-26 14:39:20 +02:00
switch ( _type )
{
case 'add' :
do _refresh = true ;
break ;
}
if ( do _refresh )
{
if ( typeof this . et2 != 'undefined' && this . et2 != null )
{
this . egw . refresh ( _msg , 'calendar' ) ;
}
else
{
2014-10-07 18:21:19 +02:00
var iframe = parent . jQuery ( parent . document ) . find ( '.egw_fw_content_browser_iframe' ) ;
var calTab = iframe . parentsUntil ( jQuery ( '.egw_fw_ui_tab_content' ) , '.egw_fw_ui_tab_content' ) ;
2014-10-30 11:24:11 +01:00
if ( ! calTab . is ( ':visible' ) )
2014-10-07 18:21:19 +02:00
{
2014-10-30 11:24:11 +01:00
// F.F can not handle to style correctly an iframe which is hidden (display:none), therefore we need to
2014-10-07 18:21:19 +02:00
// bind a handler to refresh the calendar views after it shows up
2014-11-27 18:37:18 +01:00
iframe . one ( 'show' , function ( ) { egw _refresh ( '' , 'calendar' ) ; } ) ;
2014-10-07 18:21:19 +02:00
}
else
2014-10-30 11:24:11 +01:00
{
2014-10-07 18:21:19 +02:00
//window.location.reload();
window . egw _refresh ( 'refreshing calendar' , 'calendar' ) ;
}
2014-06-25 17:39:58 +02:00
}
2014-06-26 14:39:20 +02:00
}
2014-06-25 17:39:58 +02:00
}
2014-06-26 14:39:20 +02:00
break ;
2014-08-21 14:43:14 +02:00
}
2014-06-25 17:39:58 +02:00
} ,
2014-08-21 14:43:14 +02:00
2014-01-24 16:50:17 +01:00
/ * *
* Link hander for jDots template to just reload our iframe , instead of reloading whole admin app
*
* @ param { String } _url
* @ return { boolean | string } true , if linkHandler took care of link , false for default processing or url to navigate to
* /
linkHandler : function ( _url )
{
if ( _url . match ( 'menuaction=calendar.calendar_uiviews.index' ) )
{
var state = this . getState ( ) ;
if ( state . view == 'listview' )
{
return _url . replace ( /menuaction=[^&]+/ , 'menuaction=calendar.calendar_uilist.listview&ajax=true' ) ;
}
}
// can not load our own index page, has to be done by framework
return false ;
} ,
2013-12-13 19:18:56 +01:00
/ * *
* Drag and Drop
*
*
* /
drag _n _drop : function ( )
{
var that = this ;
2014-01-30 19:24:24 +01:00
2014-02-26 14:35:27 +01:00
//Draggable & Resizable selector
2014-11-05 17:13:26 +01:00
var $drag = jQuery ( "div[id^='drag_']" )
//draggable event handler
. draggable
( {
stack : jQuery ( "div[id^='drag_']" ) ,
revert : "invalid" ,
delay : 50 ,
cursorAt : { top : 0 , left : 0 } ,
containment : ".egw_fw_content_browser_iframe" ,
scroll : true ,
opacity : . 6 ,
cursor : "move" ,
/ * *
* Triggered when the dragging of calEvent stoped .
*
* @ param { event } event
* @ param { Object } ui
* /
stop : function ( event , ui )
{
ui . helper . width ( oldWidth ) ;
ui . helper [ 0 ] . innerHTML = oldInnerHTML ;
} ,
2014-02-21 17:37:39 +01:00
2014-11-05 17:13:26 +01:00
/ * *
* Triggered while dragging a calEvent .
*
* @ param { event } event
* @ param { Object } ui
*
* /
drag : function ( event , ui )
{
//that.dragEvent();
} ,
2014-02-26 14:35:27 +01:00
2014-11-05 17:13:26 +01:00
/ * *
* Triggered when the dragging of calEvent started .
*
* @ param { event } event
* @ param { Object } ui
*
* /
start : function ( event , ui )
{
oldInnerHTML = ui . helper [ 0 ] . innerHTML ;
oldWidth = ui . helper . width ( ) ;
ui . helper . width ( jQuery ( "#calColumn" ) . width ( ) ) ;
}
} )
2014-01-30 19:24:24 +01:00
2014-11-05 17:13:26 +01:00
//Resizable event handler
. resizable
( {
distance : 10 ,
2014-01-30 19:24:24 +01:00
2014-01-30 17:48:49 +01:00
2014-11-05 17:13:26 +01:00
/ * *
* Triggered when the resizable is created .
*
* @ param { event } event
* @ param { Object } ui
* /
create : function ( event , ui )
{
var resizeHelper = event . target . getAttribute ( 'data-resize' ) . split ( "|" ) [ 3 ] ;
if ( resizeHelper == 'WD' || resizeHelper == 'WDS' )
{
jQuery ( this ) . resizable ( 'destroy' ) ;
}
} ,
2014-01-30 19:24:24 +01:00
2014-11-05 17:13:26 +01:00
/ * *
* Triggered at start of resizing a calEvent
*
* @ param { event } event
* @ param { Object } ui
* /
start : function ( event , ui )
{
var resizeHelper = event . target . getAttribute ( 'data-resize' ) ;
var dataResize = resizeHelper . split ( "|" ) ;
var time = dataResize [ 1 ] . split ( ":" ) ;
2014-01-29 19:44:12 +01:00
2014-11-05 17:13:26 +01:00
this . dropStart = that . resizeHelper ( ui . element [ 0 ] . getBoundingClientRect ( ) . left , ui . element [ 0 ] . getBoundingClientRect ( ) . top ) ;
this . dropDate = dataResize [ 0 ] + "T" + time [ 0 ] + time [ 1 ] ;
//$j(this).resizable("option","containment",".calendar_calDayCol");
} ,
2014-01-30 17:48:49 +01:00
2014-11-05 17:13:26 +01:00
/ * *
* Triggered at the end of resizing the calEvent .
*
* @ param { event } event
* @ param { Object } ui
* /
stop : function ( event , ui )
{
var eventFlag = event . target . getAttribute ( 'data-resize' ) . split ( "|" ) [ 3 ] ;
var dropdate = that . cal _dnd _tZone _converter ( this . dropDate ) ;
var sT = parseInt ( ( dropdate . split ( "T" ) [ 1 ] . substr ( 0 , 2 ) * 60 ) ) + parseInt ( dropdate . split ( "T" ) [ 1 ] . substr ( 2 , 2 ) ) ;
if ( this . dropEnd != 'undefined' && this . dropEnd )
{
var eT = parseInt ( this . dropEnd . getAttribute ( 'data-date' ) . split ( "|" ) [ 1 ] * 60 ) + parseInt ( this . dropEnd . getAttribute ( 'data-date' ) . split ( "|" ) [ 2 ] ) ;
var newDuration = ( ( eT - sT ) / 60 ) * 3600 ;
that . dropEvent ( this . getAttribute ( 'id' ) , dropdate , newDuration , eventFlag ) ;
}
} ,
2014-01-30 17:48:49 +01:00
2014-11-05 17:13:26 +01:00
/ * *
* Triggered during the resize , on the drag of the resize handler
*
* @ param { event } event
* @ param { Object } ui
* /
resize : function ( event , ui )
2014-01-30 17:48:49 +01:00
{
2014-11-05 17:13:26 +01:00
this . dropEnd = that . resizeHelper ( ui . element [ 0 ] . getBoundingClientRect ( ) . left ,
ui . element [ 0 ] . getBoundingClientRect ( ) . top + ui . size . height ) ;
if ( typeof this . dropEnd != 'undefined' && this . dropEnd )
{
if ( this . dropEnd . getAttribute ( 'id' ) . match ( /drop_/g ) )
{
var dH = this . dropEnd . getAttribute ( 'data-date' ) . split ( "|" ) [ 1 ] ;
var dM = this . dropEnd . getAttribute ( 'data-date' ) . split ( "|" ) [ 2 ] ;
}
var dataResize = event . target . getAttribute ( 'data-resize' ) . split ( "|" ) ;
this . innerHTML = '<div style="font-size: 1.1em; text-align:center; font-weight: bold; height:100%;"><span class="calendar_timeDemo" >' + dH + ':' + dM + '</span></div>' ;
}
else
{
this . innerHTML = '<div class="calendar_d-n-d_forbiden"></div>' ;
}
2014-01-30 17:48:49 +01:00
}
2014-11-05 17:13:26 +01:00
} ) ;
2013-12-13 19:18:56 +01:00
2014-02-21 17:37:39 +01:00
//Droppable selector
2014-11-05 17:13:26 +01:00
var $drop = jQuery ( "div[id^='drop_']" )
//Droppable event handler
. droppable
( {
/ * *
* Make all draggable calEvents acceptable
*
* /
accept : function ( )
{
return true ;
} ,
tolerance : 'pointer' ,
/ * *
* Triggered when the calEvent dropped .
*
* @ param { event } event
* @ param { Object } ui
* /
drop : function ( event , ui )
{
var dgId = ui . draggable [ 0 ] . getAttribute ( 'id' ) ;
var dgOwner = dgId . substring ( dgId . lastIndexOf ( "_C" ) + 2 , dgId . lastIndexOf ( "" ) ) ;
var dpOwner = event . target . getAttribute ( 'data-owner' ) ;
var eventFlag = ui . draggable [ 0 ] . getAttribute ( 'data-resize' ) . split ( "|" ) [ 3 ] ;
if ( dpOwner == null ) dpOwner = dgOwner ;
if ( dpOwner == dgOwner )
{
that . dropEvent ( ui . draggable [ 0 ] . id , event . target . getAttribute ( 'id' ) . substring ( event . target . getAttribute ( 'id' ) . lastIndexOf ( "drop_" ) + 5 , event . target . getAttribute ( 'id' ) . lastIndexOf ( "_O" ) ) , null , eventFlag ) ;
}
else
{
jQuery ( ui . draggable ) . draggable ( "option" , "revert" , true ) ;
}
2013-12-13 19:18:56 +01:00
2014-11-05 17:13:26 +01:00
} ,
2014-01-30 17:48:49 +01:00
2014-11-05 17:13:26 +01:00
/ * *
* Triggered when draggable calEvent is over a droppable calCell .
*
* @ param { event } event
* @ param { Object } ui
* /
over : function ( event , ui )
{
var timeDemo = event . target . id . substring ( event . target . id . lastIndexOf ( "T" ) + 1 , event . target . id . lastIndexOf ( "_O" ) ) ;
var dgId = ui . draggable [ 0 ] . getAttribute ( 'id' ) ;
var dgOwner = dgId . substring ( dgId . lastIndexOf ( "_C" ) + 2 , dgId . lastIndexOf ( "" ) ) ;
var dpOwner = event . target . getAttribute ( 'data-owner' ) ;
if ( dpOwner == null ) dpOwner = dgOwner ;
if ( dpOwner === dgOwner )
{
ui . helper [ 0 ] . innerHTML = '<div class="calendar_d-n-d_timeCounter"><span>' + timeDemo + '</span></div>' ;
}
else
{
ui . helper [ 0 ] . innerHTML = '<div class="calendar_d-n-d_forbiden"></div>' ;
}
}
} ) ;
2014-02-26 14:35:27 +01:00
2014-02-21 17:37:39 +01:00
//jQuery Calendar Event selector
2014-11-05 17:13:26 +01:00
var $iframeBody = jQuery ( "body" )
2014-02-21 17:37:39 +01:00
//mouseover event handler for calendar tooltip
. on ( "mouseover" , "div[data-tooltip]" , function ( ) {
2014-10-27 14:04:31 +01:00
var $ttp = jQuery ( this ) ;
2014-10-23 14:59:19 +02:00
//Check if the tooltip is already initialized
2014-10-27 14:04:31 +01:00
if ( ! $ttp . data ( 'uiTooltip' ) )
2014-10-23 14:59:19 +02:00
{
2014-10-27 14:04:31 +01:00
$ttp . tooltip ( {
2014-10-23 14:59:19 +02:00
items : "[data-tooltip]" ,
show : false ,
content : function ( )
{
2014-10-27 14:04:31 +01:00
var elem = $ttp ;
2014-10-23 14:59:19 +02:00
if ( elem . is ( "[data-tooltip]" ) )
return this . getAttribute ( 'data-tooltip' ) ;
} ,
track : true ,
open : function ( event , ui ) {
ui . tooltip . removeClass ( "ui-tooltip" ) ;
ui . tooltip . addClass ( "calendar_uitooltip" ) ;
if ( this . scrollHeight > this . clientHeight )
{
// bind on tooltip close event
2014-10-27 14:04:31 +01:00
$ttp . on ( "tooltipclose" , function ( event , ui ) {
2014-10-30 11:24:11 +01:00
// bind hover handler on tooltip helper in order to be able to freeze the tooltip and scrolling
2014-10-23 14:59:19 +02:00
ui . tooltip . hover (
function ( ) {
2014-10-27 14:04:31 +01:00
var $ttp _helper = jQuery ( this ) ;
if ( this . scrollHeight > this . clientHeight ) $ttp _helper . stop ( true ) . fadeTo ( 100 , 1 ) ;
2014-10-23 14:59:19 +02:00
} ,
function ( ) {
2014-10-27 14:04:31 +01:00
var $ttp _helper = jQuery ( this ) ;
$ttp _helper . fadeOut ( "100" , function ( ) { $ttp _helper . remove ( ) ; } ) ;
2014-10-23 14:59:19 +02:00
}
) ;
} ) ;
2014-10-15 14:03:15 +02:00
}
2014-10-23 14:59:19 +02:00
}
} ) ;
}
2014-10-27 14:04:31 +01:00
else
{
$ttp . tooltip ( 'enable' ) ;
}
2014-02-21 17:37:39 +01:00
} )
2014-01-08 17:36:15 +01:00
2014-02-21 17:37:39 +01:00
// mousedown event handler for calendar tooltip to remove disable tooltip
. on ( "mousedown" , "div[data-tooltip]" , function ( ) {
2014-10-27 14:04:31 +01:00
var $ttp = jQuery ( this ) ;
2014-10-23 14:59:19 +02:00
// Make sure the tooltip initialized before calling it
2014-10-27 14:04:31 +01:00
if ( $ttp . data ( 'uiTooltip' ) )
2014-10-23 14:59:19 +02:00
{
2014-10-27 14:04:31 +01:00
$ttp . tooltip ( "disable" ) ;
2014-10-23 14:59:19 +02:00
}
2014-02-21 17:37:39 +01:00
} )
2014-01-17 11:28:15 +01:00
2014-02-26 14:35:27 +01:00
//onClick event handler for calendar Events
2014-02-21 17:37:39 +01:00
. on ( "click" , "div.calendar_calEvent" , function ( ev ) {
var Id = ev . currentTarget . id . replace ( /drag_/g , '' ) . split ( "_" ) [ 0 ] ;
var eventId = Id . match ( /-?\d+\.?\d*/g ) [ 0 ] ;
var appName = Id . replace ( /-?\d+\.?\d*/g , '' ) ;
var startDate = ev . currentTarget . getAttribute ( 'data-resize' ) . split ( "|" ) [ 0 ] ;
var eventFlag = ev . currentTarget . getAttribute ( 'data-resize' ) . split ( "|" ) [ 3 ] ;
2014-08-25 12:30:52 +02:00
if ( eventFlag != 'S' && eventFlag != 'WDS' )
2014-02-21 17:37:39 +01:00
{
that . egw . open ( eventId , appName != "" ? appName : 'calendar' , 'edit' ) ;
}
else
{
that . edit _series ( eventId , startDate ) ;
}
} )
//Click event handler for integrated apps
. on ( "click" , "div.calendar_plannerEvent" , function ( ev ) {
2014-01-09 10:38:55 +01:00
var eventId = ev . currentTarget . getAttribute ( 'data-date' ) . split ( "|" ) [ 1 ] ;
var startDate = ev . currentTarget . getAttribute ( 'data-date' ) . split ( "|" ) [ 0 ] ;
var recurrFlag = ev . currentTarget . getAttribute ( 'data-date' ) . split ( "|" ) [ 2 ] ;
if ( recurrFlag == "n" )
2014-01-08 17:36:15 +01:00
{
egw . open ( eventId , 'calendar' , 'edit' ) ;
}
else
{
2014-01-27 17:36:49 +01:00
that . edit _series ( eventId , startDate ) ;
2014-01-08 17:36:15 +01:00
}
2014-02-21 17:37:39 +01:00
} )
2014-01-08 17:36:15 +01:00
2014-02-21 17:37:39 +01:00
//Click event handler for calendar cells
2014-02-24 10:48:22 +01:00
. on ( "click" , "div.calendar_calAddEvent, div.calendar_calTimeRowTime" , function ( ev ) {
2014-02-21 17:37:39 +01:00
var timestamp = ev . target . getAttribute ( 'data-date' ) . split ( "|" ) ;
2014-02-24 10:48:22 +01:00
if ( typeof ev . target . getAttribute ( 'id' ) != 'undefined' && ev . target . getAttribute ( 'id' ) )
2014-02-21 17:37:39 +01:00
{
2014-02-24 10:48:22 +01:00
var owner = ev . target . getAttribute ( 'id' ) . split ( "_" ) ;
var ownerId = owner [ 2 ] . match ( /Ogroup/g ) ? owner [ 2 ] . replace ( /Ogroup/g , '-' ) : owner [ 2 ] . replace ( /^\D+/g , '' ) ;
if ( owner [ 2 ] . match ( /Or/g ) )
{
ownerId = 'r' + ownerId ;
}
2014-02-21 17:37:39 +01:00
}
2013-12-13 19:18:56 +01:00
2014-11-05 17:13:26 +01:00
var eventInfo = {
date : timestamp [ 0 ] ,
hour : timestamp [ 1 ] ,
minute : timestamp [ 2 ]
} ;
2014-02-18 09:51:53 +01:00
2014-02-24 10:48:22 +01:00
if ( typeof ownerId != 'undefined' && ownerId != 0 )
2014-02-18 09:51:53 +01:00
{
2014-11-05 17:13:26 +01:00
jQuery ( eventInfo ) . extend ( eventInfo , { owner : ownerId } ) ;
2014-02-21 17:37:39 +01:00
}
2014-02-18 09:51:53 +01:00
2014-02-21 17:37:39 +01:00
that . egw . open ( null , 'calendar' , 'add' , eventInfo , '_blank' ) ;
} )
2013-12-13 19:18:56 +01:00
2014-02-21 17:37:39 +01:00
//Click event handler for calendar todos
. on ( "click" , "a[data-todo]" , function ( ev ) {
var windowSize = ev . currentTarget . getAttribute ( 'data-todo' ) . split ( "|" ) [ 1 ] ;
var link = ev . currentTarget . getAttribute ( 'href' ) ;
that . egw . open _link ( link , '_blank' , windowSize ) ;
return false ;
} ) ;
2014-11-27 18:37:18 +01:00
2014-11-05 17:13:26 +01:00
//******************************** Calendar Sortable ************************
// Calender current state
var state = this . getState ( ) ;
2014-11-27 18:37:18 +01:00
2014-11-05 17:13:26 +01:00
if ( state && state . view === "day"
&& typeof state . owner != 'undefined'
2014-12-03 01:20:57 +01:00
&& typeof state . owner == 'string' && state . owner . split ( ',' ) . length > 1 )
2014-11-05 17:13:26 +01:00
{
$iframeBody . find ( '#calendar_calDayCols' )
. addClass ( 'cal_is_sortable' )
. css ( { "white-space" : "nowrap" } )
. children ( ) . each ( function ( ) {
// Change day view columns position in order to get sortable placeholder working
jQuery ( this ) . css ( { position : "relative" , display : "inline-block" , left : "none" } ) ;
} ) ;
}
2014-11-27 18:37:18 +01:00
2014-11-05 17:13:26 +01:00
$iframeBody . find ( '.cal_is_sortable' ) . sortable ( {
cancel : "#divAppboxHeader, .calendar_calWeekNavHeader, .calendar_plannerHeader" ,
placeholder : "srotable_cal_wk_ph" ,
axis : "y" ,
revert : true ,
helper : "clone" ,
create : function ( )
{
var $sortItem = jQuery ( this ) ;
var options = { } ;
switch ( state . view )
{
case "day" :
options = {
placeholder : "srotable_cal_day_ph" ,
axis : "x"
} ;
$sortItem . sortable ( 'option' , options ) ;
break ;
case "week" :
options = {
placeholder : "srotable_cal_wk_ph" ,
axis : "y"
} ;
$sortItem . sortable ( 'option' , options ) ;
break ;
default :
$sortItem . sortable ( 'destroy' ) ;
}
} ,
start : function ( )
{
$drag . draggable ( 'disable' ) ;
$drop . droppable ( 'disable' ) ;
} ,
stop : function ( )
{
$drag . draggable ( 'enable' ) ;
$drop . droppable ( 'enable' ) ;
} ,
update : function ( )
{
if ( state && typeof state . owner !== 'undefined' )
{
var sortedArr = jQuery ( this ) . sortable ( 'toArray' , { attribute : "data-sortable-id" } ) ;
state . owner = sortedArr . join ( ',' ) ;
that . setState ( { state : state } ) ;
}
}
} ) ;
2013-12-13 19:18:56 +01:00
} ,
2014-01-30 19:24:24 +01:00
2014-01-30 17:48:49 +01:00
/ * *
* Function to help calendar resizable event , to fetch the right droppable cell
*
* @ param { int } _X position left of draggable element
* @ param { int } _Y position top of draggable element
*
* @ return { jquery object | boolean } return selected jquery if not return false
* /
resizeHelper : function ( _X , _Y )
{
2014-11-05 17:13:26 +01:00
var $drops = jQuery ( "div[id^='drop_']" ) ;
2014-01-30 17:48:49 +01:00
var top = Math . round ( _Y ) ;
var left = Math . round ( _X ) ;
2014-11-05 17:13:26 +01:00
for ( var i = 0 ; i < $drops . length ; i ++ )
2014-01-30 17:48:49 +01:00
{
2014-11-05 17:13:26 +01:00
if ( top >= Math . round ( $drops [ i ] . getBoundingClientRect ( ) . top )
&& top <= Math . round ( $drops [ i ] . getBoundingClientRect ( ) . bottom )
&& left >= Math . round ( $drops [ i ] . getBoundingClientRect ( ) . left )
&& left <= Math . round ( $drops [ i ] . getBoundingClientRect ( ) . right ) )
return $drops [ i ] ;
2014-01-30 17:48:49 +01:00
}
return false ;
} ,
2014-01-30 19:24:24 +01:00
2014-01-30 17:48:49 +01:00
/ * *
* Convert AM / PM dateTime format to 24 h
*
* @ param { string } _date dnd date format : dateTtime { am | pm } , eg . 121214 T1205 am
*
* @ return { string } 24 h format date
* /
cal _dnd _tZone _converter : function ( _date )
{
var date = _date ;
if ( _date != 'undefined' )
{
var tZone = _date . split ( 'T' ) [ 1 ] ;
if ( tZone . search ( 'am' ) > 0 )
{
tZone = tZone . replace ( ' am' , '' ) ;
var tAm = tZone . substr ( 0 , 2 ) ;
if ( tAm == '12' )
{
tZone = tZone . replace ( '12' , '00' ) ;
}
date = _date . split ( 'T' ) [ 0 ] + 'T' + tZone ;
}
if ( tZone . search ( 'pm' ) > 0 )
{
var pmTime = tZone . replace ( ' pm' , '' ) ;
var H = parseInt ( pmTime . substring ( 0 , 2 ) ) + 12 ;
pmTime = H . toString ( ) + pmTime . substr ( 2 , 2 ) ;
date = _date . split ( 'T' ) [ 0 ] + 'T' + pmTime ;
}
2013-12-13 19:18:56 +01:00
2014-01-30 17:48:49 +01:00
}
return date ;
} ,
2014-01-30 19:24:24 +01:00
2013-12-13 19:18:56 +01:00
/ * *
2014-08-21 13:20:37 +02:00
* This function tries to recognise the type of dropped event , and sends relative request to server accordingly
* - ATM we have three different requests :
* - 1. Event part of series
* - 2. Single Event ( Normall Cal Event )
* - 3. Integrated Infolog Event
2013-12-13 19:18:56 +01:00
*
* @ param { string } _id dragged event id
* @ param { array } _date array of date , hour , and minute of dropped cell
2013-12-16 19:10:08 +01:00
* @ param { string } _duration description
2014-08-21 13:20:37 +02:00
* @ param { string } _eventFlag Flag to distinguish whether the event is Whole Day , Series , or Single
* - S represents Series
2014-08-26 18:29:12 +02:00
* - WD represents Whole Day
2014-08-25 12:30:52 +02:00
* - WDS represents Whole Day Series ( recurrent whole day event )
2014-08-21 13:20:37 +02:00
* - '' represents Single
2013-12-13 19:18:56 +01:00
* /
2014-01-24 13:50:20 +01:00
dropEvent : function ( _id , _date , _duration , _eventFlag )
2013-12-13 19:18:56 +01:00
{
var eventId = _id . substring ( _id . lastIndexOf ( "drag_" ) + 5 , _id . lastIndexOf ( "_O" ) ) ;
var calOwner = _id . substring ( _id . lastIndexOf ( "_O" ) + 2 , _id . lastIndexOf ( "_C" ) ) ;
var eventOwner = _id . substring ( _id . lastIndexOf ( "_C" ) + 2 , _id . lastIndexOf ( "" ) ) ;
2014-01-30 17:48:49 +01:00
var date = this . cal _dnd _tZone _converter ( _date ) ;
2014-01-24 13:50:20 +01:00
if ( _eventFlag == 'S' )
{
et2 _dialog . show _dialog ( function ( _button _id )
2014-02-19 18:48:25 +01:00
{
if ( _button _id == et2 _dialog . OK _BUTTON )
{
2014-08-21 13:20:37 +02:00
egw ( ) . json ( 'calendar.calendar_uiforms.ajax_moveEvent' , [ eventId , calOwner , date , eventOwner , _duration ] ) . sendRequest ( ) ;
2014-02-19 18:48:25 +01:00
}
} , this . egw . lang ( "Do you really want to change the start of this series? If you do, the original series will be terminated as of today and a new series for the future reflecting your changes will be created." ) ,
this . egw . lang ( "This event is part of a series" ) , { } , et2 _dialog . BUTTONS _OK _CANCEL , et2 _dialog . WARNING _MESSAGE ) ;
2014-01-24 13:50:20 +01:00
}
else
{
2014-08-21 13:20:37 +02:00
//Get infologID if in case if it's an integrated infolog event
var infolog _id = eventId . split ( 'infolog' ) [ 1 ] ;
2014-08-21 15:31:10 +02:00
2014-08-21 13:20:37 +02:00
if ( infolog _id )
{
// If it is an integrated infolog event we need to edit infolog entry
egw ( ) . json ( 'stylite_infolog_calendar_integration::ajax_moveInfologEvent' , [ infolog _id , date , _duration ] ) . sendRequest ( ) ;
}
else
{
//Edit calendar event
egw ( ) . json ( 'calendar.calendar_uiforms.ajax_moveEvent' , [ eventId , calOwner , date , eventOwner , _duration ] ) . sendRequest ( ) ;
}
2014-01-24 13:50:20 +01:00
}
2013-12-13 19:18:56 +01:00
} ,
2014-01-30 19:24:24 +01:00
2013-10-31 15:51:19 +01:00
/ * *
* open the freetime search popup
*
2013-11-05 19:08:07 +01:00
* @ param { string } _link
2013-10-31 15:51:19 +01:00
* /
2013-11-05 19:08:07 +01:00
freetime _search _popup : function ( _link )
{
2013-10-31 15:51:19 +01:00
this . egw . open _link ( _link , 'ft_search' , '700x500' ) ;
2013-11-05 19:08:07 +01:00
} ,
2013-10-31 15:51:19 +01:00
/ * *
* send an ajax request to server to set the freetimesearch window content
*
* /
freetime _search : function ( )
2011-04-27 18:53:06 +02:00
{
2013-10-31 15:51:19 +01:00
var content = this . et2 . getArrayMgr ( 'content' ) . data ;
content [ 'start' ] = this . et2 . getWidgetById ( 'start' ) . get _value ( ) ;
content [ 'end' ] = this . et2 . getWidgetById ( 'end' ) . get _value ( ) ;
content [ 'duration' ] = this . et2 . getWidgetById ( 'duration' ) . get _value ( ) ;
var request = this . egw . json ( 'calendar.calendar_uiforms.ajax_freetimesearch' , [ content ] , null , null , null , null ) ;
request . sendRequest ( ) ;
} ,
/ * *
* Function for disabling the recur _data multiselect box
*
* /
check _recur _type : function ( )
2011-04-27 18:53:06 +02:00
{
2013-10-31 15:51:19 +01:00
var recurType = this . et2 . getWidgetById ( 'recur_type' ) ;
var recurData = this . et2 . getWidgetById ( 'recur_data' ) ;
2011-04-27 18:53:06 +02:00
2013-10-31 15:51:19 +01:00
if ( recurType && recurData )
2011-04-27 18:53:06 +02:00
{
2013-10-31 15:51:19 +01:00
recurData . set _disabled ( recurType . get _value ( ) != 2 ) ;
2011-04-27 18:53:06 +02:00
}
2013-10-31 15:51:19 +01:00
} ,
/ * *
* Show / Hide end date , for both edit and freetimesearch popups ,
* based on if "use end date" selected or not .
*
* /
set _enddate _visibility : function ( )
{
var duration = this . et2 . getWidgetById ( 'duration' ) ;
2014-11-14 10:37:49 +01:00
var start = this . et2 . getWidgetById ( 'start' ) ;
2013-10-31 15:51:19 +01:00
var end = this . et2 . getWidgetById ( 'end' ) ;
2014-11-14 10:37:49 +01:00
var content = this . et2 . getArrayMgr ( 'content' ) . data ;
2014-11-27 18:37:18 +01:00
2013-10-31 15:51:19 +01:00
if ( typeof duration != 'undefined' && typeof end != 'undefined' )
2011-04-27 18:53:06 +02:00
{
2013-10-31 15:51:19 +01:00
end . set _disabled ( duration . get _value ( ) !== '' ) ;
2015-09-29 16:49:37 +02:00
// Only set end date if not provided, adding seconds fails with DST
if ( ! end . disabled && ! content . end )
2014-11-14 10:37:49 +01:00
{
end . set _value ( start . get _value ( ) ) ;
if ( typeof content . duration != 'undefined' ) end . set _value ( "+" + content . duration ) ;
}
2011-04-27 18:53:06 +02:00
}
2013-10-31 15:51:19 +01:00
} ,
2013-01-09 22:38:18 +01:00
2013-10-31 15:51:19 +01:00
/ * *
* handles actions selectbox in calendar edit popup
*
2013-11-05 19:08:07 +01:00
* @ param { mixed } _event
2014-01-24 10:47:33 +01:00
* @ param { et2 _base _widget } widget "actions selectBox" in edit popup window
2013-10-31 15:51:19 +01:00
* /
2013-11-05 19:08:07 +01:00
actions _change : function ( _event , widget )
{
2013-10-31 15:51:19 +01:00
var event = this . et2 . getArrayMgr ( 'content' ) . data ;
if ( widget )
{
var id = this . et2 . getArrayMgr ( 'content' ) . data [ 'id' ] ;
switch ( widget . get _value ( ) )
{
case 'print' :
this . egw . open _link ( 'calendar.calendar_uiforms.edit&cal_id=' + id + '&print=1' , '_blank' , '700x700' ) ;
break ;
case 'mail' :
this . egw . json ( 'calendar.calendar_uiforms.ajax_custom_mail' , [ event , ! event [ 'id' ] , false ] , null , null , null , null ) . sendRequest ( ) ;
this . et2 . _inst . submit ( ) ;
break ;
case 'sendrequest' :
this . egw . json ( 'calendar.calendar_uiforms.ajax_custom_mail' , [ event , ! event [ 'id' ] , true ] , null , null , null , null ) . sendRequest ( ) ;
this . et2 . _inst . submit ( ) ;
break ;
case 'infolog' :
2014-07-21 11:38:35 +02:00
this . egw . open _link ( 'infolog.infolog_ui.edit&action=calendar&action_id=' + ( $j . isPlainObject ( event ) ? event [ 'id' ] : event ) , '_blank' , '700x600' , 'infolog' ) ;
2013-10-31 15:51:19 +01:00
this . et2 . _inst . submit ( ) ;
break ;
2014-02-10 13:45:57 +01:00
case 'ical' :
this . et2 . _inst . postSubmit ( ) ;
break ;
2013-10-31 15:51:19 +01:00
default :
this . et2 . _inst . submit ( ) ;
}
}
2013-11-05 19:08:07 +01:00
} ,
2013-10-31 15:51:19 +01:00
/ * *
* open mail compose popup window
*
2013-11-05 19:08:07 +01:00
* @ param { Array } vars
2013-10-31 15:51:19 +01:00
* @ todo need to provide right mail compose from server to custom _mail function
* /
2013-11-05 19:08:07 +01:00
custom _mail : function ( vars )
{
2014-01-29 19:47:49 +01:00
this . egw . open _link ( this . egw . link ( "/index.php" , vars ) , '_blank' , '700x700' ) ;
2013-11-05 19:08:07 +01:00
} ,
2014-08-21 14:43:14 +02:00
2013-10-31 15:51:19 +01:00
/ * *
* control delete _series popup visibility
*
2014-01-24 10:47:33 +01:00
* @ param { et2 _widget } widget
2013-11-05 19:08:07 +01:00
* @ param { Array } exceptions an array contains number of exception entries
2013-10-31 15:51:19 +01:00
*
* /
2014-01-23 11:27:18 +01:00
delete _btn : function ( widget , exceptions )
2013-11-05 19:08:07 +01:00
{
var content = this . et2 . getArrayMgr ( 'content' ) . data ;
2013-10-31 15:51:19 +01:00
2013-11-05 19:08:07 +01:00
if ( exceptions )
{
2014-06-16 18:49:45 +02:00
var buttons = [
{
button _id : 'keep' ,
statustext : 'All exceptions are converted into single events.' ,
text : 'Keep exceptions' ,
id : 'button[delete_keep_exceptions]' ,
image : 'keep' , "default" : true
} ,
{
button _id : 'delete' ,
statustext : 'The exceptions are deleted together with the series.' ,
text : 'Delete exceptions' ,
id : 'button[delete_exceptions]' ,
image : 'delete'
} ,
{
button _id : 'cancel' ,
text : 'Cancel' ,
id : 'dialog[cancel]' ,
image : 'cancel'
}
2014-08-21 14:43:14 +02:00
2014-06-16 18:49:45 +02:00
] ;
var self = this ;
et2 _dialog . show _dialog
(
function ( _button _id )
{
if ( _button _id != 'dialog[cancel]' )
{
self . et2 . _inst . submit ( _button _id ) ;
return true ;
}
else
{
return false ;
}
} ,
this . egw . lang ( "Do you want to keep the series exceptions in your calendar?" ) ,
this . egw . lang ( "This event is part of a series" ) , { } , buttons , et2 _dialog . WARNING _MESSAGE
) ;
2013-11-05 19:08:07 +01:00
}
else if ( content [ 'recur_type' ] !== 0 )
{
2014-01-23 11:27:18 +01:00
et2 _dialog . confirm ( widget , 'Delete this series of recuring events' , 'Delete Series' ) ;
2013-11-05 19:08:07 +01:00
}
else
{
2014-01-23 11:27:18 +01:00
et2 _dialog . confirm ( widget , 'Delete this event' , 'Delete' ) ;
2013-11-05 19:08:07 +01:00
}
} ,
2013-10-31 15:51:19 +01:00
/ * *
* print _participants _status ( egw , widget )
* Handle to apply changes from status in print popup
*
2013-11-05 19:08:07 +01:00
* @ param { mixed } _event
* @ param { et2 _base _widget } widget widget "status" in print popup window
2013-10-31 15:51:19 +01:00
*
* /
2013-11-05 19:08:07 +01:00
print _participants _status : function ( _event , widget )
{
2013-10-31 15:51:19 +01:00
if ( widget && window . opener )
{
//Parent popup window
var editPopWindow = window . opener ;
if ( editPopWindow )
{
//Update paretn popup window
editPopWindow . etemplate2 . getByApplication ( 'calendar' ) [ 0 ] . widgetContainer . getWidgetById ( widget . id ) . set _value ( widget . get _value ( ) ) ;
}
this . et2 . _inst . submit ( ) ;
editPopWindow . opener . egw _refresh ( 'status changed' , 'calendar' ) ;
}
else if ( widget )
{
window . egw _refresh ( this . egw . lang ( 'The original popup edit window is closed! You need to close the print window and reopen the entry again.' ) , 'calendar' ) ;
}
2013-11-05 19:08:07 +01:00
} ,
2013-10-31 15:51:19 +01:00
2015-03-19 16:12:07 +01:00
/ * *
* In edit popup , search for calendar participants .
* Resources need to have the start & duration ( etc . )
* passed along in the query .
*
* @ param { Object } request
* @ param { et2 _link _entry } widget
*
* @ returns { boolean } True to continue with the search
* /
edit _participant _search : function ( request , widget )
{
if ( widget . app _select . val ( ) == 'resources' )
{
// Resources search is expecting exec
var values = widget . getInstanceManager ( ) . getValues ( widget . getRoot ( ) ) ;
if ( typeof request . options != 'object' || request . options == null )
{
request . options = { } ;
}
request . options . exec = {
start : values . start ,
end : values . end ,
duration : values . duration ,
participants : values . participants ,
recur _type : values . recur _type ,
event _id : values . link _to . to _id , // cal_id, if available
show _conflict : ( egw . preference ( 'defaultresource_sel' , 'calendar' ) == 'resources_without_conflict' ) ? '0' : '1'
} ;
if ( values . whole _day )
{
request . options . exec . whole _date = true ;
}
}
return true ;
} ,
2015-08-27 14:03:29 +02:00
2013-10-31 15:51:19 +01:00
/ * *
* Handles to select freetime , and replace the selected one on Start ,
* and End date & time in edit calendar entry popup .
*
2013-11-05 19:08:07 +01:00
* @ param { mixed } _event
* @ param { et2 _base _widget } _widget widget "select button" in freetime search popup window
2013-10-31 15:51:19 +01:00
*
* /
2013-11-05 19:08:07 +01:00
freetime _select : function ( _event , _widget )
{
2013-10-31 15:51:19 +01:00
if ( _widget )
{
var content = this . et2 . _inst . widgetContainer . getArrayMgr ( 'content' ) . data ;
// Make the Id from selected button by checking the index
var selectedId = _widget . id . match ( /^select\[([0-9])\]$/i ) [ 1 ] ;
var sTime = this . et2 . getWidgetById ( selectedId + 'start' ) ;
//check the parent window is still open before to try to access it
2014-09-04 15:03:48 +02:00
if ( window . opener && sTime )
2013-10-31 15:51:19 +01:00
{
var editWindowObj = window . opener . etemplate2 . getByApplication ( 'calendar' ) [ 0 ] ;
if ( typeof editWindowObj != "undefined" )
{
var startTime = editWindowObj . widgetContainer . getWidgetById ( 'start' ) ;
var endTime = editWindowObj . widgetContainer . getWidgetById ( 'end' ) ;
if ( startTime && endTime )
{
2014-09-04 15:03:48 +02:00
startTime . set _value ( sTime . get _value ( ) ) ;
endTime . set _value ( sTime . get _value ( ) ) ;
endTime . set _value ( '+' + content [ 'duration' ] ) ;
2013-10-31 15:51:19 +01:00
}
}
}
else
{
alert ( this . egw . lang ( 'The original calendar edit popup is closed!' ) ) ;
}
}
2014-12-12 15:21:04 +01:00
egw ( window ) . close ( ) ;
2013-11-05 19:08:07 +01:00
} ,
2013-10-31 15:51:19 +01:00
/ * *
* show / hide the filter of nm list in calendar listview
*
* /
filter _change : function ( )
2013-01-09 22:45:55 +01:00
{
2014-02-19 16:20:19 +01:00
var filter = this . et2 ? this . et2 . getWidgetById ( 'filter' ) : null ;
var dates = this . et2 ? this . et2 . getWidgetById ( 'calendar.list.dates' ) : null ;
2013-10-31 15:51:19 +01:00
if ( filter && dates )
2013-01-09 22:45:55 +01:00
{
2013-10-31 15:51:19 +01:00
dates . set _disabled ( filter . value !== "custom" ) ;
2013-01-09 22:45:55 +01:00
}
2013-10-31 15:51:19 +01:00
} ,
/ * *
* this function try to fix ids which are from integrated apps
*
2013-11-05 19:08:07 +01:00
* @ param { egw _action } _action
* @ param { Array } _senders
2013-10-31 15:51:19 +01:00
* /
cal _fix _app _id : function ( _action , _senders )
2013-01-09 22:38:18 +01:00
{
2013-10-31 15:51:19 +01:00
var app = 'calendar' ;
var id = _senders [ 0 ] . id ;
2013-11-04 11:23:08 +01:00
var matches = id . match ( /^(?:calendar::)?([0-9]+)(:([0-9]+))?$/ ) ;
2013-10-31 15:51:19 +01:00
if ( matches )
{
id = matches [ 1 ] ;
}
2014-01-24 10:47:33 +01:00
else
2013-10-31 15:51:19 +01:00
{
2014-01-24 10:47:33 +01:00
matches = id . match ( /^([a-z_-]+)([0-9]+)/i ) ;
if ( matches )
{
app = matches [ 1 ] ;
id = matches [ 2 ] ;
}
2013-10-31 15:51:19 +01:00
}
var backup _url = _action . data . url ;
2013-11-05 14:30:41 +01:00
_action . data . url = _action . data . url . replace ( /(\$|%24)id/ , id ) ;
_action . data . url = _action . data . url . replace ( /(\$|%24)app/ , app ) ;
2013-10-31 15:51:19 +01:00
nm _action ( _action , _senders ) ;
2013-11-05 14:30:41 +01:00
2013-10-31 15:51:19 +01:00
_action . data . url = backup _url ; // restore url
} ,
/ * *
* Open calendar entry , taking into accout the calendar integration of other apps
*
* calendar _uilist : : get _rows sets var js _calendar _integration object
*
* @ param _action
* @ param _senders
*
* /
cal _open : function ( _action , _senders )
{
2015-08-27 14:03:29 +02:00
2014-12-03 01:20:57 +01:00
var js _integration _data = _action . parent . data . nextmatch . options . settings . js _integration _data || this . et2 . getArrayMgr ( 'content' ) . data . nm . js _integration _data ;
2013-10-31 15:51:19 +01:00
var id = _senders [ 0 ] . id ;
var matches = id . match ( /^(?:calendar::)?([0-9]+):([0-9]+)$/ ) ;
var backup = _action . data ;
if ( matches )
{
this . edit _series ( matches [ 1 ] , matches [ 2 ] ) ;
return ;
}
2014-01-24 10:47:33 +01:00
matches = id . match ( /^([a-z_-]+)([0-9]+)/i ) ;
if ( matches )
2013-10-31 15:51:19 +01:00
{
var app = matches [ 1 ] ;
_action . data . url = window . egw _webserverUrl + '/index.php?' ;
var get _params = js _integration _data [ app ] . edit ;
get _params [ js _integration _data [ app ] . edit _id ] = matches [ 2 ] ;
for ( var name in get _params )
_action . data . url += name + "=" + encodeURIComponent ( get _params [ name ] ) + "&" ;
2013-01-09 22:38:18 +01:00
2014-01-24 10:47:33 +01:00
if ( js _integration _data [ app ] . edit _popup )
2013-10-31 15:51:19 +01:00
{
2014-01-24 10:47:33 +01:00
matches = js _integration _data [ app ] . edit _popup . match ( /^(.*)x(.*)$/ ) ;
if ( matches )
{
_action . data . width = matches [ 1 ] ;
_action . data . height = matches [ 2 ] ;
}
else
{
_action . data . nm _action = 'location' ;
}
2013-10-31 15:51:19 +01:00
}
}
egw . open ( id . replace ( /^calendar::/g , '' ) , 'calendar' , 'edit' ) ;
_action . data = backup ; // restore url, width, height, nm_action
} ,
2013-01-09 22:38:18 +01:00
2013-10-31 15:51:19 +01:00
/ * *
* Delete calendar entry , asking if you want to delete series or exception
*
*
* @ param _action
* @ param _senders
* /
cal _delete : function ( _action , _senders )
{
var backup = _action . data ;
var matches = false ;
2013-01-09 22:38:18 +01:00
2013-10-31 15:51:19 +01:00
// Loop so we ask if any of the selected entries is part of a series
for ( var i = 0 ; i < _senders . length ; i ++ )
2013-01-09 22:38:18 +01:00
{
2013-10-31 15:51:19 +01:00
var id = _senders [ i ] . id ;
if ( ! matches )
{
matches = id . match ( /^(?:calendar::)?([0-9]+):([0-9]+)$/ ) ;
}
}
if ( matches )
{
2014-06-17 11:44:15 +02:00
var popup = jQuery ( '#calendar-list_delete_popup' ) . get ( 0 ) ;
if ( typeof popup != 'undefined' )
2013-11-05 19:08:07 +01:00
{
2014-06-17 11:44:15 +02:00
// nm action - show popup
nm _open _popup ( _action , _senders ) ;
2014-08-21 14:43:14 +02:00
}
2013-01-09 22:38:18 +01:00
return ;
}
2013-10-31 15:51:19 +01:00
2013-11-05 17:02:21 +01:00
nm _action ( _action , _senders ) ;
2013-10-31 15:51:19 +01:00
} ,
2014-01-23 18:15:49 +01:00
/ * *
2014-01-24 16:50:17 +01:00
* Confirmation dialog for moving a series entry
2014-01-23 18:15:49 +01:00
*
2014-01-24 16:50:17 +01:00
* @ param { object } _DOM
* @ param { et2 _widget } _button button Save | Apply
2014-01-23 18:15:49 +01:00
* /
move _edit _series : function ( _DOM , _button )
{
var content = this . et2 . getArrayMgr ( 'content' ) . data ;
var start _date = this . et2 . getWidgetById ( 'start' ) . get _value ( ) ;
2014-09-10 12:24:40 +02:00
var whole _day = this . et2 . getWidgetById ( 'whole_day' ) ;
var is _whole _day = whole _day && whole _day . get _value ( ) == whole _day . options . selected _value ;
2014-01-23 18:15:49 +01:00
var button = _button ;
var that = this ;
2014-03-25 16:04:14 +01:00
if ( typeof content != 'undefined' && content . id != null &&
typeof content . recur _type != 'undefined' && content . recur _type != null && content . recur _type != 0
)
2014-01-23 18:15:49 +01:00
{
2014-09-10 12:24:40 +02:00
if ( content . start != start _date || content . whole _day != is _whole _day )
2014-01-23 18:15:49 +01:00
{
et2 _dialog . show _dialog ( function ( _button _id )
{
if ( _button _id == et2 _dialog . OK _BUTTON )
{
that . et2 . _inst . submit ( button ) ;
}
else
{
return false ;
}
} ,
this . egw . lang ( "Do you really want to change the start of this series? If you do, the original series will be terminated as of today and a new series for the future reflecting your changes will be created." ) ,
this . egw . lang ( "This event is part of a series" ) , { } , et2 _dialog . BUTTONS _OK _CANCEL , et2 _dialog . WARNING _MESSAGE ) ;
}
else
{
return true ;
}
}
else
{
return true ;
}
} ,
2013-10-31 15:51:19 +01:00
/ * *
* Create edit exception dialog for recurrence entries
*
2013-11-05 19:08:07 +01:00
* @ param { object } event
* @ param { string } id cal _id
* @ param { integer } date timestamp
2013-10-31 15:51:19 +01:00
* /
edit _series : function ( event , id , date )
{
// Coming from list, there is no event
if ( arguments . length == 2 )
{
date = id ;
id = event ;
event = null ;
}
2013-11-05 19:08:07 +01:00
var edit _id = id ;
var edit _date = date ;
2013-10-31 15:51:19 +01:00
var that = this ;
var buttons = [
{ text : this . egw . lang ( "Edit exception" ) , id : "exception" , class : "ui-priority-primary" , "default" : true } ,
{ text : this . egw . lang ( "Edit series" ) , id : "series" } ,
2013-11-05 19:08:07 +01:00
{ text : this . egw . lang ( "Cancel" ) , id : "cancel" }
2013-10-31 15:51:19 +01:00
] ;
2013-11-05 19:08:07 +01:00
et2 _dialog . show _dialog ( function ( _button _id )
2013-10-31 15:51:19 +01:00
{
2013-11-05 19:08:07 +01:00
switch ( _button _id )
2013-10-31 15:51:19 +01:00
{
case 'exception' :
2013-11-06 09:49:29 +01:00
that . egw . open ( edit _id , 'calendar' , 'edit' , '&date=' + edit _date + '&exception=1' ) ;
2013-10-31 15:51:19 +01:00
break ;
case 'series' :
2013-11-06 09:49:29 +01:00
that . egw . open ( edit _id , 'calendar' , 'edit' , '&date=' + edit _date ) ;
2013-10-31 15:51:19 +01:00
break ;
case 'cancel' :
default :
break ;
}
2013-11-05 19:08:07 +01:00
} , this . egw . lang ( "Do you want to edit this event as an exception or the whole series?" ) ,
this . egw . lang ( "This event is part of a series" ) , { } , buttons , et2 _dialog . WARNING _MESSAGE ) ;
2013-12-05 00:28:31 +01:00
} ,
2014-01-24 10:47:33 +01:00
/ * *
* Current state , get updated via set _state method
*
* @ type object
* /
state : undefined ,
/ * *
* Method to set state for JSON requests ( jdots ajax _exec or et2 submits can NOT use egw . js script tag )
*
* @ param { object } _state
* /
set _state : function ( _state )
{
if ( typeof _state == 'object' )
{
this . state = _state ;
}
} ,
2013-12-05 00:28:31 +01:00
/ * *
* Return state object defining current view
*
* Called by favorites to query current state .
*
* @ return { object } description
* /
getState : function ( )
{
2014-01-24 10:47:33 +01:00
var state = this . state ;
2013-12-06 22:26:55 +01:00
2014-01-24 10:47:33 +01:00
if ( ! state )
{
var egw _script _tag = document . getElementById ( 'egw_script_id' ) ;
state = egw _script _tag . getAttribute ( 'data-calendar-state' ) ;
state = state ? JSON . parse ( state ) : { } ;
}
2013-12-05 01:03:13 +01:00
// we are currently in list-view
if ( this . et2 && this . et2 . getWidgetById ( 'nm' ) )
{
2013-12-06 22:26:55 +01:00
jQuery . extend ( state , this . _super . apply ( this , arguments ) ) ; // call default implementation
2013-12-05 01:03:13 +01:00
}
2013-12-05 00:28:31 +01:00
2015-01-08 16:51:36 +01:00
// Don't store current user in state to allow admins to create favourites for all
// Should make no difference for normal users.
if ( state . owner == egw . user ( 'account_id' ) )
{
// 0 is always the current user, so if an admin creates a default favorite,
// it will work for other users too.
state . owner = 0 ;
}
2015-07-10 20:05:54 +02:00
// Don't store first and last
delete state . first ;
delete state . last ;
2015-08-27 14:03:29 +02:00
2013-12-06 22:26:55 +01:00
return state ;
2013-12-05 00:28:31 +01:00
} ,
/ * *
* Set a state previously returned by getState
*
* Called by favorites to set a state saved as favorite .
*
* @ param { object } state containing "name" attribute to be used as "favorite" GET parameter to a nextmatch
* /
setState : function ( state )
{
2013-12-06 19:24:29 +01:00
// State should be an object, not a string, but we'll parse
if ( typeof state == "string" )
{
if ( state . indexOf ( '{' ) != - 1 || state == 'null' )
{
state = JSON . parse ( state ) ;
}
}
2013-12-05 00:28:31 +01:00
2015-08-27 14:03:29 +02:00
if ( jQuery . isEmptyObject ( state ) ) state . state = { } ;
2013-12-05 00:28:31 +01:00
// old calendar state handling on server-side (incl. switching to and from listview)
var menuaction = 'calendar.calendar_uiviews.index' ;
2014-02-25 00:50:51 +01:00
if ( typeof state . state != 'undefined' && ( typeof state . state . view == 'undefined' || state . state . view == 'listview' ) )
2013-12-05 00:28:31 +01:00
{
2015-08-27 14:03:29 +02:00
// 'blank' is the special name for no filters, send that instead of the nice translated name
state . state . favorite = jQuery . isEmptyObject ( state . state || state . filter ) ? 'blank' : state . name . replace ( /[^A-Za-z0-9-_]/g , '_' ) ;
// set date for "No Filter" (blank) favorite to todays date
if ( state . state . favorite == 'blank' )
state . state . date = jQuery . datepicker . formatDate ( 'yymmdd' , new Date ) ;
2014-02-26 14:35:27 +01:00
menuaction = 'calendar.calendar_uilist.listview' ;
state . state . ajax = 'true' ;
2014-01-24 10:47:33 +01:00
// check if we already use et2 / are in listview
2014-01-30 19:24:24 +01:00
if ( this . et2 || etemplate2 && etemplate2 . getByApplication ( 'calendar' ) )
2014-01-24 10:47:33 +01:00
{
// current calendar-code can set regular calendar states only via a server-request :(
// --> check if we only need to set something which can be handeled by nm internally
// or we need a redirect
// ToDo: pass them via nm's get_rows call to server (eg. by passing state), so we dont need a redirect
var current _state = this . getState ( ) ;
var need _redirect = false ;
for ( var attr in current _state )
{
switch ( attr )
{
case 'cat_id' :
case 'owner' :
case 'filter' :
if ( state . state [ attr ] != current _state [ attr ] )
{
need _redirect = true ;
2014-02-26 14:35:27 +01:00
// reset of attributes managed on server-side
if ( state . state . favorite === 'blank' )
{
switch ( attr )
{
case 'cat_id' :
state . state . cat _id = 0 ;
break ;
case 'owner' :
state . state . owner = egw . user ( 'account_id' ) ;
break ;
case 'filter' :
state . state . filter = 'default' ;
break ;
}
}
2014-01-24 10:47:33 +01:00
break ;
}
break ;
2014-02-26 14:35:27 +01:00
case 'view' :
// "No filter" (blank) favorite: if not in listview --> stay in that view
if ( state . state . favorite === 'blank' && current _state . view != 'listview' )
{
menuaction = 'calendar.calendar_uiviews.index' ;
delete state . state . ajax ;
need _redirect = true ;
}
2014-01-24 10:47:33 +01:00
}
}
if ( ! need _redirect )
{
return this . _super . apply ( this , [ state ] ) ;
}
}
2013-12-05 00:28:31 +01:00
}
2014-01-30 17:55:02 +01:00
// setting internal state now, that linkHandler does not intercept switching from listview to any old view
this . state = state ;
2013-12-12 00:51:35 +01:00
var query = jQuery . extend ( { menuaction : menuaction } , state . state || { } ) ;
2013-12-12 04:42:08 +01:00
2013-12-12 00:51:35 +01:00
// prepend an owner 0, to reset all owners and not just set given resource type
if ( typeof query . owner != 'undefined' )
2013-12-05 00:28:31 +01:00
{
2013-12-12 00:51:35 +01:00
query . owner = '0,' + query . owner ;
2013-12-05 00:28:31 +01:00
}
2013-12-12 00:51:35 +01:00
2013-12-12 04:42:08 +01:00
this . egw . open _link ( this . egw . link ( '/index.php' , query ) , 'calendar' ) ;
2013-12-12 00:51:35 +01:00
// Stop the normal bubbling if this is called on click
return false ;
2014-03-11 11:45:02 +01:00
} ,
2014-06-06 13:59:20 +02:00
2014-05-27 17:02:56 +02:00
/ * *
* Enable / Disable custom Date - time for set Alarm
*
2014-06-06 13:59:20 +02:00
* @ param { egw object } _egw
2014-05-27 17:02:56 +02:00
* @ param { widget object } _widget new _alarm [ options ] selectbox
* /
alarm _custom _date : function ( _egw , _widget )
{
var alarm _date = this . et2 . getWidgetById ( 'new_alarm[date]' ) ;
var alarm _options = _widget || this . et2 . getWidgetById ( 'new_alarm[options]' ) ;
var start = this . et2 . getWidgetById ( 'start' ) ;
2014-06-06 13:59:20 +02:00
if ( alarm _date && alarm _options
2014-05-27 17:02:56 +02:00
&& start )
{
if ( alarm _options . get _value ( ) != '0' )
{
alarm _date . set _class ( 'calendar_alarm_date_display' ) ;
}
else
{
alarm _date . set _class ( '' ) ;
}
2014-09-23 15:49:22 +02:00
var startDate = typeof start . get _value != 'undefined' ? start . get _value ( ) : start . value ;
2014-05-27 17:02:56 +02:00
if ( startDate )
{
2014-08-21 14:43:14 +02:00
var date = new Date ( startDate ) ;
2014-08-21 15:31:10 +02:00
date . setTime ( date . getTime ( ) - 1000 * parseInt ( alarm _options . get _value ( ) ) ) ;
2014-05-27 17:02:56 +02:00
alarm _date . set _value ( date ) ;
}
}
2014-05-28 17:04:06 +02:00
} ,
2014-06-06 13:59:20 +02:00
2014-05-28 17:04:06 +02:00
/ * *
2014-06-06 13:59:20 +02:00
* Set alarm options based on WD / Regular event user preferences
2014-05-28 17:04:06 +02:00
* Gets fired by wholeday checkbox
2014-06-06 13:59:20 +02:00
*
* @ param { egw object } _egw
2014-05-28 17:04:06 +02:00
* @ param { widget object } _widget whole _day checkbox
* /
set _alarmOptions _WD : function ( _egw , _widget )
{
2014-06-06 13:59:20 +02:00
var alarm = this . et2 . getWidgetById ( 'alarm' ) ;
if ( ! alarm ) return ; // no default alarm
2014-06-05 18:07:59 +02:00
var content = this . et2 . getArrayMgr ( 'content' ) . data ;
var start = this . et2 . getWidgetById ( 'start' ) ;
var self = this ;
var time = alarm . cells [ 1 ] [ 0 ] . widget ;
var event = alarm . cells [ 1 ] [ 1 ] . widget ;
2014-05-28 17:04:06 +02:00
// Convert a seconds of time to a translated label
var _secs _to _label = function ( _secs )
{
var label = '' ;
if ( _secs <= 3600 )
{
label = self . egw . lang ( '%1 minutes' , _secs / 60 ) ;
}
else if ( _secs <= 86400 )
{
label = self . egw . lang ( '%1 hours' , _secs / 3600 ) ;
}
return label ;
2014-06-06 13:59:20 +02:00
} ;
if ( typeof content [ 'alarm' ] [ 1 ] [ 'default' ] == 'undefined' )
2014-05-28 17:04:06 +02:00
{
2014-06-06 13:59:20 +02:00
// user deleted alarm --> nothing to do
2014-05-28 17:04:06 +02:00
}
else
{
2014-06-06 13:59:20 +02:00
var def _alarm = this . egw . preference ( _widget . get _value ( ) === "true" ?
'default-alarm-wholeday' : 'default-alarm' , 'calendar' ) ;
if ( ! def _alarm && def _alarm !== 0 ) // no alarm
{
jQuery ( '#calendar-edit_alarm > tbody :nth-child(1)' ) . hide ( ) ;
}
else
{
jQuery ( '#calendar-edit_alarm > tbody :nth-child(1)' ) . show ( ) ;
2014-09-05 12:34:37 +02:00
start . set _hours ( 0 ) ;
start . set _minutes ( 0 ) ;
time . set _value ( start . get _value ( ) ) ;
time . set _value ( '-' + ( 60 * def _alarm ) ) ;
2014-06-06 13:59:20 +02:00
event . set _value ( _secs _to _label ( 60 * def _alarm ) ) ;
}
2014-05-28 17:04:06 +02:00
}
2014-06-06 13:59:20 +02:00
}
2013-10-31 15:51:19 +01:00
} ) ;