drag and drop for calendar for all those who cannot wait for cooxdoo or dojoproject :o) - it is disabled by default - if you want to use it you have to go to common preferences and enable drag and drop (last entry before template-specific settings) - just for Mozilla based browsers ATM, all other browsers get auto-disabled - it lacks a lot features, e.g. recurring events and whole day events but this will come - HAVE FUN

This commit is contained in:
Christian Binder 2006-12-15 20:05:47 +00:00
parent f3670af463
commit a014327f05
5 changed files with 241 additions and 12 deletions

View File

@ -0,0 +1,66 @@
<?php
/**
* Calendar - ajax class
*
* @link http://www.egroupware.org
* @author Christian Binder <christian.binder@freakmail.de>
* @package calendar
* @copyright (c) 2006 by Christian Binder <christian.binder@freakmail.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id: class.ajaxcalendar.inc.php 22777 2006-11-26 20:55:00Z jaytraxx $
*/
require_once(EGW_INCLUDE_ROOT.'/calendar/inc/class.bocalupdate.inc.php');
/**
* General object of the calendar ajax class
*
* @package calendar
* @author Christian Binder <christian.binder@freakmail.de>
* @copyright (c) 2006 by Christian Binder <christian.binder@freakmail.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
*/
class ajaxcalendar {
/**
* @var object $calendar object to handle events
*/
var $calendar;
function ajaxcalendar() {
$this->calendar = new bocalupdate;
}
/**
* moves an event to another date/time
*
* @param string $eventID id of the event which has to be moved
* @param string $calendarOwner the owner of the calendar the event is in
* @param string $targetDateTime the datetime where the event should be moved to, format: YYYYMMDD
* @param string $targetOwner the owner of the target calendar
* @return string XML response if no error occurs
*/
function moveEvent($eventId,$calendarOwner,$targetDateTime,$targetOwner)
{
// we do not allow dragging into another users calendar ATM
if(!$calendarOwner == $targetOwner)
{
return false;
}
$event=$this->calendar->read($eventId);
$duration=$event['end']-$event['start'];
$event['start'] = $this->calendar->date2ts($targetDateTime);
$event['end'] = $event['start']+$duration;
$result=$this->calendar->update($event);
//Todo: handle the result !!!
$response =& new xajaxResponse();
$response->addRedirect($PHP_SELF);
return $response->getXML();
}
}

View File

@ -233,6 +233,7 @@ class uical
*/ */
function do_header() function do_header()
{ {
$GLOBALS['egw_info']['flags']['include_xajax'] = true;
$GLOBALS['egw']->common->egw_header(); $GLOBALS['egw']->common->egw_header();
if ($_GET['msg']) echo '<p class="redItalic" align="center">'.$this->html->htmlspecialchars($_GET['msg'])."</p>\n"; if ($_GET['msg']) echo '<p class="redItalic" align="center">'.$this->html->htmlspecialchars($_GET['msg'])."</p>\n";

View File

@ -13,6 +13,7 @@
/* $Id$ */ /* $Id$ */
include_once(EGW_INCLUDE_ROOT . '/calendar/inc/class.uical.inc.php'); include_once(EGW_INCLUDE_ROOT . '/calendar/inc/class.uical.inc.php');
include_once(EGW_INCLUDE_ROOT . '/phpgwapi/inc/class.dragdrop.inc.php');
/** /**
* Class to generate the calendar views and the necesary widgets * Class to generate the calendar views and the necesary widgets
@ -90,6 +91,13 @@ class uiviews extends uical
*/ */
var $use_time_grid=true; var $use_time_grid=true;
/**
* Dragdrop Object
*
* @var object $dragdrop;
*/
var $dragdrop;
/** /**
* Can we display the whole day in a timeGrid of the size of the workday and just scroll to workday start * Can we display the whole day in a timeGrid of the size of the workday and just scroll to workday start
* *
@ -138,6 +146,7 @@ class uiviews extends uical
$this->holidays = $this->bo->read_holidays($this->year); $this->holidays = $this->bo->read_holidays($this->year);
$this->check_owners_access(); $this->check_owners_access();
$this->dragdrop = new dragdrop();
} }
/** /**
@ -320,6 +329,10 @@ class uiviews extends uical
echo $content; echo $content;
} }
// make wz_dragdrop elements work
$this->dragdrop->setJSCode();
return $content; return $content;
} }
@ -442,6 +455,10 @@ class uiviews extends uical
echo $content; echo $content;
} }
// make wz_dragdrop elements work
$this->dragdrop->setJSCode();
return $content; return $content;
} }
@ -514,10 +531,17 @@ class uiviews extends uical
{ {
echo $cols[0]; echo $cols[0];
} }
// make wz_dragdrop elements work
$this->dragdrop->setJSCode();
} }
else else
{ {
return $this->timeGridWidget($this->bo->search($this->search_params),$this->cal_prefs['interval'],300); $content = $this->timeGridWidget($this->bo->search($this->search_params),$this->cal_prefs['interval'],300);
// make wz_dragdrop elements work
$this->dragdrop->setJSCode();
return $content;
} }
} }
@ -791,6 +815,7 @@ class uiviews extends uical
} }
$html .= "</script>\n"; $html .= "</script>\n";
} }
return $html; return $html;
} }
@ -880,6 +905,16 @@ class uiviews extends uical
if ($this->use_time_grid) if ($this->use_time_grid)
{ {
// drag and drop: check if the current user has EDIT permissions on the grid
if($owner)
{
$dropPermission = $this->bo->check_perms(EGW_ACL_EDIT,0,$owner);
}
else
{
$dropPermission = true;
}
// adding divs to click on for each row / time-span // adding divs to click on for each row / time-span
for($t = $this->scroll_to_wdstart ? 0 : $this->wd_start,$i = 1+$this->extraRows; for($t = $this->scroll_to_wdstart ? 0 : $this->wd_start,$i = 1+$this->extraRows;
$t <= $this->wd_end || $this->scroll_to_wdstart && $t < 24*60; $t <= $this->wd_end || $this->scroll_to_wdstart && $t < 24*60;
@ -888,20 +923,35 @@ class uiviews extends uical
$linkData = array( $linkData = array(
'menuaction' =>'calendar.uiforms.edit', 'menuaction' =>'calendar.uiforms.edit',
'date' => $day_ymd, 'date' => $day_ymd,
'hour' => floor($t / 60), 'hour' => sprintf("%02d",floor($t / 60)),
'minute' => floor($t % 60), 'minute' => sprintf("%02d",floor($t % 60)),
); );
if ($owner) $linkData['owner'] = $owner; if ($owner) $linkData['owner'] = $owner;
$html .= $indent."\t".'<div style="height:'. $this->rowHeight .'%; top: '. $i*$this->rowHeight . $droppableDateTime = $linkData['date'] . "T" . $linkData['hour'] . $linkData['minute'];
$droppableID='drop_'.$droppableDateTime.'_O'.$owner;
$html .= $indent."\t".'<div id="' . $droppableID . '" style="height:'. $this->rowHeight .'%; top: '. $i*$this->rowHeight .
'%;" class="calAddEvent" onclick="'.$this->popup($GLOBALS['egw']->link('/index.php',$linkData)).';return false;"></div>'."\n"; '%;" class="calAddEvent" onclick="'.$this->popup($GLOBALS['egw']->link('/index.php',$linkData)).';return false;"></div>'."\n";
if($dropPermission)
{
$this->dragdrop->addDroppable(
$droppableID,
array(
'datetime'=>$droppableDateTime,
'owner'=>$owner ? $owner : $this->user,
)
);
}
} }
} }
// displaying all event columns of the day // displaying all event columns of the day
foreach($eventCols as $n => $eventCol) foreach($eventCols as $n => $eventCol)
{ {
$html .= $this->eventColWidget($eventCol,!$n ? 0 : 60-10*(count($eventCols)-$n), $html .= $this->eventColWidget($eventCol,!$n ? 0 : 60-10*(count($eventCols)-$n),
count($eventCols) == 1 ? 100 : (!$n ? 80 : 50),$indent."\t"); count($eventCols) == 1 ? 100 : (!$n ? 80 : 50),$indent."\t",
$owner ? $owner : $this->user);
} }
$html .= $indent."</div>\n"; // calDayCol $html .= $indent."</div>\n"; // calDayCol
@ -968,8 +1018,9 @@ class uiviews extends uical
* @param int $left start of the widget * @param int $left start of the widget
* @param int $width width of the widget * @param int $width width of the widget
* @param string $indent string for correct indention * @param string $indent string for correct indention
* @param int $owner owner of the eventCol
*/ */
function eventColWidget($events,$left,$width,$indent) function eventColWidget($events,$left,$width,$indent,$owner)
{ {
if ($this->debug > 1 || $this->debug==='eventColWidget') $this->bo->debug_message('uiviews::eventColWidget(%1,left=%2,width=%3,)',False,$events,$left,$width); if ($this->debug > 1 || $this->debug==='eventColWidget') $this->bo->debug_message('uiviews::eventColWidget(%1,left=%2,width=%3,)',False,$events,$left,$width);
@ -977,7 +1028,7 @@ class uiviews extends uical
(!$this->use_time_grid ? ' top: '.$this->rowHeight.'%;' : '').'">'."\n"; (!$this->use_time_grid ? ' top: '.$this->rowHeight.'%;' : '').'">'."\n";
foreach($events as $event) foreach($events as $event)
{ {
$html .= $this->eventWidget($event,$width,$indent."\t"); $html .= $this->eventWidget($event,$width,$indent."\t",$owner);
} }
$html .= $indent."</div>\n"; $html .= $indent."</div>\n";
@ -992,11 +1043,12 @@ class uiviews extends uical
* @param $event array with the data of event to show * @param $event array with the data of event to show
* @param $width int width of the widget * @param $width int width of the widget
* @param string $indent string for correct indention * @param string $indent string for correct indention
* @param int $owner owner of the calendar the event is in
* @param boolean $return_array=false should an array with keys(tooltip,popup,html) be returned or the complete widget as string * @param boolean $return_array=false should an array with keys(tooltip,popup,html) be returned or the complete widget as string
* @param string $block='event_widget' template used the render the widget * @param string $block='event_widget' template used the render the widget
* @return string/array * @return string/array
*/ */
function eventWidget($event,$width,$indent,$return_array=false,$block='event_widget') function eventWidget($event,$width,$indent,$owner,$return_array=false,$block='event_widget')
{ {
if ($this->debug > 1 || $this->debug==='eventWidget') $this->bo->debug_message('uiviews::eventWidget(%1,width=%2)',False,$event,$width); if ($this->debug > 1 || $this->debug==='eventWidget') $this->bo->debug_message('uiviews::eventWidget(%1,width=%2)',False,$event,$width);
@ -1159,10 +1211,39 @@ class uiviews extends uical
{ {
$style = 'position: relative; margin-top: 3px;'; $style = 'position: relative; margin-top: 3px;';
} }
return $indent.'<div class="calEvent'.($is_private ? 'Private' : '').
'" style="'.$style.' border-color: '.$headerbgcolor.'; background: '.$background.';"'. $draggableID = 'drag_'.$event['id'].'_O'.$event['owner'].'_C'.$owner;
$html = $indent.'<div id="'.$draggableID.'" class="calEvent'.($is_private ? 'Private' : '').
'" style="'.$style.' border-color: '.$headerbgcolor.'; background: '.$background.'; z-index: 20;"'.
$popup.' '.$this->html->tooltip($tooltip,False,array('BorderWidth'=>0,'Padding'=>0)). $popup.' '.$this->html->tooltip($tooltip,False,array('BorderWidth'=>0,'Padding'=>0)).
'>'."\n".$ie_fix.$html.$indent."</div>\n"; '>'."\n".$ie_fix.$html."\n".
$indent."</div>"."\n";
// ATM we do not support whole day events or recurring events for dragdrop
if ( $this->use_time_grid &&
$this->bo->check_perms(EGW_ACL_EDIT,$event['id']) &&
!$event['whole_day_on_top'] &&
!$event['whole_day'] &&
!$event['recur_type']
)
{
// register event as draggable
$this->dragdrop->addDraggable(
$draggableID,
array(
'eventId'=>$event['id'],
'eventOwner'=>$event['owner'],
'calendarOwner'=>$owner,
'errorImage'=>addslashes($this->html->image('phpgwapi','dialog_error',false,'style="width: 16px;"')),
'loaderImage'=>addslashes($this->html->image('phpgwapi','ajax-loader')),
),
'calendar.dragDropFunctions.dragEvent',
'calendar.dragDropFunctions.dropEvent'
);
}
return $html;
} }
function add_nonempty($content,$label,$one_per_line=False,$space = True) function add_nonempty($content,$label,$one_per_line=False,$space = True)
@ -1781,11 +1862,18 @@ class uiviews extends uical
{ {
$start = $this->bo->date2array($event['start']); $start = $this->bo->date2array($event['start']);
$end = $this->bo->date2array($event['end']); $end = $this->bo->date2array($event['end']);
if(!$start['hour'] && !$start['minute'] && $end['hour'] == 23 && $end['minute'] == 59 && $event['non_blocking']) if(!$start['hour'] && !$start['minute'] && $end['hour'] == 23 && $end['minute'] == 59)
{ {
if($event['non_blocking'])
{
$dayEvents[$day][$num]['whole_day_on_top']=true; $dayEvents[$day][$num]['whole_day_on_top']=true;
$this->whole_day_positions[$num]=($this->rowHeight*($num+2)); $this->whole_day_positions[$num]=($this->rowHeight*($num+2));
$extraRowsToAdd++; $extraRowsToAdd++;
}
else
{
$dayEvents[$day][$num]['whole_day']=true;
}
} }
} }
// check after every day if we have to increase $this->extraRows // check after every day if we have to increase $this->extraRows

View File

@ -0,0 +1,65 @@
function dragEvent()
{
if(minOffset())
{
// make a snapshot of the old (original) innerHTML of the dragged event
if(!dd.obj.oldInnerHTML)
{
dd.obj.oldInnerHTML = dd.obj.div.innerHTML;
}
if(dropTarget = dd.obj.getEltBelow())
{
var datetime = dropTarget.my_datetime;
}
// we just allow to drop within the users own calendar
// and not crossing into another calendar ATM
if(datetime && (dd.obj.my_calendarOwner == dropTarget.my_owner ))
{
dd.obj.div.innerHTML = '<div style="font-size: 1.1em; font-weight: bold; text-align: center;">' + datetime.substr(9,2) + ":" + datetime.substr(11,2) + '</div>';
} else {
dd.obj.div.innerHTML = '<div style="background-color: red; height: 100%; width: 100%; text-align: center;">' + dd.obj.my_errorImage + '</div>';
}
}
}
function dropEvent()
{
// minimum requirements for ajax call
if( minOffset() &&
(dropTarget = dd.obj.getEltBelow()) &&
(dropTarget.my_datetime) &&
(dd.obj.my_calendarOwner == dropTarget.my_owner)
)
{
dd.obj.div.innerHTML = '<div style="height: 100%; width: 100%; text-align: center;">' + dd.obj.my_loaderImage + '</div>';
xajax_doXMLHTTP(
'calendar.ajaxcalendar.moveEvent',
dd.obj.my_eventId,
dd.obj.my_calendarOwner,
dropTarget.my_datetime,
dropTarget.my_owner
);
}
else
{
// abort - move to old position and restore old innerHTML
if(dd.obj.oldInnerHTML)
{
dd.obj.div.innerHTML = dd.obj.oldInnerHTML;
}
dd.obj.moveTo(dd.obj.defx,dd.obj.defy);
}
}
function minOffset()
{
var offsetX = Math.abs(dd.obj.defx - dd.obj.x);
var offsetY = Math.abs(dd.obj.defy - dd.obj.y);
if(offsetX > 5 || offsetY > 5) { return true; }
return false;
}

View File

@ -230,5 +230,14 @@
'help' => 'Should this help messages shown up always, when you enter the preferences or only on request.', 'help' => 'Should this help messages shown up always, when you enter the preferences or only on request.',
'xmlrpc' => False, 'xmlrpc' => False,
'admin' => False 'admin' => False
),
'enable_dragdrop' => array(
'type' => 'check',
'label' => 'Enable drag and drop functionality (experimental)',
'name' => 'enable_dragdrop',
'help' => 'Enables or disables drag and drop functions in all applications. If the browser does not support '.
'drag and drop, it will be disabled automatically. This feature is experimental at the moment.',
'xmlrpc' => False,
'admin' => False
) )
); );