added droppable/drop, refactored selectable code, fixed issue 406
This commit is contained in:
parent
5fb7644920
commit
8ebda5094f
475
src/agenda.js
475
src/agenda.js
|
@ -88,10 +88,6 @@ function Agenda(element, options, methods) {
|
||||||
return bg.find('td:eq(' + col + ') div div');
|
return bg.find('td:eq(' + col + ') div div');
|
||||||
}),
|
}),
|
||||||
slotTopCache = {},
|
slotTopCache = {},
|
||||||
daySelectionManager,
|
|
||||||
slotSelectionManager,
|
|
||||||
selectionHelper,
|
|
||||||
selectionMatrix,
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
view = $.extend(this, viewMethods, methods, {
|
view = $.extend(this, viewMethods, methods, {
|
||||||
|
@ -669,38 +665,27 @@ function Agenda(element, options, methods) {
|
||||||
|
|
||||||
function draggableDayEvent(event, eventElement, isStart) {
|
function draggableDayEvent(event, eventElement, isStart) {
|
||||||
if (!options.disableDragging && eventElement.draggable) {
|
if (!options.disableDragging && eventElement.draggable) {
|
||||||
var origPosition, origWidth,
|
var origWidth;
|
||||||
resetElement,
|
var allDay=true;
|
||||||
allDay=true,
|
var dayDelta;
|
||||||
matrix;
|
|
||||||
eventElement.draggable({
|
eventElement.draggable({
|
||||||
zIndex: 9,
|
zIndex: 9,
|
||||||
opacity: view.option('dragOpacity', 'month'), // use whatever the month view was using
|
opacity: view.option('dragOpacity', 'month'), // use whatever the month view was using
|
||||||
revertDuration: options.dragRevertDuration,
|
revertDuration: options.dragRevertDuration,
|
||||||
start: function(ev, ui) {
|
start: function(ev, ui) {
|
||||||
view.hideEvents(event, eventElement);
|
|
||||||
view.trigger('eventDragStart', eventElement, event, ev, ui);
|
view.trigger('eventDragStart', eventElement, event, ev, ui);
|
||||||
origPosition = eventElement.position();
|
view.hideEvents(event, eventElement);
|
||||||
origWidth = eventElement.width();
|
origWidth = eventElement.width();
|
||||||
resetElement = function() {
|
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
||||||
if (!allDay) {
|
eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
|
||||||
eventElement
|
clearOverlay();
|
||||||
.width(origWidth)
|
|
||||||
.height('')
|
|
||||||
.draggable('option', 'grid', null);
|
|
||||||
allDay = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
matrix = buildDayMatrix(function(cell) {
|
|
||||||
eventElement.draggable('option', 'revert', !cell || !cell.rowDelta && !cell.colDelta);
|
|
||||||
view.clearOverlays();
|
|
||||||
if (cell) {
|
if (cell) {
|
||||||
|
dayDelta = colDelta * dis;
|
||||||
if (!cell.row) {
|
if (!cell.row) {
|
||||||
// on full-days
|
// on full-days
|
||||||
renderDayOverlay(
|
renderDayOverlay(
|
||||||
matrix,
|
addDays(cloneDate(event.start), dayDelta),
|
||||||
addDays(cloneDate(event.start), cell.colDelta),
|
addDays(exclEndDay(event), dayDelta)
|
||||||
addDays(exclEndDay(event), cell.colDelta)
|
|
||||||
);
|
);
|
||||||
resetElement();
|
resetElement();
|
||||||
}else{
|
}else{
|
||||||
|
@ -710,50 +695,51 @@ function Agenda(element, options, methods) {
|
||||||
setOuterHeight(
|
setOuterHeight(
|
||||||
eventElement.width(colWidth - 10), // don't use entire width
|
eventElement.width(colWidth - 10), // don't use entire width
|
||||||
slotHeight * Math.round(
|
slotHeight * Math.round(
|
||||||
(event.end ? ((event.end - event.start)/MINUTE_MS) : options.defaultEventMinutes)
|
(event.end ? ((event.end - event.start) / MINUTE_MS) : options.defaultEventMinutes)
|
||||||
/options.slotMinutes)
|
/ options.slotMinutes
|
||||||
|
)
|
||||||
);
|
);
|
||||||
eventElement.draggable('option', 'grid', [colWidth, 1]);
|
eventElement.draggable('option', 'grid', [colWidth, 1]);
|
||||||
allDay = false;
|
allDay = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},true);
|
}, ev, 'drag');
|
||||||
matrix.mouse(ev);
|
|
||||||
},
|
|
||||||
drag: function(ev, ui) {
|
|
||||||
matrix.mouse(ev);
|
|
||||||
},
|
},
|
||||||
stop: function(ev, ui) {
|
stop: function(ev, ui) {
|
||||||
|
var cell = hoverListener.stop();
|
||||||
|
clearOverlay();
|
||||||
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
||||||
view.clearOverlays();
|
if (cell && (!allDay || dayDelta)) {
|
||||||
var cell = matrix.cell;
|
// changed!
|
||||||
var dayDelta = dis * (
|
eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
|
||||||
allDay ? // can't trust cell.colDelta when using slot grid
|
var minuteDelta = 0;
|
||||||
(cell ? cell.colDelta : 0) :
|
if (!allDay) {
|
||||||
Math.floor((ui.position.left - origPosition.left) / colWidth)
|
minuteDelta = Math.round((eventElement.offset().top - bodyContent.offset().top) / slotHeight)
|
||||||
);
|
* options.slotMinutes
|
||||||
if (!cell || !dayDelta && !cell.rowDelta) {
|
+ minMinute
|
||||||
// over nothing (has reverted)
|
- (event.start.getHours() * 60 + event.start.getMinutes());
|
||||||
|
}
|
||||||
|
view.eventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui);
|
||||||
|
}else{
|
||||||
|
// hasn't moved or is out of bounds (draggable has already reverted)
|
||||||
resetElement();
|
resetElement();
|
||||||
if ($.browser.msie) {
|
if ($.browser.msie) {
|
||||||
eventElement.css('filter', ''); // clear IE opacity side-effects
|
eventElement.css('filter', ''); // clear IE opacity side-effects
|
||||||
}
|
}
|
||||||
view.showEvents(event, eventElement);
|
view.showEvents(event, eventElement);
|
||||||
}else{
|
|
||||||
eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
|
|
||||||
view.eventDrop(
|
|
||||||
this, event, dayDelta,
|
|
||||||
allDay ? 0 : // minute delta
|
|
||||||
Math.round((eventElement.offset().top - bodyContent.offset().top) / slotHeight)
|
|
||||||
* options.slotMinutes
|
|
||||||
+ minMinute
|
|
||||||
- (event.start.getHours() * 60 + event.start.getMinutes()),
|
|
||||||
allDay, ev, ui
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
function resetElement() {
|
||||||
|
if (!allDay) {
|
||||||
|
eventElement
|
||||||
|
.width(origWidth)
|
||||||
|
.height('')
|
||||||
|
.draggable('option', 'grid', null);
|
||||||
|
allDay = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,11 +749,11 @@ function Agenda(element, options, methods) {
|
||||||
|
|
||||||
function draggableSlotEvent(event, eventElement, timeElement) {
|
function draggableSlotEvent(event, eventElement, timeElement) {
|
||||||
if (!options.disableDragging && eventElement.draggable) {
|
if (!options.disableDragging && eventElement.draggable) {
|
||||||
var origPosition,
|
var origPosition;
|
||||||
resetElement,
|
var allDay=false;
|
||||||
prevSlotDelta, slotDelta,
|
var dayDelta;
|
||||||
allDay=false,
|
var minuteDelta;
|
||||||
matrix;
|
var prevMinuteDelta;
|
||||||
eventElement.draggable({
|
eventElement.draggable({
|
||||||
zIndex: 9,
|
zIndex: 9,
|
||||||
scroll: false,
|
scroll: false,
|
||||||
|
@ -776,26 +762,20 @@ function Agenda(element, options, methods) {
|
||||||
opacity: view.option('dragOpacity'),
|
opacity: view.option('dragOpacity'),
|
||||||
revertDuration: options.dragRevertDuration,
|
revertDuration: options.dragRevertDuration,
|
||||||
start: function(ev, ui) {
|
start: function(ev, ui) {
|
||||||
view.hideEvents(event, eventElement);
|
|
||||||
view.trigger('eventDragStart', eventElement, event, ev, ui);
|
view.trigger('eventDragStart', eventElement, event, ev, ui);
|
||||||
|
view.hideEvents(event, eventElement);
|
||||||
if ($.browser.msie) {
|
if ($.browser.msie) {
|
||||||
eventElement.find('span.fc-event-bg').hide(); // nested opacities mess up in IE, just hide
|
eventElement.find('span.fc-event-bg').hide(); // nested opacities mess up in IE, just hide
|
||||||
}
|
}
|
||||||
origPosition = eventElement.position();
|
origPosition = eventElement.position();
|
||||||
resetElement = function() {
|
minuteDelta = prevMinuteDelta = 0;
|
||||||
// convert back to original slot-event
|
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
||||||
if (allDay) {
|
|
||||||
timeElement.css('display', ''); // show() was causing display=inline
|
|
||||||
eventElement.draggable('option', 'grid', [colWidth, slotHeight]);
|
|
||||||
allDay = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
prevSlotDelta = 0;
|
|
||||||
matrix = buildDayMatrix(function(cell) {
|
|
||||||
eventElement.draggable('option', 'revert', !cell);
|
eventElement.draggable('option', 'revert', !cell);
|
||||||
view.clearOverlays();
|
clearOverlay();
|
||||||
if (cell) {
|
if (cell) {
|
||||||
if (!cell.row && options.allDaySlot) { // over full days
|
dayDelta = colDelta * dis;
|
||||||
|
if (options.allDaySlot && !cell.row) {
|
||||||
|
// over full days
|
||||||
if (!allDay) {
|
if (!allDay) {
|
||||||
// convert to temporary all-day event
|
// convert to temporary all-day event
|
||||||
allDay = true;
|
allDay = true;
|
||||||
|
@ -803,61 +783,63 @@ function Agenda(element, options, methods) {
|
||||||
eventElement.draggable('option', 'grid', null);
|
eventElement.draggable('option', 'grid', null);
|
||||||
}
|
}
|
||||||
renderDayOverlay(
|
renderDayOverlay(
|
||||||
matrix,
|
addDays(cloneDate(event.start), dayDelta),
|
||||||
addDays(cloneDate(event.start), cell.colDelta),
|
addDays(exclEndDay(event), dayDelta)
|
||||||
addDays(exclEndDay(event), cell.colDelta)
|
|
||||||
);
|
);
|
||||||
}else{ // on slots
|
}else{
|
||||||
|
// on slots
|
||||||
resetElement();
|
resetElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},true);
|
}, ev, 'drag');
|
||||||
matrix.mouse(ev);
|
|
||||||
},
|
},
|
||||||
drag: function(ev, ui) {
|
drag: function(ev, ui) {
|
||||||
slotDelta = Math.round((ui.position.top - origPosition.top) / slotHeight);
|
minuteDelta = Math.round((ui.position.top - origPosition.top) / slotHeight) * options.slotMinutes;
|
||||||
if (slotDelta != prevSlotDelta) {
|
if (minuteDelta != prevMinuteDelta) {
|
||||||
if (!allDay) {
|
if (!allDay) {
|
||||||
// update time header
|
updateTimeText(minuteDelta);
|
||||||
var minuteDelta = slotDelta*options.slotMinutes,
|
|
||||||
newStart = addMinutes(cloneDate(event.start), minuteDelta),
|
|
||||||
newEnd;
|
|
||||||
if (event.end) {
|
|
||||||
newEnd = addMinutes(cloneDate(event.end), minuteDelta);
|
|
||||||
}
|
|
||||||
timeElement.text(formatDates(newStart, newEnd, view.option('timeFormat')));
|
|
||||||
}
|
}
|
||||||
prevSlotDelta = slotDelta;
|
prevMinuteDelta = minuteDelta;
|
||||||
}
|
}
|
||||||
matrix.mouse(ev);
|
|
||||||
},
|
},
|
||||||
stop: function(ev, ui) {
|
stop: function(ev, ui) {
|
||||||
view.clearOverlays();
|
var cell = hoverListener.stop();
|
||||||
|
clearOverlay();
|
||||||
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
||||||
var cell = matrix.cell,
|
if (cell && (dayDelta || minuteDelta || allDay)) {
|
||||||
dayDelta = dis * (
|
// changed!
|
||||||
allDay ? // can't trust cell.colDelta when using slot grid
|
view.eventDrop(this, event, dayDelta, allDay ? 0 : minuteDelta, allDay, ev, ui);
|
||||||
(cell ? cell.colDelta : 0) :
|
}else{
|
||||||
Math.floor((ui.position.left - origPosition.left) / colWidth)
|
// either no change or out-of-bounds (draggable has already reverted)
|
||||||
);
|
|
||||||
if (!cell || !slotDelta && !dayDelta) {
|
|
||||||
resetElement();
|
resetElement();
|
||||||
|
eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position
|
||||||
|
updateTimeText(0);
|
||||||
if ($.browser.msie) {
|
if ($.browser.msie) {
|
||||||
eventElement
|
eventElement
|
||||||
.css('filter', '') // clear IE opacity side-effects
|
.css('filter', '') // clear IE opacity side-effects
|
||||||
.find('span.fc-event-bg').css('display', ''); // .show() made display=inline
|
.find('span.fc-event-bg')
|
||||||
|
.css('display', ''); // .show() made display=inline
|
||||||
}
|
}
|
||||||
eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position
|
|
||||||
view.showEvents(event, eventElement);
|
view.showEvents(event, eventElement);
|
||||||
}else{
|
|
||||||
view.eventDrop(
|
|
||||||
this, event, dayDelta,
|
|
||||||
allDay ? 0 : slotDelta * options.slotMinutes, // minute delta
|
|
||||||
allDay, ev, ui
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
function updateTimeText(minuteDelta) {
|
||||||
|
var newStart = addMinutes(cloneDate(event.start), minuteDelta);
|
||||||
|
var newEnd;
|
||||||
|
if (event.end) {
|
||||||
|
newEnd = addMinutes(cloneDate(event.end), minuteDelta);
|
||||||
|
}
|
||||||
|
timeElement.text(formatDates(newStart, newEnd, view.option('timeFormat')));
|
||||||
|
}
|
||||||
|
function resetElement() {
|
||||||
|
// convert back to original slot-event
|
||||||
|
if (allDay) {
|
||||||
|
timeElement.css('display', ''); // show() was causing display=inline
|
||||||
|
eventElement.draggable('option', 'grid', [colWidth, slotHeight]);
|
||||||
|
allDay = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -918,114 +900,152 @@ function Agenda(element, options, methods) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Selecting
|
/* Coordinate Utilities
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
daySelectionManager = new SelectionManager(
|
|
||||||
view,
|
|
||||||
unselect,
|
|
||||||
function(startDate, endDate, allDay) {
|
|
||||||
renderDayOverlay(
|
|
||||||
selectionMatrix,
|
|
||||||
startDate,
|
|
||||||
addDays(cloneDate(endDate), 1)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
clearSelection
|
|
||||||
);
|
|
||||||
|
|
||||||
function daySelectionMousedown(ev) {
|
var coordinateGrid = new CoordinateGrid(function(rows, cols) {
|
||||||
if (view.option('selectable')) {
|
var e, n, p;
|
||||||
selectionMatrix = buildDayMatrix(function(cell) {
|
bg.find('td').each(function(i, _e) {
|
||||||
if (cell) {
|
e = $(_e);
|
||||||
var d = dayColDate(cell.col);
|
n = e.offset().left;
|
||||||
daySelectionManager.drag(d, d, true);
|
if (i) {
|
||||||
}else{
|
p[1] = n;
|
||||||
daySelectionManager.drag();
|
}
|
||||||
}
|
p = [n];
|
||||||
});
|
cols[i] = p;
|
||||||
documentDragHelp(
|
});
|
||||||
function(ev) {
|
p[1] = n + e.outerWidth();
|
||||||
selectionMatrix.mouse(ev);
|
if (options.allDaySlot) {
|
||||||
},
|
e = head.find('td');
|
||||||
function(ev) {
|
n = e.offset().top;
|
||||||
daySelectionManager.dragStop(ev);
|
rows[0] = [n, n+e.outerHeight()];
|
||||||
}
|
|
||||||
);
|
|
||||||
daySelectionManager.dragStart(ev);
|
|
||||||
selectionMatrix.mouse(ev);
|
|
||||||
return false; // prevent auto-unselect and text selection
|
|
||||||
}
|
}
|
||||||
|
var bodyContentTop = bodyContent.offset().top;
|
||||||
|
var bodyTop = body.offset().top;
|
||||||
|
var bodyBottom = bodyTop + body.outerHeight();
|
||||||
|
function constrain(n) {
|
||||||
|
return Math.max(bodyTop, Math.min(bodyBottom, n));
|
||||||
|
}
|
||||||
|
for (var i=0; i<slotCnt; i++) {
|
||||||
|
rows.push([
|
||||||
|
constrain(bodyContentTop + slotHeight*i),
|
||||||
|
constrain(bodyContentTop + slotHeight*(i+1))
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var hoverListener = new HoverListener(coordinateGrid);
|
||||||
|
|
||||||
|
// get the Y coordinate of the given time on the given day (both Date objects)
|
||||||
|
function timePosition(day, time) { // both date objects. day holds 00:00 of current day
|
||||||
|
day = cloneDate(day, true);
|
||||||
|
if (time < addMinutes(cloneDate(day), minMinute)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (time >= addMinutes(cloneDate(day), maxMinute)) {
|
||||||
|
return bodyContent.height();
|
||||||
|
}
|
||||||
|
var slotMinutes = options.slotMinutes,
|
||||||
|
minutes = time.getHours()*60 + time.getMinutes() - minMinute,
|
||||||
|
slotI = Math.floor(minutes / slotMinutes),
|
||||||
|
slotTop = slotTopCache[slotI];
|
||||||
|
if (slotTop === undefined) {
|
||||||
|
slotTop = slotTopCache[slotI] = body.find('tr:eq(' + slotI + ') td div')[0].offsetTop;
|
||||||
|
}
|
||||||
|
return Math.max(0, Math.round(
|
||||||
|
slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
slotSelectionManager = new SelectionManager(
|
|
||||||
view,
|
|
||||||
unselect,
|
|
||||||
renderSlotSelection,
|
/* Selecting
|
||||||
clearSelection
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var selected = false;
|
||||||
|
var daySelectionMousedown = selection_dayMousedown(
|
||||||
|
view, hoverListener, cellDate, renderDayOverlay, clearOverlay, reportSelection, unselect
|
||||||
);
|
);
|
||||||
|
|
||||||
function slotSelectionMousedown(ev) {
|
function slotSelectionMousedown(ev) {
|
||||||
if (view.option('selectable')) {
|
if (view.option('selectable')) {
|
||||||
selectionMatrix = buildSlotMatrix(function(cell) {
|
unselect();
|
||||||
if (cell) {
|
var dates;
|
||||||
var d = slotCellDate(cell.row, cell.origCol);
|
hoverListener.start(function(cell, origCell) {
|
||||||
slotSelectionManager.drag(d, addMinutes(cloneDate(d), options.slotMinutes), false);
|
clearSelection();
|
||||||
|
if (cell && cell.col == origCell.col) {
|
||||||
|
var d1 = cellDate(origCell);
|
||||||
|
var d2 = cellDate(cell);
|
||||||
|
dates = [
|
||||||
|
d1,
|
||||||
|
addMinutes(cloneDate(d1), options.slotMinutes),
|
||||||
|
d2,
|
||||||
|
addMinutes(cloneDate(d2), options.slotMinutes)
|
||||||
|
].sort(cmp);
|
||||||
|
renderSlotSelection(dates[0], dates[3]);
|
||||||
}else{
|
}else{
|
||||||
slotSelectionManager.drag();
|
dates = null;
|
||||||
|
}
|
||||||
|
}, ev);
|
||||||
|
$(document).one('mouseup', function() {
|
||||||
|
hoverListener.stop();
|
||||||
|
if (dates) {
|
||||||
|
reportSelection(dates[0], dates[3], false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
documentDragHelp(
|
|
||||||
function(ev) {
|
|
||||||
selectionMatrix.mouse(ev);
|
|
||||||
},
|
|
||||||
function(ev) {
|
|
||||||
slotSelectionManager.dragStop(ev);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
slotSelectionManager.dragStart(ev);
|
|
||||||
selectionMatrix.mouse(ev);
|
|
||||||
return false; // prevent auto-unselect and text selection
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
documentUnselectAuto(view, unselect);
|
view.select = function(startDate, endDate, allDay) {
|
||||||
|
coordinateGrid.build();
|
||||||
this.select = function(start, end, allDay) {
|
unselect();
|
||||||
if (allDay) {
|
if (allDay) {
|
||||||
if (options.allDaySlot) {
|
if (options.allDaySlot) {
|
||||||
if (!end) {
|
if (!endDate) {
|
||||||
end = cloneDate(start);
|
endDate = cloneDate(startDate);
|
||||||
}
|
}
|
||||||
selectionMatrix = buildDayMatrix();
|
renderDayOverlay(startDate, addDays(cloneDate(endDate), 1));
|
||||||
daySelectionManager.select(start, end, allDay);
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if (!end) {
|
if (!endDate) {
|
||||||
end = addMinutes(cloneDate(start), options.slotMinutes);
|
endDate = addMinutes(cloneDate(startDate), options.slotMinutes);
|
||||||
}
|
}
|
||||||
selectionMatrix = buildSlotMatrix();
|
renderSlotSelection(startDate, endDate);
|
||||||
slotSelectionManager.select(start, end, allDay);
|
|
||||||
}
|
}
|
||||||
|
reportSelection(startDate, endDate, allDay);
|
||||||
};
|
};
|
||||||
|
|
||||||
function unselect() {
|
function reportSelection(startDate, endDate, allDay) {
|
||||||
slotSelectionManager.unselect();
|
selected = true;
|
||||||
daySelectionManager.unselect();
|
view.trigger('select', view, startDate, endDate, allDay);
|
||||||
}
|
}
|
||||||
this.unselect = unselect;
|
|
||||||
|
function unselect() {
|
||||||
|
if (selected) {
|
||||||
|
clearSelection();
|
||||||
|
selected = false;
|
||||||
|
view.trigger('unselect', view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view.unselect = unselect;
|
||||||
|
|
||||||
|
selection_unselectAuto(view, unselect);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Selecting drawing utils
|
/* Selecting drawing utils
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var selectionHelper;
|
||||||
|
|
||||||
function renderSlotSelection(startDate, endDate) {
|
function renderSlotSelection(startDate, endDate) {
|
||||||
var helperOption = view.option('selectHelper');
|
var helperOption = view.option('selectHelper');
|
||||||
if (helperOption) {
|
if (helperOption) {
|
||||||
var col = dayDiff(startDate, view.visStart);
|
var col = dayDiff(startDate, view.visStart) * dis + dit;
|
||||||
if (col >= 0 && col < colCnt) { // only works when times are on same day
|
if (col >= 0 && col < colCnt) { // only works when times are on same day
|
||||||
var rect = selectionMatrix.rect(0, col*dis+dit, 1, col*dis+dit+1, bodyContent); // only for horizontal coords
|
var rect = coordinateGrid.rect(0, col, 0, col, bodyContent); // only for horizontal coords
|
||||||
var top = timePosition(startDate, startDate);
|
var top = timePosition(startDate, startDate);
|
||||||
var bottom = timePosition(startDate, endDate);
|
var bottom = timePosition(startDate, endDate);
|
||||||
if (bottom > top) { // protect against selections that are entirely before or after visible range
|
if (bottom > top) { // protect against selections that are entirely before or after visible range
|
||||||
|
@ -1068,18 +1088,17 @@ function Agenda(element, options, methods) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
renderSlotOverlay(selectionMatrix, startDate, endDate);
|
renderSlotOverlay(startDate, endDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearSelection() {
|
function clearSelection() {
|
||||||
clearOverlays();
|
clearOverlay();
|
||||||
if (selectionHelper) {
|
if (selectionHelper) {
|
||||||
selectionHelper.remove();
|
selectionHelper.remove();
|
||||||
selectionHelper = null;
|
selectionHelper = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1087,7 +1106,7 @@ function Agenda(element, options, methods) {
|
||||||
/* Semi-transparent Overlay Helpers
|
/* Semi-transparent Overlay Helpers
|
||||||
-----------------------------------------------------*/
|
-----------------------------------------------------*/
|
||||||
|
|
||||||
function renderDayOverlay(matrix, startDate, endDate) {
|
function renderDayOverlay(startDate, endDate) {
|
||||||
var startCol, endCol;
|
var startCol, endCol;
|
||||||
if (rtl) {
|
if (rtl) {
|
||||||
startCol = dayDiff(endDate, view.visStart)*dis+dit+1;
|
startCol = dayDiff(endDate, view.visStart)*dis+dit+1;
|
||||||
|
@ -1099,21 +1118,26 @@ function Agenda(element, options, methods) {
|
||||||
startCol = Math.max(0, startCol);
|
startCol = Math.max(0, startCol);
|
||||||
endCol = Math.min(colCnt, endCol);
|
endCol = Math.min(colCnt, endCol);
|
||||||
if (startCol < endCol) {
|
if (startCol < endCol) {
|
||||||
var rect = matrix.rect(0, startCol, 1, endCol, head);
|
|
||||||
dayBind(
|
dayBind(
|
||||||
view.renderOverlay(rect, head)
|
_renderDayOverlay(0, startCol, 0, endCol-1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _renderDayOverlay(col0, row0, col1, row1) {
|
||||||
|
var rect = coordinateGrid.rect(col0, row0, col1, row1, head);
|
||||||
|
return view.renderOverlay(rect, head);
|
||||||
|
}
|
||||||
|
|
||||||
function renderSlotOverlay(matrix, overlayStart, overlayEnd) {
|
function renderSlotOverlay(overlayStart, overlayEnd) {
|
||||||
var dayStart = cloneDate(view.visStart);
|
var dayStart = cloneDate(view.visStart);
|
||||||
var dayEnd = addDays(cloneDate(dayStart), 1);
|
var dayEnd = addDays(cloneDate(dayStart), 1);
|
||||||
for (var i=0; i<colCnt; i++) {
|
for (var i=0; i<colCnt; i++) {
|
||||||
var stretchStart = new Date(Math.max(dayStart, overlayStart));
|
var stretchStart = new Date(Math.max(dayStart, overlayStart));
|
||||||
var stretchEnd = new Date(Math.min(dayEnd, overlayEnd));
|
var stretchEnd = new Date(Math.min(dayEnd, overlayEnd));
|
||||||
if (stretchStart < stretchEnd) {
|
if (stretchStart < stretchEnd) {
|
||||||
var rect = matrix.rect(0, i*dis+dit, 1, i*dis+dit+1, bodyContent); // only use it for horizontal coords
|
var col = i*dis+dit;
|
||||||
|
var rect = coordinateGrid.rect(0, col, 0, col, bodyContent); // only use it for horizontal coords
|
||||||
var top = timePosition(dayStart, stretchStart);
|
var top = timePosition(dayStart, stretchStart);
|
||||||
var bottom = timePosition(dayStart, stretchEnd);
|
var bottom = timePosition(dayStart, stretchEnd);
|
||||||
rect.top = top;
|
rect.top = top;
|
||||||
|
@ -1127,48 +1151,42 @@ function Agenda(element, options, methods) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearOverlays() {
|
function clearOverlay() {
|
||||||
view.clearOverlays();
|
view.clearOverlays();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Coordinate Utilities
|
/* External dragging
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------*/
|
||||||
|
|
||||||
// get the Y coordinate of the given time on the given day (both Date objects)
|
view.isExternalDraggable = function(_element) {
|
||||||
function timePosition(day, time) { // both date objects. day holds 00:00 of current day
|
return _element.parentNode != daySegmentContainer[0] && _element.parentNode != slotSegmentContainer[0];
|
||||||
day = cloneDate(day, true);
|
};
|
||||||
if (time < addMinutes(cloneDate(day), minMinute)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (time >= addMinutes(cloneDate(day), maxMinute)) {
|
|
||||||
return bodyContent.height();
|
|
||||||
}
|
|
||||||
var slotMinutes = options.slotMinutes,
|
|
||||||
minutes = time.getHours()*60 + time.getMinutes() - minMinute,
|
|
||||||
slotI = Math.floor(minutes / slotMinutes),
|
|
||||||
slotTop = slotTopCache[slotI];
|
|
||||||
if (slotTop === undefined) {
|
|
||||||
slotTop = slotTopCache[slotI] = body.find('tr:eq(' + slotI + ') td div')[0].offsetTop;
|
|
||||||
}
|
|
||||||
return Math.max(0, Math.round(
|
|
||||||
slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildDayMatrix(changeCallback, includeSlotArea) {
|
view.dragStart = function(ev) {
|
||||||
var rowElements = options.allDaySlot ? head.find('td') : $([]);
|
hoverListener.start(function(cell) {
|
||||||
if (includeSlotArea) {
|
clearOverlay();
|
||||||
rowElements = rowElements.add(body);
|
if (cell) {
|
||||||
}
|
if (cellIsAllDay(cell)) {
|
||||||
return new HoverMatrix(rowElements, bg.find('td'), changeCallback);
|
_renderDayOverlay(cell.row, cell.col, cell.row, cell.col);
|
||||||
}
|
}else{
|
||||||
|
var d1 = cellDate(cell);
|
||||||
|
var d2 = addMinutes(cloneDate(d1), options.slotMinutes); //options.defaultEventMinutes);
|
||||||
|
renderSlotOverlay(d1, d2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, ev);
|
||||||
|
};
|
||||||
|
|
||||||
function buildSlotMatrix(changeCallback) {
|
view.dragStop = function(ev, ui) {
|
||||||
return new HoverMatrix(bodyTable.find('td'), bg.find('td'), changeCallback);
|
var cell = hoverListener.stop();
|
||||||
}
|
clearOverlay();
|
||||||
|
if (cell) {
|
||||||
|
view.trigger('drop', view, cellDate(cell), cellIsAllDay(cell), ev, ui);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1188,17 +1206,20 @@ function Agenda(element, options, methods) {
|
||||||
return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit;
|
return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cellDate(cell) {
|
||||||
// generating dates from cell row & columns
|
var d = addDays(cloneDate(view.visStart), cell.col*dis+dit);
|
||||||
|
var slotIndex = cell.row;
|
||||||
function dayColDate(col) {
|
if (options.allDaySlot) {
|
||||||
return addDays(cloneDate(view.visStart), col*dis+dit);
|
slotIndex--;
|
||||||
|
}
|
||||||
|
if (slotIndex >= 0) {
|
||||||
|
addMinutes(d, minMinute + slotIndex*options.slotMinutes);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
function slotCellDate(row, col) {
|
function cellIsAllDay(cell) {
|
||||||
var d = dayColDate(col);
|
return options.allDaySlot && !cell.row;
|
||||||
addMinutes(d, minMinute + row*options.slotMinutes);
|
|
||||||
return d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
183
src/grid.js
183
src/grid.js
|
@ -121,8 +121,6 @@ function Grid(element, options, methods) {
|
||||||
dayContentPositions = new HorizontalPositionCache(function(dayOfWeek) {
|
dayContentPositions = new HorizontalPositionCache(function(dayOfWeek) {
|
||||||
return tbody.find('td:eq(' + ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt) + ') div div');
|
return tbody.find('td:eq(' + ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt) + ') div div');
|
||||||
}),
|
}),
|
||||||
selectionManager,
|
|
||||||
selectionMatrix,
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
// initialize superclass
|
// initialize superclass
|
||||||
|
@ -425,37 +423,32 @@ function Grid(element, options, methods) {
|
||||||
|
|
||||||
function draggableEvent(event, eventElement) {
|
function draggableEvent(event, eventElement) {
|
||||||
if (!options.disableDragging && eventElement.draggable) {
|
if (!options.disableDragging && eventElement.draggable) {
|
||||||
var matrix,
|
var dayDelta;
|
||||||
dayDelta = 0;
|
|
||||||
eventElement.draggable({
|
eventElement.draggable({
|
||||||
zIndex: 9,
|
zIndex: 9,
|
||||||
delay: 50,
|
delay: 50,
|
||||||
opacity: view.option('dragOpacity'),
|
opacity: view.option('dragOpacity'),
|
||||||
revertDuration: options.dragRevertDuration,
|
revertDuration: options.dragRevertDuration,
|
||||||
start: function(ev, ui) {
|
start: function(ev, ui) {
|
||||||
view.hideEvents(event, eventElement);
|
|
||||||
view.trigger('eventDragStart', eventElement, event, ev, ui);
|
view.trigger('eventDragStart', eventElement, event, ev, ui);
|
||||||
matrix = buildDayMatrix(function(cell) {
|
view.hideEvents(event, eventElement);
|
||||||
eventElement.draggable('option', 'revert', !cell || !cell.rowDelta && !cell.colDelta);
|
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
||||||
clearOverlays();
|
eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
|
||||||
|
clearOverlay();
|
||||||
if (cell) {
|
if (cell) {
|
||||||
dayDelta = cell.rowDelta*7 + cell.colDelta*dis;
|
dayDelta = rowDelta*7 + colDelta*dis;
|
||||||
renderDayOverlays(
|
renderDayOverlay(
|
||||||
matrix,
|
|
||||||
addDays(cloneDate(event.start), dayDelta),
|
addDays(cloneDate(event.start), dayDelta),
|
||||||
addDays(exclEndDay(event), dayDelta)
|
addDays(exclEndDay(event), dayDelta)
|
||||||
);
|
);
|
||||||
}else{
|
}else{
|
||||||
dayDelta = 0;
|
dayDelta = 0;
|
||||||
}
|
}
|
||||||
});
|
}, ev, 'drag');
|
||||||
matrix.mouse(ev);
|
|
||||||
},
|
|
||||||
drag: function(ev) {
|
|
||||||
matrix.mouse(ev);
|
|
||||||
},
|
},
|
||||||
stop: function(ev, ui) {
|
stop: function(ev, ui) {
|
||||||
clearOverlays();
|
hoverListener.stop();
|
||||||
|
clearOverlay();
|
||||||
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
||||||
if (dayDelta) {
|
if (dayDelta) {
|
||||||
eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
|
eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
|
||||||
|
@ -495,68 +488,108 @@ function Grid(element, options, methods) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Coordinate Utilities
|
||||||
|
--------------------------------------------------------*/
|
||||||
|
|
||||||
|
var coordinateGrid = new CoordinateGrid(function(rows, cols) {
|
||||||
|
var e, n, p;
|
||||||
|
var tds = tbody.find('tr:first td');
|
||||||
|
if (rtl) {
|
||||||
|
tds = $(tds.get().reverse());
|
||||||
|
}
|
||||||
|
tds.each(function(i, _e) {
|
||||||
|
e = $(_e);
|
||||||
|
n = e.offset().left;
|
||||||
|
if (i) {
|
||||||
|
p[1] = n;
|
||||||
|
}
|
||||||
|
p = [n];
|
||||||
|
cols[i] = p;
|
||||||
|
});
|
||||||
|
p[1] = n + e.outerWidth();
|
||||||
|
tbody.find('tr').each(function(i, _e) {
|
||||||
|
e = $(_e);
|
||||||
|
n = e.offset().top;
|
||||||
|
if (i) {
|
||||||
|
p[1] = n;
|
||||||
|
}
|
||||||
|
p = [n];
|
||||||
|
rows[i] = p;
|
||||||
|
});
|
||||||
|
p[1] = n + e.outerHeight();
|
||||||
|
});
|
||||||
|
|
||||||
|
var hoverListener = new HoverListener(coordinateGrid);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Selecting
|
/* Selecting
|
||||||
--------------------------------------------------------*/
|
--------------------------------------------------------*/
|
||||||
|
|
||||||
selectionManager = new SelectionManager(
|
var selected = false;
|
||||||
view,
|
var selectionMousedown = selection_dayMousedown(
|
||||||
unselect,
|
view, hoverListener, cellDate, renderDayOverlay, clearOverlay, reportSelection, unselect
|
||||||
function(startDate, endDate, allDay) {
|
|
||||||
renderDayOverlays(
|
|
||||||
selectionMatrix,
|
|
||||||
startDate,
|
|
||||||
addDays(cloneDate(endDate), 1)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
clearOverlays
|
|
||||||
);
|
);
|
||||||
|
|
||||||
function selectionMousedown(ev) {
|
view.select = function(startDate, endDate, allDay) {
|
||||||
if (view.option('selectable')) {
|
coordinateGrid.build();
|
||||||
selectionMatrix = buildDayMatrix(function(cell) {
|
unselect();
|
||||||
if (cell) {
|
if (!endDate) {
|
||||||
var d = cellDate(cell.row, cell.col);
|
endDate = cloneDate(startDate);
|
||||||
selectionManager.drag(d, d, true);
|
|
||||||
}else{
|
|
||||||
selectionManager.drag();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
documentDragHelp(
|
|
||||||
function(ev) {
|
|
||||||
selectionMatrix.mouse(ev);
|
|
||||||
},
|
|
||||||
function(ev) {
|
|
||||||
selectionManager.dragStop(ev);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
selectionManager.dragStart(ev);
|
|
||||||
selectionMatrix.mouse(ev);
|
|
||||||
return false; // prevent auto-unselect and text selection
|
|
||||||
}
|
}
|
||||||
}
|
renderDayOverlay(startDate, addDays(cloneDate(endDate), 1));
|
||||||
|
reportSelection(startDate, endDate, allDay);
|
||||||
documentUnselectAuto(view, unselect);
|
|
||||||
|
|
||||||
view.select = function(start, end, allDay) {
|
|
||||||
if (!end) {
|
|
||||||
end = cloneDate(start);
|
|
||||||
}
|
|
||||||
selectionMatrix = buildDayMatrix();
|
|
||||||
selectionManager.select(start, end, allDay);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function reportSelection(startDate, endDate, allDay) {
|
||||||
|
selected = true;
|
||||||
|
view.trigger('select', view, startDate, endDate, allDay);
|
||||||
|
}
|
||||||
|
|
||||||
function unselect() {
|
function unselect() {
|
||||||
selectionManager.unselect();
|
if (selected) {
|
||||||
|
clearOverlay();
|
||||||
|
selected = false;
|
||||||
|
view.trigger('unselect', view);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
view.unselect = unselect;
|
view.unselect = unselect;
|
||||||
|
|
||||||
|
selection_unselectAuto(view, unselect);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* External dragging
|
||||||
|
------------------------------------------------------*/
|
||||||
|
|
||||||
|
view.isExternalDraggable = function(_element) {
|
||||||
|
return _element.parentNode != segmentContainer[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
view.dragStart = function(ev, ui) {
|
||||||
|
hoverListener.start(function(cell) {
|
||||||
|
clearOverlay();
|
||||||
|
if (cell) {
|
||||||
|
_renderDayOverlay(cell.row, cell.col, cell.row, cell.col);
|
||||||
|
}
|
||||||
|
}, ev);
|
||||||
|
};
|
||||||
|
|
||||||
|
view.dragStop = function(ev, ui) {
|
||||||
|
var cell = hoverListener.stop();
|
||||||
|
clearOverlay();
|
||||||
|
if (cell) {
|
||||||
|
var d = cellDate(cell);
|
||||||
|
view.trigger('drop', view, d, true, ev, ui);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Semi-transparent Overlay Helpers
|
/* Semi-transparent Overlay Helpers
|
||||||
------------------------------------------------------*/
|
------------------------------------------------------*/
|
||||||
|
|
||||||
function renderDayOverlays(matrix, overlayStart, overlayEnd) { // overlayEnd is exclusive
|
function renderDayOverlay(overlayStart, overlayEnd) { // overlayEnd is exclusive
|
||||||
var rowStart = cloneDate(view.visStart);
|
var rowStart = cloneDate(view.visStart);
|
||||||
var rowEnd = addDays(cloneDate(rowStart), colCnt);
|
var rowEnd = addDays(cloneDate(rowStart), colCnt);
|
||||||
for (var i=0; i<rowCnt; i++) {
|
for (var i=0; i<rowCnt; i++) {
|
||||||
|
@ -571,9 +604,8 @@ function Grid(element, options, methods) {
|
||||||
colStart = dayDiff(stretchStart, rowStart);
|
colStart = dayDiff(stretchStart, rowStart);
|
||||||
colEnd = dayDiff(stretchEnd, rowStart);
|
colEnd = dayDiff(stretchEnd, rowStart);
|
||||||
}
|
}
|
||||||
var rect = matrix.rect(i, colStart, i+1, colEnd, element);
|
|
||||||
dayBind(
|
dayBind(
|
||||||
view.renderOverlay(rect, element)
|
_renderDayOverlay(i, colStart, i, colEnd-1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
addDays(rowStart, 7);
|
addDays(rowStart, 7);
|
||||||
|
@ -581,28 +613,23 @@ function Grid(element, options, methods) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearOverlays() {
|
function _renderDayOverlay(row0, col0, row1, col1) { // row1,col1 is inclusive
|
||||||
|
var rect = coordinateGrid.rect(row0, col0, row1, col1, element);
|
||||||
|
return view.renderOverlay(rect, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearOverlay() {
|
||||||
view.clearOverlays();
|
view.clearOverlays();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Date Utils
|
||||||
/* Utils
|
|
||||||
---------------------------------------------------*/
|
---------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
function buildDayMatrix(changeCallback) {
|
|
||||||
var tds = tbody.find('tr:first td');
|
|
||||||
if (rtl) {
|
|
||||||
tds = $(tds.get().reverse());
|
|
||||||
}
|
|
||||||
return new HoverMatrix(tbody.find('tr'), tds, changeCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
function cellDate(cell) {
|
||||||
function cellDate(r, c) { // convert r,c to date
|
return addDays(cloneDate(view.visStart), cell.row*7 + cell.col*dis+dit);
|
||||||
return addDays(cloneDate(view.visStart), r*7 + c*dis+dit);
|
|
||||||
// TODO: what about weekends in middle of week?
|
// TODO: what about weekends in middle of week?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
src/main.js
15
src/main.js
|
@ -840,6 +840,21 @@ $.fn.fullCalendar = function(options) {
|
||||||
$(window).resize(windowResize);
|
$(window).resize(windowResize);
|
||||||
|
|
||||||
|
|
||||||
|
if (options.droppable) {
|
||||||
|
$(document)
|
||||||
|
.bind('dragstart', function(ev, ui) {
|
||||||
|
if (view.isExternalDraggable(ev.target)) {
|
||||||
|
view.dragStart(ev, ui);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.bind('dragstop', function(ev, ui) {
|
||||||
|
if (view.isExternalDraggable(ev.target)) {
|
||||||
|
view.dragStop(ev, ui);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// let's begin...
|
// let's begin...
|
||||||
changeView(options.defaultView);
|
changeView(options.defaultView);
|
||||||
|
|
||||||
|
|
|
@ -16,5 +16,5 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function($) {
|
(function($, undefined) {
|
||||||
|
|
||||||
|
|
|
@ -1,96 +1,28 @@
|
||||||
|
|
||||||
function SelectionManager(view, initFunc, displayFunc, clearFunc) {
|
|
||||||
|
|
||||||
var t = this;
|
function selection_dayMousedown(view, hoverListener, cellDate, renderSelection, clearSelection, reportSelection, unselect) {
|
||||||
var selected = false;
|
return function(ev) {
|
||||||
var initialElement;
|
if (view.option('selectable')) {
|
||||||
var initialRange;
|
unselect();
|
||||||
var start;
|
var dates;
|
||||||
var end;
|
hoverListener.start(function(cell, origCell) {
|
||||||
var allDay;
|
clearSelection();
|
||||||
|
if (cell) {
|
||||||
|
dates = [ cellDate(origCell), cellDate(cell) ].sort(cmp);
|
||||||
t.dragStart = function(ev) {
|
renderSelection(dates[0], addDays(cloneDate(dates[1]), 1), true);
|
||||||
initFunc();
|
}
|
||||||
start = end = undefined;
|
}, ev);
|
||||||
initialRange = undefined;
|
$(document).one('mouseup', function(ev) {
|
||||||
initialElement = ev.currentTarget;
|
if (hoverListener.stop()) { // over a cell?
|
||||||
};
|
reportSelection(dates[0], dates[1], true);
|
||||||
|
}
|
||||||
|
});
|
||||||
t.drag = function(currentStart, currentEnd, currentAllDay) {
|
|
||||||
if (currentStart) {
|
|
||||||
var range = [currentStart, currentEnd];
|
|
||||||
if (!initialRange) {
|
|
||||||
initialRange = range;
|
|
||||||
}
|
|
||||||
var dates = initialRange.concat(range).sort(cmp);
|
|
||||||
start = dates[0];
|
|
||||||
end = dates[3];
|
|
||||||
allDay = currentAllDay;
|
|
||||||
clearFunc();
|
|
||||||
displayFunc(cloneDate(start), cloneDate(end), allDay);
|
|
||||||
}else{
|
|
||||||
// called with no arguments
|
|
||||||
start = end = undefined;
|
|
||||||
clearFunc();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
t.dragStop = function(ev) {
|
|
||||||
if (start) {
|
|
||||||
if (+initialRange[0] == +start && +initialRange[1] == +end) {
|
|
||||||
view.trigger('dayClick', initialElement, start, allDay, ev);
|
|
||||||
}
|
|
||||||
_select();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
t.select = function(newStart, newEnd, newAllDay) {
|
|
||||||
initFunc();
|
|
||||||
start = newStart;
|
|
||||||
end = newEnd;
|
|
||||||
allDay = newAllDay;
|
|
||||||
displayFunc(cloneDate(start), cloneDate(end), allDay);
|
|
||||||
_select();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function _select() { // just set the selected flag, and trigger
|
|
||||||
selected = true;
|
|
||||||
view.trigger('select', view, start, end, allDay);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function unselect() {
|
|
||||||
if (selected) {
|
|
||||||
selected = false;
|
|
||||||
start = end = undefined;
|
|
||||||
clearFunc();
|
|
||||||
view.trigger('unselect', view);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.unselect = unselect;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function documentDragHelp(mousemove, mouseup) {
|
function selection_unselectAuto(view, unselect) {
|
||||||
function _mouseup(ev) {
|
|
||||||
mouseup(ev);
|
|
||||||
$(document)
|
|
||||||
.unbind('mousemove', mousemove)
|
|
||||||
.unbind('mouseup', _mouseup);
|
|
||||||
}
|
|
||||||
$(document)
|
|
||||||
.mousemove(mousemove)
|
|
||||||
.mouseup(_mouseup);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function documentUnselectAuto(view, unselectFunc) {
|
|
||||||
if (view.option('selectable') && view.option('unselectAuto')) {
|
if (view.option('selectable') && view.option('unselectAuto')) {
|
||||||
$(document).mousedown(function(ev) {
|
$(document).mousedown(function(ev) {
|
||||||
var ignore = view.option('unselectCancel');
|
var ignore = view.option('unselectCancel');
|
||||||
|
@ -99,10 +31,7 @@ function documentUnselectAuto(view, unselectFunc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unselectFunc();
|
unselect();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
138
src/util.js
138
src/util.js
|
@ -378,72 +378,47 @@ function topCorrect(tr) { // tr/th/td or anything else
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Hover Matrix
|
/* Coordinate Grid
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
function HoverMatrix(rowElements, colElements, changeCallback) {
|
function CoordinateGrid(buildFunc) {
|
||||||
|
|
||||||
var t=this,
|
var t = this;
|
||||||
tops=[], lefts=[],
|
var rows;
|
||||||
origRow, origCol,
|
var cols;
|
||||||
currRow, currCol,
|
|
||||||
e;
|
|
||||||
|
|
||||||
$.each(rowElements, function(i, _e) {
|
|
||||||
e = $(_e);
|
|
||||||
tops.push(e.offset().top + topCorrect(e));
|
|
||||||
});
|
|
||||||
tops.push(tops[tops.length-1] + e.outerHeight());
|
|
||||||
$.each(colElements, function(i, _e) {
|
|
||||||
e = $(_e);
|
|
||||||
lefts.push(e.offset().left);
|
|
||||||
});
|
|
||||||
lefts.push(lefts[lefts.length-1] + e.outerWidth());
|
|
||||||
|
|
||||||
|
t.build = function() {
|
||||||
t.mouse = function(ev) {
|
rows = [];
|
||||||
var x = ev.pageX;
|
cols = [];
|
||||||
var y = ev.pageY;
|
buildFunc(rows, cols);
|
||||||
var r, c;
|
|
||||||
for (r=0; r<tops.length && y>=tops[r]; r++) {}
|
|
||||||
for (c=0; c<lefts.length && x>=lefts[c]; c++) {}
|
|
||||||
r = r >= tops.length ? -1 : r - 1;
|
|
||||||
c = c >= lefts.length ? -1 : c - 1;
|
|
||||||
if (r != currRow || c != currCol) {
|
|
||||||
currRow = r;
|
|
||||||
currCol = c;
|
|
||||||
if (r == -1 || c == -1) {
|
|
||||||
t.cell = null;
|
|
||||||
}else{
|
|
||||||
if (origRow === undefined) {
|
|
||||||
origRow = r;
|
|
||||||
origCol = c;
|
|
||||||
}
|
|
||||||
t.cell = {
|
|
||||||
row: r,
|
|
||||||
col: c,
|
|
||||||
top: tops[r],
|
|
||||||
left: lefts[c],
|
|
||||||
width: lefts[c+1] - lefts[c],
|
|
||||||
height: tops[r+1] - tops[r],
|
|
||||||
origRow: origRow,
|
|
||||||
origCol: origCol,
|
|
||||||
isOrig: r==origRow && c==origCol,
|
|
||||||
rowDelta: r-origRow,
|
|
||||||
colDelta: c-origCol
|
|
||||||
};
|
|
||||||
}
|
|
||||||
changeCallback(t.cell);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
t.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 are exclusive
|
t.cell = function(x, y) {
|
||||||
|
var rowCnt = rows.length;
|
||||||
|
var colCnt = cols.length;
|
||||||
|
var i, r=-1, c=-1;
|
||||||
|
for (i=0; i<rowCnt; i++) {
|
||||||
|
if (y >= rows[i][0] && y < rows[i][1]) {
|
||||||
|
r = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i=0; i<colCnt; i++) {
|
||||||
|
if (x >= cols[i][0] && x < cols[i][1]) {
|
||||||
|
c = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (r>=0 && c>=0) ? { row:r, col:c } : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
t.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 is inclusive
|
||||||
var origin = originElement.offset();
|
var origin = originElement.offset();
|
||||||
return {
|
return {
|
||||||
top: tops[row0] - origin.top,
|
top: rows[row0][0] - origin.top,
|
||||||
left: lefts[col0] - origin.left,
|
left: cols[col0][0] - origin.left,
|
||||||
width: lefts[col1] - lefts[col0],
|
width: cols[col1][1] - cols[col0][0],
|
||||||
height: tops[row1] - tops[row0]
|
height: rows[row1][1] - rows[row0][0]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -451,11 +426,54 @@ function HoverMatrix(rowElements, colElements, changeCallback) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Hover Listener
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
function HoverListener(coordinateGrid) {
|
||||||
|
|
||||||
|
var t = this;
|
||||||
|
var bindType;
|
||||||
|
var change;
|
||||||
|
var firstCell;
|
||||||
|
var cell;
|
||||||
|
|
||||||
|
t.start = function(_change, ev, _bindType) {
|
||||||
|
change = _change;
|
||||||
|
firstCell = cell = null;
|
||||||
|
coordinateGrid.build();
|
||||||
|
mouse(ev);
|
||||||
|
bindType = _bindType || 'mousemove';
|
||||||
|
$(document).bind(bindType, mouse);
|
||||||
|
};
|
||||||
|
|
||||||
|
function mouse(ev) {
|
||||||
|
var newCell = coordinateGrid.cell(ev.pageX, ev.pageY);
|
||||||
|
if (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) {
|
||||||
|
if (newCell) {
|
||||||
|
if (!firstCell) {
|
||||||
|
firstCell = newCell;
|
||||||
|
}
|
||||||
|
change(newCell, firstCell, newCell.row-firstCell.row, newCell.col-firstCell.col);
|
||||||
|
}else{
|
||||||
|
change(newCell, firstCell);
|
||||||
|
}
|
||||||
|
cell = newCell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.stop = function() {
|
||||||
|
$(document).unbind(bindType, mouse);
|
||||||
|
return cell;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Misc Utils
|
/* Misc Utils
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
var undefined,
|
var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
||||||
dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
|
||||||
|
|
||||||
function zeroPad(n) {
|
function zeroPad(n) {
|
||||||
return (n < 10 ? '0' : '') + n;
|
return (n < 10 ? '0' : '') + n;
|
||||||
|
|
132
tests/droppable.html
Normal file
132
tests/droppable.html
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||||
|
<script type='text/javascript' src='loader.js'></script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
var date = new Date();
|
||||||
|
var d = date.getDate();
|
||||||
|
var m = date.getMonth();
|
||||||
|
var y = date.getFullYear();
|
||||||
|
|
||||||
|
$('#calendar').fullCalendar({
|
||||||
|
|
||||||
|
droppable: true,
|
||||||
|
drop: function(date, allDay) {
|
||||||
|
console.log('drop', date, allDay);
|
||||||
|
},
|
||||||
|
|
||||||
|
//defaultView: 'agendaWeek',
|
||||||
|
//isRTL: true,
|
||||||
|
|
||||||
|
header: {
|
||||||
|
left: 'prev,next today',
|
||||||
|
center: 'title',
|
||||||
|
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
|
||||||
|
},
|
||||||
|
editable: true,
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
title: 'All Day Event',
|
||||||
|
start: new Date(y, m, 1)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Long Event',
|
||||||
|
start: new Date(y, m, d-5),
|
||||||
|
end: new Date(y, m, d-2)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 999,
|
||||||
|
title: 'Repeating Event',
|
||||||
|
start: new Date(y, m, d-3, 16, 0),
|
||||||
|
allDay: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 999,
|
||||||
|
title: 'Repeating Event',
|
||||||
|
start: new Date(y, m, d+4, 16, 0),
|
||||||
|
allDay: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Meeting',
|
||||||
|
start: new Date(y, m, d, 10, 30),
|
||||||
|
allDay: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Lunch',
|
||||||
|
start: new Date(y, m, d, 12, 5),
|
||||||
|
end: new Date(y, m, d, 14, 43),
|
||||||
|
allDay: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Birthday Party',
|
||||||
|
start: new Date(y, m, d+1, 19, 0),
|
||||||
|
end: new Date(y, m, d+1, 22, 30),
|
||||||
|
allDay: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Click for Google',
|
||||||
|
start: new Date(y, m, 28),
|
||||||
|
end: new Date(y, m, 29),
|
||||||
|
url: 'http://google.com/'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.external-event').draggable({
|
||||||
|
revert: true,
|
||||||
|
revertDuration: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style type='text/css'>
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin-top: 40px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calendar {
|
||||||
|
width: 900px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#external-events {
|
||||||
|
position: relative;
|
||||||
|
left: 50px;
|
||||||
|
text-align: left;
|
||||||
|
float: left;
|
||||||
|
width: 140px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
background: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.external-event {
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: #fff;
|
||||||
|
background: blue;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding-left: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='calendar'></div>
|
||||||
|
<div id='external-events'>
|
||||||
|
<div class='external-event'>Draggable 1</div>
|
||||||
|
<div class='external-event'>Draggable 2</div>
|
||||||
|
<div class='external-event'>Draggable 3</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -19,6 +19,7 @@
|
||||||
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
|
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
|
||||||
},
|
},
|
||||||
editable: true,
|
editable: true,
|
||||||
|
//isRTL: true,
|
||||||
events: [
|
events: [
|
||||||
{
|
{
|
||||||
title: 'All Day Event',
|
title: 'All Day Event',
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
1.4.6
|
1.4.7
|
||||||
|
|
Loading…
Reference in a new issue