text_box.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /**
  2. * DevExtreme (ui/text_box/text_box.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var $ = require("../../core/renderer");
  11. var windowUtils = require("../../core/utils/window");
  12. var window = windowUtils.getWindow();
  13. var navigator = windowUtils.getNavigator();
  14. var browser = require("../../core/utils/browser");
  15. var eventsEngine = require("../../events/core/events_engine");
  16. var devices = require("../../core/devices");
  17. var inArray = require("../../core/utils/array").inArray;
  18. var extend = require("../../core/utils/extend").extend;
  19. var registerComponent = require("../../core/component_registrator");
  20. var TextEditor = require("./ui.text_editor");
  21. var eventUtils = require("../../events/utils");
  22. var ua = navigator.userAgent;
  23. var ignoreKeys = ["backspace", "tab", "enter", "pageUp", "pageDown", "end", "home", "leftArrow", "rightArrow", "downArrow", "upArrow", "del"];
  24. var TEXTBOX_CLASS = "dx-textbox";
  25. var SEARCHBOX_CLASS = "dx-searchbox";
  26. var ICON_CLASS = "dx-icon";
  27. var SEARCH_ICON_CLASS = "dx-icon-search";
  28. var TextBox = TextEditor.inherit({
  29. ctor: function(element, options) {
  30. if (options) {
  31. this._showClearButton = options.showClearButton
  32. }
  33. this.callBase.apply(this, arguments)
  34. },
  35. _getDefaultOptions: function() {
  36. return extend(this.callBase(), {
  37. value: "",
  38. mode: "text",
  39. maxLength: null
  40. })
  41. },
  42. _initMarkup: function() {
  43. this.$element().addClass(TEXTBOX_CLASS);
  44. this.callBase();
  45. this.setAria("role", "textbox")
  46. },
  47. _renderContentImpl: function() {
  48. this._renderMaxLengthHandlers();
  49. this.callBase()
  50. },
  51. _renderInputType: function() {
  52. this.callBase();
  53. this._renderSearchMode()
  54. },
  55. _renderMaxLengthHandlers: function() {
  56. if (this._isAndroidOrIE()) {
  57. eventsEngine.on(this._input(), eventUtils.addNamespace("keydown", this.NAME), this._onKeyDownCutOffHandler.bind(this));
  58. eventsEngine.on(this._input(), eventUtils.addNamespace("change", this.NAME), this._onChangeCutOffHandler.bind(this))
  59. }
  60. },
  61. _renderProps: function() {
  62. this.callBase();
  63. this._toggleMaxLengthProp()
  64. },
  65. _toggleMaxLengthProp: function() {
  66. var maxLength = this._getMaxLength();
  67. if (maxLength && maxLength > 0) {
  68. this._input().attr("maxLength", maxLength)
  69. } else {
  70. this._input().removeAttr("maxLength")
  71. }
  72. },
  73. _renderSearchMode: function() {
  74. var $element = this._$element;
  75. if ("search" === this.option("mode")) {
  76. $element.addClass(SEARCHBOX_CLASS);
  77. this._renderSearchIcon();
  78. if (void 0 === this._showClearButton) {
  79. this._showClearButton = this.option("showClearButton");
  80. this.option("showClearButton", true)
  81. }
  82. } else {
  83. $element.removeClass(SEARCHBOX_CLASS);
  84. this._$searchIcon && this._$searchIcon.remove();
  85. this.option("showClearButton", void 0 === this._showClearButton ? this.option("showClearButton") : this._showClearButton);
  86. delete this._showClearButton
  87. }
  88. },
  89. _renderSearchIcon: function() {
  90. var $searchIcon = $("<div>").addClass(ICON_CLASS).addClass(SEARCH_ICON_CLASS);
  91. $searchIcon.prependTo(this._input().parent());
  92. this._$searchIcon = $searchIcon
  93. },
  94. _optionChanged: function(args) {
  95. switch (args.name) {
  96. case "maxLength":
  97. this._toggleMaxLengthProp();
  98. this._renderMaxLengthHandlers();
  99. break;
  100. case "mask":
  101. this.callBase(args);
  102. this._toggleMaxLengthProp();
  103. break;
  104. default:
  105. this.callBase(args)
  106. }
  107. },
  108. _onKeyDownCutOffHandler: function(e) {
  109. var actualMaxLength = this._getMaxLength();
  110. if (actualMaxLength) {
  111. var $input = $(e.target);
  112. var key = eventUtils.normalizeKeyName(e);
  113. this._cutOffExtraChar($input);
  114. return $input.val().length < actualMaxLength || inArray(key, ignoreKeys) !== -1 || "" !== window.getSelection().toString()
  115. } else {
  116. return true
  117. }
  118. },
  119. _onChangeCutOffHandler: function(e) {
  120. var $input = $(e.target);
  121. if (this.option("maxLength")) {
  122. this._cutOffExtraChar($input)
  123. }
  124. },
  125. _cutOffExtraChar: function($input) {
  126. var actualMaxLength = this._getMaxLength();
  127. var textInput = $input.val();
  128. if (actualMaxLength && textInput.length > actualMaxLength) {
  129. $input.val(textInput.substr(0, actualMaxLength))
  130. }
  131. },
  132. _getMaxLength: function() {
  133. var isMaskSpecified = !!this.option("mask");
  134. return isMaskSpecified ? null : this.option("maxLength")
  135. },
  136. _isAndroidOrIE: function() {
  137. var realDevice = devices.real();
  138. var version = realDevice.version.join(".");
  139. return browser.msie || "android" === realDevice.platform && version && /^(2\.|4\.1)/.test(version) && !/chrome/i.test(ua)
  140. }
  141. });
  142. registerComponent("dxTextBox", TextBox);
  143. module.exports = TextBox;