range.js

  1. import { queryOne } from '@ecl/dom-utils';
  2. /**
  3. * @param {HTMLElement} element DOM element for component instantiation and scope
  4. * @param {Object} options
  5. * @param {String} options.rangeInputSelector Selector for the range input
  6. * @param {String} options.currentValueSelector Selector for the current value area
  7. * @param {Boolean} options.attachChangeListener Whether or not to bind change events on range
  8. */
  9. export class Range {
  10. /**
  11. * @static
  12. * Shorthand for instance creation and initialisation.
  13. *
  14. * @param {HTMLElement} root DOM element for component instantiation and scope
  15. *
  16. * @return {Range} An instance of Range.
  17. */
  18. static autoInit(root, { RANGE: defaultOptions = {} } = {}) {
  19. const range = new Range(root, defaultOptions);
  20. range.init();
  21. root.ECLRange = range;
  22. return range;
  23. }
  24. constructor(
  25. element,
  26. {
  27. rangeInputSelector = '[data-ecl-range-input]',
  28. currentValueSelector = '[data-ecl-range-value-current]',
  29. attachChangeListener = true,
  30. } = {},
  31. ) {
  32. // Check element
  33. if (!element || element.nodeType !== Node.ELEMENT_NODE) {
  34. throw new TypeError(
  35. 'DOM element should be given to initialize this widget.',
  36. );
  37. }
  38. this.element = element;
  39. // Options
  40. this.rangeInputSelector = rangeInputSelector;
  41. this.currentValueSelector = currentValueSelector;
  42. this.attachChangeListener = attachChangeListener;
  43. // Private variables
  44. this.rangeInput = null;
  45. this.currentValue = null;
  46. // Bind `this` for use in callbacks
  47. this.handleChange = this.handleChange.bind(this);
  48. }
  49. /**
  50. * Initialise component.
  51. */
  52. init() {
  53. if (!ECL) {
  54. throw new TypeError('Called init but ECL is not present');
  55. }
  56. ECL.components = ECL.components || new Map();
  57. this.rangeInput = queryOne(this.rangeInputSelector, this.element);
  58. this.currentValue = queryOne(this.currentValueSelector, this.element);
  59. if (this.rangeInput && this.currentValue) {
  60. // Display default value
  61. this.currentValue.innerHTML = this.rangeInput.value;
  62. // Bind change event on range
  63. if (this.attachChangeListener) {
  64. this.rangeInput.addEventListener('input', this.handleChange);
  65. }
  66. }
  67. // Set ecl initialized attribute
  68. this.element.setAttribute('data-ecl-auto-initialized', 'true');
  69. ECL.components.set(this.element, this);
  70. }
  71. /**
  72. * Destroy component.
  73. */
  74. destroy() {
  75. if (this.attachChangeListener && this.rangeInput && this.currentValue) {
  76. this.rangeInput.removeEventListener('input', this.handleChange);
  77. }
  78. if (this.element) {
  79. this.element.removeAttribute('data-ecl-auto-initialized');
  80. ECL.components.delete(this.element);
  81. }
  82. }
  83. /**
  84. * Display value when changed
  85. */
  86. handleChange() {
  87. // Update value
  88. this.currentValue.innerHTML = this.rangeInput.value;
  89. }
  90. }
  91. export default Range;