(function () { var selector = '[data-weekpicker]', all = []; var fullDate = ''; function clearWeekPickers(except) { var ii; for (ii = 0; ii < all.length; ii++) { if (all[ii] != except) { all[ii].hide(); } } } function WeekPicker(element, options) { this.$el = $(element); this.proxy('show').proxy('ahead').proxy('hide').proxy('keyHandler').proxy('selectWeek'); var options = $.extend({}, $.fn.weekpicker.defaults, options); if ((!!options.parse) || (!!options.format) || !this.detectNative()) { $.extend(this, options); this.$el.data('weekpicker', this); all.push(this); this.init(); } } WeekPicker.prototype = { detectNative:function (el) { if (navigator.userAgent.match(/(iPad|iPhone); CPU(\ iPhone)? OS 5_\d/i)) { // jQuery will only change the input type of a detached element. var $marker = $('').insertBefore(this.$el); this.$el.detach().attr('type', 'date').insertAfter($marker); $marker.remove(); return true; } return false; }, init:function () { this.setParams(); var $nav = $('
').addClass('week-nav').append(this.nav(this.months)); this.calculateDates(); $calendar = $("").addClass('calendar'); this.$months = $(''); $calendar.append(this.$months); this.$picker = $('
') .click(function (e) { e.stopPropagation(); }) // Use this to prevent accidental text selection. .mousedown(function (e) { e.preventDefault(); }) .addClass('weekpicker') .append($nav, $calendar) .insertAfter(this.$el); this.$el .focus(this.show) .click(this.show) .change($.proxy(function () { this.selectWeek(); }, this)); this.selectWeek(); this.hide(); }, setParams:function () { var data; data = this.$el.attr('data-target'); this.$target = data ? $(data) : this.$el; data = parseInt(this.$el.attr('data-months')); this.months = data ? data : this.months; data = parseInt(this.$el.attr('data-week_start')); this.week_start = data ? data : this.week_start; }, selectWeek:function (week) { if (typeof(week) == "undefined") { week = this.$target.val(); //console.log(week); } this.$months.empty(); this.renderView(); $('.week', this.$months).click($.proxy(function (e) { this.update($(e.target).parent().attr("date")); }, this)).hover(function (e) { $('.highlighted', this.$months).removeClass('highlighted'); $(this).addClass('highlighted'); }); $('.selected', this.$months).removeClass('selected'); $('[date="' + week + '"]', this.$months).addClass('selected'); this.hide(); }, renderView:function () { var dates = [ [this.rangeStart(this.start), this.mid, 999], [this.mid_next, this.end, 999] ], thisDay, prevMonth = -1, weekEnd, tmp, row, col, label, firstDay, box_class; for (var c = 0; c < (this.months <= 1 ? 1 : 2); c++) { var m = -1, w = 0; dates[c][2] = this.daysBetween(dates[c][0], dates[c][1]); $col = $('
').addClass('month-col'); $monthDays = $(''); //Render head $head = $("").addClass('head'); $head.append($('').addClass('week'); //Print month label if (thisDay.getMonth() != prevMonth) { label = $('
')); for (var i = 0; i < this.shortDayNames.length; i++) { tmp = $('').addClass('dow'); tmp.text(this.shortDayNames[(i + this.week_start) % 7]); $head.append(tmp); } $monthDays.append($head); //Render date cells with month label for (var d = 0; d <= dates[c][2]; d++) { thisDay = this.incrementDay(dates[c][0], d); box_class = 'box' + (thisDay.getMonth() % 2); //Creating and append week in to month if (this.week_start == thisDay.getDay()) { firstDay = thisDay; row = $('
'); tmp = this.incrementDay(thisDay, 6); if (tmp.getMonth() == thisDay.getMonth()) { tmp = this.incrementDay(thisDay, 28); tmp = (tmp.getMonth() == thisDay.getMonth() ? 7 : 6); label.attr('rowspan', tmp); label.text(this.monthNames[thisDay.getMonth()] + '\n' + thisDay.getFullYear().toString()); label.addClass('week-label ' + box_class.replace('box', 'span')); fullDate = thisDay.getFullYear().toString() + ' ' + this.monthNames[thisDay.getMonth()]; //console.log(fullDate); } row.append(label); } //Set week range weekEnd = this.incrementDay(thisDay, 6); row.attr('date', this.formatWeek(thisDay, weekEnd)); if (prevMonth != thisDay.getMonth()) { m = m + 1; prevMonth = thisDay.getMonth(); } } //Append Day in to Week col = $('').attr('date', this.format(thisDay)); col.text(thisDay.getDate()); col.addClass(box_class); row.append(col); if (d % 7 == 0) { $monthDays.append(row); } } $col.append($monthDays); this.$months.append($col); } }, proxy:function (meth) { this[meth] = $.proxy(this[meth], this); return this; }, daysBetween:function (start, end) { var start = Date.UTC(start.getFullYear(), start.getMonth(), start.getDate()); var end = Date.UTC(end.getFullYear(), end.getMonth(), end.getDate()); return (end - start) / 86400000; }, findClosest:function (dow, date, direction) { var difference = direction * (Math.abs(date.getDay() - dow - (direction * 7)) % 7); return new Date(date.getFullYear(), date.getMonth(), date.getDate() + difference); }, rangeStart:function (date) { return this.findClosest(this.week_start, new Date(date.getFullYear(), date.getMonth()), -1); }, rangeEnd:function (date) { return this.findClosest((this.week_start - 1) % 7, new Date(date.getFullYear(), date.getMonth() + 1, 0), 1); }, update:function (s) { this.$target.val(s); this.$target.attr("data-value", s); this.$el.val(s).change(); }, show:function (e) { e && e.stopPropagation(); clearWeekPickers(this); var offset = this.$el.offset(); this.$picker.css({ //top:offset.top + this.$el.outerHeight() + 2, //left:offset.left }).show(); $('html').on('keydown', this.keyHandler); }, hide:function () { this.$picker.hide(); $('html').off('keydown', this.keyHandler); }, keyHandler:function (e) { // Keyboard navigation shortcuts. switch (e.keyCode) { case 9: case 27: case 13: this.hide(); break; default: return; } e.preventDefault(); }, parse:function (s) { // Parse a partial RFC 3339 string into a Date. var m; if ((m = s.match(/^(\d{2,2})\/(\d{2,2})\/(\d{2,2})$/))) { return new Date(m[0], m[1] - 1, m[2]); } else { return null; } }, format:function (date) { // Format a Date into a string as specified by RFC 3339. var month = (date.getMonth() + 1).toString(), dom = date.getDate().toString(); if (month.length === 1) { month = '0' + month; } if (dom.length === 1) { dom = '0' + dom; } //return month + "/" + dom + '/' + date.getFullYear().toString().substr(2, 2); return date.getFullYear().toString() + "-" + month + "-" + dom; }, formatWeek:function (from, to) { return this.format(from) + '#' + this.format(to); }, nav:function (months) { // var date = new Date(this.start.getFullYear(), this.start.getMonth() + months, 1); var $subnav = $('
' + '<< ' + ' >> ' + '
'); $('.prev', $subnav).click($.proxy(function () { this.ahead(-months) }, this)); $('.next', $subnav).click($.proxy(function () { this.ahead(months) }, this)); $('.prev-year', $subnav).click($.proxy(function () { this.aheady(-1) }, this)); $('.next-year', $subnav).click($.proxy(function () { this.aheady(1) }, this)); return $subnav; }, incrementDay:function (d, i) { return new Date(d.getFullYear(), d.getMonth(), d.getDate() + i, 12, 00); }, ahead:function (months) { var date = new Date(this.start.getFullYear(), this.start.getMonth() + months, 1); this.calculateDates(date); this.selectWeek(); }, aheady:function (years) { var date = new Date(this.start.getFullYear() + years, this.start.getMonth() , 1); this.calculateDates(date); this.selectWeek(); }, calculateDates:function (date) { this.start = date ? date : new Date(); this.mid = this.rangeEnd(new Date(this.start.getFullYear(), this.start.getMonth() + Math.ceil(this.months / 2), 0)); this.mid_next = new Date(this.mid.getFullYear(), this.mid.getMonth(), this.mid.getDate() + 1); this.end = this.rangeEnd(new Date(this.start.getFullYear(), this.start.getMonth() + this.months, 0)); } }; /* WEEK PICKER DEFINITION * ============================ */ $(document).ready(function () { $.fn.weekpicker = function (options) { return this.each(function () { new WeekPicker(this, options); }); }; $(function () { $(selector).weekpicker(); $('html').click(clearWeekPickers); }); $.fn.weekpicker.WeekPicker = WeekPicker; $.fn.weekpicker.defaults = { monthNames:["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], shortDayNames:["周日", "周一", "周二", "周三", "周四", "周五", "周六"], week_start:0, months:6 }; }); }());