Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Calviño Sánchez <danxuliu@gmail.com>2018-11-08 20:19:00 +0300
committerDaniel Calviño Sánchez <danxuliu@gmail.com>2018-11-20 14:18:15 +0300
commit29425fa4d26b85567ccb0d9cf44921effd1d9eff (patch)
tree17b36ff09e4b65bf21178bca89796d91ed0c0aba
parent6c929cb3c4653832db6e936fbf10eeb0dd648d46 (diff)
Add support for browsers with subpixel accuracy
Before the 3.0.0 release jQuery rounded the height to the nearest integer, so the height returned by jQuery is not the correct value in browsers with subpixel accuracy (positions and sizes with decimal values), like Firefox. Due to this all the height related functions of jQuery need to be replaced with custom versions that return the height as a float instead of an integer. Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
-rw-r--r--js/views/virtuallist.js86
1 files changed, 70 insertions, 16 deletions
diff --git a/js/views/virtuallist.js b/js/views/virtuallist.js
index 454dabae1..392735d79 100644
--- a/js/views/virtuallist.js
+++ b/js/views/virtuallist.js
@@ -202,14 +202,17 @@
this._$container.append($wrapper);
- var previousWrapperHeight = $wrapper.height();
+ var previousWrapperHeight = this._getElementHeight($wrapper);
$wrapper.append(this._appendedElementsBuffer);
delete this._appendedElementsBuffer;
- var wrapperHeightDifference = $wrapper.height() - previousWrapperHeight;
+ var wrapperHeightDifference = this._getElementHeight($wrapper) - previousWrapperHeight;
- this._$wrapperBackground.height(this._$wrapperBackground.height() + wrapperHeightDifference);
+ // Although getting the height with jQuery < 3.X rounds to the
+ // nearest integer setting the height respects the given float
+ // number.
+ this._$wrapperBackground.height(this._getElementHeight(this._$wrapperBackground) + wrapperHeightDifference);
while (this._$firstAppendedElement) {
this._updateCache(this._$firstAppendedElement, $wrapper);
@@ -271,7 +274,7 @@
// position of the element would be if there was no margin, so in
// those cases the top position returned by jQuery is below the
// actual top position of the element.
- var marginTop = parseInt($element.css('margin-top'));
+ var marginTop = parseFloat($element.css('margin-top'));
if (marginTop >= 0) {
return $element.position().top;
}
@@ -280,6 +283,44 @@
},
/**
+ * Returns the height of the given element.
+ *
+ * This must be used instead of jQuery.height(); before the 3.0.0
+ * release jQuery rounded the height to the nearest integer, but Firefox
+ * has subpixel accuracy, so the height returned by jQuery can not be
+ * used in the calculations.
+ *
+ * @param jQuery $element the jQuery element to get its height.
+ */
+ _getElementHeight: function($element) {
+ return $element.get(0).getBoundingClientRect().height;
+ },
+
+ /**
+ * Returns the outer height, without margins, of the given element.
+ *
+ * The returned value includes the height, the padding and the border.
+ *
+ * This must be used instead of jQuery.height(); before the 3.0.0
+ * release jQuery rounded the height to the nearest integer, but Firefox
+ * has subpixel accuracy, so the height returned by jQuery can not be
+ * used in the calculations.
+ *
+ * @param jQuery $element the jQuery element to get its height.
+ */
+ _getElementOuterHeightWithoutMargins: function($element) {
+ // Although before jQuery 3.0.0 the height is rounded to the nearest
+ // integer the padding and border width, on the other hand, are
+ // returned as a float value as expected.
+ var paddingTop = parseFloat($element.css('padding-top'));
+ var paddingBottom = parseFloat($element.css('padding-bottom'));
+ var borderTop = parseFloat($element.css('border-top-width'));
+ var borderBottom = parseFloat($element.css('border-bottom-width'));
+
+ return this._getElementHeight($element) + paddingTop + paddingBottom + borderTop + borderBottom;
+ },
+
+ /**
* Returns the full outer height, with margins, of the given element.
*
* The returned value includes the height, the padding, the border and
@@ -288,20 +329,25 @@
* element (negative top margin) or its next element (negative bottom
* margin), but without modifying its visible height.
*
+ * This must be used instead of jQuery.height(); before the 3.0.0
+ * release jQuery rounded the height to the nearest integer, but Firefox
+ * has subpixel accuracy, so the height returned by jQuery can not be
+ * used in the calculations.
+ *
* @param jQuery $element the jQuery element to get its height.
*/
_getElementOuterHeight: function($element) {
- // When the margin is positive, jQuery returns the proper outer
- // height of the element. However, when it is negative, it
- // substracts the negative margin from the overall height of the
- // element, so in those cases the outer height returned by jQuery is
- // smaller than the actual height.
- var marginTop = parseInt($element.css('margin-top'));
- if (marginTop >= 0) {
- return $element.outerHeight(true);
- }
-
- return $element.outerHeight(true) - marginTop;
+ // Although before jQuery 3.0.0 the height is rounded to the nearest
+ // integer the margin, on the other hand, is returned as a float
+ // value as expected.
+ // Besides that note that outerHeight(true) would return a smaller
+ // height than the actual height when there are negative margins, as
+ // in that case jQuery would substract the negative margin from the
+ // overall height of the element.
+ var marginTop = Math.max(0, parseFloat($element.css('margin-top')));
+ var marginBottom = Math.max(0, parseFloat($element.css('margin-bottom')));
+
+ return this._getElementOuterHeightWithoutMargins($element) + marginTop + marginBottom;
},
/**
@@ -309,6 +355,14 @@
*
* Elements no longer in the viewport are removed, while elements now in
* the viewport are added.
+ *
+ * Note that the float precision problems are not handled in the
+ * visibility checks, so in browsers with subpixel accuracy, like
+ * Firefox, elements in which their bottom is very very close to the top
+ * of the container, or elements in which their top is very very close
+ * to the bottom of the container may be shown or hidden when they
+ * should not. However, this should not be a problem, as only fractions
+ * of a pixel would be wrongly shown or hidden.
*/
updateVisibleElements: function() {
if (!this._$firstVisibleElement && !this._$firstElement) {
@@ -323,7 +377,7 @@
}
var visibleAreaTop = this._$container.scrollTop();
- var visibleAreaBottom = visibleAreaTop + this._$container.outerHeight();
+ var visibleAreaBottom = visibleAreaTop + this._getElementOuterHeightWithoutMargins(this._$container);
var firstVisibleElementIsStillPartiallyVisible =
this._$firstVisibleElement._top <= visibleAreaTop &&