You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
5.9 KiB

  1. (function($K)
  2. {
  3. $K.add('module', 'slider', {
  4. init: function(app, context)
  5. {
  6. this.app = app;
  7. this.$win = app.$win;
  8. this.$doc = app.$doc;
  9. // defaults
  10. var defaults = {
  11. min: 0,
  12. max: 100,
  13. step: 1,
  14. value: 0,
  15. target: false
  16. };
  17. // context
  18. this.context = context;
  19. this.params = context.getParams(defaults);
  20. this.$element = context.getElement();
  21. this.$target = context.getTarget();
  22. // local
  23. this.isTicks = false;
  24. },
  25. // public
  26. start: function()
  27. {
  28. this._buildTrack();
  29. this._buildFill();
  30. this._buildHandle();
  31. this._buildTicks();
  32. this.update();
  33. this.$win.on('resize.kube.slider', this._resize.bind(this));
  34. this.$element.on('mousedown.kube.slider touchstart.kube.slider', this._handleDown.bind(this));
  35. },
  36. stop: function()
  37. {
  38. this.$win.off('.kube.slider');
  39. this.$doc.off('.kube.slider');
  40. this.$element.off('.kube.slider');
  41. },
  42. update: function(value)
  43. {
  44. this.value = (value) ? value : this.params.value;
  45. this.value = (this.value < this.params.min) ? this.params.min : this.value;
  46. this.handleWidth = this.$handle.width();
  47. this.trackWidth = this.$track.width();
  48. this.maxHandlePosition = this.trackWidth - this.handleWidth;
  49. this.fixPosition = this.handleWidth / 2;
  50. this.position = this._getPositionFromValue(this.value);
  51. this._setPosition(this.position);
  52. this._setTarget();
  53. },
  54. // private
  55. _resize: function()
  56. {
  57. this._buildTicks();
  58. this.update(this.value);
  59. },
  60. _isDisabled: function()
  61. {
  62. return (this.$element.hasClass('is-disabled') || this.$element.attr('disabled'));
  63. },
  64. _buildTrack: function()
  65. {
  66. this.$track = $K.dom('<div />');
  67. this.$track.addClass('slider-track');
  68. this.$element.prepend(this.$track);
  69. },
  70. _buildFill: function()
  71. {
  72. this.$fill = $K.dom('<div />');
  73. this.$fill.addClass('slider-fill');
  74. this.$track.append(this.$fill);
  75. },
  76. _buildHandle: function()
  77. {
  78. this.$handle = $K.dom('<div />');
  79. this.$handle.addClass('slider-handle');
  80. this.$track.append(this.$handle);
  81. },
  82. _buildTicks: function()
  83. {
  84. this.$ticks = this.$element.find('.slider-ticks span');
  85. var size = this.$ticks.length;
  86. this.isTicks = (size !== 0)
  87. if (!this.isTicks) return;
  88. var handleWidth = this.$handle.width();
  89. var width = this.$element.width() - handleWidth;
  90. var fix = handleWidth/2;
  91. var step = width/(size-1);
  92. var start = fix;
  93. this.$ticks.each(function(node, i)
  94. {
  95. var $node = $K.dom(node);
  96. var left = start + step * i;
  97. $node.css({ 'left': left + 'px', 'width': step + 'px', 'text-indent': '-' + (step-fix) + 'px' });
  98. });
  99. },
  100. _handleDown: function(e)
  101. {
  102. e.preventDefault();
  103. if (this._isDisabled()) return;
  104. this.$doc.on('mousemove.kube.slider touchmove.kube.slider', this._handleMove.bind(this));
  105. this.$doc.on('mouseup.kube.slider touchend.kube.slider', this._handleEnd.bind(this));
  106. var pos = (e.touches && e.touches.length > 0) ? e.changedTouches[0].clientX : e.clientX;
  107. var trackPos = this.$track.offset().left;
  108. var setPos = (pos - trackPos - this.fixPosition);
  109. this._setPosition(setPos);
  110. this._setTarget();
  111. },
  112. _handleMove: function(e)
  113. {
  114. e.preventDefault();
  115. var pos = (e.touches && e.touches.length > 0) ? e.changedTouches[0].clientX : e.clientX;
  116. var trackPos = this.$track.offset().left;
  117. var setPos = (pos - trackPos - this.fixPosition);
  118. this._setPosition(setPos);
  119. this._setTarget();
  120. },
  121. _handleEnd: function(e)
  122. {
  123. e.preventDefault();
  124. this.$doc.off('.kube.slider');
  125. },
  126. _setPosition: function(pos)
  127. {
  128. pos = this._getEdge(pos, 0, this.maxHandlePosition);
  129. var value = this._getValueFromPosition(pos);
  130. var newPos = this._getPositionFromValue(value);
  131. // update ui
  132. this.$fill.css('width', (newPos + this.fixPosition) + 'px');
  133. this.$handle.css('left', newPos + 'px');
  134. // update globals
  135. this.position = newPos;
  136. this.value = value;
  137. },
  138. _setTarget: function()
  139. {
  140. this.app.broadcast('slider.set', this, this.value);
  141. if (this.$target.length === 0) return;
  142. var tag = this.$target.get().tagName;
  143. if (tag === 'INPUT' || tag === 'SELECT') this.$target.val(this.value);
  144. else this.$target.text(this.value);
  145. },
  146. _getPositionFromValue: function(value)
  147. {
  148. var percentage = (value - this.params.min)/(this.params.max - this.params.min);
  149. return pos = (!Number.isNaN(percentage)) ? percentage * this.maxHandlePosition : 0;
  150. },
  151. _getValueFromPosition: function(pos)
  152. {
  153. var percentage = ((pos) / (this.maxHandlePosition || 1));
  154. var value = this.params.step * Math.round(percentage * (this.params.max - this.params.min) / this.params.step) + this.params.min;
  155. return Number((value).toFixed((this.params.step + '').replace('.', '').length - 1));
  156. },
  157. _getEdge: function(pos, min, max)
  158. {
  159. if (pos < min) return min;
  160. if (pos > max) return max;
  161. return pos;
  162. }
  163. });
  164. })(Kube);