From 288df0c4b78f07d3ff34dae37afbac47a681dbaa Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Wed, 10 Feb 2021 16:51:11 +0800 Subject: [PATCH] ready for debug --- src/static/js/datetime.js | 218 +++++++++++++++++++++++++++++- src/static/js/page/calendar.js | 150 ++++++++++++++++++-- src/static/js/utils.js | 9 ++ src/static/tmpl/scheduleItem.tmpl | 43 +++--- 4 files changed, 379 insertions(+), 41 deletions(-) diff --git a/src/static/js/datetime.js b/src/static/js/datetime.js index ba0909c..3a1efd7 100644 --- a/src/static/js/datetime.js +++ b/src/static/js/datetime.js @@ -72,8 +72,180 @@ function ccn_datetime_ResolveLoopRules4UI(strl) { return [loopRules, loopStopRules]; } -function ccn_datetime_ResolveLoopRules4Event(strl) { - return undefined; +// loopDateTimeStart's value is not correspond with database. +// it is calculated by program, should be pointed to the closing +// protential event start datetime. +// also loopDateTimeEnd, it was clamped with the tail of legal event +// clampStartDateTime is real clamp datetime of event start datetime. +// loopDateTimeStart is the start datetime for detect. +// in this section, all time should be analysed with Date((time + timezoneOffset) * 60000) +// and use .getUTC...() functions. +function ccn_datetime_ResolveLoopRules4Event(loopRules, loopDateTimeStart, loopDateTimeEnd, eventDateTimeStart, eventDateTimeEnd, timezoneOffset, clampStartDateTime) { + if (strl == '') return [ + [Math.max(eventDateTimeStart, clampStartDateTime), + Math.max(loopDateTimeEnd, eventDateTimeEnd)] + ]; + + sp = strl.split('-'); + if (sp.length != 2) return undefined; + var loopRules = sp[0]; // we don't need consider stop flag + var result = new Array(); + + // compute offset and duration + var eventDateTime = new Date((eventDateTimeStart + timezoneOffset) * 60000); + eventDateTime.setUTCHours(0, 0, 0, 0); + var eventOffset = eventDateTimeStart - (Math.floor(eventDateTime.getTime() / 60000) - timezoneOffset); + var eventDuration = eventDateTimeEnd - eventDateTimeStart; + + var detectDateTime = new Date(loopDateTimeStart * 60000); + detectDateTime.setUTCHours(0, 0, 0, 0); + var originalYear = eventDateTime.getUTCFullYear(); + var originalMonth = eventDateTime.getUTCMonth() + 1; + var originalDay = eventDateTime.getUTCDate(); + + // compute event + if (ccn_datetime_precompiledLoopRules.year.test(loopRules)) { + var isStrict = RegExp.$1 == 'S'; + var loopSpan = parseInt(RegExp.$2); + + var yearCount = detectDateTime.getFullYear() - originalYear; + var isSpecial = (originalMonth == 2 && originalDay == 29); + var realLoopSpan = isSpecial ? LCM(4, loopSpan) : loopSpan; + + var fullSpanCount = Math.floor(yearCount / realLoopSpan); + var remainYear = year % realLoopSpan; + detectDateTime.setUTCFullYear(fullSpanCount + detectDateTime.getUTCFullYear(), 1, 1); + if (remainYear != 0) + detectDateTime.setUTCFullYear(realLoopSpan - remainYear + detectDateTime.getUTCFullYear(), 1, 1); + + while(Math.floor(detectDateTime.getTime() / 60000) + eventOffset - timezoneOffset <= loopDateTimeEnd) { + if (!isSpecial || (isSpecial && ccn_datetime_IsLeapYear(detectDateTime.getUTCFullYear()))) { + detectDateTime.setUTCMonth(originalMonth, originalDay); + result.push( + [Math.floor(detectDateTime.getTime() / 60000) + eventOffset - timezoneOffset, + Math.floor(detectDateTime.getTime() / 60000) + eventOffset + eventDuration - timezoneOffset] + ); + } + + detectDateTime.setUTCFullYear(realLoopSpan + detectDateTime.getUTCFullYear()); + } + + } else if (ccn_datetime_precompiledLoopRules.month.test(loopRules)) { + var isStrict = RegExp.$1 == 'S'; + var loopMethod = RegExp.$2; + var loopSpan = parseInt(RegExp.$3); + + var monthsCount = ccn_datetime_MonthsCount(detectDateTime.getUTCFullYear(). detectDateTime.getUTCMonth() + 1) - + ccn_datetime_MonthsCount(originalYear, originalMonth); + + var fullSpanCount = Math.floor(monthsCount / loopSpan); + var remainMonth = monthsCount % loopSpan; + detectDateTime.setUTCMonth(fullSpanCount * loopSpan + detectDateTime.getUTCMonth(), 1); + if (remainMonth != 0) + detectDateTime.setUTCMonth(loopSpan - remainMonth + detectDateTime.getUTCMonth(), 1); + + while(Math.floor(detectDateTime.getTime() / 60000) + eventOffset - timezoneOffset <= loopDateTimeEnd) { + var data = ccn_datetime_GetRemanagedDayInMonth(originalYear, originalMonth, originalDay, detectDateTime.getUTCFullYear(), detectDateTime.getUTCMonth() + 1, isStrict); + var predictedDay = undefined; + switch(loopMethod) { + case 'A': + if (typeof(data[0]) != 'undefined') predictedDay = data[0]; + break; + case 'B': + if (typeof(data[1]) != 'undefined') predictedDay = data[1]; + break; + case 'C': + if (typeof(data[2]) != 'undefined') predictedDay = data[2]; + break; + case 'D': + if (typeof(data[3]) != 'undefined') predictedDay = data[3]; + break; + } + if (typeof(predictedDay) != 'undefined') { + detectDateTime.setUTCDate(predictedDay); + result.push( + [Math.floor(detectDateTime.getTime() / 60000) + eventOffset - timezoneOffset, + Math.floor(detectDateTime.getTime() / 60000) + eventOffset + eventDuration - timezoneOffset] + ); + } + + detectDateTime.setUTCMonth(loopSpan + detectDateTime.getUTCMonth(), 1); + } + + + } else if (ccn_datetime_precompiledLoopRules.week.test(loopRules)) { + var loopSpan = parseInt(RegExp.$2); + var weekOption = []; + var weekEventCount = 0 + for (var i = 0; i < 7; i++) { + weekOption.push(RegExp.$1[i] == 'T'); + if (RegExp.$1[i] == 'T') weekEventCount++; + } + + var originalWeek = ccn_datetime_DayOfWeek(originalYear, originalMonth, originalDay); + + // try insert original event + if (!weekOption[originalWeek]) { + result.push( + [eventDateTimeStart, eventDateTimeEnd] + ); + } + + var daysCount = ccn_datetime_DaysCount(detectDateTime.getUTCFullYear(), detectDateTime.getUTCMonth() + 1, detectDateTime.getDate()) - + ccn_datetime_DaysCount(originalYear, originalMonth, originalDay); + var fullSpanCount = Math.floor(daysCount / (7 * loopSpan)); + var remainFullSpanCount = Math.floor((daysCount % (7 * loopSpan)) / 7); + var remainDays = (daysCount % (7 * loopSpan)) % 7; + + detectDateTime.setUTCDate((7 * loopSpan * fullSpanCount) + detectDateTime.getUTCDate()); + if (remainFullSpanCount != 0) { + detectDateTime.setUTCDate((loopSpan - remainFullSpanCount) * 7 + detectDateTime.getUTCDate()); + } + var weekCounter = (remainDays + 7 - originalWeek) % 7 + + while(Math.floor(detectDateTime.getTime() / 60000) + eventOffset - timezoneOffset <= loopDateTimeEnd) { + if (weekOption[(weekCounter + originalWeek) % 7]) + result.push( + [Math.floor(detectDateTime.getTime() / 60000) + eventOffset - timezoneOffset, + Math.floor(detectDateTime.getTime() / 60000) + eventOffset + eventDuration - timezoneOffset] + ); + + weekCounter = (weekCounter + 1) % 7; + detectDateTime.setUTCDate(detectDateTime.getUTCDate() + 1); + if (weekCounter == 0) + detectDateTime.setUTCDate(detectDateTime.getUTCDate() + (loopSpan - 1) * 7); + } + + } else if (ccn_datetime_precompiledLoopRules.day.test(loopRules)) { + var loopSpan = parseInt(RegExp.$1); + + detectDateTime.setUTCDate( + (ccn_datetime_DaysCount(detectDateTime.getUTCFullYear(), detectDateTime.getUTCMonth() + 1, detectDateTime.getDate()) - + ccn_datetime_DaysCount(originalYear, originalMonth, originalDay)) % loopSpan + + detectDateTime.getUTCDate() + ); + while(Math.floor(detectDateTime.getTime() / 60000) + eventOffset - timezoneOffset <= loopDateTimeEnd) { + result.push( + [Math.floor(detectDateTime.getTime() / 60000) + eventOffset - timezoneOffset, + Math.floor(detectDateTime.getTime() / 60000) + eventOffset + eventDuration - timezoneOffset] + ); + detectDateTime.setUTCDate(detectDateTime.getUTCDate() + loopSpan); + } + } else return undefined; + + // clamp item + var realResult = []; + for (var i in result) { + var start = result[i][0]; + var end = result[i][1]; + if (end > clampStartDateTime && start <= loopDateTimeEnd) + realResult.push([Math.max(start, clampStartDateTime), Math.min(end, loopDateTimeEnd)]); + } + return realResult; +} + +function ccn_datetime_ResolveLoopRules4Text(loopRules) { + return ""; } function ccn_datetime_LeapYearCountEx(endYear, includeThis, baseYear, includeBase) { @@ -106,12 +278,16 @@ function ccn_datetime_DaysCount(year, month, day) { return days; } +function ccn_datetime_MonthsCount(year, month) { + return (year - 1) * 12 + (month - 1); +} + function ccn_datetime_DayOfWeek(year, month, day) { return ccn_datetime_DaysCount(year, month, day) % 7; } function ccn_datetime_GetDayInMonth(year, month, day) { - var days = ccn_datetime_monthDayCount[month - 1] + ((month == '2' && ccn_datetime_IsLeapYear(year)) ? 1 : 0); + var days = ccn_datetime_monthDayCount[month - 1] + ((month == 2 && ccn_datetime_IsLeapYear(year)) ? 1 : 0); var firstDayOfWeek = ccn_datetime_DayOfWeek(year, month, 1); var dayOfWeek = (firstDayOfWeek + day - 1) % 7; @@ -124,10 +300,40 @@ function ccn_datetime_GetDayInMonth(year, month, day) { return [dayForwards, dayBackwards, weeksForward, dayOfWeek, weeksBackwards, dayOfWeek]; } -function ccn_datetime_GetMonthWeekStatistics(year, month) { - var days = ccn_datetime_monthDayCount[month - 1] + ((month == '2' && ccn_datetime_IsLeapYear(year)) ? 1 : 0); - var firstDayOfWeek = ccn_datetime_DayOfWeek(year, month, 1); +function ccn_datetime_GetRemanagedDayInMonth(oldYear, oldMonth, oldDay, newYear, newMonth, isStrict) { + var ddata = ccn_datetime_GetDayInMonth(oldYear, oldMonth, oldDay); + var mdata = ccn_datetime_GetMonthWeekStatistics(newYear, newMonth); + var days = ccn_datetime_monthDayCount[month - 1] + ((month == 2 && ccn_datetime_IsLeapYear(year)) ? 1 : 0); + var firstDayOfWeek = ccn_datetime_DayOfWeek(newYear, newMonth, 1); var lastDayOfWeek = (firstDayOfWeek + days - 1) % 7; + + if (isStrict) { + var methodA = ddata[0] > days ? undefined : ddata[0]; + var methodB = ddata[1] > days ? undefined : (days - ddata[1] + 1); + } else { + var methodA = Math.min(ddata[0], days); + var methodB = days - Math.min(ddata[1], days) + 1; + } + + var methodC = undefined; + if (ddata[2] <= mdata[ddata[3]] || !isStrict) { + var targetWeek = Math.min(ddata[2], mdata[ddata[3]]); + methodC = (targetWeek - 1) * 7 + ((ddata[3] + 7 - firstDayOfWeek) % 7); + } + + var methodD = undefined; + if (ddata[4] <= mdata[ddata[5]] || !isStrict) { + // convert to type c and calc + var targetWeek = mdata[ddata[5]] - Math.min(ddata[4], mdata[ddata[5]]) + 1; + methodD = (targetWeek - 1) * 7 + ((ddata[3] + 7 - lastDayOfWeek) % 7); + } + + return [methodA, methodB, methodC, methodD]; +} + +function ccn_datetime_GetMonthWeekStatistics(year, month) { + var days = ccn_datetime_monthDayCount[month - 1] + ((month == 2 && ccn_datetime_IsLeapYear(year)) ? 1 : 0); + var firstDayOfWeek = ccn_datetime_DayOfWeek(year, month, 1); var result = [4, 4, 4, 4, 4, 4, 4]; var remain = days % 7; diff --git a/src/static/js/page/calendar.js b/src/static/js/page/calendar.js index ebbcfe9..6dde7a0 100644 --- a/src/static/js/page/calendar.js +++ b/src/static/js/page/calendar.js @@ -10,6 +10,7 @@ var ccn_calendar_eventModal_editing = undefined; var ccn_calendar_eventModal_collectionCache = []; var ccn_calendar_calendar_listCache = []; var ccn_calendar_calendar_displayCache = []; +var ccn_calendar_calendar_displayDateTime = 0; $(document).ready(function() { ccn_pages_currentPage = ccn_pages_enumPages.calendar; @@ -50,13 +51,16 @@ $(document).ready(function() { //refresh once ccn_calendar_collection_Refresh(); + ccn_calendar_calendar_Refresh(); + ccn_calendar_calendar_Analyse(); + ccn_calendar_calendar_Render(); // bind event $('#ccn-calendar-collection-btnRefresh').click(ccn_calendar_collection_Refresh); - $('#ccn-calendar-calendar-btnJump').click(ccn_calendar_calendar_Refresh); - $('#ccn-calendar-calendar-btnToday').click(ccn_calendar_calendar_Today); - $('#ccn-calendar-calendar-btnAdd').click(ccn_calendar_calendar_Add); + $('#ccn-calendar-calendar-btnJump').click(ccn_calendar_calendar_btnRefresh); + $('#ccn-calendar-calendar-btnToday').click(ccn_calendar_calendar_btnToday); + $('#ccn-calendar-calendar-btnAdd').click(ccn_calendar_calendar_btnAdd); }); // ================== calendar @@ -65,27 +69,153 @@ function ccn_calendar_calendar_LoadCalendarBody() { $('#ccn-calendar-calendarBody').append(ccn_template_calendarItem.render()); } +// this function only refresh cache list function ccn_calendar_calendar_Refresh() { - gottenDateTime = ccn_datetimepicker_Get(1, false); - gottenYear = gottenDateTime.getFullYear(); - gottenMonth = gottenDateTime.getMonth() + 1; + var gottenDateTime = ccn_datetimepicker_Get(1, false); + var gottenYear = gottenDateTime.getFullYear(); + var gottenMonth = gottenDateTime.getMonth() + 1; + // don't need to set anything, because its default value is enough to use. + + var gottenWeek = ccn_datetime_DayOfWeek(gottenYear, gottenMonth, 1); + var startTimestamp = Math.floor(gottenDateTime.getTime() / 60000) - gottenWeek * ccn_datetime_DAY1_SPAN; + var endTimestamp = startTimestamp + ccn_datetime_DAY1_SPAN * 6 * 7 - 1; + + ccn_calendar_calendar_listCache = new Array(); + var result = ccn_api_calendar_getFull(startTimestamp, endTimestamp); + if (typeof(result) != 'undefined') { + for(var index in result) { + ccn_calendar_calendar_listCache[result[index][0]] = result[index]; + } + } } +// this function take responsibility to analyse event +// call datetime function to resolve loop event +// and split event if some event cross 2+ days +function ccn_calendar_calendar_Analyse() { + // first, we need construct ccn_calendar_calendar_displayCache + ccn_calendar_calendar_displayCache = new Array(); + var gottenDateTime = ccn_datetimepicker_Get(1, false); + var gottenYear = gottenDateTime.getFullYear(); + var gottenMonth = gottenDateTime.getMonth() + 1; + var gottenWeek = ccn_datetime_DayOfWeek(gottenYear, gottenMonth, 1); + var startTimestamp = Math.floor(gottenDateTime.getTime() / 60000) - gottenWeek * ccn_datetime_DAY1_SPAN; + var endTimestamp = startTimestamp + ccn_datetime_DAY1_SPAN * 6 * 7 - 1; + gottenDateTime.setTime(startTimestamp * 60000); + for(var index = 0; index < 6 * 7; index++) { + ccn_calendar_calendar_displayCache.push({ + month: gottenDateTime.getMonth() + 1, + day: gottenDateTime.getDate(), + dayOfWeek: gottenDateTime.getWeekday(), + subcalendar: " ", + events: new Array() + }); + gottenDateTime.setTime(gottenDateTime.getTime() + ccn_datetime_DAY1_SPAN * 60000); + } + + var mytimezone = -(new Date().getTimezoneOffset()); + // then analyse each event + for(var index in ccn_calendar_calendar_listCache) { + var item = ccn_calendar_calendar_listCache[index]; + + var result = ccn_datetime_ResolveLoopRules4Event( + item[8], + Math.max(item[6] - item[5] + startTimestamp, item[9]), + Math.min(item[10], endTimestamp), + item[5], + item[6], + item[7], + startTimestamp + ); + if(typeof(result) != 'undefined') { + for(var i in result) { + var it = result[i]; + // try get event belong to which cell + var eventDateTime = new Date(it[0] * 60000); + var count = Math.floor((eventDateTime - startTimestamp) / ccn_datetime_DAY1_SPAN); + var exitFlag = false; + // then split event + while(count < 6 * 7) { + var eventItem = { + uuid: item[0], + title: item[2], + description: item[3], + isVisible: true, + isLocked: typeof(ccn_calendar_owned_displayCache[item[0]]) != 'undefined', + loopText: " ", // todo: finish this + timezoneWarning: mytimezone != item[7], + start: eventDateTime.toLocaleTimeString(), + end: undefined // filled in follwing code + } + eventDateTime.setHours(23, 59, 0, 0); + if (Math.floor(eventDateTime.getTime() / 60000) <= it[1]) { + exitFlag = true; + eventDateTime.setTime(it[1] * 60000); + } + eventDateTime.end = eventDateTime.toLocaleTimeString(); + ccn_calendar_calendar_displayCache[count].events.push(eventItem); + if (exitFlag) break; + count++; + } + } + } + } + +} + +// just use produced ccn_calendar_calendar_displayCache +// to re-generate ui function ccn_calendar_calendar_Render() { + // all data has been alanysed, feeback to calendar body. + var counter = 0; + for(var i = 0; i < 6; i++) { + for(var j = 0; j < 7; j++) { + var item = ccn_calendar_calendar_displayCache[counter]; + $('#ccn-calendarItem-title' + i + '-' + j).text(item.day); + $('#ccn-calendarItem-desc' + i + '-' + j).text(item.subcalendar); + $('#ccn-calendarItem-task' + i + '-' + j).text(item.events.length); + counter++; + } + } + // todo: add / migrate subcalendar feature here + + // analyse visible data + for(var i in ccn_calendar_calendar_displayCache) { + for(var j in ccn_calendar_calendar_displayCache[i].events) { + var gottenOwnedVisible = ccn_calendar_owned_displayCache[ + ccn_calendar_calendar_displayCache[i].events[j].uuid + ]; + if (typeof(gottenOwnedVisible) != 'undefined') gottenOwnedVisible = false; + var gottenSharedVisible = ccn_calendar_shared_displayCache[ + ccn_calendar_calendar_displayCache[i].events[j].uuid + ]; + if (typeof(gottenSharedVisible) != 'undefined') gottenSharedVisible = false; + + ccn_calendar_calendar_displayCache[i].events[j].isVisible = gottenOwnedVisible || gottenSharedVisible; + } + } + + // just render them + var listDOM = $('#ccn-calendar-scheduleList'); + listDOM.empty(); + listDOM.append(ccn_template_scheduleItem.render({renderdata: ccn_calendar_calendar_displayCache})); + ccn_i18n_ApplyLanguage2Content(listDOM); } -function ccn_calendar_calendar_AnalyseEvent() { - +function ccn_calendar_calendar_btnRefresh() { + ccn_calendar_calendar_Refresh(); + ccn_calendar_calendar_Analyse(); + ccn_calendar_calendar_Render(); } -function ccn_calendar_calendar_Today() { +function ccn_calendar_calendar_btnToday() { var nowtime = new Date(); ccn_datetimepicker_Set(1, nowtime, false); ccn_calendar_calendar_Refresh(); } -function ccn_calendar_calendar_Add() { +function ccn_calendar_calendar_btnAdd() { window.location.href = '/web/eventAdd'; } diff --git a/src/static/js/utils.js b/src/static/js/utils.js index 7b7b7c8..05171dc 100644 --- a/src/static/js/utils.js +++ b/src/static/js/utils.js @@ -51,6 +51,15 @@ function SmarterShowHide(boolean, element) { else element.hide(); } +function GCD(a, b) { + if (b == 0) return a; + return GCD(b, a % b); +} + +function LCM(a, b) { + return a / GCD(a, b) * b; +} + String.prototype.format = function() { var e = arguments; return !!this && this.replace( diff --git a/src/static/tmpl/scheduleItem.tmpl b/src/static/tmpl/scheduleItem.tmpl index ad272f2..d839866 100644 --- a/src/static/tmpl/scheduleItem.tmpl +++ b/src/static/tmpl/scheduleItem.tmpl @@ -1,37 +1,30 @@ +{{for renderdata}}
- 13 - Friday + {{>month}} + {{>day}} +
+ {{for event}} + {{if isVisible}}
-

This is - titleewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww -

-

this is - subtitleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee -

+

{{>title}}

+

{{>description}}

+

{{>start}}-{{>end}}

- -
- -
-
- -
-
-

This is - titleewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww -

-

this is - subtitleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee -

-
-
+ {{if isLocked}} + {{/if}} + {{if timezoneWarning}} + + {{/if}}
+ {{/if}} + {{/for}}
-
\ No newline at end of file + +{{/for}} \ No newline at end of file