diff --git a/src/dt.py b/src/dt.py index 6a39036..52aac4e 100644 --- a/src/dt.py +++ b/src/dt.py @@ -171,7 +171,7 @@ precompiledLoopRules = ( ) precompiledLoopStopRules = { - 'infinity': re.compile(r'F'), + 'infinity': re.compile(r'^F$'), 'datetime': re.compile(r'^D([1-9]\d*|0)$'), 'times': re.compile(r'^T([1-9]\d*)$') } diff --git a/src/static/css/event.css b/src/static/css/event.css index f1e6a7d..a57dbb3 100644 --- a/src/static/css/event.css +++ b/src/static/css/event.css @@ -8,4 +8,10 @@ div.control-list > * { margin-right: 0.75rem; margin-bottom: 0.75rem; margin-left: 0 !important; +} + + + +#ccn-event-eventFormBody > section { + border-top: 1px solid rgba(219,219,219,.5); } \ No newline at end of file diff --git a/src/static/js/datetime.js b/src/static/js/datetime.js index 58c689c..ebabf4e 100644 --- a/src/static/js/datetime.js +++ b/src/static/js/datetime.js @@ -10,8 +10,72 @@ ccn_datetime_MAX_TIMESTAMP = Math.floor(ccn_datetime_MAX_DATETIME.getTime() / 60 ccn_datetime_DAY1_SPAN = 60 * 24; ccn_datetime_DAY7_SPAN = 7 * ccn_datetime_DAY1_SPAN; +ccn_datetime_precompiledLoopRules = { + year: new RegExp(/^Y([SR]{1})([1-9]\d*)$/), + month: new RegExp(/^M([SR]{1})([ABCD]{1})([1-9]\d*)$/), + week: new RegExp(/^W([TF]{7})([1-9]\d*)$/), + day: new RegExp(/^D([1-9]\d*)$/) +}; + +ccn_datetime_precompiledLoopStopRules = { + infinity: new RegExp(/^F$/), + datetime: new RegExp(/^D([1-9]\d*|0)$/), + times: new RegExp(/^T([1-9]\d*)$/) +} + +/* +return format +[loopRules, loopStopRules] or undefined(invalid or no loop) + +loopRules: +year loop: [0, isStrict, yearSpan] +month loop: [1, isStrict, monthMode, monthSpan] +week loop: [2, 7 bool item..., weekSpan] +day loop: [3, daySpan] + +loopStopRules: +infinity: [0] +datetime: [1, timestamp] +times: [2, times] +*/ +function ccn_datetime_ResolveLoopRules4UI(strl) { + if (strl == '') return undefined; + + sp = strl.split('-'); + if (sp.length != 2) return undefined; + var loopRules = undefined; + var loopStopRules = undefined; + + if (ccn_datetime_precompiledLoopRules.year.test(sp[0])) { + loopRules = [1, RegExp.$1 == 'S', parseInt(RegExp.$2)]; + } else if (ccn_datetime_precompiledLoopRules.month.test(sp[0])) { + loopRules = [2, RegExp.$1 == 'S', RegExp.$2, parseInt(RedExp.$3)]; + } else if (ccn_datetime_precompiledLoopRules.week.test(sp[0])) { + loopRules = [3]; + for (index in RegExp.$1) loopRules.push(RegExp.$1[index] == 'T'); + loopRules.push(parseInt(RegExp.$2)); + } else if (ccn_datetime_precompiledLoopRules.day.test(sp[0])) { + loopRules = [4, parseInt(RegExp.$1)]; + } else return undefined; + + + if (ccn_datetime_precompiledLoopStopRules.infinity.test(sp[1])) { + loopStopRules = [0]; + } else if (ccn_datetime_precompiledLoopStopRules.datetime.test(sp[1])) { + loopStopRules = [1, parseInt(RegExp.$1)]; + } else if (ccn_datetime_precompiledLoopStopRules.times.test(sp[1])) { + loopStopRules = [2, parseInt(RegExp.$1)]; + } else return undefined; + + return [loopRules, loopStopRules]; +} + +function ccn_datetime_ResolveLoopRules4Event(strl) { + return undefined; +} + function ccn_datetime_IsLeapYear(year) { - var isLeap = true; + var isLeap = false; if (year % 4 == 0) isLeap = true; if (year % 100 == 0) isLeap = false; if (year % 400 == 0) isLeap = true; diff --git a/src/static/js/datetimepicker.js b/src/static/js/datetimepicker.js index ed80719..466ac83 100644 --- a/src/static/js/datetimepicker.js +++ b/src/static/js/datetimepicker.js @@ -5,13 +5,13 @@ function ccn_datetimepicker_Init() { .attr('max', ccn_datetime_MAX_YEAR) .attr('step', 1) .val(nowtime.getFullYear()) - .bind('propertychange', ccn_datetimepicker_Sync); + .bind('input propertychange', ccn_datetimepicker_Sync); $('.datetimepicker-month').attr('min', 1) .attr('max', 12) .attr('step', 1) .val(nowtime.getMonth() + 1) - .bind('propertychange', ccn_datetimepicker_Sync); + .bind('input propertychange', ccn_datetimepicker_Sync); $('.datetimepicker-day').attr('min', 1) .attr('step', 1) @@ -37,8 +37,8 @@ function ccn_datetimepicker_Sync() { } function ccn_datetimepicker_SyncEx(pickerIndex) { - year = $('.datetimepicker-year[datetimepicker=' + pickerIndex + ']').val(); - month = $('.datetimepicker-month[datetimepicker=' + pickerIndex + ']').val(); + year = parseInt($('.datetimepicker-year[datetimepicker=' + pickerIndex + ']').val()); + month = parseInt($('.datetimepicker-month[datetimepicker=' + pickerIndex + ']').val()); dayDOM = $('.datetimepicker-day[datetimepicker=' + pickerIndex + ']'); if (typeof(year) == 'undefined' || typeof(month) == 'undefined') { @@ -70,5 +70,5 @@ function ccn_datetimepicker_Get(pickerIndex) { if (IsUndefinedOrEmpty(hour)) hour = 0; if (IsUndefinedOrEmpty(minute)) minute = 0; - return new Date(year, month - 1, day, hour, minute, 0, 0); + return new Date(year, parseInt(month) - 1, day, hour, minute, 0, 0); } diff --git a/src/static/js/page/event.js b/src/static/js/page/event.js index 52546c3..eb148e5 100644 --- a/src/static/js/page/event.js +++ b/src/static/js/page/event.js @@ -1,3 +1,8 @@ +// if it is undefined, current mode is add +// or it is the detail data gotten from api +var ccn_event_editingEvent = undefined; +var ccn_event_collectionCache = []; + $(document).ready(function() { ccn_pages_currentPage = ccn_pages_enumPages.event; @@ -17,8 +22,25 @@ $(document).ready(function() { ccn_i18n_LoadLanguage(); ccn_i18n_ApplyLanguage(); - // init datetimepicker - ccn_datetimepicker_Init(); + // bind event + $('input[type=radio][name=loop-method]').click(ccn_event_RefreshRadioDiaplay); + $('input[type=radio][name=loop-end]').click(ccn_event_RefreshRadioDiaplay); + + // init form + ccn_event_Init(); + + // refresh once + ccn_event_RefreshRadioDiaplay(); + ccn_event_RefreshLoopMonthType(); +}); + + +function ccn_event_Init() { + // we need init some elements first + + // we need all radio and checkbox's checked is false, not undefined. + $('input[type=radio]').prop("checked", false); + $('input[type=checkbox]').prop("checked", false); // init span picker $('.spanpicker').attr('max', 100) @@ -26,48 +48,170 @@ $(document).ready(function() { .attr('step', 1) .val(1); - // refresh once + // now, init 3 datetimepicker + ccn_datetimepicker_Init(); - - // bind event + // in there, we need get uuid from meta + var uuid = $('meta[name=uuid]').attr('content'); + if (uuid != "") + ccn_event_editingEvent = ccn_api_calendar_getDetail(uuid); + // if ccn_event_editingEvent is undefined, init following content with add mode + // otherwise, init as update mode + var isAdd = typeof(ccn_event_editingEvent) == 'undefined'; -}); - - -function ccn_event_Deploy() { - var isAdd = typeof(ccn_calendar_eventModal_editing) == 'undefined'; + // init title and description $('#ccn-event-inputTitle').val( - isAdd ? '' : ccn_calendar_eventModal_editing[2] + isAdd ? '' : ccn_event_editingEvent[2] ); $('#ccn-event-inputDescription').val( - isAdd ? '' : ccn_calendar_eventModal_editing[3] + isAdd ? '' : ccn_event_editingEvent[3] ); - // we also need render eventModal collection select + // init collection picker, first we need query data + // and render it var collectionDOM = $('#ccn-event-inputCollection'); - collectionDOM.options.length = 0; - for(var index in ccn_calendar_eventModal_collectionCache) { - var uuid = ccn_calendar_eventModal_collectionCache[index]; - collectionDOM.add(new Option( + collectionDOM.empty(); + ccn_event_collectionCache = new Array(); + var result = ccn_api_collection_getFullOwn(); + if (typeof(result) != 'undefined') { + var renderdata = { + val: undefined, + name: undefined + } - )); + for (var index in result) { + var item = result[index]; + ccn_event_collectionCache.push(item[0]) + renderdata.val = item[0]; + renderdata.name = item[1]; + collectionDOM.append( + ccn_template_optionItem.render(renderdata) + ); + } } - $('#ccn-event-inputCollection').selectedIndex = isAdd ? -1 : ccn_calendar_eventModal_collectionCache.indexOf(ccn_calendar_eventModal_editing[1]); + // in add mode, set as -1, otherwise try to match original data + // indexOf will return -1 if no matched item + collectionDOM.val(isAdd ? '' : ccn_calendar_eventModal_editing[1]); - var currentDateTime = new Date(); - currentDateTime.setMilliseconds(0); - currentDateTime.setSeconds(0); - currentDateTime.setMinutes(0); - ccn_datetimepicker_Set(1, currentDateTime); + // init start and end datetime + if (isAdd) { + // in add mode, init 2 datetime picker as close hours based time. + var currentDateTime = new Date(); + currentDateTime.setMilliseconds(0); + currentDateTime.setSeconds(0); + currentDateTime.setMinutes(0); + ccn_datetimepicker_Set(1, currentDateTime); + + // time span is 2 hours + currentDateTime.setHours(currentDateTime.getHours() + 2); + ccn_datetimepicker_Set(2, currentDateTime); + } else { + // in update mode, match it with original data + var originalDateTime = new Date(ccn_event_editingEvent[5] * 60000); + ccn_datetimepicker_Set(1, originalDateTime); - currentDateTime.setHours(currentDateTime.getHours() + 2); - ccn_datetimepicker_Set(2, currentDateTime); + originalDateTime = new Date(ccn_event_editingEvent[6] * 60000); + ccn_datetimepicker_Set(2, originalDateTime); + } + // setup timezone here + // to prevent some error + // because following isAdd will change its meaning + $('#ccn-event-timezone-radioKeep').prop('checked', true); // give a default value + var nowtime = new Date(); + SmarterShowHide( + (!isAdd) && nowtime.getTimezoneOffset() != ccn_event_editingEvent[7], + $('#ccn-event-boxTimezone') + ); + // ======================== + // now we need resolve loop rules and set related data + if (!isAdd) { + data = ccn_datetime_ResolveLoopRules4UI(ccn_event_editingEvent[8]); + if (typeof(data) == 'undefined') isAdd = true; // init as add + } + + // give some value with a default value + $('#ccn-event-loopMonth-radioA').prop('checked', true); + var weekDate = undefined; + if (isAdd) weekDate = nowtime; + else weekDate = new Date(ccn_event_editingEvent[5] * 60000); + $('#ccn-event-loopWeek-check' + (weekDate.getDay() + 1)).prop('checked', true); + + // real process + if (isAdd) $('#ccn-event-radioLoopNever').prop('checked', true); + else { + switch(data[0][0]) { + case 0: + $('#ccn-event-radioLoopYear').prop('checked', true); + $('#ccn-event-loopYear-inputSpan').val(data[0][2]); + break; + case 1: + $('#ccn-event-radioLoopMonth').prop('checked', true); + $('#ccn-event-loopMonth-inputSpan').val(data[0][3]); + $('#ccn-event-loopMonth-radio' + data[0][2]).prop('checked', true); + break; + case 2: + $('#ccn-event-radioLoopWeek').prop('checked', true); + $('#ccn-event-loopWeek-inputSpan').val(data[0][8]); + for(var i = 1; i <= 7; i++) { + $('#ccn-event-loopWeek-check' + i).prop('checked', data[0][i]); + } + break; + case 3: + $('#ccn-event-radioLoopDay').prop('checked', true); + $('#ccn-event-loopDay-inputSpan').val(data[0][1]); + break; + } + } + + if (isAdd) { + $('#ccn-event-loopStop-radioForever').prop('checked', true); + ccn_datetimepicker_Set(3, nowtime); + } else { + switch(data[1][0]) { + case 0: + $('#ccn-event-loopStop-radioForever').prop('checked', true); + break; + case 1: + $('#ccn-event-loopStop-radioDateTime').prop('checked', true); + var stopDatetime = new Date(data[1][1] * 60000); + ccn_datetimepicker_Set(3, stopDatetime); + break; + case 2: + $('#ccn-event-loopStop-radioTimes').prop('checked', true); + $('#ccn-event-loopStop-inputTimes').val(data[1][1]); + break; + } + } } -function ccn_event_Refresh() { +// refresh some ui element according to form options +function ccn_event_RefreshRadioDiaplay() { + // loop method + // note: no loop control loop stop's display + // note: year and month loop also control strict mode display + SmarterShowHide(!$('#ccn-event-radioLoopNever').prop('checked'), $('#ccn-event-boxLoopStop')); + + SmarterShowHide($('#ccn-event-radioLoopDay').prop('checked'), $('#ccn-event-boxLoopDay')); + SmarterShowHide($('#ccn-event-radioLoopWeek').prop('checked'), $('#ccn-event-boxLoopWeek')); + SmarterShowHide($('#ccn-event-radioLoopMonth').prop('checked'), $('#ccn-event-boxLoopMonth')); + SmarterShowHide($('#ccn-event-radioLoopYear').prop('checked'), $('#ccn-event-boxLoopYear')); + + SmarterShowHide( + $('#ccn-event-radioLoopMonth').prop('checked') || $('#ccn-event-radioLoopYear').prop('checked'), + $('#ccn-event-boxStrictMode') + ); + + // loop stop + SmarterShowHide($('#ccn-event-loopStop-radioForever').prop('checked'), undefined); + SmarterShowHide($('#ccn-event-loopStop-radioDateTime').prop('checked'), $('#ccn-event-boxLoopStopDateTime')); + SmarterShowHide($('#ccn-event-loopStop-radioTimes').prop('checked'), $('#ccn-event-boxLoopStopTimes')); + +} + +function ccn_event_RefreshLoopMonthType() { } @@ -75,3 +219,4 @@ function ccn_event_Refresh() { function ccn_event_Get() { } + diff --git a/src/static/js/template.js b/src/static/js/template.js index cb8df2b..cf0ee57 100644 --- a/src/static/js/template.js +++ b/src/static/js/template.js @@ -8,6 +8,7 @@ var ccn_template_displayOwnedItem = undefined; var ccn_template_displaySharedItem = undefined; var ccn_template_userItem = undefined; var ccn_template_todoItem = undefined; +var ccn_template_optionItem = undefined; function ccn_template_Load() { $.ajax({ @@ -104,6 +105,13 @@ function ccn_template_Load() { } }); case ccn_pages_enumPages.event: - break; + $.ajax({ + url: $("#jsrender-tmpl-optionItem").attr('src'), + type: "GET", + async: false, + success: function (data) { + ccn_template_optionItem = $.templates(data); + } + }); } } \ No newline at end of file diff --git a/src/static/js/utils.js b/src/static/js/utils.js index 38c9bfc..fbd2dc5 100644 --- a/src/static/js/utils.js +++ b/src/static/js/utils.js @@ -43,4 +43,10 @@ function LineBreaker2Br(strl) { function IsUndefinedOrEmpty(data) { return (typeof(data) == 'undefined' || data == ""); +} + +function SmarterShowHide(boolean, element) { + if (typeof(element) == 'undefined') return; + if (boolean) element.show(); + else element.hide(); } \ No newline at end of file diff --git a/src/static/tmpl/optionItem.tmpl b/src/static/tmpl/optionItem.tmpl new file mode 100644 index 0000000..af1e935 --- /dev/null +++ b/src/static/tmpl/optionItem.tmpl @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/templates/event.html b/src/templates/event.html index 0ed89e8..2f1e338 100644 --- a/src/templates/event.html +++ b/src/templates/event.html @@ -17,6 +17,7 @@ + @@ -35,310 +36,310 @@
-