Skip to content

Commit d5a9982

Browse files
committed
feat(RTL): Adding RTL support and fixing virtualization
1 parent d062ed5 commit d5a9982

File tree

9 files changed

+180
-59
lines changed

9 files changed

+180
-59
lines changed

misc/tutorial/299_RTL.ngdoc

+15-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,21 @@ The grid supports RTL languages
1212
app.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
1313
$scope.gridOptions = {
1414
columnDefs: [
15-
{ field: 'name', width: 200 },
16-
{ field: 'gender', width: 200 },
17-
{ field: 'company', width: 200 }
15+
{ name: 'field1', field: 'name', width: 200 },
16+
{ name: 'field2', field: 'gender', width: 200 },
17+
{ name: 'field3', field: 'company', width: 200 },
18+
{ name: 'field4', field: 'name', width: 200 },
19+
{ name: 'field5', field: 'gender', width: 200 },
20+
{ name: 'field6', field: 'company', width: 200 },
21+
{ name: 'field7', field: 'name', width: 200 },
22+
{ name: 'field8', field: 'gender', width: 200 },
23+
{ name: 'field9', field: 'company', width: 200 },
24+
{ name: 'field10', field: 'name', width: 200 },
25+
{ name: 'field11', field: 'gender', width: 200 },
26+
{ name: 'field12', field: 'company', width: 200 },
27+
{ name: 'field13', field: 'name', width: 200 },
28+
{ name: 'field14', field: 'gender', width: 200 },
29+
{ name: 'field15', field: 'company', width: 200 }
1830
]
1931
};
2032

src/js/core/directives/ui-grid-native-scrollbar.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
rowContainer.horizontalScrollbarHeight = scrollBarWidth;
4949

5050
// Save the initial scroll position for use in scroll events
51-
previousScrollPosition = $elm[0].scrollLeft;
51+
previousScrollPosition = gridUtil.normalizeScrollLeft($elm);
5252
}
5353

5454
// Save the contents elm inside the scrollbar elm so it sizes correctly
@@ -154,15 +154,14 @@
154154
previousScrollPosition = newScrollTop;
155155
}
156156
else if ($scope.type === 'horizontal') {
157-
var newScrollLeft = $elm[0].scrollLeft;
157+
// var newScrollLeft = $elm[0].scrollLeft;
158+
var newScrollLeft = gridUtil.normalizeScrollLeft($elm);
158159

159160
var xDiff = previousScrollPosition - newScrollLeft;
160161

161162
var horizScrollLength = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
162163
var horizScrollPercentage = newScrollLeft / horizScrollLength;
163164

164-
$log.debug('horizScrollPercentage', horizScrollPercentage);
165-
166165
var xArgs = {
167166
target: $elm,
168167
x: {
@@ -213,7 +212,8 @@
213212

214213
var newScrollLeft = Math.max(0, args.x.percentage * horizScrollLength);
215214

216-
$elm[0].scrollLeft = newScrollLeft;
215+
// $elm[0].scrollLeft = newScrollLeft;
216+
$elm[0].scrollLeft = gridUtil.denormalizeScrollLeft($elm, newScrollLeft);
217217
}
218218
}
219219
}

src/js/core/directives/ui-grid-render-container.js

+21-6
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@
111111

112112
var scrollWidth = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
113113

114-
var oldScrollLeft = containerCtrl.viewport[0].scrollLeft;
114+
// var oldScrollLeft = containerCtrl.viewport[0].scrollLeft;
115+
var oldScrollLeft = GridUtil.normalizeScrollLeft(containerCtrl.viewport);
115116

116117
var scrollXPercentage;
117118
if (typeof(args.x.percentage) !== 'undefined' && args.x.percentage !== undefined) {
@@ -128,11 +129,14 @@
128129

129130
// uiGridCtrl.adjustScrollHorizontal(newScrollLeft, scrollXPercentage);
130131

131-
containerCtrl.viewport[0].scrollLeft = newScrollLeft;
132+
// containerCtrl.viewport[0].scrollLeft = newScrollLeft;
133+
containerCtrl.viewport[0].scrollLeft = GridUtil.denormalizeScrollLeft(containerCtrl.viewport, newScrollLeft);
134+
132135
containerCtrl.prevScrollLeft = newScrollLeft;
133136

134137
if (containerCtrl.headerViewport) {
135-
containerCtrl.headerViewport.scrollLeft = newScrollLeft;
138+
// containerCtrl.headerViewport.scrollLeft = newScrollLeft;
139+
containerCtrl.headerViewport.scrollLeft = GridUtil.denormalizeScrollLeft(containerCtrl.headerViewport, newScrollLeft);
136140
}
137141

138142
// uiGridCtrl.grid.options.offsetLeft = newScrollLeft;
@@ -165,7 +169,8 @@
165169
var scrollXAmount = newEvent.deltaX * -120;
166170

167171
// Get the scroll percentage
168-
var scrollXPercentage = (containerCtrl.viewport[0].scrollLeft + scrollXAmount) / (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
172+
var scrollLeft = GridUtil.normalizeScrollLeft(containerCtrl.viewport);
173+
var scrollXPercentage = (scrollLeft + scrollXAmount) / (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
169174

170175
// Keep scrollPercentage within the range 0-1.
171176
if (scrollXPercentage < 0) { scrollXPercentage = 0; }
@@ -229,7 +234,12 @@
229234
}
230235

231236
if (!$scope.disableColumnOffset && $scope.colContainer.currentFirstColumn !== 0) {
232-
styles['margin-left'] = $scope.colContainer.columnOffset + 'px';
237+
if ($scope.grid.isRTL()) {
238+
styles['margin-right'] = $scope.colContainer.columnOffset + 'px';
239+
}
240+
else {
241+
styles['margin-left'] = $scope.colContainer.columnOffset + 'px';
242+
}
233243
}
234244

235245
return styles;
@@ -242,7 +252,12 @@
242252
if (index === 0 && $scope.colContainer.currentFirstColumn !== 0) {
243253
var offset = $scope.colContainer.columnOffset;
244254

245-
return { 'margin-left': offset + 'px' };
255+
if ($scope.grid.isRTL()) {
256+
return { 'margin-right': offset + 'px' };
257+
}
258+
else {
259+
return { 'margin-left': offset + 'px' };
260+
}
246261
}
247262
}
248263

src/js/core/directives/ui-grid-viewport.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
(function(){
22
'use strict';
33

4-
angular.module('ui.grid').directive('uiGridViewport', ['$log',
5-
function($log) {
4+
angular.module('ui.grid').directive('uiGridViewport', ['$log', 'gridUtil',
5+
function($log, gridUtil) {
66
return {
77
replace: true,
88
scope: {},
@@ -30,7 +30,10 @@
3030

3131
$elm.on('scroll', function (evt) {
3232
var newScrollTop = $elm[0].scrollTop;
33-
var newScrollLeft = $elm[0].scrollLeft;
33+
// var newScrollLeft = $elm[0].scrollLeft;
34+
var newScrollLeft = gridUtil.normalizeScrollLeft($elm);
35+
36+
// Handle RTL here
3437

3538
if (newScrollLeft !== colContainer.prevScrollLeft) {
3639
var xDiff = newScrollLeft - colContainer.prevScrollLeft;

src/js/core/directives/ui-grid.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,13 @@
242242
$scope.$broadcast(eventName, args);
243243
};
244244

245-
self.innerCompile = function (elm) {
245+
self.innerCompile = function innerCompile(elm) {
246246
$compile(elm)($scope);
247247
};
248+
249+
$scope.grid.isRTL = self.isRTL = function isRTL() {
250+
return $elm.css('direction') === 'rtl';
251+
};
248252
}]);
249253

250254
/**

src/js/core/factories/Grid.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,7 @@ angular.module('ui.grid')
957957
return self.cellValueGetterCache[col.colDef.name](row);
958958
};
959959

960-
// Reset all sorting on the grid
960+
961961
Grid.prototype.getNextColumnSortPriority = function getNextColumnSortPriority() {
962962
var self = this,
963963
p = 0;

src/js/core/factories/GridRenderContainer.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,12 @@ angular.module('ui.grid')
395395
}
396396

397397
if (self.currentFirstColumn !== 0) {
398-
styles['margin-left'] = self.columnOffset + 'px';
398+
if (self.grid.isRTL()) {
399+
styles['margin-right'] = self.columnOffset + 'px';
400+
}
401+
else {
402+
styles['margin-left'] = self.columnOffset + 'px';
403+
}
399404
}
400405

401406
return styles;
@@ -407,7 +412,12 @@ angular.module('ui.grid')
407412
if (index === 0 && self.currentFirstColumn !== 0) {
408413
var offset = self.columnOffset;
409414

410-
return { 'margin-left': offset + 'px' };
415+
if (self.grid.isRTL()) {
416+
return { 'margin-right': offset + 'px' };
417+
}
418+
else {
419+
return { 'margin-left': offset + 'px' };
420+
}
411421
}
412422

413423
return null;

src/js/core/services/ui-grid-util.js

+115
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,121 @@ module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateC
695695
}
696696
};
697697

698+
// http://stackoverflow.com/a/22948274/888165
699+
// TODO: Opera? Mobile?
700+
s.detectBrowser = function detectBrowser() {
701+
var userAgent = $window.navigator.userAgent;
702+
703+
var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer/i};
704+
705+
for (var key in browsers) {
706+
if (browsers[key].test(userAgent)) {
707+
return key;
708+
}
709+
}
710+
711+
return 'unknown';
712+
};
713+
714+
/**
715+
* @ngdoc method
716+
* @name normalizeScrollLeft
717+
* @methodOf ui.grid.service:GridUtil
718+
*
719+
* @param {element} element The element to get the `scrollLeft` from.
720+
*
721+
* @returns {int} A normalized scrollLeft value for the current browser.
722+
*
723+
* @description
724+
* Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method normalizes them
725+
*/
726+
s.normalizeScrollLeft = function normalizeScrollLeft(element) {
727+
if (typeof(element.length) !== 'undefined' && element.length) {
728+
element = element[0];
729+
}
730+
731+
var browser = s.detectBrowser();
732+
733+
var scrollLeft = element.scrollLeft;
734+
735+
var dir = angular.element(element).css('direction');
736+
737+
// IE stays normal in RTL
738+
if (browser === 'ie') {
739+
return scrollLeft;
740+
}
741+
// 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;
742+
else if (browser === 'chrome') {
743+
if (dir === 'rtl') {
744+
// Get the max scroll for the element
745+
var maxScrollLeft = element.scrollWidth - element.clientWidth;
746+
747+
// Subtract the current scroll amount from the max scroll
748+
return maxScrollLeft - scrollLeft;
749+
}
750+
else {
751+
return scrollLeft;
752+
}
753+
}
754+
// Firefox goes negative!
755+
else if (browser === 'firefox') {
756+
return Math.abs(scrollLeft);
757+
}
758+
else {
759+
// TODO(c0bra): Handle other browsers? Android? iOS? Opera?
760+
return scrollLeft;
761+
}
762+
};
763+
764+
/**
765+
* @ngdoc method
766+
* @name normalizeScrollLeft
767+
* @methodOf ui.grid.service:GridUtil
768+
*
769+
* @param {element} element The element to normalize the `scrollLeft` value for
770+
* @param {int} scrollLeft The `scrollLeft` value to denormalize.
771+
*
772+
* @returns {int} A normalized scrollLeft value for the current browser.
773+
*
774+
* @description
775+
* Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method denormalizes a value for the current browser.
776+
*/
777+
s.denormalizeScrollLeft = function denormalizeScrollLeft(element, scrollLeft) {
778+
if (typeof(element.length) !== 'undefined' && element.length) {
779+
element = element[0];
780+
}
781+
782+
var browser = s.detectBrowser();
783+
784+
var dir = angular.element(element).css('direction');
785+
786+
// IE stays normal in RTL
787+
if (browser === 'ie') {
788+
return scrollLeft;
789+
}
790+
// 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;
791+
else if (browser === 'chrome') {
792+
if (dir === 'rtl') {
793+
// Get the max scroll for the element
794+
var maxScrollLeft = element.scrollWidth - element.clientWidth;
795+
796+
// Subtract the current scroll amount from the max scroll
797+
return maxScrollLeft - scrollLeft;
798+
}
799+
else {
800+
return scrollLeft;
801+
}
802+
}
803+
// Firefox goes negative!
804+
else if (browser === 'firefox') {
805+
return scrollLeft * -1;
806+
}
807+
else {
808+
// TODO(c0bra): Handle other browsers? Android? iOS? Opera?
809+
return scrollLeft;
810+
}
811+
};
812+
698813
return s;
699814
}]);
700815

src/templates/ui-grid/ui-grid.html

-38
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,6 @@
55
/* Styles for the grid */
66
}
77

8-
/*.grid{{ grid.id }} .ui-grid-header {
9-
width: {{ grid.getHeaderViewportWidth() }}px;
10-
}*/
11-
12-
/*.grid{{ grid.id }} .ui-grid-header-canvas {
13-
width: {{ grid.getCanvasWidth() }}px;
14-
}*/
15-
16-
/*.grid{{ grid.id }} .ui-grid-body {
17-
height: {{ grid.getBodyHeight() }}px;
18-
}
19-
20-
.grid{{ grid.id }} .ui-grid-viewport {
21-
height: {{ grid.getViewportHeight() }}px;
22-
width: {{ grid.getViewportWidth() }}px;
23-
}
24-
25-
.grid{{ grid.id }} .ui-grid-canvas {
26-
height: {{ grid.getCanvasHeight() }}px;
27-
width: {{ grid.getCanvasWidth() }}px;
28-
}*/
29-
308
.grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {
319
height: {{ grid.options.rowHeight }}px;
3210
}
@@ -35,14 +13,6 @@
3513
border-bottom-width: {{ ((grid.getTotalRowHeight() < grid.getViewportHeight()) && '1') || '0' }}px;
3614
}
3715

38-
/*{{ rowStyles }}
39-
40-
{{ columnStyles }}*/
41-
42-
/*.grid{{ grid.id }} .ui-grid-body .ui-grid-cell:first-child, .grid{{ grid.id }} .ui-grid-header .ui-grid-header-cell:first-child {
43-
margin-left: {{ grid.columnOffset || 0 }}px;
44-
}*/
45-
4616
{{ grid.verticalScrollbarStyles }}
4717
{{ grid.horizontalScrollbarStyles }}
4818

@@ -60,14 +30,6 @@
6030
{{ grid.customStyles }}
6131
</style>
6232

63-
<!-- <div ui-grid-header></div>
64-
65-
<div ui-grid-body>
66-
<div class="ui-grid-no-row-overlay" ng-show="!grid.renderedRows.length">
67-
<span>No Rows</span>
68-
</div>
69-
</div> -->
70-
7133
<div ui-grid-render-container container-id="'body'" col-container-name="'body'" row-container-name="'body'" bind-scroll-horizontal="true" bind-scroll-vertical="true" enable-scrollbars="true"></div>
7234

7335
<div ui-grid-footer></div>

0 commit comments

Comments
 (0)