From 4562ff8d7484acb74c165a62faf83012b722db1f Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Wed, 25 May 2016 16:20:20 -0700 Subject: [PATCH 1/6] Split scrollbar code into content changes and view changes; store dimensions in variables instead of querying the dom. --- core/scrollbar.js | 143 +++++++++++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 53 deletions(-) diff --git a/core/scrollbar.js b/core/scrollbar.js index 8b4bfe498..ebb2c10eb 100644 --- a/core/scrollbar.js +++ b/core/scrollbar.js @@ -147,17 +147,18 @@ Blockly.ScrollbarPair.prototype.set = function(x, y) { var hKnobValue = x * this.hScroll.ratio_; var vKnobValue = y * this.vScroll.ratio_; - var hBarLength = - parseFloat(this.hScroll.svgBackground_.getAttribute('width')); - var vBarLength = - parseFloat(this.vScroll.svgBackground_.getAttribute('height')); + var hBarLength = this.hScroll.barLength; + var vBarLength = this.vScroll.barLength; xyRatio.x = this.getRatio_(hKnobValue, hBarLength); xyRatio.y = this.getRatio_(vKnobValue, vBarLength); - this.workspace_.setMetrics(xyRatio); + this.hScroll.svgKnob_.setAttribute('x', hKnobValue); + this.hScroll.knobOffset = hKnobValue; + this.vScroll.svgKnob_.setAttribute('y', vKnobValue); + this.vScroll.knobOffset = vKnobValue; }; /** @@ -190,10 +191,18 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { this.workspace_ = workspace; this.pair_ = opt_pair || false; this.horizontal_ = horizontal; - this.oldHostMetrics_ = {}; + this.oldHostMetrics_ = null; this.createDom_(); + this.barLength = 0; + this.knobLength = 0; + this.knobOffset = 0; + this.isVisible_ = true; + + this.yCoordinate = 0; + this.xCoordinate = 0; + if (horizontal) { this.svgBackground_.setAttribute('height', Blockly.Scrollbar.scrollbarThickness); @@ -322,25 +331,41 @@ Blockly.Scrollbar.prototype.resize = function(opt_metrics) { * @private */ Blockly.Scrollbar.prototype.resizeHorizontal_ = function(hostMetrics) { - var outerLength = hostMetrics.viewWidth - 1; - if (this.pair_) { - // Shorten the scrollbar to make room for the corner square. - outerLength -= Blockly.Scrollbar.scrollbarThickness; - } else { + this.resizeViewHorizontal_(hostMetrics); + this.resizeContentHorizontal_(hostMetrics); +}; + +Blockly.Scrollbar.prototype.resizeContentHorizontal_ = function(hostMetrics) { + if (!this.pair_) { // Only show the scrollbar if needed. // Ideally this would also apply to scrollbar pairs, but that's a bigger // headache (due to interactions with the corner square). - this.setVisible(outerLength < hostMetrics.contentWidth); + this.setVisible(this.barLength < hostMetrics.contentWidth); } - this.ratio_ = outerLength / hostMetrics.contentWidth; + + this.ratio_ = this.barLength / hostMetrics.contentWidth; if (this.ratio_ === -Infinity || this.ratio_ === Infinity || isNaN(this.ratio_)) { this.ratio_ = 0; } - var innerLength = hostMetrics.viewWidth * this.ratio_; + var innerOffset = (hostMetrics.viewLeft - hostMetrics.contentLeft) * this.ratio_; - this.svgKnob_.setAttribute('width', Math.max(0, innerLength)); + this.knobOffset = this.constrainKnob_(innerOffset); + this.svgKnob_.setAttribute('x', this.knobOffset); + + var innerLength = hostMetrics.viewWidth * this.ratio_; + this.knobLength = Math.max(0, innerLength); + this.svgKnob_.setAttribute('width', this.knobLength); +}; + +Blockly.Scrollbar.prototype.resizeViewHorizontal_ = function(hostMetrics) { + var outerLength = hostMetrics.viewWidth - 1; + if (this.pair_) { + // Shorten the scrollbar to make room for the corner square. + outerLength -= Blockly.Scrollbar.scrollbarThickness; + } + this.xCoordinate = hostMetrics.absoluteLeft + 0.5; if (this.pair_ && this.workspace_.RTL) { this.xCoordinate += Blockly.Scrollbar.scrollbarThickness; @@ -350,8 +375,9 @@ Blockly.Scrollbar.prototype.resizeHorizontal_ = function(hostMetrics) { Blockly.Scrollbar.scrollbarThickness - 0.5; this.svgGroup_.setAttribute('transform', 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); - this.svgBackground_.setAttribute('width', Math.max(0, outerLength)); - this.svgKnob_.setAttribute('x', this.constrainKnob_(innerOffset)); + + this.barLength = Math.max(0, outerLength); + this.svgBackground_.setAttribute('width', this.barLength); }; /** @@ -361,23 +387,40 @@ Blockly.Scrollbar.prototype.resizeHorizontal_ = function(hostMetrics) { * @private */ Blockly.Scrollbar.prototype.resizeVertical_ = function(hostMetrics) { - var outerLength = hostMetrics.viewHeight - 1; - if (this.pair_) { - // Shorten the scrollbar to make room for the corner square. - outerLength -= Blockly.Scrollbar.scrollbarThickness; - } else { + this.resizeViewVertical_(hostMetrics); + this.resizeContentVertical_(hostMetrics); +}; + +Blockly.Scrollbar.prototype.resizeContentVertical_ = function(hostMetrics) { + if (!this.pair_) { // Only show the scrollbar if needed. - this.setVisible(outerLength < hostMetrics.contentHeight); + this.setVisible(this.barLength < hostMetrics.contentHeight); } - this.ratio_ = outerLength / hostMetrics.contentHeight; + + this.ratio_ = this.barLength / hostMetrics.contentHeight; if (this.ratio_ === -Infinity || this.ratio_ === Infinity || isNaN(this.ratio_)) { this.ratio_ = 0; } + var innerLength = hostMetrics.viewHeight * this.ratio_; + this.knobLength = Math.max(0, innerLength); + this.svgKnob_.setAttribute('height', this.knobLength); + var innerOffset = (hostMetrics.viewTop - hostMetrics.contentTop) * this.ratio_; - this.svgKnob_.setAttribute('height', Math.max(0, innerLength)); + this.knobOffset = this.constrainKnob_(innerOffset); + this.svgKnob_.setAttribute('y', this.knobOffset); + +}; + +Blockly.Scrollbar.prototype.resizeViewVertical_ = function(hostMetrics) { + var outerLength = hostMetrics.viewHeight - 1; + if (this.pair_) { + // Shorten the scrollbar to make room for the corner square. + outerLength -= Blockly.Scrollbar.scrollbarThickness; + } + this.xCoordinate = hostMetrics.absoluteLeft + 0.5; if (!this.workspace_.RTL) { this.xCoordinate += hostMetrics.viewWidth - @@ -386,8 +429,9 @@ Blockly.Scrollbar.prototype.resizeVertical_ = function(hostMetrics) { this.yCoordinate = hostMetrics.absoluteTop + 0.5; this.svgGroup_.setAttribute('transform', 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); - this.svgBackground_.setAttribute('height', Math.max(0, outerLength)); - this.svgKnob_.setAttribute('y', this.constrainKnob_(innerOffset)); + + this.barLength = Math.max(0, outerLength); + this.svgBackground_.setAttribute('height', this.barLength); }; /** @@ -421,7 +465,7 @@ Blockly.Scrollbar.prototype.createDom_ = function() { * @return {boolean} True if visible. */ Blockly.Scrollbar.prototype.isVisible = function() { - return this.svgGroup_.getAttribute('display') != 'none'; + return this.isVisible_; }; /** @@ -438,6 +482,9 @@ Blockly.Scrollbar.prototype.setVisible = function(visible) { if (this.pair_) { throw 'Unable to toggle visibility of paired scrollbars.'; } + + this.isVisible_ = visible; + if (visible) { this.svgGroup_.setAttribute('display', 'block'); } else { @@ -466,21 +513,20 @@ Blockly.Scrollbar.prototype.onMouseDownBar_ = function(e) { var knobXY = Blockly.getSvgXY_(this.svgKnob_, this.workspace_); var knobStart = this.horizontal_ ? knobXY.x : knobXY.y; - var knobLength = parseFloat( - this.svgKnob_.getAttribute(this.horizontal_ ? 'width' : 'height')); - var knobValue = parseFloat( - this.svgKnob_.getAttribute(this.horizontal_ ? 'x' : 'y')); + var knobValue = this.knobOffset; - var pageLength = knobLength * 0.95; + var pageLength = this.knobLength * 0.95; if (mouseLocation <= knobStart) { // Decrease the scrollbar's value by a page. knobValue -= pageLength; - } else if (mouseLocation >= knobStart + knobLength) { + } else if (mouseLocation >= knobStart + this.knobLength) { // Increase the scrollbar's value by a page. knobValue += pageLength; } - this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', - this.constrainKnob_(knobValue)); + + this.knobOffset = this.constrainKnob_(knobValue); + this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', this.knobOffset); + this.onScroll_(); e.stopPropagation(); e.preventDefault(); @@ -501,8 +547,7 @@ Blockly.Scrollbar.prototype.onMouseDownKnob_ = function(e) { return; } // Look up the current translation and record it. - this.startDragKnob = parseFloat( - this.svgKnob_.getAttribute(this.horizontal_ ? 'x' : 'y')); + this.startDragKnob = this.knobOffset; // Record the current mouse position. this.startDragMouse = this.horizontal_ ? e.clientX : e.clientY; Blockly.Scrollbar.onMouseUpWrapper_ = Blockly.bindEvent_(document, @@ -523,8 +568,8 @@ Blockly.Scrollbar.prototype.onMouseMoveKnob_ = function(e) { var mouseDelta = currentMouse - this.startDragMouse; var knobValue = this.startDragKnob + mouseDelta; // Position the bar. - this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', - this.constrainKnob_(knobValue)); + this.knobOffset = this.constrainKnob_(knobValue); + this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', this.knobOffset); this.onScroll_(); }; @@ -555,10 +600,7 @@ Blockly.Scrollbar.prototype.constrainKnob_ = function(value) { if (value <= 0 || isNaN(value)) { value = 0; } else { - var axis = this.horizontal_ ? 'width' : 'height'; - var barLength = parseFloat(this.svgBackground_.getAttribute(axis)); - var knobLength = parseFloat(this.svgKnob_.getAttribute(axis)); - value = Math.min(value, barLength - knobLength); + value = Math.min(value, this.barLength - this.knobLength); } return value; }; @@ -568,12 +610,8 @@ Blockly.Scrollbar.prototype.constrainKnob_ = function(value) { * @private */ Blockly.Scrollbar.prototype.onScroll_ = function() { - var knobValue = parseFloat( - this.svgKnob_.getAttribute(this.horizontal_ ? 'x' : 'y')); - var barLength = parseFloat( - this.svgBackground_.getAttribute(this.horizontal_ ? 'width' : 'height')); - var ratio = knobValue / barLength; - if (isNaN(ratio) || !barLength) { + var ratio = this.knobOffset / this.barLength; + if (isNaN(ratio)) { ratio = 0; } var xyRatio = {}; @@ -590,9 +628,8 @@ Blockly.Scrollbar.prototype.onScroll_ = function() { * @param {number} value The distance from the top/left end of the bar. */ Blockly.Scrollbar.prototype.set = function(value) { - var constrainedValue = this.constrainKnob_(value * this.ratio_); - // Move the scrollbar slider. - this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', constrainedValue); + this.knobOffset = this.constrainKnob_(value * this.ratio_); + this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', this.knobOffset); this.onScroll_(); }; From f486ac949c0f5fc14b21b1c3172d903e0db6e625 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Wed, 25 May 2016 16:38:19 -0700 Subject: [PATCH 2/6] use helper functions to set attribute on svg and in model at the same time. --- core/scrollbar.js | 99 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 24 deletions(-) diff --git a/core/scrollbar.js b/core/scrollbar.js index ebb2c10eb..0d385fe59 100644 --- a/core/scrollbar.js +++ b/core/scrollbar.js @@ -154,11 +154,8 @@ Blockly.ScrollbarPair.prototype.set = function(x, y) { xyRatio.y = this.getRatio_(vKnobValue, vBarLength); this.workspace_.setMetrics(xyRatio); - this.hScroll.svgKnob_.setAttribute('x', hKnobValue); - this.hScroll.knobOffset = hKnobValue; - - this.vScroll.svgKnob_.setAttribute('y', vKnobValue); - this.vScroll.knobOffset = vKnobValue; + this.hScroll.setKnobOffset(hKnobValue); + this.vScroll.setKnobOffset(vKnobValue) }; /** @@ -209,12 +206,18 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { this.svgKnob_.setAttribute('height', Blockly.Scrollbar.scrollbarThickness - 5); this.svgKnob_.setAttribute('y', 2.5); + + this.lengthAttribute = 'width'; + this.knobOffsetAttribute = 'x'; } else { this.svgBackground_.setAttribute('width', Blockly.Scrollbar.scrollbarThickness); this.svgKnob_.setAttribute('width', Blockly.Scrollbar.scrollbarThickness - 5); this.svgKnob_.setAttribute('x', 2.5); + + this.lengthAttribute = 'height'; + this.knobOffsetAttribute = 'y'; } var scrollbar = this; this.onMouseDownBarWrapper_ = Blockly.bindEvent_(this.svgBackground_, @@ -280,6 +283,36 @@ Blockly.Scrollbar.prototype.dispose = function() { this.workspace_ = null; }; +/** + * Set the length of the scrollbar's knob and change the SVG attribute + * accordingly. + * @param {number} newLength The new scrollbar handle length. + */ +Blockly.Scrollbar.prototype.setKnobLength = function(newLength) { + this.knobLength = newLength; + this.svgKnob_.setAttribute(this.lengthAttribute, this.knobLength); +}; + +/** + * Set the offset of the scrollbar's knob and change the SVG attribute + * accordingly. + * @param {number} newOffset The new scrollbar handle offset. + */ +Blockly.Scrollbar.prototype.setKnobOffset = function(newOffset) { + this.knobOffset = newOffset; + this.svgKnob_.setAttribute(this.knobOffsetAttribute, this.knobOffset); +}; + +/** + * Set the length of the scrollbar's background and change the SVG attribute + * accordingly. + * @param {number} newLength The new scrollbar background length. + */ +Blockly.Scrollbar.prototype.setBarLength = function(newLength) { + this.barLength = newLength; + this.svgBackground_.setAttribute(this.lengthAttribute, this.barLength); +}; + /** * Recalculate the scrollbar's location and its length. * @param {Object=} opt_metrics A data structure of from the describing all the @@ -335,6 +368,13 @@ Blockly.Scrollbar.prototype.resizeHorizontal_ = function(hostMetrics) { this.resizeContentHorizontal_(hostMetrics); }; +/** + * Recalculate a horizontal scrollbar's location within its path and length. + * This should be called when the contents of the workspace have changed. + * @param {!Object} hostMetrics A data structure describing all the + * required dimensions, possibly fetched from the host object. + * @private + */ Blockly.Scrollbar.prototype.resizeContentHorizontal_ = function(hostMetrics) { if (!this.pair_) { // Only show the scrollbar if needed. @@ -351,14 +391,19 @@ Blockly.Scrollbar.prototype.resizeContentHorizontal_ = function(hostMetrics) { var innerOffset = (hostMetrics.viewLeft - hostMetrics.contentLeft) * this.ratio_; - this.knobOffset = this.constrainKnob_(innerOffset); - this.svgKnob_.setAttribute('x', this.knobOffset); + this.setKnobOffset(this.constrainKnob_(innerOffset)); var innerLength = hostMetrics.viewWidth * this.ratio_; - this.knobLength = Math.max(0, innerLength); - this.svgKnob_.setAttribute('width', this.knobLength); + this.setKnobLength(Math.max(0, innerLength)); }; +/** + * Recalculate a horizontal scrollbar's location on the screen and path length. + * This should be called when the layout or size of the window has changed. + * @param {!Object} hostMetrics A data structure describing all the + * required dimensions, possibly fetched from the host object. + * @private + */ Blockly.Scrollbar.prototype.resizeViewHorizontal_ = function(hostMetrics) { var outerLength = hostMetrics.viewWidth - 1; if (this.pair_) { @@ -376,8 +421,7 @@ Blockly.Scrollbar.prototype.resizeViewHorizontal_ = function(hostMetrics) { this.svgGroup_.setAttribute('transform', 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); - this.barLength = Math.max(0, outerLength); - this.svgBackground_.setAttribute('width', this.barLength); + this.setBarLength(Math.max(0, outerLength)); }; /** @@ -391,6 +435,13 @@ Blockly.Scrollbar.prototype.resizeVertical_ = function(hostMetrics) { this.resizeContentVertical_(hostMetrics); }; +/** + * Recalculate a vertical scrollbar's location within its path and length. + * This should be called when the contents of the workspace have changed. + * @param {!Object} hostMetrics A data structure describing all the + * required dimensions, possibly fetched from the host object. + * @private + */ Blockly.Scrollbar.prototype.resizeContentVertical_ = function(hostMetrics) { if (!this.pair_) { // Only show the scrollbar if needed. @@ -404,16 +455,20 @@ Blockly.Scrollbar.prototype.resizeContentVertical_ = function(hostMetrics) { } var innerLength = hostMetrics.viewHeight * this.ratio_; - this.knobLength = Math.max(0, innerLength); - this.svgKnob_.setAttribute('height', this.knobLength); + this.setKnobLength(Math.max(0, innerLength)); var innerOffset = (hostMetrics.viewTop - hostMetrics.contentTop) * this.ratio_; - this.knobOffset = this.constrainKnob_(innerOffset); - this.svgKnob_.setAttribute('y', this.knobOffset); - + this.setKnobOffset(this.constrainKnob_(innerOffset)); }; +/** + * Recalculate a vertical scrollbar's location on the screen and path length. + * This should be called when the layout or size of the window has changed. + * @param {!Object} hostMetrics A data structure describing all the + * required dimensions, possibly fetched from the host object. + * @private + */ Blockly.Scrollbar.prototype.resizeViewVertical_ = function(hostMetrics) { var outerLength = hostMetrics.viewHeight - 1; if (this.pair_) { @@ -430,8 +485,7 @@ Blockly.Scrollbar.prototype.resizeViewVertical_ = function(hostMetrics) { this.svgGroup_.setAttribute('transform', 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); - this.barLength = Math.max(0, outerLength); - this.svgBackground_.setAttribute('height', this.barLength); + this.setBarLength(Math.max(0, outerLength)); }; /** @@ -524,8 +578,7 @@ Blockly.Scrollbar.prototype.onMouseDownBar_ = function(e) { knobValue += pageLength; } - this.knobOffset = this.constrainKnob_(knobValue); - this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', this.knobOffset); + this.setKnobOffset(this.constrainKnob_(knobValue)); this.onScroll_(); e.stopPropagation(); @@ -568,8 +621,7 @@ Blockly.Scrollbar.prototype.onMouseMoveKnob_ = function(e) { var mouseDelta = currentMouse - this.startDragMouse; var knobValue = this.startDragKnob + mouseDelta; // Position the bar. - this.knobOffset = this.constrainKnob_(knobValue); - this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', this.knobOffset); + this.setKnobOffset(this.constrainKnob_(knobValue)); this.onScroll_(); }; @@ -628,8 +680,7 @@ Blockly.Scrollbar.prototype.onScroll_ = function() { * @param {number} value The distance from the top/left end of the bar. */ Blockly.Scrollbar.prototype.set = function(value) { - this.knobOffset = this.constrainKnob_(value * this.ratio_); - this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', this.knobOffset); + this.setKnobOffset(this.constrainKnob_(value * this.ratio_)); this.onScroll_(); }; From 5752913b4d0b14d427d78a760046fb5903b8808a Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Thu, 26 May 2016 15:22:24 -0700 Subject: [PATCH 3/6] Make some variables private and some functions public. --- core/scrollbar.js | 246 ++++++++++++++++++++++++---------------------- 1 file changed, 126 insertions(+), 120 deletions(-) diff --git a/core/scrollbar.js b/core/scrollbar.js index 0d385fe59..226c94c99 100644 --- a/core/scrollbar.js +++ b/core/scrollbar.js @@ -144,29 +144,29 @@ Blockly.ScrollbarPair.prototype.set = function(x, y) { // Combining them speeds up rendering. var xyRatio = {}; - var hKnobValue = x * this.hScroll.ratio_; - var vKnobValue = y * this.vScroll.ratio_; + var hHandlePosition = x * this.hScroll.ratio_; + var vHandlePosition = y * this.vScroll.ratio_; - var hBarLength = this.hScroll.barLength; - var vBarLength = this.vScroll.barLength; + var hBarLength = this.hScroll.scrollViewSize_; + var vBarLength = this.vScroll.scrollViewSize_; - xyRatio.x = this.getRatio_(hKnobValue, hBarLength); - xyRatio.y = this.getRatio_(vKnobValue, vBarLength); + xyRatio.x = this.getRatio_(hHandlePosition, hBarLength); + xyRatio.y = this.getRatio_(vHandlePosition, vBarLength); this.workspace_.setMetrics(xyRatio); - this.hScroll.setKnobOffset(hKnobValue); - this.vScroll.setKnobOffset(vKnobValue) + this.hScroll.setHandlePosition(hHandlePosition); + this.vScroll.setHandlePosition(vHandlePosition); }; /** - * Helper to calculate the ratio of knob value to bar length. - * @param {number} knobValue The value of the knob. - * @param {number} barLength The length of the scroll bar. + * Helper to calculate the ratio of handle position to scrollbar view size. + * @param {number} handlePosition The value of the knob. + * @param {number} viewSize The total size of the scrollbar's view. * @return {number} Ratio. * @private */ -Blockly.ScrollbarPair.prototype.getRatio_ = function(knobValue, barLength) { - var ratio = knobValue / barLength; +Blockly.ScrollbarPair.prototype.getRatio_ = function(handlePosition, viewSize) { + var ratio = handlePosition / viewSize; if (isNaN(ratio)) { return 0; } @@ -179,6 +179,7 @@ Blockly.ScrollbarPair.prototype.getRatio_ = function(knobValue, barLength) { * Class for a pure SVG scrollbar. * This technique offers a scrollbar that is guaranteed to work, but may not * look or behave like the system's scrollbars. + * NB: "Knob" and "handle" are used interchangeably in this file. * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to. * @param {boolean} horizontal True if horizontal, false if vertical. * @param {boolean=} opt_pair True if scrollbar is part of a horiz/vert pair. @@ -192,9 +193,9 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { this.createDom_(); - this.barLength = 0; - this.knobLength = 0; - this.knobOffset = 0; + this.scrollViewSize_ = 0; + this.handleLength_ = 0; + this.handlePosition_ = 0; this.isVisible_ = true; this.yCoordinate = 0; @@ -207,8 +208,8 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { Blockly.Scrollbar.scrollbarThickness - 5); this.svgKnob_.setAttribute('y', 2.5); - this.lengthAttribute = 'width'; - this.knobOffsetAttribute = 'x'; + this.lengthAttribute_ = 'width'; + this.positionAttribute_ = 'x'; } else { this.svgBackground_.setAttribute('width', Blockly.Scrollbar.scrollbarThickness); @@ -216,8 +217,8 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { Blockly.Scrollbar.scrollbarThickness - 5); this.svgKnob_.setAttribute('x', 2.5); - this.lengthAttribute = 'height'; - this.knobOffsetAttribute = 'y'; + this.lengthAttribute_ = 'height'; + this.positionAttribute_ = 'y'; } var scrollbar = this; this.onMouseDownBarWrapper_ = Blockly.bindEvent_(this.svgBackground_, @@ -284,33 +285,34 @@ Blockly.Scrollbar.prototype.dispose = function() { }; /** - * Set the length of the scrollbar's knob and change the SVG attribute + * Set the length of the scrollbar's handle and change the SVG attribute * accordingly. * @param {number} newLength The new scrollbar handle length. */ -Blockly.Scrollbar.prototype.setKnobLength = function(newLength) { - this.knobLength = newLength; - this.svgKnob_.setAttribute(this.lengthAttribute, this.knobLength); +Blockly.Scrollbar.prototype.setHandleLength_ = function(newLength) { + this.handleLength_ = newLength; + this.svgKnob_.setAttribute(this.lengthAttribute_, this.handleLength_); }; /** - * Set the offset of the scrollbar's knob and change the SVG attribute + * Set the offset of the scrollbar's handle and change the SVG attribute * accordingly. - * @param {number} newOffset The new scrollbar handle offset. + * @param {number} newPosition The new scrollbar handle offset. */ -Blockly.Scrollbar.prototype.setKnobOffset = function(newOffset) { - this.knobOffset = newOffset; - this.svgKnob_.setAttribute(this.knobOffsetAttribute, this.knobOffset); +Blockly.Scrollbar.prototype.setHandlePosition = function(newPosition) { + this.handlePosition_ = newPosition; + this.svgKnob_.setAttribute(this.positionAttribute_, this.handlePosition_); }; /** - * Set the length of the scrollbar's background and change the SVG attribute + * Set the size of the scrollbar's background and change the SVG attribute * accordingly. - * @param {number} newLength The new scrollbar background length. + * @param {number} newSize The new scrollbar background length. + * @private */ -Blockly.Scrollbar.prototype.setBarLength = function(newLength) { - this.barLength = newLength; - this.svgBackground_.setAttribute(this.lengthAttribute, this.barLength); +Blockly.Scrollbar.prototype.setScrollViewSize_ = function(newSize) { + this.scrollViewSize_ = newSize; + this.svgBackground_.setAttribute(this.lengthAttribute_, this.scrollViewSize_); }; /** @@ -364,37 +366,9 @@ Blockly.Scrollbar.prototype.resize = function(opt_metrics) { * @private */ Blockly.Scrollbar.prototype.resizeHorizontal_ = function(hostMetrics) { - this.resizeViewHorizontal_(hostMetrics); - this.resizeContentHorizontal_(hostMetrics); -}; - -/** - * Recalculate a horizontal scrollbar's location within its path and length. - * This should be called when the contents of the workspace have changed. - * @param {!Object} hostMetrics A data structure describing all the - * required dimensions, possibly fetched from the host object. - * @private - */ -Blockly.Scrollbar.prototype.resizeContentHorizontal_ = function(hostMetrics) { - if (!this.pair_) { - // Only show the scrollbar if needed. - // Ideally this would also apply to scrollbar pairs, but that's a bigger - // headache (due to interactions with the corner square). - this.setVisible(this.barLength < hostMetrics.contentWidth); - } - - this.ratio_ = this.barLength / hostMetrics.contentWidth; - if (this.ratio_ === -Infinity || this.ratio_ === Infinity || - isNaN(this.ratio_)) { - this.ratio_ = 0; - } - - var innerOffset = (hostMetrics.viewLeft - hostMetrics.contentLeft) * - this.ratio_; - this.setKnobOffset(this.constrainKnob_(innerOffset)); - - var innerLength = hostMetrics.viewWidth * this.ratio_; - this.setKnobLength(Math.max(0, innerLength)); + // TODO: Inspect metrics to determine if we can get away with just a content + // resize. + this.resizeViewHorizontal(hostMetrics); }; /** @@ -402,14 +376,14 @@ Blockly.Scrollbar.prototype.resizeContentHorizontal_ = function(hostMetrics) { * This should be called when the layout or size of the window has changed. * @param {!Object} hostMetrics A data structure describing all the * required dimensions, possibly fetched from the host object. - * @private */ -Blockly.Scrollbar.prototype.resizeViewHorizontal_ = function(hostMetrics) { - var outerLength = hostMetrics.viewWidth - 1; +Blockly.Scrollbar.prototype.resizeViewHorizontal = function(hostMetrics) { + var viewSize = hostMetrics.viewWidth - 1; if (this.pair_) { // Shorten the scrollbar to make room for the corner square. - outerLength -= Blockly.Scrollbar.scrollbarThickness; + viewSize -= Blockly.Scrollbar.scrollbarThickness; } + this.setScrollViewSize_(Math.max(0, viewSize)); this.xCoordinate = hostMetrics.absoluteLeft + 0.5; if (this.pair_ && this.workspace_.RTL) { @@ -421,7 +395,37 @@ Blockly.Scrollbar.prototype.resizeViewHorizontal_ = function(hostMetrics) { this.svgGroup_.setAttribute('transform', 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); - this.setBarLength(Math.max(0, outerLength)); + // If the view has been resized, a content resize will also be necessary. The + // reverse is not true. + this.resizeContentHorizontal(hostMetrics); +}; + +/** + * Recalculate a horizontal scrollbar's location within its path and length. + * This should be called when the contents of the workspace have changed. + * @param {!Object} hostMetrics A data structure describing all the + * required dimensions, possibly fetched from the host object. + */ +Blockly.Scrollbar.prototype.resizeContentHorizontal = function(hostMetrics) { + if (!this.pair_) { + // Only show the scrollbar if needed. + // Ideally this would also apply to scrollbar pairs, but that's a bigger + // headache (due to interactions with the corner square). + this.setVisible(this.scrollViewSize_ < hostMetrics.contentWidth); + } + + this.ratio_ = this.scrollViewSize_ / hostMetrics.contentWidth; + if (this.ratio_ === -Infinity || this.ratio_ === Infinity || + isNaN(this.ratio_)) { + this.ratio_ = 0; + } + + var handleLength = hostMetrics.viewWidth * this.ratio_; + this.setHandleLength_(Math.max(0, handleLength)); + + var handlePosition = (hostMetrics.viewLeft - hostMetrics.contentLeft) * + this.ratio_; + this.setHandlePosition(this.constrainHandle_(handlePosition)); }; /** @@ -431,35 +435,9 @@ Blockly.Scrollbar.prototype.resizeViewHorizontal_ = function(hostMetrics) { * @private */ Blockly.Scrollbar.prototype.resizeVertical_ = function(hostMetrics) { - this.resizeViewVertical_(hostMetrics); - this.resizeContentVertical_(hostMetrics); -}; - -/** - * Recalculate a vertical scrollbar's location within its path and length. - * This should be called when the contents of the workspace have changed. - * @param {!Object} hostMetrics A data structure describing all the - * required dimensions, possibly fetched from the host object. - * @private - */ -Blockly.Scrollbar.prototype.resizeContentVertical_ = function(hostMetrics) { - if (!this.pair_) { - // Only show the scrollbar if needed. - this.setVisible(this.barLength < hostMetrics.contentHeight); - } - - this.ratio_ = this.barLength / hostMetrics.contentHeight; - if (this.ratio_ === -Infinity || this.ratio_ === Infinity || - isNaN(this.ratio_)) { - this.ratio_ = 0; - } - - var innerLength = hostMetrics.viewHeight * this.ratio_; - this.setKnobLength(Math.max(0, innerLength)); - - var innerOffset = (hostMetrics.viewTop - hostMetrics.contentTop) * - this.ratio_; - this.setKnobOffset(this.constrainKnob_(innerOffset)); + // TODO: Inspect metrics to determine if we can get away with just a content + // resize. + this.resizeViewVertical(hostMetrics); }; /** @@ -467,14 +445,14 @@ Blockly.Scrollbar.prototype.resizeContentVertical_ = function(hostMetrics) { * This should be called when the layout or size of the window has changed. * @param {!Object} hostMetrics A data structure describing all the * required dimensions, possibly fetched from the host object. - * @private */ -Blockly.Scrollbar.prototype.resizeViewVertical_ = function(hostMetrics) { - var outerLength = hostMetrics.viewHeight - 1; +Blockly.Scrollbar.prototype.resizeViewVertical = function(hostMetrics) { + var viewSize = hostMetrics.viewHeight - 1; if (this.pair_) { // Shorten the scrollbar to make room for the corner square. - outerLength -= Blockly.Scrollbar.scrollbarThickness; + viewSize -= Blockly.Scrollbar.scrollbarThickness; } + this.setScrollViewSize_(Math.max(0, viewSize)); this.xCoordinate = hostMetrics.absoluteLeft + 0.5; if (!this.workspace_.RTL) { @@ -485,7 +463,35 @@ Blockly.Scrollbar.prototype.resizeViewVertical_ = function(hostMetrics) { this.svgGroup_.setAttribute('transform', 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); - this.setBarLength(Math.max(0, outerLength)); + // If the view has been resized, a content resize will also be necessary. The + // reverse is not true. + this.resizeContentVertical(hostMetrics); +}; + +/** + * Recalculate a vertical scrollbar's location within its path and length. + * This should be called when the contents of the workspace have changed. + * @param {!Object} hostMetrics A data structure describing all the + * required dimensions, possibly fetched from the host object. + */ +Blockly.Scrollbar.prototype.resizeContentVertical = function(hostMetrics) { + if (!this.pair_) { + // Only show the scrollbar if needed. + this.setVisible(this.scrollViewSize_ < hostMetrics.contentHeight); + } + + this.ratio_ = this.scrollViewSize_ / hostMetrics.contentHeight; + if (this.ratio_ === -Infinity || this.ratio_ === Infinity || + isNaN(this.ratio_)) { + this.ratio_ = 0; + } + + var handleLength = hostMetrics.viewHeight * this.ratio_; + this.setHandleLength_(Math.max(0, handleLength)); + + var handlePosition = (hostMetrics.viewTop - hostMetrics.contentTop) * + this.ratio_; + this.setHandlePosition(this.constrainHandle_(handlePosition)); }; /** @@ -565,20 +571,20 @@ Blockly.Scrollbar.prototype.onMouseDownBar_ = function(e) { var mouseXY = Blockly.mouseToSvg(e, this.workspace_.getParentSvg()); var mouseLocation = this.horizontal_ ? mouseXY.x : mouseXY.y; - var knobXY = Blockly.getSvgXY_(this.svgKnob_, this.workspace_); - var knobStart = this.horizontal_ ? knobXY.x : knobXY.y; - var knobValue = this.knobOffset; + var handleXY = Blockly.getSvgXY_(this.svgKnob_, this.workspace_); + var handleStart = this.horizontal_ ? handleXY.x : handleXY.y; + var handlePosition = this.handlePosition_; - var pageLength = this.knobLength * 0.95; - if (mouseLocation <= knobStart) { + var pageLength = this.handleLength_ * 0.95; + if (mouseLocation <= handleStart) { // Decrease the scrollbar's value by a page. - knobValue -= pageLength; - } else if (mouseLocation >= knobStart + this.knobLength) { + handlePosition -= pageLength; + } else if (mouseLocation >= handleStart + this.handleLength_) { // Increase the scrollbar's value by a page. - knobValue += pageLength; + handlePosition += pageLength; } - this.setKnobOffset(this.constrainKnob_(knobValue)); + this.setHandlePosition(this.constrainHandle_(handlePosition)); this.onScroll_(); e.stopPropagation(); @@ -600,7 +606,7 @@ Blockly.Scrollbar.prototype.onMouseDownKnob_ = function(e) { return; } // Look up the current translation and record it. - this.startDragKnob = this.knobOffset; + this.startDragKnob = this.handlePosition_; // Record the current mouse position. this.startDragMouse = this.horizontal_ ? e.clientX : e.clientY; Blockly.Scrollbar.onMouseUpWrapper_ = Blockly.bindEvent_(document, @@ -621,7 +627,7 @@ Blockly.Scrollbar.prototype.onMouseMoveKnob_ = function(e) { var mouseDelta = currentMouse - this.startDragMouse; var knobValue = this.startDragKnob + mouseDelta; // Position the bar. - this.setKnobOffset(this.constrainKnob_(knobValue)); + this.setHandlePosition(this.constrainHandle_(knobValue)); this.onScroll_(); }; @@ -642,17 +648,17 @@ Blockly.Scrollbar.prototype.onMouseUpKnob_ = function() { }; /** - * Constrain the knob's position within the minimum (0) and maximum + * Constrain the handle's position within the minimum (0) and maximum * (length of scrollbar) values allowed for the scrollbar. * @param {number} value Value that is potentially out of bounds. * @return {number} Constrained value. * @private */ -Blockly.Scrollbar.prototype.constrainKnob_ = function(value) { +Blockly.Scrollbar.prototype.constrainHandle_ = function(value) { if (value <= 0 || isNaN(value)) { value = 0; } else { - value = Math.min(value, this.barLength - this.knobLength); + value = Math.min(value, this.scrollViewSize_ - this.handleLength_); } return value; }; @@ -662,7 +668,7 @@ Blockly.Scrollbar.prototype.constrainKnob_ = function(value) { * @private */ Blockly.Scrollbar.prototype.onScroll_ = function() { - var ratio = this.knobOffset / this.barLength; + var ratio = this.handlePosition_ / this.scrollViewSize_; if (isNaN(ratio)) { ratio = 0; } @@ -680,7 +686,7 @@ Blockly.Scrollbar.prototype.onScroll_ = function() { * @param {number} value The distance from the top/left end of the bar. */ Blockly.Scrollbar.prototype.set = function(value) { - this.setKnobOffset(this.constrainKnob_(value * this.ratio_)); + this.setHandlePosition(this.constrainHandle_(value * this.ratio_)); this.onScroll_(); }; From 06b9bb68e6762934fb5e7e1c004bb33dac1f1e0e Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 27 May 2016 10:25:19 -0700 Subject: [PATCH 4/6] Rename knob to handle --- core/css.js | 12 +++++----- core/scrollbar.js | 59 +++++++++++++++++++++++------------------------ 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/core/css.js b/core/css.js index ed9859f0e..9ee01dfc5 100644 --- a/core/css.js +++ b/core/css.js @@ -326,12 +326,12 @@ Blockly.Css.CONTENT = [ 'opacity: 0;', '}', - '.blocklyScrollbarKnob {', + '.blocklyScrollbarHandle {', 'fill: #ccc;', '}', - '.blocklyScrollbarBackground:hover+.blocklyScrollbarKnob,', - '.blocklyScrollbarKnob:hover {', + '.blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,', + '.blocklyScrollbarHandle:hover {', 'fill: #bbb;', '}', @@ -349,12 +349,12 @@ Blockly.Css.CONTENT = [ /* Darken flyout scrollbars due to being on a grey background. */ /* By contrast, workspace scrollbars are on a white background. */ - '.blocklyFlyout .blocklyScrollbarKnob {', + '.blocklyFlyout .blocklyScrollbarHandle {', 'fill: #bbb;', '}', - '.blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarKnob,', - '.blocklyFlyout .blocklyScrollbarKnob:hover {', + '.blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,', + '.blocklyFlyout .blocklyScrollbarHandle:hover {', 'fill: #aaa;', '}', diff --git a/core/scrollbar.js b/core/scrollbar.js index 226c94c99..4c2303683 100644 --- a/core/scrollbar.js +++ b/core/scrollbar.js @@ -160,7 +160,7 @@ Blockly.ScrollbarPair.prototype.set = function(x, y) { /** * Helper to calculate the ratio of handle position to scrollbar view size. - * @param {number} handlePosition The value of the knob. + * @param {number} handlePosition The value of the handle. * @param {number} viewSize The total size of the scrollbar's view. * @return {number} Ratio. * @private @@ -179,7 +179,6 @@ Blockly.ScrollbarPair.prototype.getRatio_ = function(handlePosition, viewSize) { * Class for a pure SVG scrollbar. * This technique offers a scrollbar that is guaranteed to work, but may not * look or behave like the system's scrollbars. - * NB: "Knob" and "handle" are used interchangeably in this file. * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to. * @param {boolean} horizontal True if horizontal, false if vertical. * @param {boolean=} opt_pair True if scrollbar is part of a horiz/vert pair. @@ -204,18 +203,18 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { if (horizontal) { this.svgBackground_.setAttribute('height', Blockly.Scrollbar.scrollbarThickness); - this.svgKnob_.setAttribute('height', + this.svgHandle_.setAttribute('height', Blockly.Scrollbar.scrollbarThickness - 5); - this.svgKnob_.setAttribute('y', 2.5); + this.svgHandle_.setAttribute('y', 2.5); this.lengthAttribute_ = 'width'; this.positionAttribute_ = 'x'; } else { this.svgBackground_.setAttribute('width', Blockly.Scrollbar.scrollbarThickness); - this.svgKnob_.setAttribute('width', + this.svgHandle_.setAttribute('width', Blockly.Scrollbar.scrollbarThickness - 5); - this.svgKnob_.setAttribute('x', 2.5); + this.svgHandle_.setAttribute('x', 2.5); this.lengthAttribute_ = 'height'; this.positionAttribute_ = 'y'; @@ -223,8 +222,8 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { var scrollbar = this; this.onMouseDownBarWrapper_ = Blockly.bindEvent_(this.svgBackground_, 'mousedown', scrollbar, scrollbar.onMouseDownBar_); - this.onMouseDownKnobWrapper_ = Blockly.bindEvent_(this.svgKnob_, - 'mousedown', scrollbar, scrollbar.onMouseDownKnob_); + this.onMouseDownHandleWrapper_ = Blockly.bindEvent_(this.svgHandle_, + 'mousedown', scrollbar, scrollbar.onMouseDownHandle_); }; /** @@ -271,16 +270,16 @@ Blockly.Scrollbar.metricsAreEquivalent_ = function(first, second) { * Unlink from all DOM elements to prevent memory leaks. */ Blockly.Scrollbar.prototype.dispose = function() { - this.onMouseUpKnob_(); + this.onMouseUpHandle_(); Blockly.unbindEvent_(this.onMouseDownBarWrapper_); this.onMouseDownBarWrapper_ = null; - Blockly.unbindEvent_(this.onMouseDownKnobWrapper_); - this.onMouseDownKnobWrapper_ = null; + Blockly.unbindEvent_(this.onMouseDownHandleWrapper_); + this.onMouseDownHandleWrapper_ = null; goog.dom.removeNode(this.svgGroup_); this.svgGroup_ = null; this.svgBackground_ = null; - this.svgKnob_ = null; + this.svgHandle_ = null; this.workspace_ = null; }; @@ -291,7 +290,7 @@ Blockly.Scrollbar.prototype.dispose = function() { */ Blockly.Scrollbar.prototype.setHandleLength_ = function(newLength) { this.handleLength_ = newLength; - this.svgKnob_.setAttribute(this.lengthAttribute_, this.handleLength_); + this.svgHandle_.setAttribute(this.lengthAttribute_, this.handleLength_); }; /** @@ -301,7 +300,7 @@ Blockly.Scrollbar.prototype.setHandleLength_ = function(newLength) { */ Blockly.Scrollbar.prototype.setHandlePosition = function(newPosition) { this.handlePosition_ = newPosition; - this.svgKnob_.setAttribute(this.positionAttribute_, this.handlePosition_); + this.svgHandle_.setAttribute(this.positionAttribute_, this.handlePosition_); }; /** @@ -503,7 +502,7 @@ Blockly.Scrollbar.prototype.createDom_ = function() { /* Create the following DOM: - + */ var className = 'blocklyScrollbar' + @@ -512,8 +511,8 @@ Blockly.Scrollbar.prototype.createDom_ = function() { this.svgBackground_ = Blockly.createSvgElement('rect', {'class': 'blocklyScrollbarBackground'}, this.svgGroup_); var radius = Math.floor((Blockly.Scrollbar.scrollbarThickness - 5) / 2); - this.svgKnob_ = Blockly.createSvgElement('rect', - {'class': 'blocklyScrollbarKnob', 'rx': radius, 'ry': radius}, + this.svgHandle_ = Blockly.createSvgElement('rect', + {'class': 'blocklyScrollbarHandle', 'rx': radius, 'ry': radius}, this.svgGroup_); Blockly.Scrollbar.insertAfter_(this.svgGroup_, this.workspace_.getBubbleCanvas()); @@ -561,7 +560,7 @@ Blockly.Scrollbar.prototype.setVisible = function(visible) { * @private */ Blockly.Scrollbar.prototype.onMouseDownBar_ = function(e) { - this.onMouseUpKnob_(); + this.onMouseUpHandle_(); if (Blockly.isRightButton(e)) { // Right-click. // Scrollbars have no context menu. @@ -571,7 +570,7 @@ Blockly.Scrollbar.prototype.onMouseDownBar_ = function(e) { var mouseXY = Blockly.mouseToSvg(e, this.workspace_.getParentSvg()); var mouseLocation = this.horizontal_ ? mouseXY.x : mouseXY.y; - var handleXY = Blockly.getSvgXY_(this.svgKnob_, this.workspace_); + var handleXY = Blockly.getSvgXY_(this.svgHandle_, this.workspace_); var handleStart = this.horizontal_ ? handleXY.x : handleXY.y; var handlePosition = this.handlePosition_; @@ -593,12 +592,12 @@ Blockly.Scrollbar.prototype.onMouseDownBar_ = function(e) { /** * Start a dragging operation. - * Called when scrollbar knob is clicked. + * Called when scrollbar handle is clicked. * @param {!Event} e Mouse down event. * @private */ -Blockly.Scrollbar.prototype.onMouseDownKnob_ = function(e) { - this.onMouseUpKnob_(); +Blockly.Scrollbar.prototype.onMouseDownHandle_ = function(e) { + this.onMouseUpHandle_(); if (Blockly.isRightButton(e)) { // Right-click. // Scrollbars have no context menu. @@ -606,28 +605,28 @@ Blockly.Scrollbar.prototype.onMouseDownKnob_ = function(e) { return; } // Look up the current translation and record it. - this.startDragKnob = this.handlePosition_; + this.startDragHandle = this.handlePosition_; // Record the current mouse position. this.startDragMouse = this.horizontal_ ? e.clientX : e.clientY; Blockly.Scrollbar.onMouseUpWrapper_ = Blockly.bindEvent_(document, - 'mouseup', this, this.onMouseUpKnob_); + 'mouseup', this, this.onMouseUpHandle_); Blockly.Scrollbar.onMouseMoveWrapper_ = Blockly.bindEvent_(document, - 'mousemove', this, this.onMouseMoveKnob_); + 'mousemove', this, this.onMouseMoveHandle_); e.stopPropagation(); e.preventDefault(); }; /** - * Drag the scrollbar's knob. + * Drag the scrollbar's handle. * @param {!Event} e Mouse up event. * @private */ -Blockly.Scrollbar.prototype.onMouseMoveKnob_ = function(e) { +Blockly.Scrollbar.prototype.onMouseMoveHandle_ = function(e) { var currentMouse = this.horizontal_ ? e.clientX : e.clientY; var mouseDelta = currentMouse - this.startDragMouse; - var knobValue = this.startDragKnob + mouseDelta; + var handlePosition = this.startDragHandle + mouseDelta; // Position the bar. - this.setHandlePosition(this.constrainHandle_(knobValue)); + this.setHandlePosition(this.constrainHandle_(handlePosition)); this.onScroll_(); }; @@ -635,7 +634,7 @@ Blockly.Scrollbar.prototype.onMouseMoveKnob_ = function(e) { * Stop binding to the global mouseup and mousemove events. * @private */ -Blockly.Scrollbar.prototype.onMouseUpKnob_ = function() { +Blockly.Scrollbar.prototype.onMouseUpHandle_ = function() { Blockly.hideChaff(true); if (Blockly.Scrollbar.onMouseUpWrapper_) { Blockly.unbindEvent_(Blockly.Scrollbar.onMouseUpWrapper_); From 8afb04d9ee9453f736562df6d68bf09ac36ab430 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 27 May 2016 10:37:40 -0700 Subject: [PATCH 5/6] Move values to prototype and use coordinate. --- core/scrollbar.js | 77 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/core/scrollbar.js b/core/scrollbar.js index 4c2303683..86b52a339 100644 --- a/core/scrollbar.js +++ b/core/scrollbar.js @@ -118,12 +118,12 @@ Blockly.ScrollbarPair.prototype.resize = function() { if (!this.oldHostMetrics_ || this.oldHostMetrics_.viewWidth != hostMetrics.viewWidth || this.oldHostMetrics_.absoluteLeft != hostMetrics.absoluteLeft) { - this.corner_.setAttribute('x', this.vScroll.xCoordinate); + this.corner_.setAttribute('x', this.vScroll.position_.x); } if (!this.oldHostMetrics_ || this.oldHostMetrics_.viewHeight != hostMetrics.viewHeight || this.oldHostMetrics_.absoluteTop != hostMetrics.absoluteTop) { - this.corner_.setAttribute('y', this.hScroll.yCoordinate); + this.corner_.setAttribute('y', this.hScroll.position_.y); } // Cache the current metrics to potentially short-cut the next resize event. @@ -192,13 +192,12 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { this.createDom_(); - this.scrollViewSize_ = 0; - this.handleLength_ = 0; - this.handlePosition_ = 0; - this.isVisible_ = true; - - this.yCoordinate = 0; - this.xCoordinate = 0; + /** + * The upper left corner of the scrollbar's svg group. + * @type {goog.math.Coordinate} + * @private + */ + this.position_ = new goog.math.Coordinate(0, 0); if (horizontal) { this.svgBackground_.setAttribute('height', @@ -226,6 +225,34 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { 'mousedown', scrollbar, scrollbar.onMouseDownHandle_); }; +/** + * The size of the area within which the scrollbar handle can move. + * @type {number} + * @private + */ +Blockly.Scrollbar.prototype.scrollViewSize_ = 0; + +/** + * The length of the scrollbar handle. + * @type {number} + * @private + */ +Blockly.Scrollbar.prototype.handleLength_ = 0; + +/** + * The offset of the start of the handle from the start of the scrollbar range. + * @type {number} + * @private + */ +Blockly.Scrollbar.prototype.handlePosition_ = 0; + +/** + * Whether the scrollbar handle is visible. + * @type {boolean} + * @private + */ +Blockly.Scrollbar.prototype.isVisible_ = true; + /** * Width of vertical scrollbar or height of horizontal scrollbar. * Increase the size of scrollbars on touch devices. @@ -314,6 +341,19 @@ Blockly.Scrollbar.prototype.setScrollViewSize_ = function(newSize) { this.svgBackground_.setAttribute(this.lengthAttribute_, this.scrollViewSize_); }; +/** + * Set the position of the scrollbar's svg group. + * @param {number} x The new x coordinate. + * @param {number} y The new y coordinate. + */ +Blockly.Scrollbar.prototype.setPosition = function(x, y) { + this.position_.x = x; + this.position_.y = y; + + this.svgGroup_.setAttribute('transform', + 'translate(' + this.position_.x + ',' + this.position_.y + ')'); +}; + /** * Recalculate the scrollbar's location and its length. * @param {Object=} opt_metrics A data structure of from the describing all the @@ -384,15 +424,15 @@ Blockly.Scrollbar.prototype.resizeViewHorizontal = function(hostMetrics) { } this.setScrollViewSize_(Math.max(0, viewSize)); - this.xCoordinate = hostMetrics.absoluteLeft + 0.5; + var xCoordinate = hostMetrics.absoluteLeft + 0.5; if (this.pair_ && this.workspace_.RTL) { - this.xCoordinate += Blockly.Scrollbar.scrollbarThickness; + xCoordinate += Blockly.Scrollbar.scrollbarThickness; } + // Horizontal toolbar should always be just above the bottom of the workspace. - this.yCoordinate = hostMetrics.absoluteTop + hostMetrics.viewHeight - + var yCoordinate = hostMetrics.absoluteTop + hostMetrics.viewHeight - Blockly.Scrollbar.scrollbarThickness - 0.5; - this.svgGroup_.setAttribute('transform', - 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); + this.setPosition(xCoordinate, yCoordinate); // If the view has been resized, a content resize will also be necessary. The // reverse is not true. @@ -453,14 +493,13 @@ Blockly.Scrollbar.prototype.resizeViewVertical = function(hostMetrics) { } this.setScrollViewSize_(Math.max(0, viewSize)); - this.xCoordinate = hostMetrics.absoluteLeft + 0.5; + var xCoordinate = hostMetrics.absoluteLeft + 0.5; if (!this.workspace_.RTL) { - this.xCoordinate += hostMetrics.viewWidth - + xCoordinate += hostMetrics.viewWidth - Blockly.Scrollbar.scrollbarThickness - 1; } - this.yCoordinate = hostMetrics.absoluteTop + 0.5; - this.svgGroup_.setAttribute('transform', - 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); + var yCoordinate = hostMetrics.absoluteTop + 0.5; + this.setPosition(xCoordinate, yCoordinate); // If the view has been resized, a content resize will also be necessary. The // reverse is not true. From 5532e879ebeaae474cff65934d937444bc2daaf4 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 27 May 2016 10:38:41 -0700 Subject: [PATCH 6/6] Check for infinity with == in scrollbar --- core/scrollbar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/scrollbar.js b/core/scrollbar.js index 86b52a339..ee080b0bc 100644 --- a/core/scrollbar.js +++ b/core/scrollbar.js @@ -454,7 +454,7 @@ Blockly.Scrollbar.prototype.resizeContentHorizontal = function(hostMetrics) { } this.ratio_ = this.scrollViewSize_ / hostMetrics.contentWidth; - if (this.ratio_ === -Infinity || this.ratio_ === Infinity || + if (this.ratio_ == -Infinity || this.ratio_ == Infinity || isNaN(this.ratio_)) { this.ratio_ = 0; } @@ -519,7 +519,7 @@ Blockly.Scrollbar.prototype.resizeContentVertical = function(hostMetrics) { } this.ratio_ = this.scrollViewSize_ / hostMetrics.contentHeight; - if (this.ratio_ === -Infinity || this.ratio_ === Infinity || + if (this.ratio_ == -Infinity || this.ratio_ == Infinity || isNaN(this.ratio_)) { this.ratio_ = 0; }