pikaday.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /*!
  2. * Pikaday
  3. * Copyright © 2012 David Bushell | BSD & MIT license | http://dbushell.com/
  4. */
  5. (function (window, document, undefined) {
  6. 'use strict';
  7. /**
  8. * feature detection and helper functions
  9. */
  10. var hasMoment = typeof window.moment === 'function',
  11. hasEventListeners = !!window.addEventListener,
  12. sto = window.setTimeout,
  13. addEvent = function (el, e, callback, capture) {
  14. if (hasEventListeners) {
  15. el.addEventListener(e, callback, !!capture);
  16. } else {
  17. el.attachEvent('on' + e, callback);
  18. }
  19. },
  20. removeEvent = function (el, e, callback, capture) {
  21. if (hasEventListeners) {
  22. el.removeEventListener(e, callback, !!capture);
  23. } else {
  24. el.detachEvent('on' + e, callback);
  25. }
  26. },
  27. trim = function (str) {
  28. return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
  29. },
  30. hasClass = function (el, cn) {
  31. return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1;
  32. },
  33. addClass = function (el, cn) {
  34. if (!hasClass(el, cn)) {
  35. el.className = (el.className === '') ? cn : el.className + ' ' + cn;
  36. }
  37. },
  38. removeClass = function (el, cn) {
  39. el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' '));
  40. },
  41. isArray = function (obj) {
  42. return (/Array/).test(Object.prototype.toString.call(obj));
  43. },
  44. isDate = function (obj) {
  45. return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
  46. },
  47. isLeapYear = function (year) {
  48. // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
  49. return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
  50. },
  51. getDaysInMonth = function (year, month) {
  52. return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
  53. },
  54. compareDates = function (a, b) {
  55. // weak date comparison (use date.setHours(0,0,0,0) to ensure correct result)
  56. return a.getTime() === b.getTime();
  57. },
  58. extend = function (to, from, overwrite) {
  59. var prop, hasProp;
  60. for (prop in from) {
  61. hasProp = to[prop] !== undefined;
  62. if (hasProp && typeof from[prop] === 'object' && from[prop].nodeName === undefined) {
  63. if (isDate(from[prop])) {
  64. if (overwrite) {
  65. to[prop] = new Date(from[prop].getTime());
  66. }
  67. }
  68. else if (isArray(from[prop])) {
  69. if (overwrite) {
  70. to[prop] = from[prop].slice(0);
  71. }
  72. } else {
  73. to[prop] = extend({}, from[prop], overwrite);
  74. }
  75. } else if (overwrite || !hasProp) {
  76. to[prop] = from[prop];
  77. }
  78. }
  79. return to;
  80. },
  81. /**
  82. * defaults and localisation
  83. */
  84. defaults = {
  85. // bind the picker to a form field
  86. field: null,
  87. // automatically show/hide the picker on `field` focus (default `true` if `field` is set)
  88. bound: undefined,
  89. // the default output format for `.toString()` and `field` value
  90. format: 'YYYY-MM-DD',
  91. // the initial date to view when first opened
  92. defaultDate: null,
  93. // make the `defaultDate` the initial selected value
  94. setDefaultDate: false,
  95. // first day of week (0: Sunday, 1: Monday etc)
  96. firstDay: 0,
  97. // the minimum/earliest date that can be selected
  98. minDate: null,
  99. // the maximum/latest date that can be selected
  100. maxDate: null,
  101. // number of years either side, or array of upper/lower range
  102. yearRange: 10,
  103. // used internally (don't config outside)
  104. minYear: 1990,
  105. maxYear: 2099,
  106. minMonth: undefined,
  107. maxMonth: undefined,
  108. isRTL: false,
  109. // how many months are visible (not implemented yet)
  110. numberOfMonths: 1,
  111. // internationalization
  112. /* i18n: {
  113. months : ['January','February','March','April','May','June','July','August','September','October','November','December'],
  114. //monthsShort : ['Jan_Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
  115. weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
  116. weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
  117. }, */
  118. i18n: {
  119. months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
  120. monthsShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
  121. weekdays: ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
  122. weekdaysShort: ['日', '一', '二', '三', '四', '五', '六']
  123. },
  124. // callback function
  125. onSelect: null,
  126. onOpen: null,
  127. onClose: null
  128. },
  129. /**
  130. * templating functions to abstract HTML rendering
  131. */
  132. renderDayName = function (opts, day, abbr) {
  133. day += opts.firstDay;
  134. while (day >= 7) {
  135. day -= 7;
  136. }
  137. return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day];
  138. },
  139. renderDay = function (i, isSelected, isToday, isDisabled, isEmpty) {
  140. if (isEmpty) {
  141. return '<td class="is-empty"></td>';
  142. }
  143. var arr = [];
  144. if (isDisabled) {
  145. arr.push('is-disabled');
  146. }
  147. if (isToday) {
  148. arr.push('is-today');
  149. }
  150. if (isSelected) {
  151. arr.push('is-selected');
  152. }
  153. return '<td data-day="' + i + '" class="' + arr.join(' ') + '"><a class="pika-button" href="javascript:void(0);">' + i + '</a>' + '</td>';
  154. },
  155. renderRow = function (days, isRTL) {
  156. return '<tr>' + (isRTL ? days.reverse() : days).join('') + '</tr>';
  157. },
  158. renderBody = function (rows) {
  159. return '<tbody>' + rows.join('') + '</tbody>';
  160. },
  161. renderHead = function (opts) {
  162. var i, arr = [];
  163. for (i = 0; i < 7; i++) {
  164. arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>');
  165. }
  166. return '<thead>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</thead>';
  167. },
  168. renderTitle = function (instance) {
  169. var i, j, arr,
  170. opts = instance._o,
  171. month = instance._m,
  172. year = instance._y,
  173. isMinYear = year === opts.minYear,
  174. isMaxYear = year === opts.maxYear,
  175. html = '<div class="pika-title">',
  176. prev = true,
  177. next = true,
  178. months = opts.i18n.monthsShort ? opts.i18n.monthsShort : opts.i18n.months;
  179. if (isMinYear && (month === 0 || opts.minMonth >= month)) {
  180. prev = false;
  181. }
  182. html += '<a class="pika-prev' + (prev ? '' : ' is-disabled') + '" href="javascript:void(0);">&lt;</a>';
  183. if (isArray(opts.yearRange)) {
  184. i = opts.yearRange[0];
  185. j = opts.yearRange[1] + 1;
  186. } else {
  187. i = year - opts.yearRange;
  188. j = 1 + year + opts.yearRange;
  189. }
  190. for (arr = []; i < j && i <= opts.maxYear; i++) {
  191. if (i >= opts.minYear) {
  192. arr.push('<option value="' + i + '"' + (i === year ? ' selected' : '') + '>' + (i) + '</option>');
  193. }
  194. }
  195. html += '<div class="pika-label pika-label-year">' + year + '年 <select class="pika-select pika-select-year">' + arr.join('') + '</select></div>';
  196. for (arr = [], i = 0; i < 12; i++) {
  197. arr.push('<option value="' + i + '"' +
  198. (i === month ? ' selected' : '') +
  199. ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled' : '') + '>' +
  200. months[i] + '</option>');
  201. }
  202. html += '<div class="pika-label pika-label-month">' + months[month] + '月<select class="pika-select pika-select-month">' + arr.join('') + '</select></div>';
  203. if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
  204. next = false;
  205. }
  206. html += '<a class="pika-next' + (next ? '' : ' is-disabled') + '" href="javascript:void(0);">&gt;</a>';
  207. return html += '</div>';
  208. },
  209. renderTable = function (opts, data) {
  210. return '<table cellpadding="0" cellspacing="0" class="pika-table">' + renderHead(opts) + renderBody(data) + '</table>';
  211. };
  212. /**
  213. * Pikaday constructor
  214. */
  215. window.Pikaday = function (options) {
  216. var self = this,
  217. opts = self.config(options);
  218. self._hh = 0;
  219. self._mi = 0;
  220. self._onMouseDown = function (e) {
  221. if (!self._v) {
  222. return;
  223. }
  224. e = e || window.event;
  225. var target = e.target || e.srcElement;
  226. if (!target) {
  227. return;
  228. }
  229. if (!hasClass(target, 'is-disabled')) {
  230. if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty')) {
  231. self.setDate(new Date(self._y, self._m, parseInt(target.innerHTML, 10)));
  232. if (opts.bound) {
  233. sto(function () {
  234. self.hide();
  235. }, 100);
  236. }
  237. return;
  238. }
  239. else if (hasClass(target, 'pika-prev')) {
  240. self.prevMonth();
  241. }
  242. else if (hasClass(target, 'pika-next')) {
  243. self.nextMonth();
  244. }
  245. }
  246. if (!hasClass(target, 'pika-select')) {
  247. if (e.preventDefault) {
  248. e.preventDefault();
  249. } else {
  250. return e.returnValue = false;
  251. }
  252. } else {
  253. self._c = true;
  254. }
  255. };
  256. self._onChange = function (e) {
  257. e = e || window.event;
  258. var target = e.target || e.srcElement;
  259. if (!target) {
  260. return;
  261. }
  262. if (hasClass(target, 'pika-select-month')) {
  263. self.gotoMonth(target.value);
  264. }
  265. else if (hasClass(target, 'pika-select-year')) {
  266. self.gotoYear(target.value);
  267. }
  268. };
  269. self._onInputChange = function (e) {
  270. if (hasMoment) {
  271. self.setDate(window.moment(opts.field.value, opts.format).toDate());
  272. }
  273. else {
  274. var date = new Date(Date.parse(opts.field.value));
  275. self.setDate(isDate(date) ? date : null);
  276. }
  277. if (!self._v) {
  278. self.show();
  279. }
  280. };
  281. self._onInputFocus = function (e) {
  282. self.show();
  283. };
  284. self._onInputClick = function (e) {
  285. self.show();
  286. };
  287. self._onInputBlur = function (e) {
  288. if (!self._c) {
  289. self._b = sto(function () {
  290. self.hide();
  291. }, 50);
  292. }
  293. self._c = false;
  294. };
  295. self._onClick = function (e) {
  296. e = e || window.event;
  297. var target = e.target || e.srcElement,
  298. pEl = target;
  299. if (!target) {
  300. return;
  301. }
  302. if (!hasEventListeners && hasClass(target, 'pika-select')) {
  303. if (!target.onchange) {
  304. target.setAttribute('onchange', 'return;');
  305. addEvent(target, 'change', self._onChange);
  306. }
  307. }
  308. do {
  309. if (hasClass(pEl, 'pika-single')) {
  310. return;
  311. }
  312. }
  313. while ((pEl = pEl.parentNode));
  314. if (self._v && target !== opts.field) {
  315. self.hide();
  316. }
  317. };
  318. self.el = document.createElement('div');
  319. self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '');
  320. addEvent(self.el, 'mousedown', self._onMouseDown, true);
  321. addEvent(self.el, 'change', self._onChange);
  322. if (opts.field) {
  323. if (opts.bound) {
  324. $('body').prepend(self.el);
  325. //document.body.appendChild(self.el);
  326. } else {
  327. opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling);
  328. }
  329. addEvent(opts.field, 'change', self._onInputChange);
  330. if (!opts.defaultDate) {
  331. if (hasMoment && opts.field.value) {
  332. opts.defaultDate = window.moment(opts.field.value, opts.format).toDate();
  333. } else {
  334. opts.defaultDate = new Date(Date.parse(opts.field.value));
  335. }
  336. opts.setDefaultDate = true;
  337. }
  338. }
  339. var defDate = opts.defaultDate;
  340. if (isDate(defDate)) {
  341. if (opts.setDefaultDate) {
  342. self.setDate(defDate);
  343. } else {
  344. self.gotoDate(defDate);
  345. }
  346. } else {
  347. self.gotoDate(new Date());
  348. }
  349. if (opts.bound) {
  350. this.hide();
  351. self.el.className += ' is-bound';
  352. addEvent(opts.field, 'click', self._onInputClick);
  353. addEvent(opts.field, 'focus', self._onInputFocus);
  354. addEvent(opts.field, 'blur', self._onInputBlur);
  355. } else {
  356. this.show();
  357. }
  358. };
  359. /**
  360. * public Pikaday API
  361. */
  362. window.Pikaday.prototype = {
  363. /**
  364. * configure functionality
  365. */
  366. config: function (options) {
  367. if (!this._o) {
  368. this._o = extend({}, defaults, true);
  369. }
  370. var opts = extend(this._o, options, true);
  371. opts.isRTL = !!opts.isRTL;
  372. opts.field = (opts.field && opts.field.nodeName) ? opts.field : null;
  373. opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field);
  374. var nom = parseInt(opts.numberOfMonths, 10) || 1;
  375. opts.numberOfMonths = nom > 4 ? 4 : nom;
  376. if (!isDate(opts.minDate)) {
  377. opts.minDate = false;
  378. }
  379. if (!isDate(opts.maxDate)) {
  380. opts.maxDate = false;
  381. }
  382. if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) {
  383. opts.maxDate = opts.minDate = false;
  384. }
  385. if (opts.minDate) {
  386. opts.minYear = opts.minDate.getFullYear();
  387. opts.minMonth = opts.minDate.getMonth();
  388. }
  389. if (opts.maxDate) {
  390. opts.maxYear = opts.maxDate.getFullYear();
  391. opts.maxMonth = opts.maxDate.getMonth();
  392. }
  393. if (isArray(opts.yearRange)) {
  394. var fallback = new Date().getFullYear() - 10;
  395. opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback;
  396. opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback;
  397. } else {
  398. opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange;
  399. if (opts.yearRange > 100) {
  400. opts.yearRange = 100;
  401. }
  402. }
  403. return opts;
  404. },
  405. /**
  406. * return a formatted string of the current selection (using Moment.js if available)
  407. */
  408. toString: function (format) {
  409. if (!isDate(this._d)) return '';
  410. var y = this._d.getFullYear();
  411. var m = this._d.getMonth() + 1;
  412. var d = this._d.getDate();
  413. m = m < 10 ? '0' + m : m;
  414. d = d < 10 ? '0' + d : d;
  415. return hasMoment ? window.moment(this._d).format(format || this._o.format) : (y + '-' + m + '-' + d);
  416. },
  417. /**
  418. * return a Moment.js object of the current selection (if available)
  419. */
  420. getMoment: function () {
  421. return hasMoment ? window.moment(this._d) : null;
  422. },
  423. /**
  424. * return a Date object of the current selection
  425. */
  426. getDate: function () {
  427. return isDate(this._d) ? new Date(this._d.getTime()) : null;
  428. },
  429. /**
  430. * set the current selection
  431. */
  432. setDate: function (date) {
  433. if (!date) {
  434. this._d = null;
  435. return this.draw();
  436. }
  437. if (typeof date === 'string') {
  438. date = new Date(Date.parse(date));
  439. }
  440. if (!isDate(date)) {
  441. return;
  442. }
  443. var min = this._o.minDate,
  444. max = this._o.maxDate;
  445. if (isDate(min) && date < min) {
  446. date = min;
  447. } else if (isDate(max) && date > max) {
  448. date = max;
  449. }
  450. this._d = new Date(date.getTime());
  451. this._d.setHours(0, 0, 0, 0);
  452. this.gotoDate(this._d);
  453. if (this._o.field) {
  454. this._o.field.value = this.toString();
  455. }
  456. if (typeof this._o.onSelect === 'function') {
  457. this._o.onSelect.call(this, this.getDate());
  458. }
  459. },
  460. /**
  461. * change view to a specific date
  462. */
  463. gotoDate: function (date) {
  464. if (!isDate(date)) {
  465. return;
  466. }
  467. this._y = date.getFullYear();
  468. this._m = date.getMonth();
  469. this.draw();
  470. },
  471. gotoToday: function () {
  472. this.gotoDate(new Date());
  473. },
  474. /**
  475. * change view to a specific month (zero-index, e.g. 0: January)
  476. */
  477. gotoMonth: function (month) {
  478. if (!isNaN((month = parseInt(month, 10)))) {
  479. this._m = month < 0 ? 0 : month > 11 ? 11 : month;
  480. this.draw();
  481. }
  482. },
  483. nextMonth: function () {
  484. if (++this._m > 11) {
  485. this._m = 0;
  486. this._y++;
  487. }
  488. this.draw();
  489. },
  490. prevMonth: function () {
  491. if (--this._m < 0) {
  492. this._m = 11;
  493. this._y--;
  494. }
  495. this.draw();
  496. },
  497. /**
  498. * change view to a specific full year (e.g. "2012")
  499. */
  500. gotoYear: function (year) {
  501. if (!isNaN(year)) {
  502. this._y = parseInt(year, 10);
  503. this.draw();
  504. }
  505. },
  506. /**
  507. * refresh the HTML
  508. */
  509. draw: function (force) {
  510. if (!this._v && !force) {
  511. return;
  512. }
  513. var opts = this._o,
  514. minYear = opts.minYear,
  515. maxYear = opts.maxYear,
  516. minMonth = opts.minMonth,
  517. maxMonth = opts.maxMonth;
  518. if (this._y <= minYear) {
  519. this._y = minYear;
  520. if (!isNaN(minMonth) && this._m < minMonth) {
  521. this._m = minMonth;
  522. }
  523. }
  524. if (this._y >= maxYear) {
  525. this._y = maxYear;
  526. if (!isNaN(maxMonth) && this._m > maxMonth) {
  527. this._m = maxMonth;
  528. }
  529. }
  530. this.el.innerHTML = renderTitle(this) + this.render(this._y, this._m);
  531. if (opts.bound) {
  532. var pEl = opts.field,
  533. left = pEl.offsetLeft,
  534. top = pEl.offsetTop + pEl.offsetHeight;
  535. while ((pEl = pEl.offsetParent)) {
  536. left += pEl.offsetLeft;
  537. top += pEl.offsetTop;
  538. }
  539. //alert($(this.el).offset().top)
  540. this.el.style.cssText = 'position:absolute;left:' + (left) + 'px;top:' + top + 'px;';
  541. //this.el.style.cssText = 'position:absolute;left:' + (left + 1.5) + 'px;top:' + (top + 2) + 'px;';
  542. sto(function () {
  543. opts.field.focus();
  544. }, 1);
  545. }
  546. },
  547. /**
  548. * render HTML for a particular month
  549. */
  550. render: function (year, month) {
  551. var opts = this._o,
  552. now = new Date(),
  553. days = getDaysInMonth(year, month),
  554. before = new Date(year, month, 1).getDay(),
  555. data = [],
  556. row = [];
  557. now.setHours(0, 0, 0, 0);
  558. if (opts.firstDay > 0) {
  559. before -= opts.firstDay;
  560. if (before < 0) {
  561. before += 7;
  562. }
  563. }
  564. var cells = days + before,
  565. after = cells;
  566. while (after > 7) {
  567. after -= 7;
  568. }
  569. cells += 7 - after;
  570. for (var i = 0, r = 0; i < cells; i++) {
  571. var day = new Date(year, month, 1 + (i - before)),
  572. isDisabled = (opts.minDate && day < opts.minDate) || (opts.maxDate && day > opts.maxDate),
  573. isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
  574. isToday = compareDates(day, now),
  575. isEmpty = i < before || i >= (days + before);
  576. row.push(renderDay(1 + (i - before), isSelected, isToday, isDisabled, isEmpty));
  577. if (++r === 7) {
  578. data.push(renderRow(row, opts.isRTL));
  579. row = [];
  580. r = 0;
  581. }
  582. }
  583. return renderTable(opts, data);
  584. },
  585. isVisible: function () {
  586. return this._v;
  587. },
  588. show: function () {
  589. if (!this._v) {
  590. if (this._o.bound) {
  591. addEvent(document, 'click', this._onClick);
  592. }
  593. removeClass(this.el, 'is-hidden');
  594. this._v = true;
  595. this.draw();
  596. if (typeof this._o.onOpen === 'function') {
  597. this._o.onOpen.call(this);
  598. }
  599. }
  600. },
  601. hide: function () {
  602. var v = this._v;
  603. if (v !== false) {
  604. if (this._o.bound) {
  605. removeEvent(document, 'click', this._onClick);
  606. }
  607. this.el.style.cssText = '';
  608. addClass(this.el, 'is-hidden');
  609. this._v = false;
  610. if (v !== undefined && typeof this._o.onClose === 'function') {
  611. this._o.onClose.call(this);
  612. }
  613. }
  614. },
  615. /**
  616. * GAME OVER
  617. */
  618. destroy: function () {
  619. this.hide();
  620. removeEvent(this.el, 'mousedown', this._onMouseDown, true);
  621. removeEvent(this.el, 'change', this._onChange);
  622. if (this._o.field) {
  623. removeEvent(this._o.field, 'change', this._onInputChange);
  624. if (this._o.bound) {
  625. removeEvent(this._o.field, 'click', this._onInputClick);
  626. removeEvent(this._o.field, 'focus', this._onInputFocus);
  627. removeEvent(this._o.field, 'blur', this._onInputBlur);
  628. }
  629. }
  630. if (this.el.parentNode) {
  631. this.el.parentNode.removeChild(this.el);
  632. }
  633. }
  634. };
  635. })(window, window.document);