From fbb363197ab3975411589dfa0904495f861795c0 Mon Sep 17 00:00:00 2001 From: Brian Hann Date: Wed, 11 Mar 2015 12:23:31 -0500 Subject: [PATCH] fix(RTL): Use feature detection to determine RTL Rather than relying on browser detection to determine how scrollLeft will be defined when an element is RTL, use the method from this library: https://github.com/othree/jquery.rtl-scroll-type which creates a temporary element to see how scrollLeft turns out. Fixes #1689 --- .../directives/ui-grid-render-container.js | 4 +- src/js/core/services/ui-grid-util.js | 111 +++++++++--------- 2 files changed, 56 insertions(+), 59 deletions(-) diff --git a/src/js/core/directives/ui-grid-render-container.js b/src/js/core/directives/ui-grid-render-container.js index 02044d89b2..4b10cb4f2e 100644 --- a/src/js/core/directives/ui-grid-render-container.js +++ b/src/js/core/directives/ui-grid-render-container.js @@ -97,7 +97,7 @@ // Horizontal scroll if (args.x && $scope.bindScrollHorizontal) { containerCtrl.prevScrollArgs = args; - var newScrollLeft = args.getNewScrollLeft(colContainer,containerCtrl.viewport); + var newScrollLeft = args.getNewScrollLeft(colContainer, containerCtrl.viewport); // Make the current horizontal scroll position available in the $scope $scope.newScrollLeft = newScrollLeft; @@ -112,7 +112,7 @@ // Scroll came from somewhere else, so the viewport must be positioned if (args.source !== ScrollEvent.Sources.ViewPortScroll) { - containerCtrl.viewport[0].scrollLeft = newScrollLeft; + containerCtrl.viewport[0].scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport, newScrollLeft); } containerCtrl.prevScrollLeft = newScrollLeft; diff --git a/src/js/core/services/ui-grid-util.js b/src/js/core/services/ui-grid-util.js index da230e577e..04106be9c3 100644 --- a/src/js/core/services/ui-grid-util.js +++ b/src/js/core/services/ui-grid-util.js @@ -879,6 +879,34 @@ module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateC return 'unknown'; }; + // Borrowed from https://github.com/othree/jquery.rtl-scroll-type + // Determine the scroll "type" this browser is using for RTL + s.rtlScrollType = function rtlScrollType() { + if (rtlScrollType.type) { + return rtlScrollType.type; + } + + var definer = angular.element('
A
')[0], + type = 'reverse'; + + document.body.appendChild(definer); + + if (definer.scrollLeft > 0) { + type = 'default'; + } + else { + definer.scrollLeft = 1; + if (definer.scrollLeft === 0) { + type = 'negative'; + } + } + + definer.remove(); + rtlScrollType.type = type; + + return type; + }; + /** * @ngdoc method * @name normalizeScrollLeft @@ -896,37 +924,22 @@ module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateC element = element[0]; } - var browser = s.detectBrowser(); - var scrollLeft = element.scrollLeft; - var dir = s.getStyles(element)['direction']; - - // IE stays normal in RTL - if (browser === 'ie') { - return scrollLeft; - } - // Chrome doesn't alter the scrollLeft value. So with RTL on a 400px-wide grid, the right-most position will still be 400 and the left-most will still be 0; - else if (browser === 'chrome') { - if (dir === 'rtl') { - // Get the max scroll for the element - var maxScrollLeft = element.scrollWidth - element.clientWidth; - - // Subtract the current scroll amount from the max scroll - return maxScrollLeft - scrollLeft; + var dir = s.getStyles(element).direction; + + if (dir === 'rtl') { + switch (s.rtlScrollType()) { + case 'default': + return element.scrollWidth - scrollLeft - element.clientWidth; + case 'negative': + return scrollLeft + element.scrollWidth - element.clientWidth; + case 'reverse': + return scrollLeft; } - else { - return scrollLeft; - } - } - // Firefox goes negative! - else if (browser === 'firefox') { - return Math.abs(scrollLeft); - } - else { - // TODO(c0bra): Handle other browsers? Android? iOS? Opera? - return scrollLeft; } + + return scrollLeft; }; /** @@ -947,40 +960,24 @@ module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateC element = element[0]; } - var browser = s.detectBrowser(); + var dir = s.getStyles(element).direction; - var dir = s.getStyles(element)['direction']; + if (dir === 'rtl') { + switch (s.rtlScrollType()) { + case 'default': + // Get the max scroll for the element + var maxScrollLeft = element.scrollWidth - element.clientWidth; - // IE stays normal in RTL - if (browser === 'ie') { - return scrollLeft; - } - // Chrome doesn't alter the scrollLeft value. So with RTL on a 400px-wide grid, the right-most position will still be 400 and the left-most will still be 0; - else if (browser === 'chrome') { - if (dir === 'rtl') { - // Get the max scroll for the element - var maxScrollLeft = element.scrollWidth - element.clientWidth; - - // Subtract the current scroll amount from the max scroll - return maxScrollLeft - scrollLeft; - } - else { - return scrollLeft; + // Subtract the current scroll amount from the max scroll + return maxScrollLeft - scrollLeft; + case 'negative': + return scrollLeft * -1; + case 'reverse': + return scrollLeft; } } - // Firefox goes negative! - else if (browser === 'firefox') { - if (dir === 'rtl') { - return scrollLeft * -1; - } - else { - return scrollLeft; - } - } - else { - // TODO(c0bra): Handle other browsers? Android? iOS? Opera? - return scrollLeft; - } + + return scrollLeft; }; /**