diff options
author | Thomas ZILLIOX <thomas@zilliox.me> | 2013-05-08 20:42:09 +0400 |
---|---|---|
committer | Thomas ZILLIOX <thomas@zilliox.me> | 2013-05-08 20:42:09 +0400 |
commit | b830387b839f6a1732d310e26fa81de27e19ff95 (patch) | |
tree | a6cf18412a42b0db34b9941de89724bb2f7dadd9 /plugins/CoreHome/javascripts/calendar.js | |
parent | eeb6be9d1e4bb54a05b78537a080622dc764e72e (diff) |
Reorganizing the stylesheets & javascripts folders for every plugins
Diffstat (limited to 'plugins/CoreHome/javascripts/calendar.js')
-rw-r--r-- | plugins/CoreHome/javascripts/calendar.js | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/plugins/CoreHome/javascripts/calendar.js b/plugins/CoreHome/javascripts/calendar.js new file mode 100644 index 0000000000..e531e375a9 --- /dev/null +++ b/plugins/CoreHome/javascripts/calendar.js @@ -0,0 +1,539 @@ +/*! + * Piwik - Web Analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +(function ($) { + + Date.prototype.getWeek = function () { + var onejan = new Date(this.getFullYear(), 0, 1), // needed for getDay() + + // use UTC times since getTime() can differ based on user's timezone + onejan_utc = Date.UTC(this.getFullYear(), 0, 1), + this_utc = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate()), + + daysSinceYearStart = (this_utc - onejan_utc) / 86400000; // constant is millisecs in one day + + return Math.ceil((daysSinceYearStart + onejan.getDay()) / 7); + } + + var currentYear, currentMonth, currentDay, currentDate, currentWeek; + + function setCurrentDate(dateStr) { + var splitDate = dateStr.split("-"); + currentYear = splitDate[0]; + currentMonth = splitDate[1] - 1; + currentDay = splitDate[2]; + currentDate = new Date(currentYear, currentMonth, currentDay); + currentWeek = currentDate.getWeek(); + } + + setCurrentDate(piwik.currentDateString); + + var todayDate = new Date; + var todayMonth = todayDate.getMonth(); + var todayYear = todayDate.getFullYear(); + var todayDay = todayDate.getDate(); + +// min/max date for picker + var piwikMinDate = new Date(piwik.minDateYear, piwik.minDateMonth - 1, piwik.minDateDay), + piwikMaxDate = new Date(piwik.maxDateYear, piwik.maxDateMonth - 1, piwik.maxDateDay); + +// we start w/ the current period + var selectedPeriod = piwik.period; + + function isDateInCurrentPeriod(date) { + // if the selected period isn't the current period, don't highlight any dates + if (selectedPeriod != piwik.period) { + return [true, '']; + } + + var valid = false; + + var dateMonth = date.getMonth(); + var dateYear = date.getFullYear(); + var dateDay = date.getDate(); + var style = ''; + + // we don't color dates in the future + if (dateMonth == todayMonth + && dateYear == todayYear + && dateDay > todayDay + ) { + return [true, '']; + } + + // we don't color dates before the minimum date + if (dateYear < piwik.minDateYear + || ( dateYear == piwik.minDateYear + && + ( + (dateMonth == piwik.minDateMonth - 1 + && dateDay < piwik.minDateDay) + || (dateMonth < piwik.minDateMonth - 1) + ) + ) + ) { + return [true, '']; + } + + // we color all day of the month for the same year for the month period + if (piwik.period == "month" + && dateMonth == currentMonth + && dateYear == currentYear + ) { + valid = true; + } + // we color all day of the year for the year period + else if (piwik.period == "year" + && dateYear == currentYear + ) { + valid = true; + } + else if (piwik.period == "week" + && date.getWeek() == currentWeek + && dateYear == currentYear + ) { + valid = true; + } + else if (piwik.period == "day" + && dateDay == currentDay + && dateMonth == currentMonth + && dateYear == currentYear + ) { + valid = true; + } + + if (valid) { + return [true, 'ui-datepicker-current-period']; + } + + return [true, '']; + } + + piwik.getBaseDatePickerOptions = function (defaultDate) { + return { + showOtherMonths: false, + dateFormat: 'yy-mm-dd', + firstDay: 1, + minDate: piwikMinDate, + maxDate: piwikMaxDate, + prevText: "", + nextText: "", + currentText: "", + defaultDate: defaultDate, + changeMonth: true, + changeYear: true, + stepMonths: 1, + // jquery-ui-i18n 1.7.2 lacks some translations, so we use our own + dayNamesMin: [ + _pk_translate('General_DaySu_js'), + _pk_translate('General_DayMo_js'), + _pk_translate('General_DayTu_js'), + _pk_translate('General_DayWe_js'), + _pk_translate('General_DayTh_js'), + _pk_translate('General_DayFr_js'), + _pk_translate('General_DaySa_js')], + dayNamesShort: [ + _pk_translate('General_ShortDay_1_js'), + _pk_translate('General_ShortDay_2_js'), + _pk_translate('General_ShortDay_3_js'), + _pk_translate('General_ShortDay_4_js'), + _pk_translate('General_ShortDay_5_js'), + _pk_translate('General_ShortDay_6_js'), + _pk_translate('General_ShortDay_7_js')], + dayNames: [ + _pk_translate('General_LongDay_1_js'), + _pk_translate('General_LongDay_2_js'), + _pk_translate('General_LongDay_3_js'), + _pk_translate('General_LongDay_4_js'), + _pk_translate('General_LongDay_5_js'), + _pk_translate('General_LongDay_6_js'), + _pk_translate('General_LongDay_7_js')], + monthNamesShort: [ + _pk_translate('General_ShortMonth_1_js'), + _pk_translate('General_ShortMonth_2_js'), + _pk_translate('General_ShortMonth_3_js'), + _pk_translate('General_ShortMonth_4_js'), + _pk_translate('General_ShortMonth_5_js'), + _pk_translate('General_ShortMonth_6_js'), + _pk_translate('General_ShortMonth_7_js'), + _pk_translate('General_ShortMonth_8_js'), + _pk_translate('General_ShortMonth_9_js'), + _pk_translate('General_ShortMonth_10_js'), + _pk_translate('General_ShortMonth_11_js'), + _pk_translate('General_ShortMonth_12_js')], + monthNames: [ + _pk_translate('General_MonthJanuary_js'), + _pk_translate('General_MonthFebruary_js'), + _pk_translate('General_MonthMarch_js'), + _pk_translate('General_MonthApril_js'), + _pk_translate('General_MonthMay_js'), + _pk_translate('General_MonthJune_js'), + _pk_translate('General_MonthJuly_js'), + _pk_translate('General_MonthAugust_js'), + _pk_translate('General_MonthSeptember_js'), + _pk_translate('General_MonthOctober_js'), + _pk_translate('General_MonthNovember_js'), + _pk_translate('General_MonthDecember_js')] + }; + }; + + var updateDate; + + function getDatePickerOptions() { + var result = piwik.getBaseDatePickerOptions(currentDate); + result.beforeShowDay = isDateInCurrentPeriod; + result.stepMonths = selectedPeriod == 'year' ? 12 : 1; + result.onSelect = function () { updateDate.apply(this, arguments); }; + return result; + }; + + $(document).ready(function () { + + var datepickerElem = $('#datepicker').datepicker(getDatePickerOptions()), + periodLabels = $('#periodString').find('.period-type label'), + periodTooltip = $('#periodString').find('.period-click-tooltip').html(); + + var toggleWhitespaceHighlighting = function (klass, toggleTop, toggleBottom) { + var viewedYear = $('.ui-datepicker-year', datepickerElem).val(), + viewedMonth = +$('.ui-datepicker-month', datepickerElem).val(), // convert to int w/ '+' + firstOfViewedMonth = new Date(viewedYear, viewedMonth, 1), + lastOfViewedMonth = new Date(viewedYear, viewedMonth + 1, 0); + + // only highlight dates between piwik.minDate... & piwik.maxDate... + // we select the cells to highlight by checking whether the first & last of the + // currently viewed month are within the min/max dates. + if (firstOfViewedMonth >= piwikMinDate) { + $('tbody>tr:first-child td.ui-datepicker-other-month', datepickerElem).toggleClass(klass, toggleTop); + } + if (lastOfViewedMonth < piwikMaxDate) { + $('tbody>tr:last-child td.ui-datepicker-other-month', datepickerElem).toggleClass(klass, toggleBottom); + } + }; + + // 'this' is the table cell + var highlightCurrentPeriod = function () { + switch (selectedPeriod) { + case 'day': + // highlight this link + $('a', $(this)).addClass('ui-state-hover'); + break; + case 'week': + var row = $(this).parent(); + + // highlight parent row (the week) + $('a', row).addClass('ui-state-hover'); + + // toggle whitespace if week goes into previous or next month. we check if week is on + // top or bottom row. + var toggleTop = row.is(':first-child'), + toggleBottom = row.is(':last-child'); + toggleWhitespaceHighlighting('ui-state-hover', toggleTop, toggleBottom); + break; + case 'month': + // highlight all parent rows (the month) + $('a', $(this).parent().parent()).addClass('ui-state-hover'); + break; + case 'year': + // highlight table (month + whitespace) + $('a', $(this).parent().parent()).addClass('ui-state-hover'); + toggleWhitespaceHighlighting('ui-state-hover', true, true); + break; + } + }; + + var unhighlightAllDates = function () { + // make sure nothing is highlighted + $('.ui-state-active,.ui-state-hover', datepickerElem).removeClass('ui-state-active ui-state-hover'); + + // color whitespace + if (piwik.period == 'year') { + var viewedYear = $('.ui-datepicker-year', datepickerElem).val(), + toggle = selectedPeriod == 'year' && currentYear == viewedYear; + toggleWhitespaceHighlighting('ui-datepicker-current-period', toggle, toggle); + } + else if (piwik.period == 'week') { + var toggleTop = $('tr:first-child a', datepickerElem).parent().hasClass('ui-datepicker-current-period'), + toggleBottom = $('tr:last-child a', datepickerElem).parent().hasClass('ui-datepicker-current-period'); + toggleWhitespaceHighlighting('ui-datepicker-current-period', toggleTop, toggleBottom); + } + }; + + updateDate = function (dateText) { + piwikHelper.showAjaxLoading('ajaxLoadingCalendar'); + + // select new dates in calendar + setCurrentDate(dateText); + piwik.period = selectedPeriod; + + // make sure it's called after jquery-ui is done, otherwise everything we do will + // be undone. + setTimeout(unhighlightAllDates, 1); + + datepickerElem.datepicker('refresh'); + + // Let broadcast do its job: + // It will replace date value to both search query and hash and load the new page. + broadcast.propagateNewPage('date=' + dateText + '&period=' + selectedPeriod); + }; + + var toggleMonthDropdown = function (disable) { + if (typeof disable === 'undefined') { + disable = selectedPeriod == 'year'; + } + + // enable/disable month dropdown based on period == year + $('.ui-datepicker-month', datepickerElem).attr('disabled', disable); + }; + + var togglePeriodPickers = function (showSingle) { + $('#periodString .period-date').toggle(showSingle); + $('#periodString .period-range').toggle(!showSingle); + $('#calendarRangeApply').toggle(!showSingle); + }; + + // + // setup datepicker + // + + unhighlightAllDates(); + + // + // hook up event slots + // + + // highlight current period when mouse enters date + datepickerElem.on('mouseenter', 'tbody td', function () { + if ($(this).hasClass('ui-state-hover')) // if already highlighted, do nothing + { + return; + } + + // unhighlight if cell is disabled/blank, unless the period is year + if ($(this).hasClass('ui-state-disabled') && selectedPeriod != 'year') { + unhighlightAllDates(); + + // if period is week, then highlight the current week + if (selectedPeriod == 'week') { + highlightCurrentPeriod.call(this); + } + } + else { + highlightCurrentPeriod.call(this); + } + }); + + // make sure cell stays highlighted when mouse leaves cell (overrides jquery-ui behavior) + datepickerElem.on('mouseleave', 'tbody td', function () { + $('a', this).addClass('ui-state-hover'); + }); + + // unhighlight everything when mouse leaves table body (can't do event on tbody, for some reason + // that fails, so we do two events, one on the table & one on thead) + datepickerElem.on('mouseleave', 'table', unhighlightAllDates) + .on('mouseenter', 'thead', unhighlightAllDates); + + // make sure whitespace is clickable when the period makes it appropriate + datepickerElem.on('click', 'tbody td.ui-datepicker-other-month', function () { + if ($(this).hasClass('ui-state-hover')) { + var row = $(this).parent(), tbody = row.parent(); + + if (row.is(':first-child')) { + // click on first of the month + $('a', tbody).first().click(); + } + else { + // click on last of month + $('a', tbody).last().click(); + } + } + }); + + // Hack to get around firefox bug. When double clicking a label in firefox, the 'click' + // event of its associated input will not be fired twice. We want to change the period + // if clicking the select period's label OR input, so we catch the click event on the + // label & the input. + var reloading = false; + var changePeriodOnClick = function (periodInput) { + if (reloading) // if a click event resulted in reloading, don't reload again + { + return; + } + + var url = periodInput.val(), + period = broadcast.getValueFromUrl('period', url); + + // if clicking on the selected period, change the period but not the date + if (selectedPeriod == period && selectedPeriod != 'range') { + // only reload if current period is different from selected + if (piwik.period != selectedPeriod && !reloading) { + reloading = true; + selectedPeriod = period; + updateDate(piwik.currentDateString); + } + return true; + } + + return false; + }; + + $("#otherPeriods label").on('click', function (e) { + var id = $(e.target).attr('for'); + changePeriodOnClick($('#' + id)); + }); + + // when non-range period is clicked, change the period & refresh the date picker + $("#otherPeriods input").on('click', function (e) { + var request_URL = $(e.target).val(), + period = broadcast.getValueFromUrl('period', request_URL), + lastPeriod = selectedPeriod; + + if (changePeriodOnClick($(e.target))) { + return true; + } + + // switch the selected period + selectedPeriod = period; + + // remove tooltips from the period inputs + periodLabels.each(function () { $(this).attr('title', '').removeClass('selected-period-label'); }); + + // range periods are handled in an event handler below + if (period == 'range') { + return true; + } + + // set the tooltip of the current period + if (period != piwik.period) // don't add tooltip for current period + { + $(this).parent().find('label[for=period_id_' + period + ']') + .attr('title', periodTooltip).addClass('selected-period-label'); + } + + // toggle the right selector controls (show period selector datepicker & hide 'apply range' button) + togglePeriodPickers(true); + + // set months step to 12 for year period (or set back to 1 if leaving year period) + if (selectedPeriod == 'year' || lastPeriod == 'year') { + // setting stepMonths will change the month in view back to the selected date. to avoid + // we set the selected date to the month in view. + var currentMonth = $('.ui-datepicker-month', datepickerElem).val(), + currentYear = $('.ui-datepicker-year', datepickerElem).val(); + + datepickerElem + .datepicker('option', 'stepMonths', selectedPeriod == 'year' ? 12 : 1) + .datepicker('setDate', new Date(currentYear, currentMonth)); + } + + datepickerElem.datepicker('refresh'); // must be last datepicker call, otherwise cells get highlighted + + unhighlightAllDates(); + toggleMonthDropdown(); + + return true; + }); + + // clicking left/right re-enables the month dropdown, so we disable it again + $(datepickerElem).on('click', '.ui-datepicker-next,.ui-datepicker-prev', function () { + unhighlightAllDates(); // make sure today's date isn't highlighted & toggle extra year highlighting + toggleMonthDropdown(selectedPeriod == 'year'); + }); + + // reset date/period when opening calendar + var firstClick = true; + $('#periodString #date').click(function () { + if (!firstClick) { + datepickerElem.datepicker('setDate', currentDate); + $('#period_id_' + piwik.period).click(); + } + + firstClick = false; + }); + + function onDateRangeSelect(dateText, inst) { + var toOrFrom = inst.id == 'calendarFrom' ? 'From' : 'To'; + $('#inputCalendar' + toOrFrom).val(dateText); + } + + // this will trigger to change only the period value on search query and hash string. + $("#period_id_range").on('click', function (e) { + togglePeriodPickers(false); + + var options = getDatePickerOptions(); + + // Custom Date range callback + options.onSelect = onDateRangeSelect; + // Do not highlight the period + options.beforeShowDay = ''; + // Create both calendars + options.defaultDate = piwik.startDateString; + $('#calendarFrom').datepicker(options).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', piwik.startDateString)); + + // Technically we should trigger the onSelect event on the calendar, but I couldn't find how to do that + // So calling the onSelect bind function manually... + //$('#calendarFrom').trigger('dateSelected'); // or onSelect + onDateRangeSelect(piwik.startDateString, { "id": "calendarFrom" }); + + // Same code for the other calendar + options.defaultDate = piwik.endDateString; + $('#calendarTo').datepicker(options).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', piwik.endDateString)); + onDateRangeSelect(piwik.endDateString, { "id": "calendarTo" }); + + + // If not called, the first date appears light brown instead of dark brown + $('.ui-state-hover').removeClass('ui-state-hover'); + + // Apply date range button will reload the page with the selected range + $('#calendarRangeApply') + .on('click', function () { + var request_URL = $(e.target).val(); + var dateFrom = $('#inputCalendarFrom').val(), + dateTo = $('#inputCalendarTo').val(), + oDateFrom = $.datepicker.parseDate('yy-mm-dd', dateFrom), + oDateTo = $.datepicker.parseDate('yy-mm-dd', dateTo); + + if (!isValidDate(oDateFrom) + || !isValidDate(oDateTo) + || oDateFrom > oDateTo) { + $('#alert h2').text(_pk_translate('General_InvalidDateRange_js')); + piwikHelper.modalConfirm('#alert', {}); + return false; + } + piwikHelper.showAjaxLoading('ajaxLoadingCalendar'); + broadcast.propagateNewPage('period=range&date=' + dateFrom + ',' + dateTo); + }) + .show(); + + + // Bind the input fields to update the calendar's date when date is manually changed + $('#inputCalendarFrom, #inputCalendarTo') + .keyup(function (e) { + var fromOrTo = this.id == 'inputCalendarFrom' ? 'From' : 'To'; + var dateInput = $(this).val(); + try { + var newDate = $.datepicker.parseDate('yy-mm-dd', dateInput); + } catch (e) { + return; + } + $("#calendar" + fromOrTo).datepicker("setDate", newDate); + if (e.keyCode == 13) { + $('#calendarRangeApply').click(); + } + }); + return true; + }); + function isValidDate(d) { + if (Object.prototype.toString.call(d) !== "[object Date]") + return false; + return !isNaN(d.getTime()); + } + + var period = broadcast.getValueFromUrl('period'); + if (period == 'range') { + $("#period_id_range").click(); + } + }); + +}(jQuery)); |