refactoring/bugfixes to selectable code. new methods: select/unselect. new options: unselectAuto/unselectCancel
This commit is contained in:
parent
1b24a5f63b
commit
a469d8d3c4
18 changed files with 708 additions and 553 deletions
4
Makefile
4
Makefile
|
@ -9,6 +9,7 @@ JS_SRC_FILES = \
|
|||
${SRC_DIR}/grid.js \
|
||||
${SRC_DIR}/agenda.js \
|
||||
${SRC_DIR}/view.js \
|
||||
${SRC_DIR}/selection_util.js \
|
||||
${SRC_DIR}/util.js
|
||||
|
||||
CSS_SRC_FILES = \
|
||||
|
@ -37,9 +38,6 @@ zip:
|
|||
@cat ${SRC_DIR}/gcal.js \
|
||||
| ${VER_SED} | ${DATE_SED} \
|
||||
> ${BUILD_DIR}/fullcalendar/gcal.js
|
||||
@cat ${SRC_DIR}/selectable.js \
|
||||
| ${VER_SED} | ${DATE_SED} \
|
||||
> ${BUILD_DIR}/fullcalendar/selectable.js
|
||||
|
||||
@echo "compressing js..."
|
||||
@java -jar ${BUILD_DIR}/compiler.jar --js ${BUILD_DIR}/fullcalendar/fullcalendar.js \
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/gcal.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<script type='text/javascript' src='../src/selectable.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
<dist>
|
||||
|
@ -24,7 +24,6 @@
|
|||
<script type='text/javascript' src='../jquery/ui.draggable.js'></script>
|
||||
<script type='text/javascript' src='../jquery/ui.resizable.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar.min.js'></script>
|
||||
<script type='text/javascript' src='../selectable.js'></script>
|
||||
</dist>
|
||||
-->
|
||||
<script type='text/javascript'>
|
||||
|
@ -36,39 +35,30 @@
|
|||
var m = date.getMonth();
|
||||
var y = date.getFullYear();
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
var calendar = $('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay'
|
||||
},
|
||||
editable: true,
|
||||
|
||||
/********** new selecting options **********/
|
||||
|
||||
selectable: true, // activate selecting!
|
||||
unselectable: true, // automatically hide the selection when user clicks elsewhere? (defaults to true)
|
||||
selectHelper: true, // use a "fake" event for selecting? (only works in agenda views right now)
|
||||
select: function(start, end, allDay, view) {
|
||||
console.log(
|
||||
'---- selection ----\n' +
|
||||
'start: ' + start + '\n' +
|
||||
'end: ' + end + '\n' + // exclusive!!
|
||||
'allDay: ' + allDay
|
||||
selectable: true,
|
||||
selectHelper: true,
|
||||
select: function(start, end, allDay) {
|
||||
var title = prompt('Event Title:');
|
||||
if (title) {
|
||||
calendar.fullCalendar('renderEvent',
|
||||
{
|
||||
title: title,
|
||||
start: start,
|
||||
end: end,
|
||||
allDay: allDay
|
||||
},
|
||||
true
|
||||
);
|
||||
/*
|
||||
if (confirm("clear the selection?")) {
|
||||
$('#calendar').fullCalendar('unselect'); // 'unselect' method to manually clear selection
|
||||
// a 'select' method coming soon...
|
||||
}
|
||||
*/
|
||||
calendar.fullCalendar('unselect');
|
||||
},
|
||||
unselect: function() {
|
||||
console.log('unselected');
|
||||
},
|
||||
|
||||
/******************************************/
|
||||
|
||||
editable: true,
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
|
|
405
src/agenda.js
405
src/agenda.js
|
@ -88,6 +88,8 @@ function Agenda(element, options, methods) {
|
|||
return bg.find('td:eq(' + col + ') div div');
|
||||
}),
|
||||
slotTopCache = {},
|
||||
daySelectionManager,
|
||||
slotSelectionManager,
|
||||
// ...
|
||||
|
||||
view = $.extend(this, viewMethods, methods, {
|
||||
|
@ -184,7 +186,7 @@ function Agenda(element, options, methods) {
|
|||
}
|
||||
s+= "</table></div>";
|
||||
head = $(s).appendTo(element);
|
||||
bindDayHandlers(head.find('td'));
|
||||
dayBind(head.find('td'));
|
||||
|
||||
// all-day event container
|
||||
daySegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(head);
|
||||
|
@ -207,10 +209,10 @@ function Agenda(element, options, methods) {
|
|||
}
|
||||
s += "</table>";
|
||||
body = $("<div class='fc-agenda-body' style='position:relative;z-index:2;overflow:auto'/>")
|
||||
.append(view.bodyContent = bodyContent = $("<div style='position:relative;overflow:hidden'>")
|
||||
.append(bodyContent = $("<div style='position:relative;overflow:hidden'>")
|
||||
.append(bodyTable = $(s)))
|
||||
.appendTo(element);
|
||||
bindSlotHandlers(body.find('td')); // .click(slotClick);
|
||||
slotBind(body.find('td'));
|
||||
|
||||
// slot event container
|
||||
slotSegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(bodyContent);
|
||||
|
@ -348,22 +350,20 @@ function Agenda(element, options, methods) {
|
|||
-----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function bindDayHandlers(tds) {
|
||||
function dayBind(tds) {
|
||||
tds.click(slotClick);
|
||||
if ($.fullCalendar.bindBgHandlers) {
|
||||
$.fullCalendar.bindBgHandlers(view, tds, true);
|
||||
if (daySelectionManager) {
|
||||
tds.mousedown(daySelectionMousedown);
|
||||
}
|
||||
}
|
||||
view.bindDayHandlers = bindDayHandlers;
|
||||
|
||||
|
||||
function bindSlotHandlers(tds) {
|
||||
function slotBind(tds) {
|
||||
tds.click(slotClick);
|
||||
if ($.fullCalendar.bindBgHandlers) {
|
||||
$.fullCalendar.bindBgHandlers(view, tds, false);
|
||||
if (slotSelectionManager) {
|
||||
tds.mousedown(slotSelectionMousedown);
|
||||
}
|
||||
}
|
||||
view.bindSlotHandlers = bindSlotHandlers;
|
||||
|
||||
|
||||
function slotClick(ev) {
|
||||
|
@ -478,13 +478,13 @@ function Agenda(element, options, methods) {
|
|||
return head.find('tr.fc-all-day');
|
||||
},
|
||||
function(dayOfWeek) {
|
||||
return axisWidth + colContentPositions.left(day2col(dayOfWeek));
|
||||
return axisWidth + colContentPositions.left(dayOfWeekCol(dayOfWeek));
|
||||
},
|
||||
function(dayOfWeek) {
|
||||
return axisWidth + colContentPositions.right(day2col(dayOfWeek));
|
||||
return axisWidth + colContentPositions.right(dayOfWeekCol(dayOfWeek));
|
||||
},
|
||||
daySegmentContainer,
|
||||
bindDaySegHandlers,
|
||||
daySegBind,
|
||||
modifiedEventId
|
||||
);
|
||||
setHeight(viewHeight); // might have pushed the body down, so resize
|
||||
|
@ -554,7 +554,7 @@ function Agenda(element, options, methods) {
|
|||
seg.left = left;
|
||||
seg.outerWidth = outerWidth;
|
||||
seg.outerHeight = bottom - top;
|
||||
html += segHtml(event, seg, className);
|
||||
html += slotSegHtml(event, seg, className);
|
||||
}
|
||||
slotSegmentContainer[0].innerHTML = html; // faster than html()
|
||||
eventElements = slotSegmentContainer.children();
|
||||
|
@ -580,7 +580,7 @@ function Agenda(element, options, methods) {
|
|||
}
|
||||
seg.element = eventElement;
|
||||
if (event._id === modifiedEventId) {
|
||||
bindSlotSegHandlers(event, eventElement, seg);
|
||||
slotSegBind(event, eventElement, seg);
|
||||
}else{
|
||||
eventElement[0]._fci = i; // for lazySegBind
|
||||
}
|
||||
|
@ -588,7 +588,7 @@ function Agenda(element, options, methods) {
|
|||
}
|
||||
}
|
||||
|
||||
lazySegBind(slotSegmentContainer, segs, bindSlotSegHandlers);
|
||||
lazySegBind(slotSegmentContainer, segs, slotSegBind);
|
||||
|
||||
// record event sides and title positions
|
||||
for (i=0; i<segCnt; i++) {
|
||||
|
@ -625,8 +625,7 @@ function Agenda(element, options, methods) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
function segHtml(event, seg, className) {
|
||||
function slotSegHtml(event, seg, className) {
|
||||
return "<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;top:" + seg.top + "px;left:" + seg.left + "px'>" +
|
||||
"<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
||||
"<span class='fc-event-bg'></span>" +
|
||||
|
@ -638,33 +637,10 @@ function Agenda(element, options, methods) {
|
|||
: '') +
|
||||
"</div>";
|
||||
}
|
||||
view.segHtml = segHtml;
|
||||
|
||||
|
||||
function visEventEnd(event) { // returns exclusive 'visible' end, for rendering
|
||||
if (event.allDay) {
|
||||
return visEventEndAllDay(event);
|
||||
}
|
||||
if (event.end) {
|
||||
return cloneDate(event.end);
|
||||
}else{
|
||||
return addMinutes(cloneDate(event.start), options.defaultEventMinutes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function visEventEndAllDay(event) {
|
||||
if (event.end) {
|
||||
var end = cloneDate(event.end);
|
||||
return (event.allDay || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end;
|
||||
}else{
|
||||
return addDays(cloneDate(event.start), 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function bindDaySegHandlers(event, eventElement, seg) {
|
||||
function daySegBind(event, eventElement, seg) {
|
||||
view.eventElementHandlers(event, eventElement);
|
||||
if (event.editable || event.editable === undefined && options.editable) {
|
||||
draggableDayEvent(event, eventElement, seg.isStart);
|
||||
|
@ -676,7 +652,7 @@ function Agenda(element, options, methods) {
|
|||
|
||||
|
||||
|
||||
function bindSlotSegHandlers(event, eventElement, seg) {
|
||||
function slotSegBind(event, eventElement, seg) {
|
||||
view.eventElementHandlers(event, eventElement);
|
||||
if (event.editable || event.editable === undefined && options.editable) {
|
||||
var timeElement = eventElement.find('span.fc-event-time');
|
||||
|
@ -721,7 +697,7 @@ function Agenda(element, options, methods) {
|
|||
allDay = true;
|
||||
}
|
||||
};
|
||||
matrix = buildMainMatrix(function(cell) {
|
||||
matrix = buildDayMatrix(function(cell) {
|
||||
eventElement.draggable('option', 'revert', !cell || !cell.rowDelta && !cell.colDelta);
|
||||
view.clearOverlays();
|
||||
if (cell) {
|
||||
|
@ -729,8 +705,8 @@ function Agenda(element, options, methods) {
|
|||
// on full-days
|
||||
renderDayOverlay(
|
||||
matrix,
|
||||
cellOffset(addDays(cloneDate(event.start), cell.colDelta)),
|
||||
cellOffset(addDays(visEventEnd(event), cell.colDelta)) // visEventEnd returns a clone
|
||||
dayDateCol(addDays(cloneDate(event.start), cell.colDelta)),
|
||||
dayDateCol(addDays(visEventEnd(event), cell.colDelta)) // visEventEnd returns a clone
|
||||
);
|
||||
resetElement();
|
||||
}else{
|
||||
|
@ -748,11 +724,11 @@ function Agenda(element, options, methods) {
|
|||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
},true);
|
||||
matrix.mouse(ev);
|
||||
},
|
||||
drag: function(ev, ui) {
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
matrix.mouse(ev);
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
||||
|
@ -821,7 +797,7 @@ function Agenda(element, options, methods) {
|
|||
}
|
||||
};
|
||||
prevSlotDelta = 0;
|
||||
matrix = buildMainMatrix(function(cell) {
|
||||
matrix = buildDayMatrix(function(cell) {
|
||||
eventElement.draggable('option', 'revert', !cell);
|
||||
view.clearOverlays();
|
||||
if (cell) {
|
||||
|
@ -834,15 +810,16 @@ function Agenda(element, options, methods) {
|
|||
}
|
||||
renderDayOverlay(
|
||||
matrix,
|
||||
cellOffset(addDays(cloneDate(event.start), cell.colDelta)),
|
||||
cellOffset(addDays(visEventEndAllDay(event), cell.colDelta)) // visEventEnd returns a clone
|
||||
dayDateCol(addDays(cloneDate(event.start), cell.colDelta)),
|
||||
dayDateCol(addDays(visEventEndAllDay(event), cell.colDelta)) // visEventEndAllDay returns a clone
|
||||
// TODO: test this stuff further!!!
|
||||
);
|
||||
}else{ // on slots
|
||||
resetElement();
|
||||
}
|
||||
}
|
||||
});
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
},true);
|
||||
matrix.mouse(ev);
|
||||
},
|
||||
drag: function(ev, ui) {
|
||||
slotDelta = Math.round((ui.position.top - origPosition.top) / slotHeight);
|
||||
|
@ -859,7 +836,7 @@ function Agenda(element, options, methods) {
|
|||
}
|
||||
prevSlotDelta = slotDelta;
|
||||
}
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
matrix.mouse(ev);
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
view.clearOverlays();
|
||||
|
@ -948,11 +925,209 @@ function Agenda(element, options, methods) {
|
|||
|
||||
|
||||
|
||||
/* Misc
|
||||
/* Selecting
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
if (view.option('selectable')) {
|
||||
|
||||
var selectionHelper;
|
||||
var selectionMatrix;
|
||||
|
||||
if (options.allDaySlot) {
|
||||
|
||||
// all-day selecting
|
||||
|
||||
daySelectionManager = new SelectionManager(
|
||||
view,
|
||||
function(startDate, endDate) {
|
||||
renderDayOverlay(
|
||||
selectionMatrix,
|
||||
dayDateCol(startDate),
|
||||
dayDateCol(addDays(endDate, 1))
|
||||
);
|
||||
},
|
||||
clearSelection
|
||||
);
|
||||
|
||||
function daySelectionMousedown(ev) {
|
||||
selectionMatrix = buildDayMatrix(function(cell) {
|
||||
if (cell) {
|
||||
var d = dayColDate(cell.col);
|
||||
daySelectionManager.drag(d, d, true);
|
||||
}else{
|
||||
daySelectionManager.drag();
|
||||
}
|
||||
});
|
||||
documentDragHelp(
|
||||
function(ev) {
|
||||
selectionMatrix.mouse(ev);
|
||||
},
|
||||
function(ev) {
|
||||
daySelectionManager.dragStop(ev);
|
||||
}
|
||||
);
|
||||
daySelectionManager.dragStart(ev);
|
||||
selectionMatrix.mouse(ev);
|
||||
ev.stopPropagation(); // prevent auto-unselect
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// slot selecting
|
||||
|
||||
slotSelectionManager = new SelectionManager(
|
||||
view,
|
||||
renderSlotSelection,
|
||||
clearSelection
|
||||
);
|
||||
|
||||
function slotSelectionMousedown(ev) {
|
||||
selectionMatrix = buildSlotMatrix(function(cell) {
|
||||
if (cell) {
|
||||
var d = slotCellDate(cell.row, cell.origCol);
|
||||
slotSelectionManager.drag(d, addMinutes(cloneDate(d), options.slotMinutes), false);
|
||||
}else{
|
||||
slotSelectionManager.drag();
|
||||
}
|
||||
});
|
||||
documentDragHelp(
|
||||
function(ev) {
|
||||
selectionMatrix.mouse(ev);
|
||||
},
|
||||
function(ev) {
|
||||
slotSelectionManager.dragStop(ev);
|
||||
}
|
||||
);
|
||||
slotSelectionManager.dragStart(ev);
|
||||
selectionMatrix.mouse(ev);
|
||||
ev.stopPropagation(); // prevent auto-unselect
|
||||
}
|
||||
|
||||
documentAutoUnselect(view, unselect);
|
||||
|
||||
}
|
||||
|
||||
function renderSlotSelection(startDate, endDate) {
|
||||
// startDate and endDate are assumed to be in same day
|
||||
var helperOption = view.option('selectHelper');
|
||||
if (helperOption) {
|
||||
var startCell = slotDateCell(startDate);
|
||||
var endCell = slotDateCell(endDate);
|
||||
var rect = selectionMatrix.rect(startCell[0], startCell[1], endCell[0], startCell[1]+1, bodyContent);
|
||||
rect.left += 2;
|
||||
rect.width -= 5;
|
||||
if ($.isFunction(helperOption)) {
|
||||
selectionHelper = helperOption(startDate, endDate);
|
||||
if (selectionHelper) {
|
||||
selectionHelper.css(rect);
|
||||
}
|
||||
}else{
|
||||
selectionHelper = $(slotSegHtml(
|
||||
{
|
||||
title: '',
|
||||
start: startDate,
|
||||
end: endDate,
|
||||
className: [],
|
||||
editable: false
|
||||
},
|
||||
rect,
|
||||
'fc-event fc-event-vert fc-corner-top fc-corner-bottom '
|
||||
));
|
||||
if (!$.browser.msie) {
|
||||
// IE makes the event completely clear!!?
|
||||
selectionHelper.css('opacity', view.option('dragOpacity'));
|
||||
}
|
||||
}
|
||||
if (selectionHelper) {
|
||||
slotBind(selectionHelper);
|
||||
bodyContent.append(selectionHelper);
|
||||
setOuterWidth(selectionHelper, rect.width, true);
|
||||
setOuterHeight(selectionHelper, rect.height, true);
|
||||
}
|
||||
}else{
|
||||
renderSlotOverlay(
|
||||
selectionMatrix,
|
||||
slotDateCell(startDate),
|
||||
slotDateCell(endDate)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelection() {
|
||||
clearOverlays();
|
||||
if (selectionHelper) {
|
||||
selectionHelper.remove();
|
||||
selectionHelper = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.select = function(start, end, allDay) {
|
||||
if (allDay) {
|
||||
if (daySelectionManager) {
|
||||
selectionMatrix = buildDayMatrix();
|
||||
daySelectionManager.select(start, end, allDay);
|
||||
}
|
||||
}else{
|
||||
if (slotSelectionManager) {
|
||||
selectionMatrix = buildSlotMatrix();
|
||||
slotSelectionManager.select(start, end, allDay);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function unselect() {
|
||||
if (slotSelectionManager) {
|
||||
slotSelectionManager.unselect();
|
||||
if (daySelectionManager) {
|
||||
daySelectionManager.unselect();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.unselect = unselect;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Semi-transparent Overlay Helpers
|
||||
-----------------------------------------------------*/
|
||||
|
||||
function renderDayOverlay(matrix, startCol, endCol) {
|
||||
renderDayOverlayRect(
|
||||
matrix.rect(0, startCol, 1, endCol, head)
|
||||
);
|
||||
}
|
||||
|
||||
function renderDayOverlayRect(rect) {
|
||||
dayBind(
|
||||
view.renderOverlay(rect, head)
|
||||
);
|
||||
}
|
||||
|
||||
function renderSlotOverlay(matrix, startCell, endCell) {
|
||||
renderSlotOverlayRect(
|
||||
matrix.rect(startCell[0], startCell[1], endCell[0], startCell[1]+1, bodyContent)
|
||||
);
|
||||
// TODO: implement wrapping
|
||||
}
|
||||
|
||||
function renderSlotOverlayRect(rect) {
|
||||
slotBind(
|
||||
view.renderOverlay(rect, bodyContent)
|
||||
);
|
||||
}
|
||||
|
||||
function clearOverlays() {
|
||||
view.clearOverlays();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Coordinate Utilities
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
// 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)) {
|
||||
|
@ -973,41 +1148,7 @@ function Agenda(element, options, methods) {
|
|||
));
|
||||
}
|
||||
|
||||
|
||||
function day2col(dayOfWeek) {
|
||||
return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit;
|
||||
}
|
||||
|
||||
|
||||
function cellOffset(date) { // the "offset" index in the matrix
|
||||
var d = rtl ? addDays(cloneDate(view.visEnd), -1) : cloneDate(view.visStart);
|
||||
for (var i=0; i<colCnt; i++) {
|
||||
addDays(d, dis);
|
||||
if (nwe) {
|
||||
skipWeekend(d, dis);
|
||||
}
|
||||
if (d > date) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
function slotTime(dayIndex, slotIndex) { // TODO: immune to DST???
|
||||
var d = clearTime(addDays(cloneDate(view.visStart), dayIndex));
|
||||
addMinutes(d, minMinute);
|
||||
for (var i=0; i < slotIndex; i++) { // need a loop here !!!!!!!!!!!??????????
|
||||
addMinutes(d, options.slotMinutes);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
view.slotTime = slotTime;
|
||||
|
||||
|
||||
// matrix building
|
||||
|
||||
function buildMainMatrix(changeCallback) {
|
||||
function buildDayMatrix(changeCallback, includeSlotArea) {
|
||||
var matrix = new HoverMatrix(changeCallback);
|
||||
if (options.allDaySlot) {
|
||||
matrix.row(head.find('td'));
|
||||
|
@ -1015,10 +1156,11 @@ function Agenda(element, options, methods) {
|
|||
bg.find('td').each(function() {
|
||||
matrix.col(this);
|
||||
});
|
||||
if (includeSlotArea) {
|
||||
matrix.row(body);
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
view.buildMainMatrix = buildMainMatrix;
|
||||
|
||||
function buildSlotMatrix(changeCallback) {
|
||||
var matrix = new HoverMatrix(changeCallback);
|
||||
|
@ -1030,18 +1172,77 @@ function Agenda(element, options, methods) {
|
|||
});
|
||||
return matrix;
|
||||
}
|
||||
view.buildSlotMatrix = buildSlotMatrix;
|
||||
|
||||
|
||||
// overlay for dropping and selecting
|
||||
|
||||
function renderDayOverlay(matrix, startCol, endCol) {
|
||||
view.renderOverlay(
|
||||
matrix.rect(0, startCol, 1, endCol, head),
|
||||
head
|
||||
);
|
||||
|
||||
/* Date Utilities
|
||||
----------------------------------------------------*/
|
||||
|
||||
|
||||
// generating event end dates
|
||||
|
||||
function visEventEnd(event) { // returns exclusive 'visible' end, for rendering
|
||||
if (event.allDay) {
|
||||
return visEventEndAllDay(event);
|
||||
}
|
||||
view.renderDayOverlay = renderDayOverlay;
|
||||
if (event.end) {
|
||||
return cloneDate(event.end);
|
||||
}else{
|
||||
return addMinutes(cloneDate(event.start), options.defaultEventMinutes);
|
||||
}
|
||||
}
|
||||
|
||||
function visEventEndAllDay(event) {
|
||||
if (event.end) {
|
||||
var end = cloneDate(event.end);
|
||||
return (event.allDay || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end;
|
||||
}else{
|
||||
return addDays(cloneDate(event.start), 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// generating indexes from dates
|
||||
|
||||
function dayDateCol(date) {
|
||||
var d = cloneDate(view.visStart);
|
||||
var c;
|
||||
for (c=0; c<colCnt; c++) {
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
if (d > date) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return c*dis+dit;
|
||||
}
|
||||
|
||||
function slotDateCell(date) {
|
||||
var col = dayDateCol(date);
|
||||
var row = Math.floor((date.getHours() * 60 + date.getMinutes()) / options.slotMinutes);
|
||||
return [row, col];
|
||||
}
|
||||
|
||||
function dayOfWeekCol(dayOfWeek) {
|
||||
return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit;
|
||||
}
|
||||
|
||||
|
||||
// generating dates from cell row & columns
|
||||
|
||||
function dayColDate(col) {
|
||||
return addDays(cloneDate(view.visStart), col*dis+dit);
|
||||
}
|
||||
|
||||
function slotCellDate(row, col) {
|
||||
var d = dayColDate(col);
|
||||
addMinutes(d, minMinute + row*options.slotMinutes);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
207
src/grid.js
207
src/grid.js
|
@ -121,6 +121,7 @@ function Grid(element, options, methods) {
|
|||
dayContentPositions = new HorizontalPositionCache(function(dayOfWeek) {
|
||||
return tbody.find('td:eq(' + ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt) + ') div div');
|
||||
}),
|
||||
selectionManager,
|
||||
// ...
|
||||
|
||||
// initialize superclass
|
||||
|
@ -155,7 +156,7 @@ function Grid(element, options, methods) {
|
|||
}
|
||||
|
||||
rowCnt = r;
|
||||
colCnt = view.colCnt = c;
|
||||
colCnt = c;
|
||||
|
||||
// update option-derived variables
|
||||
tm = options.theme ? 'ui' : 'fc';
|
||||
|
@ -214,7 +215,7 @@ function Grid(element, options, methods) {
|
|||
s += "</tr>";
|
||||
}
|
||||
tbody = $(s + "</tbody>").appendTo(table);
|
||||
bindDayHandlers(tbody.find('td'));
|
||||
dayBind(tbody.find('td'));
|
||||
|
||||
segmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(element);
|
||||
|
||||
|
@ -247,7 +248,7 @@ function Grid(element, options, methods) {
|
|||
}
|
||||
tbody.append(s);
|
||||
}
|
||||
bindDayHandlers(tbody.find('td.fc-new').removeClass('fc-new'));
|
||||
dayBind(tbody.find('td.fc-new').removeClass('fc-new'));
|
||||
|
||||
// re-label and re-class existing cells
|
||||
d = cloneDate(view.visStart);
|
||||
|
@ -452,27 +453,27 @@ function Grid(element, options, methods) {
|
|||
start: function(ev, ui) {
|
||||
view.hideEvents(event, eventElement);
|
||||
view.trigger('eventDragStart', eventElement, event, ev, ui);
|
||||
matrix = buildMatrix(function(cell) {
|
||||
matrix = buildDayMatrix(function(cell) {
|
||||
eventElement.draggable('option', 'revert', !cell || !cell.rowDelta && !cell.colDelta);
|
||||
view.clearOverlays();
|
||||
clearOverlays();
|
||||
if (cell) {
|
||||
dayDelta = cell.rowDelta*7 + cell.colDelta*dis;
|
||||
renderOverlays(
|
||||
renderDayOverlays(
|
||||
matrix,
|
||||
cellOffset(addDays(cloneDate(event.start), dayDelta)),
|
||||
cellOffset(addDays(visEventEnd(event), dayDelta)) // visEventEnd returns a clone
|
||||
dateCell(addDays(cloneDate(event.start), dayDelta)),
|
||||
dateCell(addDays(visEventEnd(event), dayDelta))
|
||||
);
|
||||
}else{
|
||||
dayDelta = 0;
|
||||
}
|
||||
});
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
matrix.mouse(ev);
|
||||
},
|
||||
drag: function(ev) {
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
matrix.mouse(ev);
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
view.clearOverlays();
|
||||
clearOverlays();
|
||||
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
||||
if (dayDelta) {
|
||||
eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
|
||||
|
@ -490,18 +491,15 @@ function Grid(element, options, methods) {
|
|||
|
||||
|
||||
|
||||
/* Day clicking and day event binding
|
||||
/* Day clicking and binding
|
||||
---------------------------------------------------------*/
|
||||
|
||||
|
||||
function bindDayHandlers(days) {
|
||||
function dayBind(days) {
|
||||
days.click(dayClick);
|
||||
if ($.fullCalendar.bindBgHandlers) {
|
||||
$.fullCalendar.bindBgHandlers(view, days, true);
|
||||
if (selectionManager) {
|
||||
days.mousedown(selectionMousedown);
|
||||
}
|
||||
}
|
||||
view.bindDayHandlers = bindDayHandlers;
|
||||
|
||||
|
||||
function dayClick(ev) {
|
||||
var n = parseInt(this.className.match(/fc\-day(\d+)/)[1]),
|
||||
|
@ -509,62 +507,106 @@ function Grid(element, options, methods) {
|
|||
cloneDate(view.visStart),
|
||||
Math.floor(n/colCnt) * 7 + n % colCnt
|
||||
);
|
||||
// TODO: what about weekends in middle of week?
|
||||
view.trigger('dayClick', this, date, true, ev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Selecting
|
||||
--------------------------------------------------------*/
|
||||
|
||||
/* Utilities
|
||||
if (view.option('selectable')) {
|
||||
|
||||
var selectionMatrix;
|
||||
|
||||
selectionManager = new SelectionManager(
|
||||
view,
|
||||
function(startDate, endDate) {
|
||||
renderDayOverlays(selectionMatrix, dateCell(startDate), dateCell(addDays(endDate, 1)));
|
||||
},
|
||||
clearOverlays
|
||||
);
|
||||
|
||||
function selectionMousedown(ev) {
|
||||
selectionMatrix = buildDayMatrix(function(cell) {
|
||||
if (cell) {
|
||||
var d = cellDate(cell.row, cell.col);
|
||||
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);
|
||||
ev.stopPropagation(); // prevent auto-unselect
|
||||
}
|
||||
|
||||
documentAutoUnselect(view, unselect);
|
||||
|
||||
}
|
||||
|
||||
view.select = function(start, end) {
|
||||
if (selectionManager) {
|
||||
selectionMatrix = buildDayMatrix();
|
||||
selectionManager.select(start, end, true);
|
||||
}
|
||||
};
|
||||
|
||||
function unselect() {
|
||||
if (selectionManager) {
|
||||
selectionManager.unselect();
|
||||
}
|
||||
}
|
||||
view.unselect = unselect;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Semi-transparent Overlay Helpers
|
||||
------------------------------------------------------*/
|
||||
|
||||
function renderDayOverlays(matrix, startCell, endCell) { // for rendering overlays across weeks
|
||||
var r0 = startCell[0];
|
||||
var c0 = startCell[1];
|
||||
var r1 = endCell[0];
|
||||
var c1 = endCell[1];
|
||||
var localC0, localC1;
|
||||
for (var r=r0; r<=r1; r++) {
|
||||
if (rtl) {
|
||||
localC0 = r==r1 ? c1+1 : 0;
|
||||
localC1 = r==r0 ? c0+1 : colCnt;
|
||||
}else{
|
||||
localC0 = r==r0 ? c0 : 0;
|
||||
localC1 = r==r1 ? c1 : colCnt;
|
||||
}
|
||||
if (localC0 < localC1) {
|
||||
var rect = matrix.rect(r, localC0, r+1, localC1, element);
|
||||
dayBind(
|
||||
view.renderOverlay(rect, element)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearOverlays() {
|
||||
view.clearOverlays();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Matrix Construction
|
||||
---------------------------------------------------*/
|
||||
|
||||
|
||||
function cellOffset(date) { // always returns index in range
|
||||
var d = cloneDate(view.visStart),
|
||||
i, j, k=0;
|
||||
for (i=0; i<rowCnt; i++) {
|
||||
for (j=0; j<colCnt; j++) {
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
if (d > date) {
|
||||
return k;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
function offset2date(cellOffset) {
|
||||
return addDays(cloneDate(view.visStart), cellOffset);
|
||||
}
|
||||
view.offset2date = offset2date;
|
||||
|
||||
|
||||
function renderOverlays(matrix, offset, endOffset) {
|
||||
var len = endOffset - offset,
|
||||
localLen,
|
||||
r = Math.floor(offset / colCnt),
|
||||
c = offset % colCnt,
|
||||
origin = element.offset();
|
||||
while (len > 0) {
|
||||
localLen = Math.min(len, colCnt - c);
|
||||
view.renderOverlay(
|
||||
matrix.rect(r, c, r+1, c+localLen, element),
|
||||
element
|
||||
);
|
||||
len -= localLen;
|
||||
r += 1;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
view.renderOverlays = renderOverlays;
|
||||
|
||||
|
||||
function buildMatrix(changeCallback) {
|
||||
function buildDayMatrix(changeCallback) {
|
||||
var matrix = new HoverMatrix(changeCallback);
|
||||
tbody.find('tr').each(function() {
|
||||
matrix.row(this);
|
||||
|
@ -578,7 +620,38 @@ function Grid(element, options, methods) {
|
|||
});
|
||||
return matrix;
|
||||
}
|
||||
view.buildMatrix = buildMatrix;
|
||||
|
||||
|
||||
|
||||
/* Date Utilities
|
||||
------------------------------------------------------*/
|
||||
|
||||
function dateCell(date) { // convert date to [row, col]
|
||||
var d = cloneDate(view.visStart);
|
||||
var r, c;
|
||||
var found = false;
|
||||
for (r=0; r<rowCnt; r++) {
|
||||
for (c=0; c<colCnt; c++) {
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
if (d > date) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [r, c*dis+dit];
|
||||
}
|
||||
|
||||
function cellDate(r, c) { // convert r,c to date
|
||||
return addDays(cloneDate(view.visStart), r*7 + c*dis+dit);
|
||||
// TODO: what about weekends in middle of week?
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
30
src/main.js
30
src/main.js
|
@ -71,7 +71,7 @@ var defaults = {
|
|||
},
|
||||
|
||||
//selectable: false,
|
||||
unselectable: true
|
||||
unselectAuto: true
|
||||
|
||||
};
|
||||
|
||||
|
@ -114,9 +114,6 @@ $.fn.fullCalendar = function(options) {
|
|||
var data = $.data(this, 'fullCalendar');
|
||||
if (data) {
|
||||
var meth = data[options];
|
||||
if (!meth) {
|
||||
meth = $.fullCalendar.publicMethods[options];
|
||||
}
|
||||
if (meth) {
|
||||
var r = meth.apply(this, args);
|
||||
if (res === undefined) {
|
||||
|
@ -202,7 +199,7 @@ $.fn.fullCalendar = function(options) {
|
|||
if (v != viewName) {
|
||||
ignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached
|
||||
|
||||
viewUpdate();
|
||||
viewUnselect();
|
||||
|
||||
var oldView = view,
|
||||
newViewElement;
|
||||
|
@ -225,7 +222,7 @@ $.fn.fullCalendar = function(options) {
|
|||
if (viewInstances[v]) {
|
||||
(view = viewInstances[v]).element.show();
|
||||
}else{
|
||||
view = viewInstances[v] = $.fullCalendar.views[v](
|
||||
view = viewInstances[v] = fc.views[v](
|
||||
newViewElement = absoluteViewElement =
|
||||
$("<div class='fc-view fc-view-" + v + "' style='position:absolute'/>")
|
||||
.appendTo(content),
|
||||
|
@ -258,7 +255,7 @@ $.fn.fullCalendar = function(options) {
|
|||
if (elementVisible()) {
|
||||
ignoreWindowResize++; // because view.renderEvents might temporarily change the height before setSize is reached
|
||||
|
||||
viewUpdate();
|
||||
viewUnselect();
|
||||
|
||||
if (suggestedViewHeight === undefined) {
|
||||
calcSize();
|
||||
|
@ -314,10 +311,9 @@ $.fn.fullCalendar = function(options) {
|
|||
return $('body')[0].offsetWidth !== 0;
|
||||
}
|
||||
|
||||
function viewUpdate() {
|
||||
// this function is ONLY for the ghetto plugin archicture
|
||||
if (view && view.viewUpdate) {
|
||||
view.viewUpdate();
|
||||
function viewUnselect() {
|
||||
if (view) {
|
||||
view.unselect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -667,6 +663,18 @@ $.fn.fullCalendar = function(options) {
|
|||
|
||||
refetchEvents: function() {
|
||||
fetchEvents(eventsChanged);
|
||||
},
|
||||
|
||||
//
|
||||
// selection
|
||||
//
|
||||
|
||||
select: function(start, end, allDay) {
|
||||
view.select(start, end, allDay);
|
||||
},
|
||||
|
||||
unselect: function() {
|
||||
view.unselect();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,328 +0,0 @@
|
|||
(function($, undefined) {
|
||||
|
||||
|
||||
|
||||
var fc = $.fullCalendar,
|
||||
setOuterWidth = fc.setOuterWidth,
|
||||
setOuterHeight = fc.setOuterHeight,
|
||||
addDays = fc.addDays,
|
||||
cloneDate = fc.cloneDate,
|
||||
cmp = fc.cmp;
|
||||
|
||||
|
||||
|
||||
var selectionManagers = {};
|
||||
|
||||
$.fullCalendar.bindBgHandlers = function(view, elements, allDay) {
|
||||
if (view.option('selectable')) {
|
||||
getSelectionManager(view).bind(elements, allDay);
|
||||
}
|
||||
};
|
||||
|
||||
function getSelectionManager(view) {
|
||||
var name = view.name,
|
||||
manager = selectionManagers[name];
|
||||
if (!manager) {
|
||||
if (name.indexOf('agenda') == 0) {
|
||||
manager = new AgendaSelectionManager(view);
|
||||
}else{
|
||||
manager = new GridSelectionManager(view);
|
||||
}
|
||||
selectionManagers[name] = manager;
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* methods
|
||||
---------------------------------------------------*/
|
||||
|
||||
$.extend($.fullCalendar.publicMethods, {
|
||||
|
||||
select: function(start, end, allDay) {
|
||||
getSelectionManager($(this).fullCalendar('getView')).select(start, end, allDay);
|
||||
// not yet implemented...
|
||||
},
|
||||
|
||||
unselect: function() {
|
||||
for (var name in selectionManagers) {
|
||||
selectionManagers[name].unselect();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
/* month, basicWeek, basicDay
|
||||
---------------------------------------------------*/
|
||||
|
||||
function GridSelectionManager(view) {
|
||||
|
||||
var selected=false,
|
||||
matrix,
|
||||
start, // the "offset" (row*colCnt+col) of the cell
|
||||
end, // the "offset" (row*colCnt+col) of the cell (inclusive)
|
||||
range; // sorted array
|
||||
|
||||
this.bind = function(elements) {
|
||||
elements.mousedown(mousedown);
|
||||
};
|
||||
|
||||
function mousedown(ev) {
|
||||
start = undefined;
|
||||
matrix = view.buildMatrix(function(cell) {
|
||||
view.clearOverlays();
|
||||
if (cell) {
|
||||
end = cell.row * view.colCnt + cell.col;
|
||||
if (start === undefined) {
|
||||
unselect();
|
||||
start = end;
|
||||
}
|
||||
range = [start, end].sort(cmp);
|
||||
view.renderOverlays(matrix, range[0], range[1]+1);
|
||||
$.each(view.overlays, function() {
|
||||
view.bindDayHandlers(this);
|
||||
});
|
||||
selected = true;
|
||||
}else{
|
||||
selected = false;
|
||||
}
|
||||
});
|
||||
$(document)
|
||||
.mousemove(mousemove)
|
||||
.mouseup(mouseup);
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
function mousemove(ev) {
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
}
|
||||
|
||||
function mouseup(ev) {
|
||||
$(document)
|
||||
.unbind('mousemove', mousemove)
|
||||
.unbind('mouseup', mouseup);
|
||||
if (selected) {
|
||||
view.trigger(
|
||||
'select',
|
||||
view,
|
||||
view.offset2date(range[0]),
|
||||
view.offset2date(range[1]+1),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function unselect() {
|
||||
if (selected) {
|
||||
view.clearOverlays();
|
||||
view.trigger('unselect', view);
|
||||
selected = false;
|
||||
}
|
||||
}
|
||||
this.unselect = unselect;
|
||||
view.viewUpdate = unselect;
|
||||
|
||||
if (view.option('unselectable')) {
|
||||
$(document).mousedown(function() {
|
||||
unselect();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* agenda views
|
||||
-----------------------------------------------*/
|
||||
|
||||
function AgendaSelectionManager(view) {
|
||||
|
||||
var selected=false,
|
||||
matrix,
|
||||
start, // for all-day, the COLUMN of the day. for slot, the ROW of the slot
|
||||
end, // for all-day, the COLUMN of the day. for slot, the ROW of the slot
|
||||
day, // only used for slots. the COLUMN of the day
|
||||
range, // start & end, sorted array
|
||||
helper;
|
||||
|
||||
this.bind = function(elements, allDay) {
|
||||
if (allDay) {
|
||||
dayBind(elements);
|
||||
}else{
|
||||
slotBind(elements);
|
||||
}
|
||||
};
|
||||
|
||||
// all-day
|
||||
|
||||
function dayBind(elements) {
|
||||
elements.mousedown(dayMousedown);
|
||||
}
|
||||
|
||||
function dayMousedown(ev) {
|
||||
start = undefined;
|
||||
matrix = view.buildMainMatrix(function(cell) {
|
||||
clear();
|
||||
if (cell) {
|
||||
end = cell.col;
|
||||
if (start === undefined) {
|
||||
unselect();
|
||||
start = end;
|
||||
}
|
||||
range = [start, end].sort(cmp);
|
||||
view.renderDayOverlay(matrix, range[0], range[1]+1);
|
||||
view.bindDayHandlers(view.overlays[0]);
|
||||
selected = true;
|
||||
}else{
|
||||
selected = false;
|
||||
}
|
||||
});
|
||||
$(document)
|
||||
.mousemove(dayMousemove)
|
||||
.mouseup(dayMouseup);
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
function dayMousemove(ev) {
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
}
|
||||
|
||||
function dayMouseup(ev) {
|
||||
$(document)
|
||||
.unbind('mousemove', dayMousemove)
|
||||
.unbind('mouseup', dayMouseup);
|
||||
if (selected) {
|
||||
view.trigger(
|
||||
'select',
|
||||
view,
|
||||
addDays(cloneDate(view.visStart), range[0]),
|
||||
addDays(cloneDate(view.visStart), range[1]+1),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// slot
|
||||
|
||||
function slotBind(elements) {
|
||||
elements.mousedown(slotMousedown);
|
||||
}
|
||||
|
||||
function slotMousedown(ev) {
|
||||
day = undefined;
|
||||
matrix = view.buildSlotMatrix(function(cell) {
|
||||
clear();
|
||||
if (cell) {
|
||||
if (day === undefined) {
|
||||
unselect();
|
||||
day = cell.col;
|
||||
start = cell.row;
|
||||
}
|
||||
end = cell.row;
|
||||
range = [start, end].sort(cmp);
|
||||
var helperOption = view.option('selectHelper'),
|
||||
bodyContent = view.bodyContent;
|
||||
if (helperOption) {
|
||||
var rect = matrix.rect(range[0], day, range[1]+1, day+1, bodyContent);
|
||||
rect.left += 2;
|
||||
rect.width -= 5;
|
||||
if ($.isFunction(helperOption)) {
|
||||
helper = helperOption();
|
||||
if (helper) {
|
||||
helper.css(rect);
|
||||
}
|
||||
}else{
|
||||
helper = $(view.segHtml(
|
||||
{
|
||||
title: '',
|
||||
start: view.slotTime(day, range[0]),
|
||||
end: view.slotTime(day, range[1]+1),
|
||||
className: [],
|
||||
editable: false
|
||||
},
|
||||
rect,
|
||||
'fc-event fc-event-vert fc-corner-top fc-corner-bottom '
|
||||
));
|
||||
if (!$.browser.msie) {
|
||||
// IE makes the event completely clear!!?
|
||||
helper.css('opacity', view.option('dragOpacity'));
|
||||
}
|
||||
}
|
||||
if (helper) {
|
||||
// TODO: change cursor
|
||||
view.bindSlotHandlers(helper);
|
||||
bodyContent.append(helper);
|
||||
setOuterWidth(helper, rect.width, true);
|
||||
setOuterHeight(helper, rect.height, true);
|
||||
}
|
||||
}else{
|
||||
view.renderOverlay(
|
||||
matrix.rect(range[0], day, range[1]+1, day+1, bodyContent),
|
||||
bodyContent
|
||||
);
|
||||
view.bindSlotHandlers(view.overlays[0]);
|
||||
}
|
||||
selected = true;
|
||||
}else{
|
||||
selected = false;
|
||||
}
|
||||
});
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
$(document)
|
||||
.mousemove(slotMousemove)
|
||||
.mouseup(slotMouseup);
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
function slotMousemove(ev) {
|
||||
matrix.mouse(ev.pageX, ev.pageY);
|
||||
}
|
||||
|
||||
function slotMouseup(ev) {
|
||||
$(document)
|
||||
.unbind('mousemove', slotMousemove)
|
||||
.unbind('mouseup', slotMouseup);
|
||||
if (selected) {
|
||||
view.trigger('select',
|
||||
view,
|
||||
view.slotTime(day, range[0]),
|
||||
view.slotTime(day, range[1]+1),
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// common
|
||||
|
||||
function unselect() {
|
||||
if (selected) {
|
||||
clear();
|
||||
view.trigger('unselect', view);
|
||||
selected = false;
|
||||
}
|
||||
}
|
||||
this.unselect = unselect;
|
||||
view.viewUpdate = unselect;
|
||||
|
||||
function clear() {
|
||||
if (helper) {
|
||||
helper.remove();
|
||||
helper = null;
|
||||
}
|
||||
view.clearOverlays();
|
||||
}
|
||||
|
||||
if (view.option('unselectable')) {
|
||||
$(document).mousedown(function() {
|
||||
unselect();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})(jQuery);
|
103
src/selection_util.js
Normal file
103
src/selection_util.js
Normal file
|
@ -0,0 +1,103 @@
|
|||
|
||||
function SelectionManager(view, displayFunc, clearFunc) {
|
||||
|
||||
var t = this;
|
||||
var selected = false;
|
||||
var initialElement;
|
||||
var initialRange;
|
||||
var start;
|
||||
var end;
|
||||
var allDay;
|
||||
|
||||
|
||||
t.dragStart = function(ev) {
|
||||
unselect();
|
||||
start = end = undefined;
|
||||
initialRange = undefined;
|
||||
initialElement = ev.currentTarget;
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
selected = true;
|
||||
view.trigger('select', view, start, end, allDay);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
t.select = function(newStart, newEnd, newAllDay) {
|
||||
unselect();
|
||||
start = newStart;
|
||||
end = newEnd;
|
||||
allDay = newAllDay;
|
||||
selected = true;
|
||||
displayFunc(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 _mouseup(ev) {
|
||||
mouseup(ev);
|
||||
$(document)
|
||||
.unbind('mousemove', mousemove)
|
||||
.unbind('mouseup', _mouseup);
|
||||
}
|
||||
$(document)
|
||||
.mousemove(mousemove)
|
||||
.mouseup(_mouseup);
|
||||
}
|
||||
|
||||
|
||||
function documentAutoUnselect(view, unselectFunc) {
|
||||
if (view.option('unselectAuto')) {
|
||||
$(document).mousedown(function(ev) {
|
||||
var ignore = view.option('unselectCancel');
|
||||
if (ignore) {
|
||||
if ($(ev.target).parents(ignore).length) { // could be optimized to stop after first match
|
||||
return;
|
||||
}
|
||||
}
|
||||
unselectFunc();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
10
src/util.js
10
src/util.js
|
@ -397,7 +397,9 @@ function HoverMatrix(changeCallback) {
|
|||
lefts.push(prevColE.offset().left);
|
||||
};
|
||||
|
||||
t.mouse = function(x, y) {
|
||||
t.mouse = function(ev) {
|
||||
var x = ev.pageX;
|
||||
var y = ev.pageY;
|
||||
if (origRow === undefined) {
|
||||
tops.push(tops[tops.length-1] + prevRowE.outerHeight());
|
||||
lefts.push(lefts[lefts.length-1] + prevColE.outerWidth());
|
||||
|
@ -425,6 +427,8 @@ function HoverMatrix(changeCallback) {
|
|||
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
|
||||
|
@ -525,7 +529,3 @@ function cmp(a, b) {
|
|||
fc.cmp = cmp;
|
||||
|
||||
|
||||
fc.publicMethods = {};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -180,6 +180,7 @@ var viewMethods = {
|
|||
.css(rect)
|
||||
.appendTo(parent);
|
||||
this.overlays.push(e);
|
||||
return e;
|
||||
},
|
||||
|
||||
clearOverlays: function() {
|
||||
|
|
|
@ -83,6 +83,7 @@ if (_build) {
|
|||
includeJS('../src/grid.js');
|
||||
includeJS('../src/agenda.js');
|
||||
includeJS('../src/view.js');
|
||||
includeJS('../src/selection_util.js');
|
||||
includeJS('../src/util.js');
|
||||
includeJS('../src/gcal.js');
|
||||
}
|
||||
|
|
|
@ -19,18 +19,6 @@
|
|||
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
|
||||
},
|
||||
editable: true,
|
||||
//defaultView: 'agendaWeek',
|
||||
selectable: true,
|
||||
selectHelper: true,
|
||||
select: function(start, end, allDay) {
|
||||
console.log('select');
|
||||
console.log(start);
|
||||
console.log(end);
|
||||
console.log(allDay);
|
||||
},
|
||||
unselect: function() {
|
||||
console.log('unselect');
|
||||
},
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
|
|
114
tests/selectable.html
Normal file
114
tests/selectable.html
Normal file
|
@ -0,0 +1,114 @@
|
|||
<!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({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
|
||||
},
|
||||
//defaultView: 'agendaWeek',
|
||||
//isRTL: true,
|
||||
selectable: true,
|
||||
selectHelper: true,
|
||||
//unselectAuto: false,
|
||||
//unselectCancel: '.fc',
|
||||
select: function(start, end, allDay) {
|
||||
console.log(
|
||||
'---- selection ----\n' +
|
||||
'start: ' + start + '\n' +
|
||||
'end: ' + end + '\n' + // exclusive!!
|
||||
'allDay: ' + allDay
|
||||
);
|
||||
},
|
||||
unselect: function() {
|
||||
console.log('unselect');
|
||||
},
|
||||
dayClick: function(date, allDay) {
|
||||
console.log(date, allDay);
|
||||
console.log(this);
|
||||
},
|
||||
editable: true,
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
start: new Date(y, m, 1)
|
||||
},
|
||||
{
|
||||
title: 'Long Event',
|
||||
start: new Date(y, m, d-5, 5, 0),
|
||||
end: new Date(y, m, d-2, 2, 0),
|
||||
allDay: false
|
||||
},
|
||||
{
|
||||
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/'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</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;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='calendar'></div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue