From 2a37ffe985f8f5f8f4ebabb268cf05b406f587d3 Mon Sep 17 00:00:00 2001 From: Sean Kenny Date: Tue, 12 Aug 2014 19:56:24 +0100 Subject: [PATCH] Finishing drag and drop off --- src/resource/ResourceEventRenderer.js | 259 +++----------------------- src/resource/ResourceView.js | 181 ++++++++++-------- tests/resourceDayView.html | 2 + 3 files changed, 133 insertions(+), 309 deletions(-) diff --git a/src/resource/ResourceEventRenderer.js b/src/resource/ResourceEventRenderer.js index 813dfeb..5b10bb3 100644 --- a/src/resource/ResourceEventRenderer.js +++ b/src/resource/ResourceEventRenderer.js @@ -92,10 +92,8 @@ function ResourceEventRenderer() { i, j, seg, colSegs, - segs = []; //, - //col; - - //new + segs = []; + for (i=0; i= 0) { - resourceEvents.push(events[i]); - } + var resourceEvents = []; + for (var i = 0; i < events.length; i++) { + if (events[i].resources && $.inArray(resource.id, events[i].resources) >= 0) { + resourceEvents.push(events[i]); + } + } + return resourceEvents; } - return resourceEvents; - } - - // function slotEventEnd(event) { - // if (event.end) { - // return event.end.clone(); - // }else{ - // return event.start.clone().add('m', opt('defaultEventMinutes')); - // } - // } // renders events in the 'time slots' at the bottom @@ -260,6 +250,7 @@ function ResourceEventRenderer() { seg.outerHeight = bottom - top; html += slotSegHtml(event, seg); } + slotSegmentContainer[0].innerHTML = html; // faster than html() eventElements = slotSegmentContainer.children(); @@ -318,7 +309,9 @@ function ResourceEventRenderer() { if (seg.contentTop !== undefined && height - seg.contentTop < 10) { // not enough room for title, put it in the time (TODO: maybe make both display:inline instead) eventElement.find('div.fc-event-time') - .text(formatDate(event.start, opt('timeFormat')) + ' - ' + event.title); + .text( + formatDate(event.start, opt('timeFormat')) + ' - ' + event.title + ); eventElement.find('div.fc-event-title') .remove(); } @@ -352,6 +345,7 @@ function ResourceEventRenderer() { }else{ html += "div"; } + html += " class='" + classes.join(' ') + "'" + " style=" + @@ -371,6 +365,7 @@ function ResourceEventRenderer() { "" + "" + "
"; + if (seg.isEnd && isEventResizable(event)) { html += "
=
"; @@ -436,7 +431,7 @@ function ResourceEventRenderer() { dayDelta = date.diff(origDate, 'days'); if (!cell.row) { // on full-days - + renderDayOverlay( event.start.clone().add('days', dayDelta), getEventEnd(event).add('days', dayDelta) @@ -582,11 +577,6 @@ function ResourceEventRenderer() { colDelta = Math.round((ui.position.left - origPosition.left) / colWidth); if (colDelta != prevColDelta) { // calculate the day delta based off of the original clicked column and the column delta - //var origDate = cellToDate(0, origCell.col); - //var col = origCell.col + colDelta; - //col = Math.max(0, col); - //col = Math.min(colCnt-1, col); - //dayDelta = 0; //dayDiff(date, origDate); resourceDelta = colDelta; } @@ -630,10 +620,13 @@ function ResourceEventRenderer() { stop: function(ev, ui) { clearOverlays(); - trigger('eventDragStop', eventElement, event, ev, ui); + + trigger('eventDragStop', eventElement[0], event, ev, ui); if (isInBounds && (isAllDay || resourceDelta || snapDelta)) { // changed! - event.resources = [ resources()[origCell.col + resourceDelta].id ]; + if (resourceDelta){ + event.resources = [ resources()[origCell.col + resourceDelta].id ]; + } eventDrop( eventElement[0], event, @@ -731,7 +724,7 @@ function ResourceEventRenderer() { } }, stop: function(ev, ui) { - trigger('eventResizeStop', this, event, ev, ui); + trigger('eventResizeStop', eventElement[0], event, ev, ui); if (snapDelta) { eventResize( eventElement[0], @@ -750,208 +743,4 @@ function ResourceEventRenderer() { } -} - - - -// /* Agenda Event Segment Utilities -// -----------------------------------------------------------------------------*/ -// // Sets the seg.backwardCoord and seg.forwardCoord on each segment and returns a new -// // list in the order they should be placed into the DOM (an implicit z-index). -// function placeSlotSegs(segs) { -// var levels = buildSlotSegLevels(segs); -// var level0 = levels[0]; -// var i; - -// computeForwardSlotSegs(levels); - -// if (level0) { - -// for (i=0; i seg2.start && seg1.start < seg2.end; -// } - - -// // A cmp function for determining which forward segment to rely on more when computing coordinates. -// function compareForwardSlotSegs(seg1, seg2) { -// // put higher-pressure first -// return seg2.forwardPressure - seg1.forwardPressure || -// // put segments that are closer to initial edge first (and favor ones with no coords yet) -// (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) || -// // do normal sorting... -// compareSlotSegs(seg1, seg2); -// } - - -// // A cmp function for determining which segment should be closer to the initial edge -// // (the left edge on a left-to-right calendar). -// function compareSlotSegs(seg1, seg2) { -// return seg1.start - seg2.start || // earlier start time goes first -// (seg2.end - seg2.start) - (seg1.end - seg1.start) || // tie? longer-duration goes first -// (seg1.event.title || '').localeCompare(seg2.event.title); // tie? alphabetically by title -// } +} \ No newline at end of file diff --git a/src/resource/ResourceView.js b/src/resource/ResourceView.js index 3c9ea69..3d067e0 100644 --- a/src/resource/ResourceView.js +++ b/src/resource/ResourceView.js @@ -1,9 +1,17 @@ + setDefaults({ allDaySlot: true, allDayText: 'all-day', + scrollTime: '06:00:00', - slotMinutes: 30, + slotDuration: '00:30:00', + + axisFormat: generateAgendaAxisFormat, + timeFormat: { + agenda: generateAgendaTimeFormat + }, + dragOpacity: { agenda: .5 }, @@ -13,6 +21,20 @@ setDefaults({ }); +function generateAgendaAxisFormat(options, langData) { + return langData.longDateFormat('LT') + .replace(':mm', '(:mm)') + .replace(/(\Wmm)$/, '($1)') // like above, but for foreign langs + .replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand +} + + +function generateAgendaTimeFormat(options, langData) { + return langData.longDateFormat('LT') + .replace(/\s*a$/i, ''); // remove trailing AM/PM +} + + // TODO: make it work in quirks mode (event corners, all-day height) // TODO: test liquid width, especially in IE6 @@ -66,13 +88,14 @@ function ResourceView(element, calendar, viewName) { var clearOverlays = t.clearOverlays; var reportSelection = t.reportSelection; var unselect = t.unselect; + //var daySelectionMousedown = t.daySelectionMousedown; var slotSegHtml = t.slotSegHtml; var cellToDate = t.cellToDate; var dateToCell = t.dateToCell; var rangeToSegments = t.rangeToSegments; var formatDate = calendar.formatDate; var calculateWeekNumber = calendar.calculateWeekNumber; - + // locals @@ -255,10 +278,9 @@ function ResourceView(element, calendar, viewName) { s += "" + ""; - // slotTable = $(s).appendTo(slotContainer); - // slotTableFirstInner = slotTable.find('div:first'); - slotTable = $(s).appendTo(slotContainer); + slotTable = $(s).appendTo(slotContainer); + slotBind(slotTable.find('td')); } @@ -361,7 +383,7 @@ function ResourceView(element, calendar, viewName) { var headerClass = tm + "-widget-header"; // TODO: make these when updateOptions() called var contentClass = tm + "-widget-content"; var date; - var today = makeMoment(new Date()).stripTime(); + var today = calendar.getNow().stripTime(); var col; var cellsHTML; var cellHTML; @@ -381,10 +403,11 @@ function ResourceView(element, calendar, viewName) { classNames = [ 'fc-col' + col, + 'fc-' + dayIDs[date.day()], resource.className, contentClass ]; - if (+date == +today) { + if (date.isSame(today, 'day')) { classNames.push( tm + '-state-highlight', 'fc-today' @@ -547,6 +570,7 @@ function ResourceView(element, calendar, viewName) { .mousedown(slotSelectionMousedown); } + function slotClick(ev) { if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick var col = Math.min(colCnt-1, Math.floor((ev.pageX - dayTable.offset().left - axisWidth) / colWidth)); @@ -575,7 +599,7 @@ function ResourceView(element, calendar, viewName) { } } } - + /* Semi-transparent Overlay Helpers @@ -595,19 +619,12 @@ function ResourceView(element, calendar, viewName) { dayBind( renderCellOverlay( segment.row, - col, //segment.leftCol, + col, segment.row, - col //segment.rightCol + col ) ); } - - // var allDayRow = 0; - // if (refreshCoordinateGrid) { - // coordinateGrid.build(); - // } - - // dayBind(renderCellOverlay(allDayRow, col, allDayRow, col)); } @@ -710,7 +727,10 @@ function ResourceView(element, calendar, viewName) { } - function getIsCellAllDay(cell) { + // NOTE: the row index of these "cells" doesn't correspond to the slot index, but rather the "snap" index + + + function getIsCellAllDay(cell) { // TODO: remove because mom.hasTime() from realCellToDate() is better return opt('allDaySlot') && !cell.row; } @@ -731,7 +751,7 @@ function ResourceView(element, calendar, viewName) { return date; } - + function computeDateTop(date, startOfDayDate) { return computeTimeTop( moment.duration( @@ -775,25 +795,27 @@ function ResourceView(element, calendar, viewName) { } + /* Selection ---------------------------------------------------------------------------------*/ + - - function defaultSelectionEnd(startDate, allDay) { - if (allDay) { - return startDate.clone(); + function defaultSelectionEnd(start) { + if (start.hasTime()) { + return start.clone().add(slotDuration); + } + else { + return start.clone().add('days', 1); } - return startDate.clone().add('m', opt('slotMinutes')); } - function renderSelection(startDate, endDate, allDay, col) { // only for all-day - if (allDay) { - if (opt('allDaySlot')) { - renderDayOverlay(startDate, endDate, true, col); - } - }else{ - renderSlotSelection(startDate, endDate); + function renderSelection(start, end, col) { + if (start.hasTime() || end.hasTime()) { + renderSlotSelection(start, end); //, col); + } + else if (opt('allDaySlot')) { + renderDayOverlay(start, end, true, col); // true for refreshing coordinate grid } } @@ -857,38 +879,7 @@ function ResourceView(element, calendar, viewName) { } } - function daySelectionMousedown(ev) { - var getIsCellAllDay = t.getIsCellAllDay; - var hoverListener = t.getHoverListener(); - var reportDayClick = t.reportDayClick; // this is hacky and sort of weird - var col; - if (ev.which == 1 && opt('selectable')) { // which==1 means left mouse button - unselect(ev); - var dates; - hoverListener.start(function(cell, origCell) { // TODO: maybe put cellToDate/getIsCellAllDay info in cell - clearSelection(); - if (cell && getIsCellAllDay(cell)) { - col = cell.col; - dates = [ realCellToDate(origCell), realCellToDate(cell) ].sort(dateCompare); - renderSelection(dates[0], dates[1], true, col); - }else{ - dates = null; - } - }, ev); - $(document).one('mouseup', function(ev) { - hoverListener.stop(); - if (dates) { - if (+dates[0] == +dates[1]) { - reportDayClick(dates[0], true, ev); - } - ev.data = resources()[col]; - reportSelection(dates[0], dates[1], true, ev); - } - }); - } - } - - // select on the calendar somewhere + function slotSelectionMousedown(ev) { if (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button unselect(ev); @@ -915,18 +906,18 @@ function ResourceView(element, calendar, viewName) { hoverListener.stop(); if (dates) { if (+dates[0] == +dates[1]) { - reportDayClick(dates[0], false, ev); + reportDayClick(dates[0], ev); } ev.data = resources()[col]; // added - reportSelection(dates[0], dates[3], false, ev); + reportSelection(dates[0], dates[3], ev); } }); } } - function reportDayClick(date, allDay, ev) { - trigger('dayClick', dayBodyCells[dateToCell(date).col], date, allDay, ev); + function reportDayClick(date, ev) { + trigger('dayClick', dayBodyCells[dateToCell(date).col], date, ev); } @@ -939,13 +930,16 @@ function ResourceView(element, calendar, viewName) { hoverListener.start(function(cell) { clearOverlays(); if (cell) { - if (getIsCellAllDay(cell)) { - renderCellOverlay(cell.row, cell.col, cell.row, cell.col); - }else{ - var d1 = realCellToDate(cell); - var d2 = d1.clone().add('m', opt('defaultEventMinutes')); + var d1 = realCellToDate(cell); + var d2 = d1.clone(); + if (d1.hasTime()) { + d2.add(calendar.defaultTimedEventDuration); renderSlotOverlay(d1, d2, cell.col); } + else { + d2.add(calendar.defaultAllDayEventDuration); + renderDayOverlay(d1, d2, true, cell.col); + } } }, ev); } @@ -955,8 +949,47 @@ function ResourceView(element, calendar, viewName) { var cell = hoverListener.stop(); clearOverlays(); if (cell) { - ev.data = resources()[cell.col]; - trigger('drop', _dragElement, realCellToDate(cell), getIsCellAllDay(cell), ev, ui); + ev.data = resources()[cell.col]; + trigger( + 'drop', + _dragElement, + realCellToDate(cell), + ev, + ui + ); } } + + /* OVERRIDES */ + function daySelectionMousedown(ev) { + var getIsCellAllDay = t.getIsCellAllDay; + var hoverListener = t.getHoverListener(); + var reportDayClick = t.reportDayClick; // this is hacky and sort of weird + var col; + if (ev.which == 1 && opt('selectable')) { // which==1 means left mouse button + unselect(ev); + var dates; + hoverListener.start(function(cell, origCell) { // TODO: maybe put cellToDate/getIsCellAllDay info in cell + clearSelection(); + if (cell && getIsCellAllDay(cell)) { + col = cell.col; + dates = [ realCellToDate(origCell), realCellToDate(cell) ].sort(dateCompare); + renderSelection(dates[0], dates[1], col); + }else{ + dates = null; + } + }, ev); + $(document).one('mouseup', function(ev) { + hoverListener.stop(); + if (dates) { + if (+dates[0] == +dates[1]) { + reportDayClick(dates[0], true, ev); + } + ev.data = resources()[col]; + reportSelection(dates[0], dates[1], ev); + } + }); + } + } + } \ No newline at end of file diff --git a/tests/resourceDayView.html b/tests/resourceDayView.html index d1d5e01..91c4b55 100644 --- a/tests/resourceDayView.html +++ b/tests/resourceDayView.html @@ -121,10 +121,12 @@ { title: 'R1: All day', allDay: true, + start: new Date(y, m, d, 12, 0), resources: 'resource1' }, { title: 'R2: All Day', + start: new Date(y, m, d, 12, 0), allDay: true, resources: 'resource2' },