diff --git a/.eslintrc.js b/.eslintrc.js index cc720d6..635379b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,7 +6,6 @@ module.exports = { "env": { "browser": true, "jasmine": true, - "jquery": true, "commonjs": true }, "globals": { diff --git a/README.md b/README.md index 7b9d012..cd4a3d2 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,7 @@ For more information on PR's step, please see links of Contributing section. * [Getting Started](https://github.com/nhn/tui.date-picker/blob/production/docs/getting-started.md) * [Tutorials](https://github.com/nhn/tui.date-picker/tree/production/docs) * [APIs](https://nhn.github.io/tui.date-picker/latest) +* [v4.0.0 Migration Guide](https://github.com/nhn/tui.date-picker/blob/master/docs/getting-started.md#v400-migration-guide) You can also see the older versions of API page on the [releases page](https://github.com/nhn/tui.date-picker/releases). @@ -226,8 +227,8 @@ You can also see the older versions of API page on the [releases page](https://g ## 🔩 Dependency * [tui-code-snippet](https://github.com/nhn/tui.code-snippet) >=1.5.0 -* [tui-time-picker](https://github.com/nhn/tui.time-picker) >=1.3.0 -* [jquery](https://jquery.com/) >=1.11.0 +* [tui-dom](https://github.com/nhn/tui.dom) >=3.0.0 +* [tui-time-picker](https://github.com/nhn/tui.time-picker) >=2.0.0 ## 📜 License diff --git a/bower.json b/bower.json index 31e8599..3af033c 100644 --- a/bower.json +++ b/bower.json @@ -23,8 +23,8 @@ "package-lock.json" ], "dependencies": { - "jquery": "^1.11.0", "tui-code-snippet": "^1.5.0", - "tui-time-picker": "^1.3.0" + "tui-dom": "^3.0.0", + "tui-time-picker": "^2.0.0" } } diff --git a/docs/README.md b/docs/README.md index 5161ac4..0ab0c11 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,11 +1,10 @@ ## Tutorials - [Getting Started](getting-started.md) -- [v3.0.0 Migration Guide](v3.0.0-migration-guide.md) ## Documents -- [Code of Conducting](../CODE_OF_CONDUCTING.md) +- [Code of Conducting](../CODE_OF_CONDUCT.md) - [Contributing Guide](../CONTRIBUTING.md) - [Commit Message Convention](COMMIT_MESSAGE_CONVENTION.md) - [API & Examples](https://nhn.github.io/tui.date-picker/latest) diff --git a/docs/getting-started.md b/docs/getting-started.md index 0409472..f2e2cd1 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,6 +1,34 @@ +## v4.0.0 Migration Guide +In v4.0.0, jQuery is removed. It might cause other components to fail if they pass a jQuery object as a container. + +Previously, you can use a `jQuery` to create an instance. +```javascript +// v3 +var instance = new tui.DatePicker($('#datepicker-wrapper'), { + // options +}); +``` + +Now, you have to use `selector` or `HTMLElement` as a container. +```javascript +// v4 +var instance = new tui.DatePicker('#datepicker-wrapper', { + // options +}); + +// or + +var container = document.getElementById('datepicker-wrapper'); +var instance = new tui.DatePicker(container, { + // options +}); +``` + ## Load dependency files -* Script - [jQuery](https://github.com/jquery/jquery) 1.11.0 or later -* Script - [tui-code-snippet](https://github.com/nhn/tui.code-snippet) 1.2.5 or later +* Script - [tui-code-snippet](https://github.com/nhn/tui.code-snippet) 1.5.0 or later +* Script - [tui-dom](https://github.com/nhn/tui.dom) 3.0.0 or later + > If your project should support IE8, please use `tui-dom.js`, not `tui-dom.min.js`. +* Script - [tui-time-picker](https://github.com/nhn/tui.time-picker) 2.0.0 or later ```html @@ -10,8 +38,8 @@ .... - + .... @@ -37,7 +65,7 @@ var instance = new tui.DatePicker('#datepicker-wrapper', { ### Datepicker * language (default 'en') * There are two supporting types by default - 'en' and 'ko'. - * For custom texts - See the [Datepicker.localeTexts](https://nhn.github.io/tui.date-picker/latest/DatePicker.html#.localeTexts) + * For custom texts - See the [Datepicker.localeTexts](https://nhn.github.io/tui.date-picker/latest/DatePicker#localeTexts) * If set both calendar-language and datepicker-language, will apply datepicker-language first. * showAlways (default false) * If true, the datepicker will not close until you call "close()". @@ -51,7 +79,7 @@ var instance = new tui.DatePicker('#datepicker-wrapper', { * See the [Date-Time text format](#date-time-text-format) * type (default 'date') * Type of picker - 'date', 'month', year' - * See [examples](https://nhn.github.io/tui.date-picker/latest/tutorial-example05-picking-month.html) in API page + * See [examples](https://nhn.github.io/tui.date-picker/latest/tutorial-example05-picking-month) in API page * selectableRanges * Set selectable dates of datepicker * 2d-Array: `[[startDate1, endDate1], [startDate2, endDate2], ...]` @@ -66,7 +94,7 @@ var instance = new tui.DatePicker('#datepicker-wrapper', { ### Calendar * language (default 'en') * There are two supporting types by default - 'en' and 'ko'. - * For custom texts - See the [Calendar.localeTexts](https://nhn.github.io/tui.date-picker/latest/Calendar.html#.localeTexts) + * For custom texts - See the [Calendar.localeTexts](https://nhn.github.io/tui.date-picker/latest/Calendar#localeTexts) * showToday (default true) * If true, calendar shows today * showJumpButtons diff --git a/examples/example01-basic.html b/examples/example01-basic.html index e6b7b5d..105cfa7 100644 --- a/examples/example01-basic.html +++ b/examples/example01-basic.html @@ -15,8 +15,8 @@
- + + + - + + + + + + + diff --git a/jsdoc.conf.json b/jsdoc.conf.json deleted file mode 100644 index 43641e1..0000000 --- a/jsdoc.conf.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "source": { - "include": [ - "src", - "README.md" - ], - "exclude": [], - "includePattern": ".+\\.js(doc)?$", - "excludePattern": "(^|\\/|\\\\)_" - }, - "plugins": [ - "plugins/markdown" - ], - "templates": { - "name": "DatePicker", - "logo": { - "url": "https://cloud.githubusercontent.com/assets/12269563/20029815/01133928-a39a-11e6-80f3-12500a91c755.png", - "width": "150px", - "height": "13px", - "link": "https://github.com/nhn/tui.jsdoc-template" - } - }, - "opts": { - "private": false, - "recurse": true, - "destination": "doc", - "tutorials": "examples", - "template": "./node_modules/tui-jsdoc-template", - "package": "package.json" - } -} diff --git a/package-lock.json b/package-lock.json index 2ba8c2c..eefc25b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tui-date-picker", - "version": "3.3.3", + "version": "4.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1042,9 +1042,9 @@ } }, "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true }, "commondir": { @@ -1742,9 +1742,9 @@ } }, "es5-shim": { - "version": "4.5.12", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.12.tgz", - "integrity": "sha512-MjoCAHE6P2Dirme70Cxd9i2Ng8rhXiaVSsxDWdSwimfLERJL/ypR2ed2rTYkeeYrMk8gq281dzKLiGcdrmc8qg==", + "version": "4.5.13", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.13.tgz", + "integrity": "sha512-xi6hh6gsvDE0MaW4Vp1lgNEBpVcCXRWfPXj5egDvtgLz4L9MEvNwYEMdJH+JJinWkwa8c3c3o5HduV7dB/e1Hw==", "dev": true }, "escape-html": { @@ -3730,9 +3730,9 @@ "dev": true }, "is-my-json-valid": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", - "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", + "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", "dev": true, "requires": { "generate-function": "^2.0.0", @@ -3975,11 +3975,6 @@ "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=", "dev": true }, - "jquery": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-1.12.4.tgz", - "integrity": "sha1-AeHfuikP5z3rp3zurLD5ui/sngw=" - }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -4144,12 +4139,6 @@ "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=", "dev": true }, - "karma-jquery": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/karma-jquery/-/karma-jquery-0.2.3.tgz", - "integrity": "sha1-5nEHk00LQEfCBrqlIOQ8eNfoQR8=", - "dev": true - }, "karma-junit-reporter": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/karma-junit-reporter/-/karma-junit-reporter-1.2.0.tgz", @@ -4170,8 +4159,8 @@ } }, "karma-webdriver-launcher": { - "version": "git+https://github.com/nhnent/karma-webdriver-launcher.git#ed09d73cc68b21ee631426d6abff0a3315aac958", - "from": "git+https://github.com/nhnent/karma-webdriver-launcher.git#v1.1.0", + "version": "git+https://github.com/nhn/karma-webdriver-launcher.git#ed09d73cc68b21ee631426d6abff0a3315aac958", + "from": "git+https://github.com/nhn/karma-webdriver-launcher.git#v1.1.0", "dev": true, "requires": { "ip": "^0.3.2", @@ -5256,9 +5245,9 @@ "dev": true }, "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz", + "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==", "dev": true }, "punycode": { @@ -6969,17 +6958,32 @@ "dev": true }, "tui-code-snippet": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/tui-code-snippet/-/tui-code-snippet-1.5.0.tgz", - "integrity": "sha512-grVv/lrHDXp9sRWypmMe76fHDlpdSfVYLiVmy8f765mWEBk+2JtiKgH+ACuipNtPZbUAy2pYgIWRQfDcg0zdCw==" + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/tui-code-snippet/-/tui-code-snippet-1.5.2.tgz", + "integrity": "sha512-6UqTlQaaC1KLcmC0HAoq5dtl1G4Fib+R+NC7pmaV7kiIlZ7JqKhUmnOoGRcreAyzd81UTK/vCvhrw9QJskpCFQ==" + }, + "tui-dom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tui-dom/-/tui-dom-3.0.0.tgz", + "integrity": "sha512-/MTX6rG8zmHN6AqGiK9u5LfkwfTOdJC75+wpB8xdKJ3UeLfc/AolXxHDmnssh++8dZXSnCoS3VynbsjvOqRTdg==", + "requires": { + "tui-code-snippet": "^1.2.5" + } }, "tui-time-picker": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/tui-time-picker/-/tui-time-picker-1.5.0.tgz", - "integrity": "sha512-L3/HpAq4TNxrl/7NOB/ESkAIf8zBoXC7CVVPaNB2Wr2kc0X8skpBNOts0iykxIxYiXs+h2S42jJXUaclyCZf8w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tui-time-picker/-/tui-time-picker-2.0.0.tgz", + "integrity": "sha512-Q2HI6zn+Uz2Rg9GiUbW5JVtvbLN2W07DrtQhRihBxYARDVIdiByTO2MYfRT4wqwXLyCdqZWOZgWLtteQMENlMA==", "requires": { - "jquery": "^1.11.0", - "tui-code-snippet": "^1.5.0" + "tui-code-snippet": "^1.5.2", + "tui-dom": "^3.0.0" + }, + "dependencies": { + "tui-code-snippet": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/tui-code-snippet/-/tui-code-snippet-1.5.2.tgz", + "integrity": "sha512-6UqTlQaaC1KLcmC0HAoq5dtl1G4Fib+R+NC7pmaV7kiIlZ7JqKhUmnOoGRcreAyzd81UTK/vCvhrw9QJskpCFQ==" + } } }, "tunnel-agent": { diff --git a/package.json b/package.json index d3c4996..342aab2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tui-date-picker", - "version": "3.3.4", + "version": "4.0.0", "description": "TOAST UI Components: DatePicker", "main": "dist/tui-date-picker", "files": [ @@ -12,8 +12,7 @@ "bundle": "webpack & webpack --production", "serve": "webpack-dev-server --inline --hot -d", "serve:ie8": "webpack-dev-server -d", - "doc:dev": "tuidoc --dev", - "doc": "tuidoc" + "doc": "tuidoc && tuidoc --serv" }, "repository": { "type": "git", @@ -32,7 +31,7 @@ "license": "MIT", "devDependencies": { "css-loader": "^1.0.1", - "es5-shim": "^4.5.9", + "es5-shim": "^4.5.13", "eslint": "^4.5.0", "eslint-config-tui": "^1.0.1", "eslint-loader": "^1.6.1", @@ -47,7 +46,6 @@ "karma-coverage": "^1.1.1", "karma-es5-shim": "^0.0.4", "karma-jasmine": "^1.0.2", - "karma-jquery": "^0.2.2", "karma-junit-reporter": "^1.2.0", "karma-sourcemap-loader": "^0.3.7", "karma-webdriver-launcher": "git+https://github.com/nhn/karma-webdriver-launcher.git#v1.1.0", @@ -59,8 +57,8 @@ "webpack-dev-server": "^1.11.0" }, "dependencies": { - "jquery": "^1.11.0", "tui-code-snippet": "^1.5.0", - "tui-time-picker": "^1.3.0" + "tui-dom": "^3.0.0", + "tui-time-picker": "^2.0.0" } } diff --git a/src/css/calendar.css b/src/css/calendar.css index bda8bf5..3438c06 100644 --- a/src/css/calendar.css +++ b/src/css/calendar.css @@ -102,14 +102,17 @@ vertical-align: top } -.tui-calendar .tui-calendar-btn-prev-month, .tui-calendar .tui-calendar-btn-next-month, .tui-calendar .tui-calendar-btn-prev-year, .tui-calendar .tui-calendar-btn-next-year { +.tui-calendar-btn { overflow: hidden; position: absolute; top: 0; width: 32px; height: 50px; line-height: 400px; - z-index: 10 + z-index: 10; + cursor: pointer; + border: none; + background-color: #fff; } .tui-calendar .tui-calendar-btn-prev-month { @@ -540,3 +543,7 @@ .tui-dropdown-area .tui-datepicker-dropdown+.tui-datepicker-dropdown { margin-left: 5px } + +.tui-hidden { + display: none; +} diff --git a/src/js/calendar/body.js b/src/js/calendar/body.js index e4f6d0f..c05e660 100644 --- a/src/js/calendar/body.js +++ b/src/js/calendar/body.js @@ -5,7 +5,6 @@ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); var DateLayer = require('./layerBody/date'); @@ -27,10 +26,10 @@ var Body = snippet.defineClass(/** @lends Body.prototype */{ /** * Body container element - * @type {jQuery} + * @type {HTMLElement} * @private */ - this._$container = $(bodyContainer); + this._container = bodyContainer; /** * DateLayer @@ -109,15 +108,14 @@ var Body = snippet.defineClass(/** @lends Body.prototype */{ var prevLayer = this._currentLayer; prevLayer.remove(); - nextLayer.render(date); - nextLayer.appendTo(this._$container); + nextLayer.render(date, this._container); this._currentLayer = nextLayer; }, /** - * Returns date jQuery elements - * @returns {jQuery} + * Returns date elements + * @returns {HTMLElement[]} */ getDateElements: function() { return this._currentLayer.getDateElements(); @@ -131,7 +129,7 @@ var Body = snippet.defineClass(/** @lends Body.prototype */{ layer.remove(); }); - this._$container = this._currentLayer = this._dateLayer = this._monthLayer = this._yearLayer = null; + this._container = this._currentLayer = this._dateLayer = this._monthLayer = this._yearLayer = null; } }); diff --git a/src/js/calendar/header.js b/src/js/calendar/header.js index d7446f2..380c6b2 100644 --- a/src/js/calendar/header.js +++ b/src/js/calendar/header.js @@ -5,33 +5,34 @@ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); +var domUtil = require('tui-dom'); var localeTexts = require('./../localeTexts'); var headerTmpl = require('./../../template/calendar/header.hbs'); var DateTimeFormatter = require('../dateTimeFormatter'); var constants = require('../constants'); +var util = require('../util'); +var mouseTouchEvent = require('../mouseTouchEvent'); var TYPE_DATE = constants.TYPE_DATE; var TYPE_MONTH = constants.TYPE_MONTH; var TYPE_YEAR = constants.TYPE_YEAR; -var CLASS_NAME_PREV_MONTH_BTN = constants.CLASS_NAME_PREV_MONTH_BTN; -var CLASS_NAME_PREV_YEAR_BTN = constants.CLASS_NAME_PREV_YEAR_BTN; -var CLASS_NAME_NEXT_YEAR_BTN = constants.CLASS_NAME_NEXT_YEAR_BTN; -var CLASS_NAME_NEXT_MONTH_BTN = constants.CLASS_NAME_NEXT_MONTH_BTN; - var CLASS_NAME_TITLE_MONTH = 'tui-calendar-title-month'; var CLASS_NAME_TITLE_YEAR = 'tui-calendar-title-year'; var CLASS_NAME_TITLE_YEAR_TO_YEAR = 'tui-calendar-title-year-to-year'; +var SELECTOR_INNER_ELEM = '.tui-calendar-header-inner'; +var SELECTOR_INFO_ELEM = '.tui-calendar-header-info'; +var SELECTOR_BTN = '.tui-calendar-btn'; + var YEAR_TITLE_FORMAT = 'yyyy'; /** * @ignore * @class - * @param {string|Element|jQuery} container - Header container + * @param {string|HTMLElement} container - Header container or selector * @param {object} option - Header option * @param {string} option.language - Header language * @param {boolean} option.showToday - Has today box or not. @@ -41,17 +42,24 @@ var Header = snippet.defineClass(/** @lends Header.prototype */{ init: function(container, option) { /** * Container element - * @type {jQuery} + * @type {HTMLElement} + * @private + */ + this._container = util.getElement(container); + + /** + * Header inner element + * @type {HTMLElement} * @private */ - this._$container = $(container); + this._innerElement = null; /** - * headerElement - * @type {jQuery} + * Header info element + * @type {HTMLElement} * @private */ - this._$element = $(); + this._infoElement = null; /** * Render today box or not @@ -93,7 +101,6 @@ var Header = snippet.defineClass(/** @lends Header.prototype */{ }, /** - * Set formatters * @param {object} localeText - Locale text * @private */ @@ -104,29 +111,35 @@ var Header = snippet.defineClass(/** @lends Header.prototype */{ }, /** - * Set events for firing customEvents * @param {object} option - Constructor option * @private */ _setEvents: function() { - var self = this; - var classNames = [ - CLASS_NAME_PREV_MONTH_BTN, - CLASS_NAME_PREV_YEAR_BTN, - CLASS_NAME_NEXT_MONTH_BTN, - CLASS_NAME_NEXT_YEAR_BTN - ]; - - snippet.forEach(classNames, function(className) { - self._$container.on('touchend.calendar click.calendar', '.' + className, function(ev) { - self.fire('click', ev); - ev.preventDefault(); // To prevent click after touchend - }); - }); + mouseTouchEvent.on(this._container, 'click', this._onClickHandler, this); + }, + + /** + * @private + */ + _removeEvents: function() { + this.off(); + mouseTouchEvent.off(this._container, 'click', this._onClickHandler); + }, + + /** + * Fire customEvents + * @param {Event} ev An event object + * @private + */ + _onClickHandler: function(ev) { + var target = util.getTarget(ev); + + if (domUtil.closest(target, SELECTOR_BTN)) { + this.fire('click', ev); + } }, /** - * Returns title class * @param {string} type - Calendar type * @returns {string} * @private @@ -145,7 +158,6 @@ var Header = snippet.defineClass(/** @lends Header.prototype */{ }, /** - * Returns title text * @param {Date} date - date * @param {string} type - Calendar type * @returns {string} @@ -193,25 +205,28 @@ var Header = snippet.defineClass(/** @lends Header.prototype */{ title: this._getTitleText(date, type) }; - this._$element.remove(); - this._$element = $(headerTmpl(context)); - this._$element.appendTo(this._$container); + this._container.innerHTML = headerTmpl(context).replace(/^\s+|\s+$/g, ''); + this._innerElement = this._container.querySelector(SELECTOR_INNER_ELEM); + if (context.showToday) { + this._infoElement = this._container.querySelector(SELECTOR_INFO_ELEM); + } }, /** * Destroy header */ destroy: function() { - this.off(); - this._$container.off('.calendar'); - this._$element.remove(); - this._$container + this._removeEvents(); + domUtil.removeElement(this._innerElement); + domUtil.removeElement(this._infoElement); + this._container = this._showToday = this._showJumpButtons = this._yearMonthTitleFormatter = this._yearTitleFormatter = this._todayFormatter - = this._$element + = this._innerElement + = this._infoElement = null; } }); diff --git a/src/js/calendar/index.js b/src/js/calendar/index.js index 755848d..1406612 100644 --- a/src/js/calendar/index.js +++ b/src/js/calendar/index.js @@ -5,8 +5,8 @@ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); +var domUtil = require('tui-dom'); var tmpl = require('./../../template/calendar/index.hbs'); var Header = require('./header'); @@ -14,6 +14,7 @@ var Body = require('./body'); var localeTexts = require('../localeTexts'); var constants = require('../constants'); var dateUtil = require('../dateUtil'); +var util = require('../util'); var DEFAULT_LANGUAGE_TYPE = constants.DEFAULT_LANGUAGE_TYPE; @@ -28,15 +29,15 @@ var CLASS_NAME_NEXT_MONTH_BTN = constants.CLASS_NAME_NEXT_MONTH_BTN; var CLASS_NAME_CALENDAR_MONTH = 'tui-calendar-month'; var CLASS_NAME_CALENDAR_YEAR = 'tui-calendar-year'; +var CLASS_NAME_HIDDEN = 'tui-hidden'; var HEADER_SELECTOR = '.tui-calendar-header'; var BODY_SELECTOR = '.tui-calendar-body'; -var util = snippet; /** * Calendar class * @constructor - * @param {HTMLElement|jQuery|string} wrapperElement - Wrapper element or selector + * @param {HTMLElement|string} wrapperElement - Wrapper element or selector * @param {Object} [options] - Options for initialize * @param {string} [options.language = 'en'] - Calendar language - {@link Calendar.localeTexts} * @param {boolean} [options.showToday] - If true, shows today @@ -55,16 +56,17 @@ var util = snippet; * }); * * calendar.on('draw', function(event) { + * var i, len; * console.log(event.date); * console.log(event.type); - * event.dateElements.each(function() { - * var $el = $(this); - * var date = new Date($el.data('timestamp')); + * for (i = 0, len = event.dateElements.length; i < len; i += 1) { + * var el = event.dateElements[i]; + * var date = new Date(domUtil.getData(el, 'timestamp')); * console.log(date); - * }); + * } * }); */ -var Calendar = util.defineClass(/** @lends Calendar.prototype */ { +var Calendar = snippet.defineClass(/** @lends Calendar.prototype */ { static: { /** * Locale text data @@ -110,17 +112,18 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { /** * Container element - * @type {jQuery} + * @type {HTMLElement} * @private */ - this._$container = $(container); + this._container = util.getElement(container); + this._container.innerHTML = tmpl(options); /** * Wrapper element - * @type {jQuery} + * @type {HTMLElement} * @private */ - this._$element = $(tmpl(options)).appendTo(this._$container); + this._element = this._container.firstChild; /** * Date @@ -168,18 +171,18 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { * @private */ _initHeader: function(options) { - var $headerContainer = this._$element.find(HEADER_SELECTOR); + var headerContainer = this._element.querySelector(HEADER_SELECTOR); - this._header = new Header($headerContainer, options); + this._header = new Header(headerContainer, options); this._header.on('click', function(ev) { - var $target = $(ev.target); - if ($target.hasClass(CLASS_NAME_PREV_MONTH_BTN)) { + var target = util.getTarget(ev); + if (domUtil.hasClass(target, CLASS_NAME_PREV_MONTH_BTN)) { this.drawPrev(); - } else if ($target.hasClass(CLASS_NAME_PREV_YEAR_BTN)) { + } else if (domUtil.hasClass(target, CLASS_NAME_PREV_YEAR_BTN)) { this._onClickPrevYear(); - } else if ($target.hasClass(CLASS_NAME_NEXT_MONTH_BTN)) { + } else if (domUtil.hasClass(target, CLASS_NAME_NEXT_MONTH_BTN)) { this.drawNext(); - } else if ($target.hasClass(CLASS_NAME_NEXT_YEAR_BTN)) { + } else if (domUtil.hasClass(target, CLASS_NAME_NEXT_YEAR_BTN)) { this._onClickNextYear(); } }, this); @@ -191,9 +194,9 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { * @private */ _initBody: function(options) { - var $bodyContainer = this._$element.find(BODY_SELECTOR); + var bodyContainer = this._element.querySelector(BODY_SELECTOR); - this._body = new Body($bodyContainer, options); + this._body = new Body(bodyContainer, options); }, /** @@ -273,14 +276,14 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { this._header.render(date, type); this._body.render(date, type); - this._$element.removeClass([CLASS_NAME_CALENDAR_MONTH, CLASS_NAME_CALENDAR_YEAR].join(' ')); + domUtil.removeClass(this._element, CLASS_NAME_CALENDAR_MONTH, CLASS_NAME_CALENDAR_YEAR); switch (type) { case TYPE_MONTH: - this._$element.addClass(CLASS_NAME_CALENDAR_MONTH); + domUtil.addClass(this._element, CLASS_NAME_CALENDAR_MONTH); break; case TYPE_YEAR: - this._$element.addClass(CLASS_NAME_CALENDAR_YEAR); + domUtil.addClass(this._element, CLASS_NAME_CALENDAR_YEAR); break; default: break; } @@ -333,7 +336,7 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { * @type {object} evt * @property {Date} date - Calendar date * @property {string} type - Calendar type - * @property {jQuery} $dateElements - Calendar date elements + * @property {HTMLElement} dateElements - Calendar date elements * @example * calendar.on('draw', function(evt) { * console.error(evt.date); @@ -342,7 +345,7 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { this.fire('draw', { date: this._date, type: type, - $dateElements: this._body.getDateElements() + dateElements: this._body.getDateElements() }); }, @@ -350,14 +353,14 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { * Show calendar */ show: function() { - this._$element.show(); + domUtil.removeClass(this._element, CLASS_NAME_HIDDEN); }, /** * Hide calendar */ hide: function() { - this._$element.hide(); + domUtil.addClass(this._element, CLASS_NAME_HIDDEN); }, /** @@ -444,7 +447,7 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { /** * Change language * @param {string} language - Language - * @see {@link Calendar.localeTexts} + * @see {@link Calendar#localeTexts} */ changeLanguage: function(language) { this._header.changeLanguage(language); @@ -469,8 +472,8 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { }, /** - * Returns date elements(jQuery) on body - * @returns {jQuery} + * Returns date elements on body + * @returns {HTMLElement[]} */ getDateElements: function() { return this._body.getDateElements(); @@ -481,7 +484,7 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { * @param {string} className - Class name */ addCssClass: function(className) { - this._$element.addClass(className); + domUtil.addClass(this._element, className); }, /** @@ -489,7 +492,7 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { * @param {string} className - Class name */ removeCssClass: function(className) { - this._$element.removeClass(className); + domUtil.removeClass(this._element, className); }, /** @@ -498,11 +501,17 @@ var Calendar = util.defineClass(/** @lends Calendar.prototype */ { destroy: function() { this._header.destroy(); this._body.destroy(); - this._$element.remove(); - - this._type = this._date = this._$container = this._$element = this._header = this._body = null; + domUtil.removeElement(this._element); + + this._type + = this._date + = this._container + = this._element + = this._header + = this._body + = null; } }); -util.CustomEvents.mixin(Calendar); +snippet.CustomEvents.mixin(Calendar); module.exports = Calendar; diff --git a/src/js/calendar/layerBody/base.js b/src/js/calendar/layerBody/base.js index 765418e..c41806e 100644 --- a/src/js/calendar/layerBody/base.js +++ b/src/js/calendar/layerBody/base.js @@ -6,6 +6,7 @@ 'use strict'; var snippet = require('tui-code-snippet'); +var domUtil = require('tui-dom'); var localeText = require('../../localeTexts'); var DEFAULT_LANGUAGE_TYPE = require('../../constants').DEFAULT_LANGUAGE_TYPE; @@ -23,10 +24,10 @@ var LayerBase = snippet.defineClass(/** @lends LayerBase.prototype */{ /** * Layer element - * @type {jQuery} + * @type {HTMLElement} * @private */ - this._$element = null; + this._element = null; /** * Language type @@ -67,7 +68,7 @@ var LayerBase = snippet.defineClass(/** @lends LayerBase.prototype */{ * Returns date elements * @abstract * @throws {Error} - * @returns {jQuery} + * @returns {HTMLElement[]} */ getDateElements: function() { throwOverrideError(this.getType(), 'getDateElements'); @@ -89,23 +90,14 @@ var LayerBase = snippet.defineClass(/** @lends LayerBase.prototype */{ this._localeText = localeText[language]; }, - /** - * Append to parent element - * @param {string|HTMLElement|jQuery} parent - Parent element - * @returns {jQuery} - */ - appendTo: function(parent) { - return this._$element.appendTo(parent); - }, - /** * Remove elements */ remove: function() { - if (this._$element) { - this._$element.remove(); + if (this._element) { + domUtil.removeElement(this._element); } - this._$element = null; + this._element = null; } }); diff --git a/src/js/calendar/layerBody/date.js b/src/js/calendar/layerBody/date.js index f5b5421..55c37c7 100644 --- a/src/js/calendar/layerBody/date.js +++ b/src/js/calendar/layerBody/date.js @@ -5,7 +5,6 @@ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); var bodyTmpl = require('./../../../template/calendar/dateLayer.hbs'); @@ -61,21 +60,23 @@ var DateLayer = snippet.defineClass(LayerBase, /** @lends DateLayer.prototype */ /** * Render date-layer * @override - * @param {Date} date - Date to render + * @param {Date} date Date to render + * @param {HTMLElement} container A container element for the rendered element */ - render: function(date) { + render: function(date, container) { var context = this._makeContext(date); - this._$element = $(bodyTmpl(context)); + container.innerHTML = bodyTmpl(context); + this._element = container.firstChild; }, /** - * Retunrs date elements + * Return date elements * @override - * @returns {jQuery} + * @returns {HTMLElement[]} */ getDateElements: function() { - return this._$element.find(DATE_SELECTOR); + return this._element.querySelectorAll(DATE_SELECTOR); } }); diff --git a/src/js/calendar/layerBody/month.js b/src/js/calendar/layerBody/month.js index a4f24fd..25e6f6f 100644 --- a/src/js/calendar/layerBody/month.js +++ b/src/js/calendar/layerBody/month.js @@ -5,7 +5,6 @@ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); var bodyTmpl = require('./../../../template/calendar/monthLayer.hbs'); @@ -60,20 +59,23 @@ var MonthLayer = snippet.defineClass(LayerBase, /** @lends MonthLayer.prototype /** * Render month-layer element * @override + * @param {Date} date Date to render + * @param {HTMLElement} container A container element for the rendered element */ - render: function(date) { + render: function(date, container) { var context = this._makeContext(date); - this._$element = $(bodyTmpl(context)); + container.innerHTML = bodyTmpl(context); + this._element = container.firstChild; }, /** * Returns month elements * @override - * @returns {jQuery} + * @returns {HTMLElement[]} */ getDateElements: function() { - return this._$element.find(DATE_SELECTOR); + return this._element.querySelectorAll(DATE_SELECTOR); } }); diff --git a/src/js/calendar/layerBody/year.js b/src/js/calendar/layerBody/year.js index 91ca984..7448b00 100644 --- a/src/js/calendar/layerBody/year.js +++ b/src/js/calendar/layerBody/year.js @@ -5,7 +5,6 @@ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); var bodyTmpl = require('../../../template/calendar/yearLayer.hbs'); @@ -51,22 +50,25 @@ var YearLayer = snippet.defineClass(LayerBase, /** @lends YearLayer.prototype */ }, /** - * Render month-layer element + * Render year-layer element * @override + * @param {Date} date Date to render + * @param {HTMLElement} container A container element for the rendered element */ - render: function(date) { + render: function(date, container) { var context = this._makeContext(date); - this._$element = $(bodyTmpl(context)); + container.innerHTML = bodyTmpl(context); + this._element = container.firstChild; }, /** * Returns year elements * @override - * @returns {jQuery} + * @returns {HTMLElement[]} */ getDateElements: function() { - return this._$element.find(DATE_SELECTOR); + return this._element.querySelectorAll(DATE_SELECTOR); } }); diff --git a/src/js/dateRangePicker/index.js b/src/js/dateRangePicker/index.js index 5c47240..83adbe0 100644 --- a/src/js/dateRangePicker/index.js +++ b/src/js/dateRangePicker/index.js @@ -5,12 +5,13 @@ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); +var domUtil = require('tui-dom'); var DatePicker = require('../datepicker'); var dateUtil = require('../dateUtil'); var constants = require('../constants'); +var util = require('../util'); var CLASS_NAME_RANGE_PICKER = 'tui-rangepicker'; var CLASS_NAME_SELECTED = constants.CLASS_NAME_SELECTED; @@ -20,11 +21,11 @@ var CLASS_NAME_SELECTED_RANGE = 'tui-is-selected-range'; * @class * @param {object} options - Date-Range picker options * @param {object} options.startpicker - Startpicker options - * @param {Element|jQuery|string} options.startpicker.input - Startpicker input element - * @param {Element|jQuery|string} options.startpicker.container - Startpicker container element + * @param {HTMLElement|string} options.startpicker.input - Startpicker input element or selector + * @param {HTMLElement|string} options.startpicker.container - Startpicker container element or selector * @param {object} options.endpicker - Endpicker options - * @param {Element|jQuery|string} options.endpicker.input - Endpicker input element - * @param {Element|jQuery|string} options.endpicker.container - Endpicker container element + * @param {HTMLElement|string} options.endpicker.input - Endpicker input element or selector + * @param {HTMLElement|string} options.endpicker.container - Endpicker container element or selector * @param {string} options.format - Input date-string format * @param {string} [options.type = 'date'] - DatePicker type - ('date' | 'month' | 'year') * @param {string} [options.language='en'] - Language key @@ -95,30 +96,30 @@ var DateRangePicker = snippet.defineClass(/** @lends DateRangePicker.prototype * * @private */ _initializePickers: function(options) { - var $startpickerContainer = $(options.startpicker.container); - var $endpickerContainer = $(options.endpicker.container); - var $startInput = $(options.startpicker.input); - var $endInput = $(options.endpicker.input); + var startpickerContainer = util.getElement(options.startpicker.container); + var endpickerContainer = util.getElement(options.endpicker.container); + var startInput = util.getElement(options.startpicker.input); + var endInput = util.getElement(options.endpicker.input); var startpickerOpt = snippet.extend({}, options, { input: { - element: $startInput, + element: startInput, format: options.format } }); var endpickerOpt = snippet.extend({}, options, { input: { - element: $endInput, + element: endInput, format: options.format } }); - this._startpicker = new DatePicker($startpickerContainer, startpickerOpt); + this._startpicker = new DatePicker(startpickerContainer, startpickerOpt); this._startpicker.addCssClass(CLASS_NAME_RANGE_PICKER); this._startpicker.on('change', this._onChangeStartpicker, this); this._startpicker.on('draw', this._onDrawPicker, this); - this._endpicker = new DatePicker($endpickerContainer, endpickerOpt); + this._endpicker = new DatePicker(endpickerContainer, endpickerOpt); this._endpicker.addCssClass(CLASS_NAME_RANGE_PICKER); this._endpicker.on('change', this._onChangeEndpicker, this); this._endpicker.on('draw', this._onDrawPicker, this); @@ -130,9 +131,8 @@ var DateRangePicker = snippet.defineClass(/** @lends DateRangePicker.prototype * * @private */ _onDrawPicker: function(eventData) { - var self = this; var calendarType = eventData.type; - var $dateElements = eventData.$dateElements; + var dateElements = snippet.toArray(eventData.dateElements); var startDate = this._startpicker.getDate(); var endDate = this._endpicker.getDate(); @@ -145,45 +145,44 @@ var DateRangePicker = snippet.defineClass(/** @lends DateRangePicker.prototype * endDate = new Date(NaN); } - $dateElements.each(function(idx, el) { - var $el = $(el); - var elDate = new Date($el.data('timestamp')); + snippet.forEach(dateElements, function(el) { + var elDate = new Date(Number(domUtil.getData(el, 'timestamp'))); var isInRange = dateUtil.inRange(startDate, endDate, elDate, calendarType); var isSelected = ( dateUtil.isSame(startDate, elDate, calendarType) || dateUtil.isSame(endDate, elDate, calendarType) ); - self._setRangeClass($el, isInRange); - self._setSelectedClass($el, isSelected); - }); + this._setRangeClass(el, isInRange); + this._setSelectedClass(el, isSelected); + }, this); }, /** * Set range class to element - * @param {jQuery} $el - Element + * @param {HTMLElement} el - Element * @param {boolean} isInRange - In range * @private */ - _setRangeClass: function($el, isInRange) { + _setRangeClass: function(el, isInRange) { if (isInRange) { - $el.addClass(CLASS_NAME_SELECTED_RANGE); + domUtil.addClass(el, CLASS_NAME_SELECTED_RANGE); } else { - $el.removeClass(CLASS_NAME_SELECTED_RANGE); + domUtil.removeClass(el, CLASS_NAME_SELECTED_RANGE); } }, /** * Set selected class to element - * @param {jQuery} $el - Element + * @param {HTMLElement} el - Element * @param {boolean} isSelected - Is selected * @private */ - _setSelectedClass: function($el, isSelected) { + _setSelectedClass: function(el, isSelected) { if (isSelected) { - $el.addClass(CLASS_NAME_SELECTED); + domUtil.addClass(el, CLASS_NAME_SELECTED); } else { - $el.removeClass(CLASS_NAME_SELECTED); + domUtil.removeClass(el, CLASS_NAME_SELECTED); } }, @@ -295,7 +294,7 @@ var DateRangePicker = snippet.defineClass(/** @lends DateRangePicker.prototype * /** * Set selectable ranges * @param {Array.>} ranges - Selectable ranges - * @see DatePicker#setRanges + * @see {@link DatePicker#setRanges} */ setRanges: function(ranges) { this._startpicker.setRanges(ranges); @@ -306,7 +305,7 @@ var DateRangePicker = snippet.defineClass(/** @lends DateRangePicker.prototype * * Add a range * @param {Date|number} start - startDate * @param {Date|number} end - endDate - * @see DatePicker#addRange + * @see {@link DatePicker#addRange} */ addRange: function(start, end) { this._startpicker.addRange(start, end); @@ -318,7 +317,7 @@ var DateRangePicker = snippet.defineClass(/** @lends DateRangePicker.prototype * * @param {Date|number} start - startDate * @param {Date|number} end - endDate * @param {null|'date'|'month'|'year'} type - Range type, If falsy -> Use strict timestamp; - * @see DatePicker#removeRange + * @see {@link DatePicker#removeRange} */ removeRange: function(start, end, type) { this._startpicker.removeRange(start, end, type); @@ -328,7 +327,7 @@ var DateRangePicker = snippet.defineClass(/** @lends DateRangePicker.prototype * /** * Change language * @param {string} language - Language - * @see {@link DatePicker.localeTexts} + * @see {@link DatePicker#localeTexts} */ changeLanguage: function(language) { this._startpicker.changeLanguage(language); diff --git a/src/js/dateUtil.js b/src/js/dateUtil.js index c5a88d2..62f405e 100644 --- a/src/js/dateUtil.js +++ b/src/js/dateUtil.js @@ -1,7 +1,6 @@ /** * @fileoverview Utils for DatePicker component * @author NHN. FE dev Lab. - * @dependency tui-code-snippet ^1.0.2 */ 'use strict'; diff --git a/src/js/datepicker/index.js b/src/js/datepicker/index.js index 604a3f6..f06f24b 100644 --- a/src/js/datepicker/index.js +++ b/src/js/datepicker/index.js @@ -5,8 +5,8 @@ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); +var domUtil = require('tui-dom'); var TimePicker = require('tui-time-picker'); var Calendar = require('../calendar'); @@ -14,7 +14,8 @@ var RangeModel = require('./../rangeModel/index'); var constants = require('../constants'); var localeTexts = require('../localeTexts'); var dateUtil = require('../dateUtil'); -var setTouchClickEvent = require('../setTouchClickEvent'); +var util = require('../util'); +var mouseTouchEvent = require('../mouseTouchEvent'); var tmpl = require('../../template/datepicker/index.hbs'); var DatePickerInput = require('./input'); @@ -33,10 +34,13 @@ var CLASS_NAME_BLOCKED = 'tui-is-blocked'; var CLASS_NAME_CHECKED = 'tui-is-checked'; var CLASS_NAME_SELECTOR_BUTTON = 'tui-datepicker-selector-button'; var CLASS_NAME_TODAY = 'tui-calendar-today'; +var CLASS_NAME_HIDDEN = 'tui-hidden'; var SELECTOR_BODY = '.tui-datepicker-body'; -var SELECTOR_FOOTER = '.tui-datepicker-footer'; var SELECTOR_DATE_ICO = '.tui-ico-date'; +var SELECTOR_CALENDAR_TITLE = '.tui-calendar-title'; +var SELECTOR_CALENDAR_CONTAINER = '.tui-calendar-container'; +var SELECTOR_TIMEPICKER_CONTAINER = '.tui-timepicker-container'; /** * Merge default option @@ -85,7 +89,7 @@ var mergeDefaultOption = function(option) { /** * @class - * @param {HTMLElement|jQuery|string} container - Container element of datepicker + * @param {HTMLElement|string} container - Container element or selector of datepicker * @param {Object} [options] - Options * @param {Date|number} [options.date] - Initial date. Default - null for no initial date * @param {string} [options.type = 'date'] - DatePicker type - ('date' | 'month' | 'year') @@ -94,7 +98,7 @@ var mergeDefaultOption = function(option) { * [TimePicker]{@link https://nhn.github.io/tui.time-picker/latest} options * @param {object} [options.calendar] - {@link Calendar} options * @param {object} [options.input] - Input option - * @param {HTMLElement|string|jQuery} [options.input.element] - Input element + * @param {HTMLElement|string} [options.input.element] - Input element or selector * @param {string} [options.input.format = 'yyyy-mm-dd'] - Date string format * @param {Array.>} [options.selectableRanges = 1900/1/1 ~ 2999/12/31] * - Selectable date ranges. @@ -187,26 +191,30 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ /** * DatePicker container - * @type {jQuery} + * @type {HTMLElement} * @private */ - this._$container = $(container); + this._container = util.getElement(container); + this._container.innerHTML = tmpl(options); /** * DatePicker element - * @type {jQuery} + * @type {HTMLElement} * @private */ - this._$element = $(tmpl(options)).appendTo(this._$container); + this._element = this._container.firstChild; /** * Calendar instance * @type {Calendar} * @private */ - this._calendar = new Calendar(this._$element.find(SELECTOR_BODY), snippet.extend(options.calendar, { - usageStatistics: options.usageStatistics - })); + this._calendar = new Calendar( + this._element.querySelector(SELECTOR_CALENDAR_CONTAINER), + snippet.extend(options.calendar, { + usageStatistics: options.usageStatistics + }) + ); /** * TimePicker instance @@ -286,7 +294,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ */ _initializeDatePicker: function(option) { this.setRanges(option.selectableRanges); - this._setEvents(option); + this._setEvents(); this._initTimePicker(option.timepicker, option.usageStatistics); this.setInput(option.input.element); this.setDateFormat(option.input.format); @@ -294,47 +302,65 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ snippet.forEach(option.openers, this.addOpener, this); if (!this.showAlways) { - this._$element.hide(); + this._hide(); } if (this.getType() === TYPE_DATE) { - this._$element.find(SELECTOR_BODY).addClass('tui-datepicker-type-date'); + domUtil.addClass(this._element.querySelector(SELECTOR_BODY), 'tui-datepicker-type-date'); } }, /** - * Set events + * Set events on the date picker's element * @param {object} option - Constructor option * @private */ - _setEvents: function(option) { - setTouchClickEvent(this._$element, $.proxy(this._onClickDate, this), { - selector: '.' + CLASS_NAME_SELECTABLE, - namespace: this._id - }); + _setEvents: function() { + mouseTouchEvent.on(this._element, 'click', this._onClickHandler, this); + this._calendar.on('draw', this._onDrawCalendar, this); + }, - setTouchClickEvent(this._$element, $.proxy(this._onClickCalendarTitle, this), { - selector: '.tui-calendar-title', - namespace: this._id - }); + /** + * Remove events on the date picker's element + * @private + */ + _removeEvents: function() { + mouseTouchEvent.off(this._element, 'click', this._onClickHandler, this); + this._calendar.off(); + }, - if (option.timepicker && option.timepicker.layoutType === 'tab') { - setTouchClickEvent(this._$element, $.proxy(this._onClickSelectorButton, this), { - selector: '.' + CLASS_NAME_SELECTOR_BUTTON, - namespace: this._id - }); - } + /** + * Set events on the document + * @private + */ + _setDocumentEvents: function() { + mouseTouchEvent.on(document, 'mousedown', this._onMousedownDocument, this); + }, - this._calendar.on('draw', this._onDrawCalendar, this); + /** + * Remove events on the document + * @private + */ + _removeDocumentEvents: function() { + mouseTouchEvent.off(document, 'mousedown', this._onMousedownDocument); + }, + + /** + * Set events on the opener + * @param {HTMLElement} opener An opener to bind the events + * @private + */ + _setOpenerEvents: function(opener) { + mouseTouchEvent.on(opener, 'click', this.toggle, this); }, /** - * Off datepicker's events - * @param {string|jQuery|Element} el - Element + * Remove events on the opener + * @param {HTMLElement} opener An opener to unbind the events * @private */ - _offDatePickerEvents: function(el) { - $(el).off('.' + this._id); + _removeOpenerEvents: function(opener) { + mouseTouchEvent.off(opener, 'click', this.toggle); }, /** @@ -359,11 +385,10 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ }; } + this._timepicker = new TimePicker(this._element.querySelector(SELECTOR_TIMEPICKER_CONTAINER), opTimePicker); + if (layoutType.toLowerCase() === 'tab') { - this._timepicker = new TimePicker(this._$element.find(SELECTOR_BODY), opTimePicker); this._timepicker.hide(); - } else { - this._timepicker = new TimePicker(this._$element.find(SELECTOR_FOOTER), opTimePicker); } this._timepicker.on('change', function(ev) { @@ -376,22 +401,14 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ }, /** - * Calendar-header click handler - * @private - */ - _onClickCalendarTitle: function() { - this.drawUpperCalendar(this._date); - }, - - /** - * Selector button click handler - * @param {jQuery.Event} ev - Event object + * Change picker's type by a selector button. + * @param {HTMLElement} target A target element * @private */ - _onClickSelectorButton: function(ev) { + _changePicker: function(target) { var btnSelector = '.' + CLASS_NAME_SELECTOR_BUTTON; - var $selectedBtn = $(ev.target).closest(btnSelector); - var isDate = !!$selectedBtn.find(SELECTOR_DATE_ICO).length; + var selectedBtn = domUtil.closest(target, btnSelector); + var isDate = selectedBtn.querySelector(SELECTOR_DATE_ICO); if (isDate) { this._calendar.show(); @@ -400,73 +417,73 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ this._calendar.hide(); this._timepicker.show(); } - this._$element.find(btnSelector).removeClass(CLASS_NAME_CHECKED); - $selectedBtn.addClass(CLASS_NAME_CHECKED); + domUtil.removeClass(this._element.querySelector('.' + CLASS_NAME_CHECKED), CLASS_NAME_CHECKED); + domUtil.addClass(selectedBtn, CLASS_NAME_CHECKED); }, /** * Returns whether the element is opener - * @param {string|jQuery|HTMLElement} element - Element + * @param {string|HTMLElement} element - Element or selector * @returns {boolean} * @private */ _isOpener: function(element) { - var el = $(element)[0]; + var el = util.getElement(element); return snippet.inArray(el, this._openers) > -1; }, /** * add/remove today-class-name to date element - * @param {jQuery} $el - date element + * @param {HTMLElement} el - date element * @private */ - _setTodayClassName: function($el) { + _setTodayClassName: function(el) { var timestamp, isToday; if (this.getCalendarType() !== TYPE_DATE) { return; } - timestamp = $el.data('timestamp'); + timestamp = Number(domUtil.getData(el, 'timestamp')); isToday = timestamp === new Date().setHours(0, 0, 0, 0); if (isToday) { - $el.addClass(CLASS_NAME_TODAY); + domUtil.addClass(el, CLASS_NAME_TODAY); } else { - $el.removeClass(CLASS_NAME_TODAY); + domUtil.removeClass(el, CLASS_NAME_TODAY); } }, /** * add/remove selectable-class-name to date element - * @param {jQuery} $el - date element + * @param {HTMLElement} el - date element * @private */ - _setSelectableClassName: function($el) { - var elDate = new Date($el.data('timestamp')); + _setSelectableClassName: function(el) { + var elDate = new Date(Number(domUtil.getData(el, 'timestamp'))); if (this._isSelectableOnCalendar(elDate)) { - $el.addClass(CLASS_NAME_SELECTABLE) - .removeClass(CLASS_NAME_BLOCKED); + domUtil.addClass(el, CLASS_NAME_SELECTABLE); + domUtil.removeClass(el, CLASS_NAME_BLOCKED); } else { - $el.addClass(CLASS_NAME_BLOCKED) - .removeClass(CLASS_NAME_SELECTABLE); + domUtil.removeClass(el, CLASS_NAME_SELECTABLE); + domUtil.addClass(el, CLASS_NAME_BLOCKED); } }, /** * add/remove selected-class-name to date element - * @param {jQuery} $el - date element + * @param {HTMLElement} el - date element * @private */ - _setSelectedClassName: function($el) { - var elDate = new Date($el.data('timestamp')); + _setSelectedClassName: function(el) { + var elDate = new Date(Number(domUtil.getData(el, 'timestamp'))); if (this._isSelectedOnCalendar(elDate)) { - $el.addClass(CLASS_NAME_SELECTED); + domUtil.addClass(el, CLASS_NAME_SELECTED); } else { - $el.removeClass(CLASS_NAME_SELECTED); + domUtil.removeClass(el, CLASS_NAME_SELECTED); } }, @@ -497,6 +514,20 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ return curDate && dateUtil.isSame(curDate, date, calendarType); }, + /** + * Show the date picker element + */ + _show: function() { + domUtil.removeClass(this._element, CLASS_NAME_HIDDEN); + }, + + /** + * Hide the date picker element + */ + _hide: function() { + domUtil.addClass(this._element, CLASS_NAME_HIDDEN); + }, + /** * Set value a date-string of current this instance to input element * @private @@ -553,11 +584,12 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * @private */ _onMousedownDocument: function(ev) { - var evTarget = ev.target; - var isContains = $.contains(this._$element[0], evTarget); - var isInput = this._datepickerInput.is(evTarget); - var isInOpener = !!$(evTarget).closest(this._openers).length; - var shouldClose = !(this.showAlways || isInput || isContains || isInOpener); + var target = util.getTarget(ev); + var selector = util.getSelector(target); + var isContain = selector ? this._element.querySelector(selector) : false; + var isInput = this._datepickerInput.is(target); + var isInOpener = (snippet.inArray(target, this._openers) > -1); + var shouldClose = !(this.showAlways || isInput || isContain || isInOpener); if (shouldClose) { this.close(); @@ -565,13 +597,28 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ }, /** - * Event handler for click of calendar
- * - Update date form event-target - * @param {Event} ev - event object + * Event handler for click of calendar + * @param {Event} ev An event object + */ + _onClickHandler: function(ev) { + var target = util.getTarget(ev); + + if (domUtil.closest(target, '.' + CLASS_NAME_SELECTABLE)) { + this._updateDate(target); + } else if (domUtil.closest(target, SELECTOR_CALENDAR_TITLE)) { + this.drawUpperCalendar(this._date); + } else if (domUtil.closest(target, '.' + CLASS_NAME_SELECTOR_BUTTON)) { + this._changePicker(target); + } + }, + + /** + * Update date from event-target + * @param {HTMLElement} target An event target element * @private */ - _onClickDate: function(ev) { - var timestamp = $(ev.target).data('timestamp'); + _updateDate: function(target) { + var timestamp = Number(domUtil.getData(target, 'timestamp')); var newDate = new Date(timestamp); var timepicker = this._timepicker; var prevDate = this._date; @@ -597,19 +644,17 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ /** * Event handler for 'draw'-custom event of calendar * @param {Object} eventData - custom event data - * @see {Calendar.draw} + * @see {@link Calendar#draw} * @private */ _onDrawCalendar: function(eventData) { - var $dateElements = eventData.$dateElements; - var self = this; - - $dateElements.each(function(idx, el) { - var $el = $(el); - self._setTodayClassName($el); - self._setSelectableClassName($el); - self._setSelectedClassName($el); - }); + var dateElements = snippet.toArray(eventData.dateElements); + + snippet.forEach(dateElements, function(el) { + this._setTodayClassName(el); + this._setSelectableClassName(el); + this._setSelectedClassName(el); + }, this); this._setDisplayHeadButtons(); /** @@ -618,7 +663,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * @type {Object} evt - See {@link Calendar#event:draw} * @property {Date} date - Calendar date * @property {string} type - Calendar type - * @property {jQuery} $dateElements - Calendar date elements + * @property {HTMLElement} dateElements - Calendar date elements * @example * * datepicker.on('draw', function(evt) { @@ -630,7 +675,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ /** * Hide useless buttons (next, next-year, prev, prev-year) - * @see Don't save buttons reference. The buttons are rerendered every "calendar.darw". + * @see Don't save buttons reference. The buttons are rerendered every "calendar.draw". * @private */ _setDisplayHeadButtons: function() { @@ -638,19 +683,19 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ var prevYearDate = this._calendar.getPrevYearDate(); var maxTimestamp = this._rangeModel.getMaximumValue(); var minTimestamp = this._rangeModel.getMinimumValue(); - var $nextYearBtn = this._$element.find('.' + CLASS_NAME_NEXT_YEAR_BTN); - var $prevYearBtn = this._$element.find('.' + CLASS_NAME_PREV_YEAR_BTN); - var nextMonthDate, prevMonthDate, $nextMonBtn, $prevMonBtn; + var nextYearBtn = this._element.querySelector('.' + CLASS_NAME_NEXT_YEAR_BTN); + var prevYearBtn = this._element.querySelector('.' + CLASS_NAME_PREV_YEAR_BTN); + var nextMonthDate, prevMonthDate, nextMonBtn, prevMonBtn; if (this.getCalendarType() === TYPE_DATE) { nextMonthDate = dateUtil.cloneWithStartOf(this._calendar.getNextDate(), TYPE_MONTH); prevMonthDate = dateUtil.cloneWithEndOf(this._calendar.getPrevDate(), TYPE_MONTH); - $nextMonBtn = this._$element.find('.' + CLASS_NAME_NEXT_MONTH_BTN); - $prevMonBtn = this._$element.find('.' + CLASS_NAME_PREV_MONTH_BTN); + nextMonBtn = this._element.querySelector('.' + CLASS_NAME_NEXT_MONTH_BTN); + prevMonBtn = this._element.querySelector('.' + CLASS_NAME_PREV_MONTH_BTN); - this._setDisplay($nextMonBtn, nextMonthDate.getTime() <= maxTimestamp); - this._setDisplay($prevMonBtn, prevMonthDate.getTime() >= minTimestamp); + this._setDisplay(nextMonBtn, nextMonthDate.getTime() <= maxTimestamp); + this._setDisplay(prevMonBtn, prevMonthDate.getTime() >= minTimestamp); prevYearDate.setDate(1); nextYearDate.setDate(1); @@ -659,21 +704,23 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ nextYearDate.setMonth(0, 1); } - this._setDisplay($nextYearBtn, nextYearDate.getTime() <= maxTimestamp); - this._setDisplay($prevYearBtn, prevYearDate.getTime() >= minTimestamp); + this._setDisplay(nextYearBtn, nextYearDate.getTime() <= maxTimestamp); + this._setDisplay(prevYearBtn, prevYearDate.getTime() >= minTimestamp); }, /** * Set display show/hide by condition - * @param {jQuery} $el - jQuery Element + * @param {HTMLElement} el - An Element * @param {boolean} shouldShow - Condition * @private */ - _setDisplay: function($el, shouldShow) { - if (shouldShow) { - $el.show(); - } else { - $el.hide(); + _setDisplay: function(el, shouldShow) { + if (el) { + if (shouldShow) { + domUtil.removeClass(el, CLASS_NAME_HIDDEN); + } else { + domUtil.addClass(el, CLASS_NAME_HIDDEN); + } } }, @@ -830,27 +877,29 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ /** * Add opener - * @param {HTMLElement|jQuery|string} opener - element or selector + * @param {HTMLElement|string} opener - element or selector */ addOpener: function(opener) { + opener = util.getElement(opener); + if (!this._isOpener(opener)) { - this._openers.push($(opener)[0]); - setTouchClickEvent(opener, $.proxy(this.toggle, this), { - namespace: this._id - }); + this._openers.push(opener); + this._setOpenerEvents(opener); } }, /** * Remove opener - * @param {HTMLElement|jQuery|string} opener - element or selector + * @param {HTMLElement|string} opener - element or selector */ removeOpener: function(opener) { - var $opener = $(opener); - var index = snippet.inArray($opener[0], this._openers); + var index; + + opener = util.getElement(opener); + index = snippet.inArray(opener, this._openers); if (index > -1) { - this._offDatePickerEvents(opener); + this._removeOpenerEvents(opener); this._openers.splice(index, 1); } }, @@ -859,7 +908,9 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * Remove all openers */ removeAllOpeners: function() { - this._offDatePickerEvents(this._openers); + snippet.forEach(this._openers, function(opener) { + this._removeOpenerEvents(opener); + }, this); this._openers = []; }, @@ -869,7 +920,6 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * datepicker.open(); */ open: function() { - var docEvTypes; if (this.isOpened() || !this._isEnabled) { return; } @@ -878,11 +928,10 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ date: this._date, type: this._type }); - this._$element.show(); + this._show(); if (!this.showAlways) { - docEvTypes = 'touchstart.' + this._id + ' mousedown.' + this._id; - $(document).on(docEvTypes, $.proxy(this._onMousedownDocument, this)); + this._setDocumentEvents(); } /** @@ -952,8 +1001,8 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ if (!this.isOpened()) { return; } - this._offDatePickerEvents(document); - this._$element.hide(); + this._removeDocumentEvents(); + this._hide(); /** * Close event - DatePicker @@ -972,9 +1021,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * datepicker.toggle(); */ toggle: function() { - var isOpened = this.isOpened(); - - if (isOpened) { + if (this.isOpened()) { this.close(); } else { this.open(); @@ -1075,7 +1122,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * @example * datepicker.setDateFormat('yyyy-MM-dd'); * datepicker.setDateFormat('MM-dd, yyyy'); - * datepicker.setDateFormat('y/M/d'); + * datepicker.setDateFormat('yy/M/d'); * datepicker.setDateFormat('yy/MM/dd'); */ setDateFormat: function(format) { @@ -1094,7 +1141,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * datepicker.isOpened(); // true */ isOpened: function() { - return this._$element.css('display') !== 'none'; + return !domUtil.hasClass(this._element, CLASS_NAME_HIDDEN); }, /** @@ -1125,7 +1172,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ /** * Set input element - * @param {string|jQuery|HTMLElement} element - Input element + * @param {string|HTMLElement} element - Input element or selector * @param {object} [options] - Input option * @param {string} [options.format = prevInput.format] - Input text format * @param {boolean} [options.syncFromInput = false] - Set date from input value @@ -1173,10 +1220,8 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ this._datepickerInput.enable(); snippet.forEach(this._openers, function(opener) { - $(opener).removeAttr('disabled'); - setTouchClickEvent(opener, $.proxy(this.toggle, this), { - namespace: this._id - }); + opener.removeAttribute('disabled'); + this._setOpenerEvents(opener); }, this); }, @@ -1195,9 +1240,9 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ this.close(); this._datepickerInput.disable(); - this._offDatePickerEvents(this._openers); snippet.forEach(this._openers, function(opener) { - $(opener).attr('disabled', true); + opener.setAttribute('disabled', true); + this._removeOpenerEvents(opener); }, this); }, @@ -1215,7 +1260,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * @param {string} className - Class name */ addCssClass: function(className) { - this._$element.addClass(className); + domUtil.addClass(this._element, className); }, /** @@ -1223,12 +1268,12 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * @param {string} className - Class name */ removeCssClass: function(className) { - this._$element.removeClass(className); + domUtil.removeClass(this._element, className); }, /** - * Returns date elements(jQuery) on calendar - * @returns {jQuery} + * Returns date elements on calendar + * @returns {HTMLElement[]} */ getDateElements: function() { return this._calendar.getDateElements(); @@ -1251,7 +1296,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ /** * Change language * @param {string} language - Language - * @see {@link DatePicker.localeTexts} + * @see {@link DatePicker#localeTexts} */ changeLanguage: function(language) { this._language = language; @@ -1268,7 +1313,7 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ * Destroy */ destroy: function() { - this._offDatePickerEvents(document); + this._removeDocumentEvents(); this._calendar.destroy(); if (this._timepicker) { this._timepicker.destroy(); @@ -1276,14 +1321,15 @@ var DatePicker = snippet.defineClass(/** @lends DatePicker.prototype */{ if (this._datepickerInput) { this._datepickerInput.destroy(); } - this._$element.remove(); + this._removeEvents(); + domUtil.removeElement(this._element); this.removeAllOpeners(); this._calendar = this._timepicker = this._datepickerInput - = this._$container - = this._$element + = this._container + = this._element = this._date = this._rangeModel = this._openers diff --git a/src/js/datepicker/input.js b/src/js/datepicker/input.js index 98cff29..39ffdc0 100644 --- a/src/js/datepicker/input.js +++ b/src/js/datepicker/input.js @@ -5,11 +5,12 @@ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); +var domUtil = require('tui-dom'); var DateTimeFormatter = require('../dateTimeFormatter'); -var setTouchClickEvent = require('../setTouchClickEvent'); +var mouseTouchEvent = require('../mouseTouchEvent'); +var util = require('../util'); var DEFAULT_FORMAT = 'yyyy-MM-dd'; @@ -17,7 +18,7 @@ var DEFAULT_FORMAT = 'yyyy-MM-dd'; * DatePicker Input * @ignore * @class - * @param {string|jQuery|HTMLElement} inputElement - Input element + * @param {string|HTMLElement} inputElement - Input element or selector * @param {object} option - Option * @param {string} option.id - Id * @param {string} option.format - Text format @@ -28,10 +29,10 @@ var DatePickerInput = snippet.defineClass(/** @lends DatePickerInput.prototype * /** * Input element - * @type {jQuery} + * @type {HTMLElement} * @private */ - this._$input = $(inputElement); + this._input = util.getElement(inputElement); /** * Id @@ -70,34 +71,64 @@ var DatePickerInput = snippet.defineClass(/** @lends DatePickerInput.prototype * * @private */ _setEvents: function() { - this._$input.on('change.' + this._id, $.proxy(this.fire, this, 'change')); + if (this._input) { + domUtil.on(this._input, 'change', this._onChangeHandler, this); + mouseTouchEvent.on(this._input, 'click', this._onClickHandler, this); + } + }, + + /** + * Remove events + * @private + */ + _removeEvents: function() { + this.off(); + + if (this._input) { + domUtil.off(this._input, 'change', this._onChangeHandler); + mouseTouchEvent.off(this._input, 'click', this._onClickHandler); + } + }, + + /** + * Onchange handler + */ + _onChangeHandler: function() { + this.fire('change'); + }, - setTouchClickEvent(this._$input, $.proxy(this.fire, this, 'click'), { - namespace: this._id - }); + /** + * Onclick handler + */ + _onClickHandler: function() { + this.fire('click'); }, /** - * @see {@link http://api.jquery.com/is/} - * @param {string|jQuery|HTMLElement|function} el - To check matched set of elements + * Check element is same as the input element. + * @param {HTMLElement} el - To check matched set of elements * @returns {boolean} */ is: function(el) { - return this._$input.is(el); + return this._input === el; }, /** * Enable input */ enable: function() { - this._$input.removeAttr('disabled'); + if (this._input) { + this._input.removeAttribute('disabled'); + } }, /** * Disable input */ disable: function() { - this._$input.attr('disabled', true); + if (this._input) { + this._input.setAttribute('disabled', true); + } }, /** @@ -124,7 +155,9 @@ var DatePickerInput = snippet.defineClass(/** @lends DatePickerInput.prototype * * Clear text */ clearText: function() { - this._$input.val(''); + if (this._input) { + this._input.value = ''; + } }, /** @@ -132,7 +165,9 @@ var DatePickerInput = snippet.defineClass(/** @lends DatePickerInput.prototype * * @param {Date} date - Date */ setDate: function(date) { - this._$input.val(this._formatter.format(date)); + if (this._input) { + this._input.value = this._formatter.format(date); + } }, /** @@ -141,7 +176,11 @@ var DatePickerInput = snippet.defineClass(/** @lends DatePickerInput.prototype * * @throws {Error} */ getDate: function() { - var value = this._$input.val(); + var value = ''; + + if (this._input) { + value = this._input.value; + } return this._formatter.parse(value); }, @@ -150,12 +189,9 @@ var DatePickerInput = snippet.defineClass(/** @lends DatePickerInput.prototype * * Destroy */ destroy: function() { - var evNamespace = '.' + this._id; - - this.off(); - this._$input.off(evNamespace); + this._removeEvents(); - this._$input + this._input = this._id = this._formatter = null; diff --git a/src/js/index.js b/src/js/index.js index 36f900e..eb2639b 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -14,7 +14,7 @@ require('../css/calendar.css'); /** * Create a calendar component * @static - * @param {HTMLElement|jQuery|string} wrapperElement - Wrapper element or selector + * @param {HTMLElement|string} wrapperElement - Wrapper element or selector * @param {Object} [options] - Options for initialize * @param {string} [options.language = 'en'] - Calendar language - {@link Calendar.localeTexts} * @param {boolean} [options.showToday] - If true, shows today @@ -42,11 +42,11 @@ DatePicker.createCalendar = function(wrapperElement, options) { * @static * @param {object} options - Date-Range picker options * @param {object} options.startpicker - Startpicker options - * @param {Element|jQuery|string} options.startpicker.input - Startpicker input element - * @param {Element|jQuery|string} options.startpicker.container - Startpicker container element + * @param {HTMLElement|string} options.startpicker.input - Startpicker input element or selector + * @param {HTMLElement|string} options.startpicker.container - Startpicker container element or selector * @param {object} options.endpicker - Endpicker options - * @param {Element|jQuery|string} options.endpicker.input - Endpicker input element - * @param {Element|jQuery|string} options.endpicker.container - Endpicker container element + * @param {HTMLElement|string} options.endpicker.input - Endpicker input element or selector + * @param {HTMLElement|string} options.endpicker.container - Endpicker container element or selector * @param {string} options.format - Input date-string format * @param {string} [options.type = 'date'] - DatePicker type - ('date' | 'month' | 'year') * @param {string} [options.language='en'] - Language key diff --git a/src/js/mouseTouchEvent.js b/src/js/mouseTouchEvent.js new file mode 100644 index 0000000..be7ceaa --- /dev/null +++ b/src/js/mouseTouchEvent.js @@ -0,0 +1,60 @@ +/** + * @fileoverview Set mouse-touch event + * @author NHN. FE Development Lab + */ + +'use strict'; + +var domUtil = require('tui-dom'); + +var mouseTouchEvent = { + /** + * Detect mobile browser + * @type {boolean} Whether using Mobile browser + * @private + */ + _isMobile: (function() { + return /Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i.test(navigator.userAgent); + })(), + + /** + * Return a matched event type by a mouse event type + * @param {string} type A mouse event type - mousedown, click + * @returns {string} + * @private + */ + _getEventType: function(type) { + if (this._isMobile) { + if (type === 'mousedown') { + type = 'touchstart'; + } else if (type === 'click') { + type = 'touchend'; + } + } + + return type; + }, + + /** + * Bind touch or mouse events + * @param {HTMLElement} element An element to bind + * @param {string} type A mouse event type - mousedown, click + * @param {Function} handler A handler function + * @param {object} [context] A context for handler. + */ + on: function(element, type, handler, context) { + domUtil.on(element, this._getEventType(type), handler, context); + }, + + /** + * Unbind touch or mouse events + * @param {HTMLElement} element - Target element + * @param {string} type A mouse event type - mousedown, click + * @param {Function} handler - Handler + */ + off: function(element, type, handler) { + domUtil.off(element, this._getEventType(type), handler); + } +}; + +module.exports = mouseTouchEvent; diff --git a/src/js/setTouchClickEvent.js b/src/js/setTouchClickEvent.js deleted file mode 100644 index 8b11120..0000000 --- a/src/js/setTouchClickEvent.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @fileoverview Set mouse-touch event - * @author NHN. FE Development Lab - */ - -'use strict'; - -var $ = require('jquery'); - -/** - * Detect mobile browser - * @private - * @returns {boolean} Whether using Mobile browser - */ -function isMobile() { - return /Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i.test(navigator.userAgent); -} - -/** - * For using one - Touch or Mouse Events - * @param {jQuery|string|Element} target - Target element - * @param {Function} handler - Handler - * @param {object} [option] - Option - * @param {string} option.selector - Selector - * @param {string} option.namespace - Event namespace - */ -module.exports = function(target, handler, option) { - var $target = $(target); - var eventType = isMobile() ? 'touchend' : 'click'; - var selector, namespace; - - option = option || {}; - selector = option.selector || null; - namespace = option.namespace || ''; - - if (namespace) { - eventType = eventType + '.' + namespace; - } - - $target.on(eventType, selector, handler); -}; diff --git a/src/js/util.js b/src/js/util.js new file mode 100644 index 0000000..bf8144d --- /dev/null +++ b/src/js/util.js @@ -0,0 +1,46 @@ +/** + * @fileoverview Utils for Datepicker component + * @author NHN. FE Development Lab + */ + +'use strict'; + +var snippet = require('tui-code-snippet'); + +var utils = { + /** + * Get a target element + * @param {Event} ev Event object + * @returns {HTMLElement} An event target element + */ + getTarget: function(ev) { + return ev.target || ev.srcElement; + }, + + /** + * Return the same element with an element or a matched element searched by a selector. + * @param {HTMLElement|string} param HTMLElement or selector + * @returns {HTMLElement} A matched element + */ + getElement: function(param) { + return snippet.isHTMLNode(param) ? param : document.querySelector(param); + }, + + /** + * Get a selector of the element. + * @param {HTMLElement} elem An element + * @returns {string} + */ + getSelector: function(elem) { + var selector = ''; + if (elem.id) { + selector = '#' + elem.id; + } else if (elem.className) { + selector = '.' + elem.className.split(' ')[0]; + } + + return selector; + } +}; + +module.exports = utils; diff --git a/src/template/calendar/header.hbs b/src/template/calendar/header.hbs index 314afad..bd88a80 100644 --- a/src/template/calendar/header.hbs +++ b/src/template/calendar/header.hbs @@ -1,24 +1,24 @@ {{#if isDateCalendar}} {{#if showJumpButtons}}
- Prev year - Prev month + + {{title}} - Next month - Next year + +
{{else}}
- Prev month + {{title}} - Next month +
{{/if}} {{else}}
- Prev year + {{title}} - Next year +
{{/if}} diff --git a/src/template/datepicker/index.hbs b/src/template/datepicker/index.hbs index 02d0dfe..0367839 100644 --- a/src/template/datepicker/index.hbs +++ b/src/template/datepicker/index.hbs @@ -9,12 +9,21 @@ {{localeText.time}} -
+
+
+
+
{{else}} -
- +
+
+
+ {{/if}} {{else}} -
+
+
+
{{/if}} diff --git a/test/calendar/body.spec.js b/test/calendar/body.spec.js index 3149688..2a04c80 100644 --- a/test/calendar/body.spec.js +++ b/test/calendar/body.spec.js @@ -4,16 +4,14 @@ */ 'use strict'; -var $ = require('jquery'); - var Body = require('../../src/js/calendar/body'); describe('Calendar - Body', function() { var body; - var $container = $('
'); + var container = document.createElement('div'); beforeEach(function() { - body = new Body($container, {language: 'en'}); + body = new Body(container, {language: 'en'}); }); afterEach(function() { @@ -43,14 +41,13 @@ describe('Calendar - Body', function() { expect(body._monthLayer.render).toHaveBeenCalled(); }); - it('"getDateElements" should return date jquery elements', function() { - var $dateElements; + it('"getDateElements" should return date HTML elements', function() { + var dateElements; body.render(new Date(2016, 0), 'month'); - $dateElements = body.getDateElements(); + dateElements = body.getDateElements(); - expect($dateElements.length).toBe(12); - expect($dateElements.jquery).toBeTruthy(); + expect(dateElements.length).toBe(12); }); }); diff --git a/test/calendar/calendar.spec.js b/test/calendar/calendar.spec.js index dc8f1be..dcec87d 100644 --- a/test/calendar/calendar.spec.js +++ b/test/calendar/calendar.spec.js @@ -4,18 +4,17 @@ */ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); var Calendar = require('../../src/js/calendar'); describe('Calendar', function() { describe('Api', function() { - var $container = $('
'); + var container = document.createElement('div'); var calendar; beforeEach(function() { - calendar = new Calendar($container); + calendar = new Calendar(container); }); afterEach(function() { @@ -163,7 +162,7 @@ describe('Calendar', function() { expect(calendar.getDate().getMonth()).toBe(0); }); - it('"getDateElements" should return jQuery elements', function() { + it('"getDateElements" should return HTML elements', function() { var dateElements; calendar.draw({ @@ -173,7 +172,6 @@ describe('Calendar', function() { dateElements = calendar.getDateElements(); - expect(dateElements.jquery).toBeTruthy(); expect(dateElements.length).toBe(42); }); @@ -190,12 +188,12 @@ describe('Calendar', function() { }); it('"destory" should destory', function() { - var $nContainer = $('
'); - var nCalendar = new Calendar($nContainer); + var nContainer = document.createElement('div'); + var nCalendar = new Calendar(nContainer); nCalendar.destroy(); - expect($nContainer.children().length).toBe(0); + expect(nContainer.children.length).toBe(0); expect(nCalendar._header).toBeNull(); expect(nCalendar._body).toBeNull(); }); @@ -205,14 +203,14 @@ describe('Calendar', function() { var nCalendar; it('should send hostname by default', function() { spyOn(snippet, 'sendHostname'); - nCalendar = new Calendar($('
')); + nCalendar = new Calendar(document.createElement('div')); expect(snippet.sendHostname).toHaveBeenCalled(); }); it('should not send hostname on usageStatistics option false', function() { spyOn(snippet, 'sendHostname'); - nCalendar = new Calendar($('
'), {usageStatistics: false}); + nCalendar = new Calendar(document.createElement('div'), {usageStatistics: false}); expect(snippet.sendHostname).not.toHaveBeenCalled(); }); diff --git a/test/calendar/header.spec.js b/test/calendar/header.spec.js index 059fb7d..7e7fbb1 100644 --- a/test/calendar/header.spec.js +++ b/test/calendar/header.spec.js @@ -4,18 +4,16 @@ */ 'use strict'; -var $ = require('jquery'); - var Header = require('../../src/js/calendar/header'); var constants = require('../../src/js/constants'); describe('Calendar', function() { describe('Header', function() { var header = null; - var $container = $('
'); + var container = document.createElement('div'); beforeEach(function() { - header = new Header($container, { + header = new Header(container, { language: 'en', showJumpButtons: true }); @@ -27,51 +25,53 @@ describe('Calendar', function() { }); it('should render buttons', function() { - expect(header._$element.find('.' + constants.CLASS_NAME_NEXT_MONTH_BTN).length).toBe(1); - expect(header._$element.find('.' + constants.CLASS_NAME_NEXT_YEAR_BTN).length).toBe(1); - expect(header._$element.find('.' + constants.CLASS_NAME_PREV_MONTH_BTN).length).toBe(1); - expect(header._$element.find('.' + constants.CLASS_NAME_PREV_YEAR_BTN).length).toBe(1); + expect(header._container.querySelectorAll('.' + constants.CLASS_NAME_NEXT_MONTH_BTN).length).toBe(1); + expect(header._container.querySelectorAll('.' + constants.CLASS_NAME_NEXT_YEAR_BTN).length).toBe(1); + expect(header._container.querySelectorAll('.' + constants.CLASS_NAME_PREV_MONTH_BTN).length).toBe(1); + expect(header._container.querySelectorAll('.' + constants.CLASS_NAME_PREV_YEAR_BTN).length).toBe(1); }); it('should set title text formatted', function() { - expect(header._$element.find('.tui-calendar-title').text()).toBe('December 2016'); + expect(header._container.querySelector('.tui-calendar-title').innerText).toBe('December 2016'); }); it('should fire "click" custom event when click a button', function() { var spy = jasmine.createSpy('button click handler'); header.on('click', spy); - header._$element.find('.' + constants.CLASS_NAME_NEXT_MONTH_BTN).click(); + header._container.querySelector('.' + constants.CLASS_NAME_NEXT_MONTH_BTN).click(); expect(spy).toHaveBeenCalled(); spy.calls.reset(); - header._$element.find('.' + constants.CLASS_NAME_NEXT_YEAR_BTN).click(); + header._container.querySelector('.' + constants.CLASS_NAME_NEXT_YEAR_BTN).click(); expect(spy).toHaveBeenCalled(); spy.calls.reset(); - header._$element.find('.' + constants.CLASS_NAME_PREV_MONTH_BTN).click(); + header._container.querySelector('.' + constants.CLASS_NAME_PREV_MONTH_BTN).click(); expect(spy).toHaveBeenCalled(); spy.calls.reset(); - header._$element.find('.' + constants.CLASS_NAME_PREV_YEAR_BTN).click(); + header._container.querySelector('.' + constants.CLASS_NAME_PREV_YEAR_BTN).click(); expect(spy).toHaveBeenCalled(); }); it('should be able to destroy', function() { - var $nContainer = $('
'); - var nHeader = new Header($nContainer, { - language: 'en' + var nContainer = document.createElement('div'); + var nHeader = new Header(nContainer, { + language: 'en', + showToday: true }); nHeader.render(); nHeader.destroy(); - expect($nContainer.children().length).toBe(0); - expect(nHeader._$container).toBeNull(); - expect(nHeader._$element).toBeNull(); + expect(nContainer.children.length).toBe(0); + expect(nHeader._container).toBeNull(); + expect(nHeader._innerElement).toBeNull(); + expect(nHeader._infoElement).toBeNull(); }); it('"changeLanaguage" should re-initilize formatters', function() { @@ -82,15 +82,15 @@ describe('Calendar', function() { }); it('should render today box if allowed', function() { - var $nContainer = $('
'); - var nHeader = new Header($nContainer, { + var nContainer = document.createElement('div'); + var nHeader = new Header(nContainer, { language: 'en', showToday: true }); nHeader.render(); - expect(nHeader._$element.find('.tui-calendar-title-today').length).toBe(1); + expect(nHeader._container.querySelectorAll('.tui-calendar-title-today').length).toBe(1); nHeader.destroy(); }); diff --git a/test/datepicker/datepicker.spec.js b/test/datepicker/datepicker.spec.js index 8bbdee1..01ef0ae 100755 --- a/test/datepicker/datepicker.spec.js +++ b/test/datepicker/datepicker.spec.js @@ -4,14 +4,18 @@ */ 'use strict'; -var $ = require('jquery'); var snippet = require('tui-code-snippet'); +var domUtil = require('tui-dom'); + var TimePicker = require('tui-time-picker'); var DatePicker = require('../../src/js/datepicker'); var Calendar = require('../../src/js/calendar'); var constants = require('../../src/js/constants'); +var CLASS_NAME_SELECTABLE = 'tui-is-selectable'; +var CLASS_NAME_HIDDEN = 'tui-hidden'; + describe('Date Picker', function() { describe('date=null on constructor', function() { var datepicker, input, container; @@ -89,7 +93,7 @@ describe('Date Picker', function() { var datepicker; beforeEach(function() { - datepicker = new DatePicker($('
'), { + datepicker = new DatePicker(document.createElement('div'), { date: new Date(2017, 10, 27), selectableRanges: [ [new Date(2016, 10, 27), new Date(2018, 10, 27)] @@ -390,7 +394,7 @@ describe('Date Picker', function() { beforeEach(function() { input = document.createElement('input'); - datepicker = new DatePicker($('
'), { + datepicker = new DatePicker(document.createElement('div'), { input: { element: input, format: 'yy년 MM월 dd일' @@ -406,14 +410,17 @@ describe('Date Picker', function() { datepicker.destroy(); }); - it('_onClickDate', function() { + it('click-date event should change the date', function() { var td = document.createElement('td'); - var ev = { - target: td - }; var today = new Date(); - $(td).data('timestamp', today.setHours(0, 0, 0, 0)); // Calendar-date does not have hours - datepicker._onClickDate(ev); + + domUtil.addClass(td, CLASS_NAME_SELECTABLE); + domUtil.setData(td, 'timestamp', today.setHours(0, 0, 0, 0)); // Calendar-date does not have hours + document.body.appendChild(td); + + datepicker._onClickHandler({ + target: td + }); expect(datepicker.getDate().getTime()).toEqual(today.setHours(0, 0, 0, 0)); }); @@ -426,21 +433,13 @@ describe('Date Picker', function() { expect(input.value).toEqual('17년 02월 03일'); }); - it('click-opener event should call "toggle"', function() { - var opener = document.createElement('button'); - - spyOn(datepicker, 'toggle'); - datepicker.addOpener(opener); - $(opener).click(); - - expect(datepicker.toggle).toHaveBeenCalled(); - }); - it('mousedown-document event should call "close" when showAlways=false', function() { spyOn(datepicker, 'close'); datepicker.showAlways = false; datepicker.open(); - $(document).mousedown(); + datepicker._onMousedownDocument({ + target: document + }); expect(datepicker.close).toHaveBeenCalled(); }); @@ -449,32 +448,39 @@ describe('Date Picker', function() { spyOn(datepicker, 'close'); datepicker.showAlways = true; datepicker.open(); - $(document).mousedown(); + datepicker._onMousedownDocument({ + target: document + }); expect(datepicker.close).not.toHaveBeenCalled(); }); it('click-date event should call "close" when autoClose=true', function() { - var $el = $(''); + var el = document.createElement('td'); + domUtil.addClass(el, CLASS_NAME_SELECTABLE); + domUtil.setData(el, 'timestamp', new Date(2017, 0, 1).getTime()); + document.body.appendChild(el); spyOn(datepicker, 'close'); datepicker.autoClose = true; datepicker.open(); - datepicker._onClickDate({ - target: $el[0] + datepicker._onClickHandler({ + target: el }); expect(datepicker.close).toHaveBeenCalled(); }); it('click-date event should not call "close" when autoClose=false', function() { - var $el = $(''); + var el = document.createElement('td'); + domUtil.addClass(el, CLASS_NAME_SELECTABLE); + domUtil.setData(el, 'timestamp', new Date(2017, 0, 1).getTime()); spyOn(datepicker, 'close'); datepicker.autoClose = false; datepicker.open(); - datepicker._onClickDate({ - target: $el[0] + datepicker._onClickHandler({ + target: el }); expect(datepicker.close).not.toHaveBeenCalled(); @@ -559,15 +565,15 @@ describe('Date Picker', function() { }); describe('about useless-buttons', function() { - var datepicker, $container; + var datepicker, container; - function isHidden($el) { // eslint-disable-line - return $el.css('display') === 'none'; + function isHidden(el) { // eslint-disable-line + return domUtil.hasClass(el, CLASS_NAME_HIDDEN); } beforeEach(function() { - $container = $('
'); - datepicker = new DatePicker($container, { + container = document.createElement('div'); + datepicker = new DatePicker(container, { date: new Date(2017, 6, 1), calendar: { showJumpButtons: true @@ -580,65 +586,65 @@ describe('Date Picker', function() { afterEach(function() { datepicker.destroy(); - $container.remove(); - $container = null; + domUtil.removeElement(container); + container = null; }); it('should hide the prev-year-btn out of selectables', function() { - var $btn = $container.find('.' + constants.CLASS_NAME_PREV_YEAR_BTN); - expect(isHidden($btn)).toBe(false); + var btn = container.querySelector('.' + constants.CLASS_NAME_PREV_YEAR_BTN); + expect(isHidden(btn)).toBe(false); datepicker.setDate(new Date(2017, 3, 1)); - $btn = $container.find('.' + constants.CLASS_NAME_PREV_YEAR_BTN); - expect(isHidden($btn)).toBe(true); + btn = container.querySelector('.' + constants.CLASS_NAME_PREV_YEAR_BTN); + expect(isHidden(btn)).toBe(true); }); it('should hide the prev-month-btn out of selectables', function() { - var $btn = $container.find('.' + constants.CLASS_NAME_PREV_MONTH_BTN); - expect(isHidden($btn)).toBe(false); + var btn = container.querySelector('.' + constants.CLASS_NAME_PREV_MONTH_BTN); + expect(isHidden(btn)).toBe(false); datepicker.setDate(new Date(2016, 4, 3)); - $btn = $container.find('.' + constants.CLASS_NAME_PREV_MONTH_BTN); - expect(isHidden($btn)).toBe(true); + btn = container.querySelector('.' + constants.CLASS_NAME_PREV_MONTH_BTN); + expect(isHidden(btn)).toBe(true); }); it('should hide the next-year-btn out of selectables', function() { - var $btn; + var btn; datepicker.setDate(new Date(2017, 4, 3)); - $btn = $container.find('.' + constants.CLASS_NAME_NEXT_YEAR_BTN); - expect(isHidden($btn)).toBe(false); + btn = container.querySelector('.' + constants.CLASS_NAME_NEXT_YEAR_BTN); + expect(isHidden(btn)).toBe(false); datepicker.setDate(new Date(2017, 5, 3)); - $btn = $container.find('.' + constants.CLASS_NAME_NEXT_YEAR_BTN); - expect(isHidden($btn)).toBe(true); + btn = container.querySelector('.' + constants.CLASS_NAME_NEXT_YEAR_BTN); + expect(isHidden(btn)).toBe(true); }); it('should hide the next-month-btn out of selectables', function() { - var $btn = $container.find('.' + constants.CLASS_NAME_NEXT_MONTH_BTN); - expect(isHidden($btn)).toBe(false); + var btn = container.querySelector('.' + constants.CLASS_NAME_NEXT_MONTH_BTN); + expect(isHidden(btn)).toBe(false); datepicker.setDate(new Date(2018, 4, 1)); - $btn = $container.find('.' + constants.CLASS_NAME_NEXT_MONTH_BTN); - expect(isHidden($btn)).toBe(true); + btn = container.querySelector('.' + constants.CLASS_NAME_NEXT_MONTH_BTN); + expect(isHidden(btn)).toBe(true); }); it('should not hide next/prev-year-btn when equals to selectables minimum/maximum', function() { - var $btn; + var btn; datepicker.setRanges([ [new Date(2015, 0, 1), new Date(2017, 0, 1)] ]); datepicker.setDate(new Date(2016, 0, 1)); - $btn = $container.find('.' + constants.CLASS_NAME_NEXT_YEAR_BTN); - expect(isHidden($btn)).toBe(false); + btn = container.querySelector('.' + constants.CLASS_NAME_NEXT_YEAR_BTN); + expect(isHidden(btn)).toBe(false); - $btn = $container.find('.' + constants.CLASS_NAME_PREV_YEAR_BTN); - expect(isHidden($btn)).toBe(false); + btn = container.querySelector('.' + constants.CLASS_NAME_PREV_YEAR_BTN); + expect(isHidden(btn)).toBe(false); }); }); }); diff --git a/tuidoc.config.json b/tuidoc.config.json index d1b7f14..dd5aa53 100644 --- a/tuidoc.config.json +++ b/tuidoc.config.json @@ -22,7 +22,8 @@ "filePath": "README.md" }, "api": { - "filePath": "src/js/**" + "filePath": "src/js/**", + "fileLink": true }, "examples": { "filePath": "examples", diff --git a/webpack.config.js b/webpack.config.js index 5dbaca5..54dd243 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -34,18 +34,18 @@ var config = { filename: FILENAME }, externals: { - 'jquery': { - 'commonjs': 'jquery', - 'commonjs2': 'jquery', - 'amd': 'jquery', - 'root': '$' - }, 'tui-code-snippet': { 'commonjs': 'tui-code-snippet', 'commonjs2': 'tui-code-snippet', 'amd': 'tui-code-snippet', 'root': ['tui', 'util'] }, + 'tui-dom': { + 'commonjs': 'tui-dom', + 'commonjs2': 'tui-dom', + 'amd': 'tui-dom', + 'root': ['tui', 'dom'] + }, 'tui-time-picker': { 'commonjs': 'tui-time-picker', 'commonjs2': 'tui-time-picker',