morpheus.ScrollBar = function(isVertical) { morpheus.AbstractCanvas.call(this); this.isVertical = isVertical; $(this.canvas).css('border', '1px solid #d8d8d8'); if (isVertical) { this.setBounds({ width : 12 }); } else { this.setBounds({ height : 12 }); } this.field = this.isVertical ? 'y' : 'x'; var that = this; var mouseMove = function(event) { if (!morpheus.CanvasUtil.dragging) { var position = morpheus.CanvasUtil.getMousePos(event.target, event, true); var mouseOver = (position[that.field] >= that.thumbPos && position[that.field] <= (that.thumbPos + that.thumbExtent)); if (that.thumbMouseOver !== mouseOver) { that.thumbMouseOver = mouseOver; that.repaint(); } } }; var mouseExit = function(e) { if (!morpheus.CanvasUtil.dragging && that.thumbMouseOver) { that.thumbMouseOver = false; that.repaint(); } }; $(this.canvas).on('mousemove', mouseMove).on('mouseout', mouseExit).on( 'mouseenter', mouseMove); this.hammer = morpheus.Util .hammer(this.canvas, [ this.isVertical ? 'panv' : 'panh', 'tap' ]) .on( 'panstart', function(event) { var position = morpheus.CanvasUtil.getMousePos( event.target, event, true); if (position[that.field] >= that.thumbPos && position[that.field] <= (that.thumbPos + that.thumbExtent)) { that.draggingThumb = true; that.dragStartThumbPos = that.thumbPos; } else { that.draggingThumb = false; } }) .on('panend', function(event) { that.draggingThumb = false; }) .on( 'panmove', function(event) { if (that.draggingThumb) { var position = morpheus.CanvasUtil.getMousePos( event.target, event); var thumbPosPix = that.dragStartThumbPos + (that.isVertical ? event.deltaY : event.deltaX); var f = thumbPosPix / (that.visibleExtent - that.thumbExtent); var value = f * that.maxValue; // convert pix to value that.setValue(value, true); event.preventDefault(); event.srcEvent.stopPropagation(); event.srcEvent.stopImmediatePropagation(); } }) .on( 'tap doubletap', function(event) { // ensure not clicked on the thumb if (!that.draggingThumb) { var position = morpheus.CanvasUtil.getMousePos( event.target, event); if (!that.decorator.tap(position)) { // scroll up or down by thumbExtent var thumbExtentToValue = (that.thumbExtent / that.totalExtent) * that.totalExtent; that.scrollToTop = position[that.field] < that.thumbPos; that.setValue(that.scrollToTop ? that.value - thumbExtentToValue : that.value + thumbExtentToValue, true); } } }); }; morpheus.ScrollBar.prototype = { thumbPos : 0, // the top of the thumb, from 0 to visibleExtent-thumbExtent thumbExtent : 0, extent : 0, value : 0, // from 0 to totalExtent-extent maxValue : 0, // totalExtent-extent totalExtent : 0, visibleExtent : 0, dragStartThumbPos : 0, draggingThumb : false, thumbMouseOver : false, draw : function(clip, context) { var width = this.getUnscaledWidth(); var height = this.getUnscaledHeight(); if (this.visibleExtent === this.totalExtent) { context.clearRect(0, 0, width, height); } else { context.fillStyle = 'rgb(241,241,241)'; context.fillRect(0, 0, width, height); context.fillStyle = !this.thumbMouseOver ? 'rgb(137,137,137)' : 'rgb(100,100,100)'; if (this.isVertical) { context.fillRect(0, this.thumbPos, width, this.thumbExtent); } else { context.fillRect(this.thumbPos, 0, this.thumbExtent, height); } } this.decorator.draw(clip, context); }, setThumbPosFromValue : function() { // value is thumb top position var f = this.maxValue == 0 ? 0 : this.value / this.maxValue; this.thumbPos = f * (this.visibleExtent - this.thumbExtent); this.thumbPos = Math.max(0, this.thumbPos); }, getValue : function() { return this.value; }, getMaxValue : function() { return this.maxValue; }, setValue : function(value, trigger) { if (isNaN(value)) { value = 0; } if (this.visibleExtent === this.totalExtent) { value = 0; } value = Math.max(value, 0); value = Math.min(this.maxValue, value); this.value = value; this.setThumbPosFromValue(); if (trigger) { this.trigger('scroll', this.value); this.repaint(); } return this.value; }, setTotalExtent : function(totalExtent) { this.totalExtent = totalExtent; this._setRange(); }, getTotalExtent : function() { return this.totalExtent; }, _setRange : function() { this.thumbExtent = Math.max(10, this.visibleExtent * (this.visibleExtent / this.totalExtent)); this.maxValue = this.totalExtent - this.visibleExtent; this.maxValue = Math.max(0, this.maxValue); if (this.isVertical) { this.setBounds({ height : this.visibleExtent }); } else { this.setBounds({ width : this.visibleExtent }); } }, setExtent : function(visibleExtent, totalExtent, value) { this.visibleExtent = visibleExtent; this.totalExtent = totalExtent; this._setRange(); this.setValue(value, false); } }; morpheus.Util.extend(morpheus.ScrollBar, morpheus.AbstractCanvas); morpheus.Util.extend(morpheus.ScrollBar, morpheus.Events);