diff --git a/dist/css/datepicker.css b/dist/css/datepicker.css index 7c5359a..bfb6f39 100644 --- a/dist/css/datepicker.css +++ b/dist/css/datepicker.css @@ -7,6 +7,11 @@ box-sizing: content-box; width: 224px; } +.datepicker--body { + display: none; } + .datepicker--body.active { + display: block; } + .datepicker--days-names { display: flex; flex-wrap: wrap; } @@ -48,11 +53,19 @@ flex-wrap: wrap; } .datepicker--cell { + border-radius: 2px; + cursor: pointer; display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; } + .datepicker--cell:hover { + background: #eee; } .datepicker--cell-day.-another-month- { color: #ddd; } + +.datepicker--cell-month { + width: 33.33%; + height: 40px; } diff --git a/dist/js/datepicker.js b/dist/js/datepicker.js index aca90e0..7881bc9 100644 --- a/dist/js/datepicker.js +++ b/dist/js/datepicker.js @@ -43,8 +43,8 @@ var Datepicker; this.inited = false; this.currentDate = this.opts.start; - this.view = this.opts.defaultView; - this.activeView = this.opts.defaultView; + this.currentView = this.opts.defaultView; + this.views = {}; this.init() }; @@ -56,7 +56,9 @@ var Datepicker; this._buildBaseHtml(); this.nav = new Datepicker.Navigation(this, this.opts); - this.days = new Datepicker.Body(this, 'days', this.opts); + this.views[this.currentView] = new Datepicker.Body(this, this.currentView, this.opts); + + this.views[this.currentView].show(); this.inited = true; }, @@ -87,34 +89,67 @@ var Datepicker; next: function () { var d = this.parsedDate; - this.date = new Date(d.year, d.month + 1, 1); + switch (this.view) { + case 'days': + this.date = new Date(d.year, d.month + 1, 1); + break; + case 'months': + this.date = new Date(d.year + 1, d.month, 1); + } + }, prev: function () { var d = this.parsedDate; - this.date = new Date(d.year, d.month - 1, 1); + switch (this.view) { + case 'days': + this.date = new Date(d.year, d.month - 1, 1); + break; + case 'months': + this.date = new Date(d.year - 1, d.month, 1); + } }, get parsedDate() { return Datepicker.getParsedDate(this.date); - } - }; + }, - Object.defineProperty(Datepicker.prototype , 'date', { - set: function (val) { + set date (val) { this.currentDate = val; if (this.inited) { - this[this.activeView]._render(); + this.views[this.view]._render(); this.nav._render(); } return val; }, - get: function () { + + get date () { return this.currentDate + }, + + set view (val) { + this.prevView = this.currentView; + this.currentView = val; + + if (this.inited) { + if (!this.views[val]) { + this.views[val] = new Datepicker.Body(this, val, this.opts) + } + + this.views[this.prevView].hide(); + this.views[val].show(); + this.nav._render(); + } + + return val + }, + + get view() { + return this.currentView; } - }); + }; Datepicker.getDaysCount = function (date) { @@ -156,8 +191,6 @@ var Datepicker; }; })(window, jQuery, ''); - - ;(function () { Datepicker.region = { 'ru': { @@ -188,6 +221,7 @@ var Datepicker; _bindEvents: function () { this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this)); + this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this)); }, _buildBaseHtml: function () { @@ -204,9 +238,13 @@ var Datepicker; _getTitle: function (date) { var month = this.d.loc.months[date.getMonth()], - year = date.getFullYear(); + year = date.getFullYear(), + types = { + days: month + ', ' + year, + months: year + }; - return month + ', ' + year; + return types[this.d.view]; }, _onClickNavButton: function (e) { @@ -214,6 +252,14 @@ var Datepicker; action = $el.data('action'); this.d[action](); + }, + + _onClickNavTitle: function () { + if (this.d.view == 'days') { + return this.d.view = 'months' + } + + this.d.view = 'years'; } } @@ -225,9 +271,17 @@ Datepicker.Cell = function () { ;(function () { var templates = { days:'' + - '
' + + '
' + '
' + '
' + + '
', + months: '' + + '
' + + '
' + + '
', + years: '' + + '
' + + '
' + '
' }; @@ -303,6 +357,51 @@ Datepicker.Cell = function () { return '
' + date.getDate() + '
'; }, + /** + * Generates months html + * @param {object} date - date instance + * @returns {string} + * @private + */ + _getMonthsHtml: function (date) { + var html = '', + d = Datepicker.getParsedDate(date), + i = 0; + + while(i < 12) { + html += this._getMonthHtml(new Date(d.year, i)); + i++ + } + + return html; + }, + + _getMonthHtml: function (date) { + var _class = "datepicker--cell datepicker--cell-month", + d = Datepicker.getParsedDate(date), + loc = this.d.loc; + + return '
' + loc.months[d.month] + '
' + }, + + _renderTypes: { + days: function () { + var dayNames = this._getDayNamesHtml(this.opts.firstDay), + days = this._getDaysHtml(this.d.currentDate); + + this.$cells.html(days); + this.$names.html(dayNames) + }, + months: function () { + var html = this._getMonthsHtml(this.d.currentDate); + + this.$cells.html(html) + }, + years: function () { + this.$cells.html('Years') + } + }, + _renderDays: function () { var dayNames = this._getDayNamesHtml(this.opts.firstDay), days = this._getDaysHtml(this.d.currentDate); @@ -312,7 +411,17 @@ Datepicker.Cell = function () { }, _render: function () { - this._renderDays(); + this._renderTypes[this.type].bind(this)() + }, + + show: function () { + this.$el.addClass('active'); + this.acitve = true; + }, + + hide: function () { + this.$el.removeClass('active'); + this.active = false; } }; })(); diff --git a/js/datepicker/body.js b/js/datepicker/body.js index ee5652c..9a7d821 100644 --- a/js/datepicker/body.js +++ b/js/datepicker/body.js @@ -1,9 +1,17 @@ ;(function () { var templates = { days:'' + - '
' + + '
' + '
' + '
' + + '
', + months: '' + + '
' + + '
' + + '
', + years: '' + + '
' + + '
' + '
' }; @@ -79,6 +87,51 @@ return '
' + date.getDate() + '
'; }, + /** + * Generates months html + * @param {object} date - date instance + * @returns {string} + * @private + */ + _getMonthsHtml: function (date) { + var html = '', + d = Datepicker.getParsedDate(date), + i = 0; + + while(i < 12) { + html += this._getMonthHtml(new Date(d.year, i)); + i++ + } + + return html; + }, + + _getMonthHtml: function (date) { + var _class = "datepicker--cell datepicker--cell-month", + d = Datepicker.getParsedDate(date), + loc = this.d.loc; + + return '
' + loc.months[d.month] + '
' + }, + + _renderTypes: { + days: function () { + var dayNames = this._getDayNamesHtml(this.opts.firstDay), + days = this._getDaysHtml(this.d.currentDate); + + this.$cells.html(days); + this.$names.html(dayNames) + }, + months: function () { + var html = this._getMonthsHtml(this.d.currentDate); + + this.$cells.html(html) + }, + years: function () { + this.$cells.html('Years') + } + }, + _renderDays: function () { var dayNames = this._getDayNamesHtml(this.opts.firstDay), days = this._getDaysHtml(this.d.currentDate); @@ -88,7 +141,17 @@ }, _render: function () { - this._renderDays(); + this._renderTypes[this.type].bind(this)() + }, + + show: function () { + this.$el.addClass('active'); + this.acitve = true; + }, + + hide: function () { + this.$el.removeClass('active'); + this.active = false; } }; })(); diff --git a/js/datepicker/datepicker.js b/js/datepicker/datepicker.js index f42bbe9..7262f6a 100644 --- a/js/datepicker/datepicker.js +++ b/js/datepicker/datepicker.js @@ -43,8 +43,8 @@ var Datepicker; this.inited = false; this.currentDate = this.opts.start; - this.view = this.opts.defaultView; - this.activeView = this.opts.defaultView; + this.currentView = this.opts.defaultView; + this.views = {}; this.init() }; @@ -56,7 +56,9 @@ var Datepicker; this._buildBaseHtml(); this.nav = new Datepicker.Navigation(this, this.opts); - this.days = new Datepicker.Body(this, 'days', this.opts); + this.views[this.currentView] = new Datepicker.Body(this, this.currentView, this.opts); + + this.views[this.currentView].show(); this.inited = true; }, @@ -87,34 +89,67 @@ var Datepicker; next: function () { var d = this.parsedDate; - this.date = new Date(d.year, d.month + 1, 1); + switch (this.view) { + case 'days': + this.date = new Date(d.year, d.month + 1, 1); + break; + case 'months': + this.date = new Date(d.year + 1, d.month, 1); + } + }, prev: function () { var d = this.parsedDate; - this.date = new Date(d.year, d.month - 1, 1); + switch (this.view) { + case 'days': + this.date = new Date(d.year, d.month - 1, 1); + break; + case 'months': + this.date = new Date(d.year - 1, d.month, 1); + } }, get parsedDate() { return Datepicker.getParsedDate(this.date); - } - }; + }, - Object.defineProperty(Datepicker.prototype , 'date', { - set: function (val) { + set date (val) { this.currentDate = val; if (this.inited) { - this[this.activeView]._render(); + this.views[this.view]._render(); this.nav._render(); } return val; }, - get: function () { + + get date () { return this.currentDate + }, + + set view (val) { + this.prevView = this.currentView; + this.currentView = val; + + if (this.inited) { + if (!this.views[val]) { + this.views[val] = new Datepicker.Body(this, val, this.opts) + } + + this.views[this.prevView].hide(); + this.views[val].show(); + this.nav._render(); + } + + return val + }, + + get view() { + return this.currentView; } - }); + }; Datepicker.getDaysCount = function (date) { @@ -155,5 +190,4 @@ var Datepicker; } }; -})(window, jQuery, ''); - +})(window, jQuery, ''); \ No newline at end of file diff --git a/js/datepicker/navigation.js b/js/datepicker/navigation.js index 61120fd..700bcfe 100644 --- a/js/datepicker/navigation.js +++ b/js/datepicker/navigation.js @@ -19,6 +19,7 @@ _bindEvents: function () { this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this)); + this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this)); }, _buildBaseHtml: function () { @@ -35,9 +36,13 @@ _getTitle: function (date) { var month = this.d.loc.months[date.getMonth()], - year = date.getFullYear(); + year = date.getFullYear(), + types = { + days: month + ', ' + year, + months: year + }; - return month + ', ' + year; + return types[this.d.view]; }, _onClickNavButton: function (e) { @@ -45,6 +50,14 @@ action = $el.data('action'); this.d[action](); + }, + + _onClickNavTitle: function () { + if (this.d.view == 'days') { + return this.d.view = 'months' + } + + this.d.view = 'years'; } } diff --git a/sass/datepicker/_cell.scss b/sass/datepicker/_cell.scss index 9731e1a..61ba244 100644 --- a/sass/datepicker/_cell.scss +++ b/sass/datepicker/_cell.scss @@ -10,11 +10,17 @@ } .datepicker--cell { + border-radius: $datepickerBorderRadius; + cursor: pointer; display: flex; align-items: center; justify-content: center; width: $dayCellSize; height: $dayCellSize; + + &:hover { + background: $colorCellHover; + } } // Day cell @@ -24,4 +30,18 @@ &.-another-month- { color: $colorAnotherMonth; } +} + + +// Months +// ------------------------------------------------- + +.datepicker--months {} + +// Month cells +// ------------------------- + +.datepicker--cell-month { + width: 33.33%; + height: 40px; } \ No newline at end of file diff --git a/sass/datepicker/_datepicker.scss b/sass/datepicker/_datepicker.scss index 406b7b4..5a9f079 100644 --- a/sass/datepicker/_datepicker.scss +++ b/sass/datepicker/_datepicker.scss @@ -6,15 +6,21 @@ .datepicker { border: 1px solid $colorGrey; - border-radius: 2px; + border-radius: $datepickerBorderRadius; box-sizing: content-box; width: $datepickerWidth; } -// Days +// Body // ------------------------------------------------- -.datepicker--days {} +.datepicker--body { + display: none; + + &.active { + display: block; + } +} // Day names @@ -31,4 +37,5 @@ width: $dayCellSize; height: $dayCellSize; text-align: center; -} \ No newline at end of file +} + diff --git a/sass/datepicker/datepicker-config.scss b/sass/datepicker/datepicker-config.scss index d14430d..f565105 100644 --- a/sass/datepicker/datepicker-config.scss +++ b/sass/datepicker/datepicker-config.scss @@ -1,5 +1,6 @@ $dayCellSize: 32px; $datepickerWidth: 7 * $dayCellSize; +$datepickerBorderRadius: 2px; $navigationHeight: 32px; @@ -7,7 +8,7 @@ $navigationHeight: 32px; $colorGrey: #ddd; $colorAnotherMonth: #ddd; -$colorCellHover: ''; +$colorCellHover: #eee; $colorCellCurrent: ''; $colorCellSelected: ''; $colorCellWeekend: ''; \ No newline at end of file