InputHandler.js

  1. 'use strict';
  2. import $ from 'jquery';
  3. import ColorItem from './ColorItem';
  4. /**
  5. * Handles everything related to the colorpicker input
  6. * @ignore
  7. */
  8. class InputHandler {
  9. /**
  10. * @param {Colorpicker} colorpicker
  11. */
  12. constructor(colorpicker) {
  13. /**
  14. * @type {Colorpicker}
  15. */
  16. this.colorpicker = colorpicker;
  17. /**
  18. * @type {jQuery|false}
  19. */
  20. this.input = this.colorpicker.element.is('input') ? this.colorpicker.element : (this.colorpicker.options.input ?
  21. this.colorpicker.element.find(this.colorpicker.options.input) : false);
  22. if (this.input && (this.input.length === 0)) {
  23. this.input = false;
  24. }
  25. this._initValue();
  26. }
  27. bind() {
  28. if (!this.hasInput()) {
  29. return;
  30. }
  31. this.input.on({
  32. 'keyup.colorpicker': $.proxy(this.onkeyup, this)
  33. });
  34. this.input.on({
  35. 'change.colorpicker': $.proxy(this.onchange, this)
  36. });
  37. }
  38. unbind() {
  39. if (!this.hasInput()) {
  40. return;
  41. }
  42. this.input.off('.colorpicker');
  43. }
  44. _initValue() {
  45. if (!this.hasInput()) {
  46. return;
  47. }
  48. let val = '';
  49. [
  50. // candidates:
  51. this.input.val(),
  52. this.input.data('color'),
  53. this.input.attr('data-color')
  54. ].map((item) => {
  55. if (item && (val === '')) {
  56. val = item;
  57. }
  58. });
  59. if (val instanceof ColorItem) {
  60. val = this.getFormattedColor(val.string(this.colorpicker.format));
  61. } else if (!(typeof val === 'string' || val instanceof String)) {
  62. val = '';
  63. }
  64. this.input.prop('value', val);
  65. }
  66. /**
  67. * Returns the color string from the input value.
  68. * If there is no input the return value is false.
  69. *
  70. * @returns {String|boolean}
  71. */
  72. getValue() {
  73. if (!this.hasInput()) {
  74. return false;
  75. }
  76. return this.input.val();
  77. }
  78. /**
  79. * If the input element is present, it updates the value with the current color object color string.
  80. * If the value is changed, this method fires a "change" event on the input element.
  81. *
  82. * @param {String} val
  83. *
  84. * @fires Colorpicker#change
  85. */
  86. setValue(val) {
  87. if (!this.hasInput()) {
  88. return;
  89. }
  90. let inputVal = this.input.prop('value');
  91. val = val ? val : '';
  92. if (val === (inputVal ? inputVal : '')) {
  93. // No need to set value or trigger any event if nothing changed
  94. return;
  95. }
  96. this.input.prop('value', val);
  97. /**
  98. * (Input) Triggered on the input element when a new color is selected.
  99. *
  100. * @event Colorpicker#change
  101. */
  102. this.input.trigger({
  103. type: 'change',
  104. colorpicker: this.colorpicker,
  105. color: this.colorpicker.color,
  106. value: val
  107. });
  108. }
  109. /**
  110. * Returns the formatted color string, with the formatting options applied
  111. * (e.g. useHashPrefix)
  112. *
  113. * @param {String|null} val
  114. *
  115. * @returns {String}
  116. */
  117. getFormattedColor(val = null) {
  118. val = val ? val : this.colorpicker.colorHandler.getColorString();
  119. if (!val) {
  120. return '';
  121. }
  122. val = this.colorpicker.colorHandler.resolveColorDelegate(val, false);
  123. if (this.colorpicker.options.useHashPrefix === false) {
  124. val = val.replace(/^#/g, '');
  125. }
  126. return val;
  127. }
  128. /**
  129. * Returns true if the widget has an associated input element, false otherwise
  130. * @returns {boolean}
  131. */
  132. hasInput() {
  133. return (this.input !== false);
  134. }
  135. /**
  136. * Returns true if the input exists and is disabled
  137. * @returns {boolean}
  138. */
  139. isEnabled() {
  140. return this.hasInput() && !this.isDisabled();
  141. }
  142. /**
  143. * Returns true if the input exists and is disabled
  144. * @returns {boolean}
  145. */
  146. isDisabled() {
  147. return this.hasInput() && (this.input.prop('disabled') === true);
  148. }
  149. /**
  150. * Disables the input if any
  151. *
  152. * @fires Colorpicker#colorpickerDisable
  153. * @returns {boolean}
  154. */
  155. disable() {
  156. if (this.hasInput()) {
  157. this.input.prop('disabled', true);
  158. }
  159. }
  160. /**
  161. * Enables the input if any
  162. *
  163. * @fires Colorpicker#colorpickerEnable
  164. * @returns {boolean}
  165. */
  166. enable() {
  167. if (this.hasInput()) {
  168. this.input.prop('disabled', false);
  169. }
  170. }
  171. /**
  172. * Calls setValue with the current internal color value
  173. *
  174. * @fires Colorpicker#change
  175. */
  176. update() {
  177. if (!this.hasInput()) {
  178. return;
  179. }
  180. if (
  181. (this.colorpicker.options.autoInputFallback === false) &&
  182. this.colorpicker.colorHandler.isInvalidColor()
  183. ) {
  184. // prevent update if color is invalid, autoInputFallback is disabled and the last event is keyup.
  185. return;
  186. }
  187. this.setValue(this.getFormattedColor());
  188. }
  189. /**
  190. * Function triggered when the input has changed, so the colorpicker gets updated.
  191. *
  192. * @private
  193. * @param {Event} e
  194. * @returns {boolean}
  195. */
  196. onchange(e) {
  197. this.colorpicker.lastEvent.alias = 'input.change';
  198. this.colorpicker.lastEvent.e = e;
  199. let val = this.getValue();
  200. if (val !== e.value) {
  201. this.colorpicker.setValue(val);
  202. }
  203. }
  204. /**
  205. * Function triggered after a keyboard key has been released.
  206. *
  207. * @private
  208. * @param {Event} e
  209. * @returns {boolean}
  210. */
  211. onkeyup(e) {
  212. this.colorpicker.lastEvent.alias = 'input.keyup';
  213. this.colorpicker.lastEvent.e = e;
  214. let val = this.getValue();
  215. if (val !== e.value) {
  216. this.colorpicker.setValue(val);
  217. }
  218. }
  219. }
  220. export default InputHandler;