diff --git a/dist/css/datepicker.css b/dist/css/datepicker.css index bfb6f39..61026a0 100644 --- a/dist/css/datepicker.css +++ b/dist/css/datepicker.css @@ -43,7 +43,14 @@ .datepicker--nav-action { width: 32px; } .datepicker--nav-action:hover { - background: #f6f6f6; } + background: #eee; } + +.datepicker--nav-title { + align-self: center; + padding: 4px; + border-radius: 2px; } + .datepicker--nav-title:hover { + background: #eee; } /* ------------------------------------------------- Datepicker cells @@ -69,3 +76,9 @@ .datepicker--cell-month { width: 33.33%; height: 40px; } + +.datepicker--cell-year { + width: 25%; + height: 40px; } + .datepicker--cell-year.-another-decade- { + color: #ddd; } diff --git a/dist/js/datepicker.js b/dist/js/datepicker.js index 7881bc9..c0c49a1 100644 --- a/dist/js/datepicker.js +++ b/dist/js/datepicker.js @@ -95,6 +95,10 @@ var Datepicker; break; case 'months': this.date = new Date(d.year + 1, d.month, 1); + break; + case 'years': + this.date = new Date(d.year + 10, 0, 1); + break; } }, @@ -107,6 +111,10 @@ var Datepicker; break; case 'months': this.date = new Date(d.year - 1, d.month, 1); + break; + case 'years': + this.date = new Date(d.year - 10, 0, 1); + break; } }, @@ -136,6 +144,8 @@ var Datepicker; if (this.inited) { if (!this.views[val]) { this.views[val] = new Datepicker.Body(this, val, this.opts) + } else { + this.views[val]._render(); } this.views[this.prevView].hide(); @@ -164,6 +174,12 @@ var Datepicker; } }; + Datepicker.getDecade = function (date) { + var firstYear = Math.floor(date.getFullYear() / 10) * 10; + + return [firstYear, firstYear + 9]; + }; + Datepicker.template = function (str, data) { return str.replace(/#\{([\w]+)\}/g, function (source, match) { if (data[match] || data[match] === 0) { @@ -239,9 +255,11 @@ var Datepicker; _getTitle: function (date) { var month = this.d.loc.months[date.getMonth()], year = date.getFullYear(), + decade = Datepicker.getDecade(date), types = { days: month + ', ' + year, - months: year + months: year, + years: decade[0] + ' - ' + decade[1] }; return types[this.d.view]; @@ -297,6 +315,12 @@ Datepicker.Cell = function () { init: function () { this._buildBaseHtml(); this._render(); + + this._bindEvents(); + }, + + _bindEvents: function () { + this.$el.on('click', '.datepicker--cell', $.proxy(this._onClickCell, this)); }, _buildBaseHtml: function () { @@ -354,7 +378,7 @@ Datepicker.Cell = function () { if (this.d.isWeekend(date.getDay())) _class += " -weekend-"; if (date.getMonth() != this.d.currentDate.getMonth()) _class += " -another-month-"; - return '
' + date.getDate() + '
'; + return '
' + date.getDate() + '
'; }, /** @@ -381,7 +405,33 @@ Datepicker.Cell = function () { d = Datepicker.getParsedDate(date), loc = this.d.loc; - return '
' + loc.months[d.month] + '
' + return '
' + loc.months[d.month] + '
' + }, + + _getYearsHtml: function (date) { + var d = Datepicker.getParsedDate(date), + decade = Datepicker.getDecade(date), + firstYear = decade[0] - 1, + html = '', + i = firstYear; + + for (i; i <= decade[1] + 1; i++) { + html += this._getYearHtml(new Date(i , 0)); + } + + return html; + }, + + _getYearHtml: function (date) { + var _class = "datepicker--cell datepicker--cell-year", + decade = Datepicker.getDecade(this.d.date), + d = Datepicker.getParsedDate(date); + + if (d.year < decade[0] || d.year > decade[1]) { + _class += ' -another-decade-'; + } + + return '
' + d.year + '
' }, _renderTypes: { @@ -398,18 +448,12 @@ Datepicker.Cell = function () { this.$cells.html(html) }, years: function () { - this.$cells.html('Years') + var html = this._getYearsHtml(this.d.currentDate); + + this.$cells.html(html) } }, - _renderDays: function () { - var dayNames = this._getDayNamesHtml(this.opts.firstDay), - days = this._getDaysHtml(this.d.currentDate); - - this.$cells.html(days); - this.$names.html(dayNames) - }, - _render: function () { this._renderTypes[this.type].bind(this)() }, @@ -422,6 +466,34 @@ Datepicker.Cell = function () { hide: function () { this.$el.removeClass('active'); this.active = false; + }, + + // Events + // ------------------------------------------------- + + _handleClick: { + days: function (el) { + + }, + months: function (el) { + var month = el.data('month'), + d = this.d.parsedDate; + + this.d.date = new Date(d.year, month, 1); + this.d.view = 'days'; + }, + years: function (el) { + var year = el.data('year'); + + this.d.date = new Date(year, 0, 1); + this.d.view = 'months'; + } + }, + + _onClickCell: function (e) { + var $el = $(e.target).closest('.datepicker--cell'); + + this._handleClick[this.d.currentView].bind(this)($el); } }; })(); diff --git a/js/datepicker/body.js b/js/datepicker/body.js index 9a7d821..e4e4116 100644 --- a/js/datepicker/body.js +++ b/js/datepicker/body.js @@ -27,6 +27,12 @@ init: function () { this._buildBaseHtml(); this._render(); + + this._bindEvents(); + }, + + _bindEvents: function () { + this.$el.on('click', '.datepicker--cell', $.proxy(this._onClickCell, this)); }, _buildBaseHtml: function () { @@ -84,7 +90,7 @@ if (this.d.isWeekend(date.getDay())) _class += " -weekend-"; if (date.getMonth() != this.d.currentDate.getMonth()) _class += " -another-month-"; - return '
' + date.getDate() + '
'; + return '
' + date.getDate() + '
'; }, /** @@ -111,7 +117,33 @@ d = Datepicker.getParsedDate(date), loc = this.d.loc; - return '
' + loc.months[d.month] + '
' + return '
' + loc.months[d.month] + '
' + }, + + _getYearsHtml: function (date) { + var d = Datepicker.getParsedDate(date), + decade = Datepicker.getDecade(date), + firstYear = decade[0] - 1, + html = '', + i = firstYear; + + for (i; i <= decade[1] + 1; i++) { + html += this._getYearHtml(new Date(i , 0)); + } + + return html; + }, + + _getYearHtml: function (date) { + var _class = "datepicker--cell datepicker--cell-year", + decade = Datepicker.getDecade(this.d.date), + d = Datepicker.getParsedDate(date); + + if (d.year < decade[0] || d.year > decade[1]) { + _class += ' -another-decade-'; + } + + return '
' + d.year + '
' }, _renderTypes: { @@ -128,18 +160,12 @@ this.$cells.html(html) }, years: function () { - this.$cells.html('Years') + var html = this._getYearsHtml(this.d.currentDate); + + this.$cells.html(html) } }, - _renderDays: function () { - var dayNames = this._getDayNamesHtml(this.opts.firstDay), - days = this._getDaysHtml(this.d.currentDate); - - this.$cells.html(days); - this.$names.html(dayNames) - }, - _render: function () { this._renderTypes[this.type].bind(this)() }, @@ -152,6 +178,34 @@ hide: function () { this.$el.removeClass('active'); this.active = false; + }, + + // Events + // ------------------------------------------------- + + _handleClick: { + days: function (el) { + + }, + months: function (el) { + var month = el.data('month'), + d = this.d.parsedDate; + + this.d.date = new Date(d.year, month, 1); + this.d.view = 'days'; + }, + years: function (el) { + var year = el.data('year'); + + this.d.date = new Date(year, 0, 1); + this.d.view = 'months'; + } + }, + + _onClickCell: function (e) { + var $el = $(e.target).closest('.datepicker--cell'); + + this._handleClick[this.d.currentView].bind(this)($el); } }; })(); diff --git a/js/datepicker/datepicker.js b/js/datepicker/datepicker.js index 7262f6a..367a2b3 100644 --- a/js/datepicker/datepicker.js +++ b/js/datepicker/datepicker.js @@ -95,6 +95,10 @@ var Datepicker; break; case 'months': this.date = new Date(d.year + 1, d.month, 1); + break; + case 'years': + this.date = new Date(d.year + 10, 0, 1); + break; } }, @@ -107,6 +111,10 @@ var Datepicker; break; case 'months': this.date = new Date(d.year - 1, d.month, 1); + break; + case 'years': + this.date = new Date(d.year - 10, 0, 1); + break; } }, @@ -136,6 +144,8 @@ var Datepicker; if (this.inited) { if (!this.views[val]) { this.views[val] = new Datepicker.Body(this, val, this.opts) + } else { + this.views[val]._render(); } this.views[this.prevView].hide(); @@ -164,6 +174,12 @@ var Datepicker; } }; + Datepicker.getDecade = function (date) { + var firstYear = Math.floor(date.getFullYear() / 10) * 10; + + return [firstYear, firstYear + 9]; + }; + Datepicker.template = function (str, data) { return str.replace(/#\{([\w]+)\}/g, function (source, match) { if (data[match] || data[match] === 0) { diff --git a/js/datepicker/navigation.js b/js/datepicker/navigation.js index 700bcfe..f4cf556 100644 --- a/js/datepicker/navigation.js +++ b/js/datepicker/navigation.js @@ -37,9 +37,11 @@ _getTitle: function (date) { var month = this.d.loc.months[date.getMonth()], year = date.getFullYear(), + decade = Datepicker.getDecade(date), types = { days: month + ', ' + year, - months: year + months: year, + years: decade[0] + ' - ' + decade[1] }; return types[this.d.view]; diff --git a/sass/datepicker/_cell.scss b/sass/datepicker/_cell.scss index 61ba244..8842157 100644 --- a/sass/datepicker/_cell.scss +++ b/sass/datepicker/_cell.scss @@ -44,4 +44,21 @@ .datepicker--cell-month { width: 33.33%; height: 40px; +} + +// Years +// ------------------------------------------------- + +.datepicker--years {} + +// Month cells +// ------------------------- + +.datepicker--cell-year { + width: 100% / $yearsPerRow; + height: 40px; + + &.-another-decade- { + color: $colorAnotherMonth; + } } \ No newline at end of file diff --git a/sass/datepicker/_navigation.scss b/sass/datepicker/_navigation.scss index cb3c711..a5f254c 100644 --- a/sass/datepicker/_navigation.scss +++ b/sass/datepicker/_navigation.scss @@ -23,6 +23,16 @@ width: $dayCellSize; &:hover { - background: #f6f6f6; + background: $colorCellHover; + } +} + +.datepicker--nav-title { + align-self: center; + padding: 4px; + border-radius: $datepickerBorderRadius; + + &:hover { + background: $colorCellHover; } } \ No newline at end of file diff --git a/sass/datepicker/datepicker-config.scss b/sass/datepicker/datepicker-config.scss index f565105..7509961 100644 --- a/sass/datepicker/datepicker-config.scss +++ b/sass/datepicker/datepicker-config.scss @@ -1,6 +1,7 @@ $dayCellSize: 32px; $datepickerWidth: 7 * $dayCellSize; $datepickerBorderRadius: 2px; +$yearsPerRow: 4; $navigationHeight: 32px;