Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit bc7833b

Browse files
marosoftjelbourn
authored andcommitted
fix(rtl): support applying dir="rtl" on DOM elements other than the body (#11579)
Create a single function to check text direction based on dir attribute on DOM element or document. Fixes #11016 Fixes #9754
1 parent 0077d3e commit bc7833b

File tree

7 files changed

+38
-14
lines changed

7 files changed

+38
-14
lines changed

src/components/gridList/grid-list.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ angular.module('material.components.gridList', ['material.core'])
9393
* </md-grid-list>
9494
* </hljs>
9595
*/
96-
function GridListDirective($interpolate, $mdConstant, $mdGridLayout, $mdMedia) {
96+
function GridListDirective($interpolate, $mdConstant, $mdGridLayout, $mdMedia, $mdUtil) {
9797
return {
9898
restrict: 'E',
9999
controller: GridListController,
@@ -270,8 +270,7 @@ function GridListDirective($interpolate, $mdConstant, $mdGridLayout, $mdMedia) {
270270

271271
// The width and horizontal position of each tile is always calculated the same way, but the
272272
// height and vertical position depends on the rowMode.
273-
var ltr = document.dir != 'rtl' && document.body.dir != 'rtl';
274-
var style = ltr ? {
273+
var style = (!$mdUtil.isRtl(attrs)) ? {
275274
left: POSITION({ unit: hUnit, offset: position.col, gutter: gutter }),
276275
width: DIMENSION({ unit: hUnit, span: spans.col, gutter: gutter }),
277276
// resets

src/components/menu/js/menuServiceProvider.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ function MenuProvider($$interimElementProvider) {
494494
throw new Error('Invalid target mode "' + positionMode.top + '" specified for md-menu on Y axis.');
495495
}
496496

497-
var rtl = ($mdUtil.bidi() === 'rtl');
497+
var rtl = $mdUtil.isRtl(el);
498498

499499
switch (positionMode.left) {
500500
case 'target':

src/components/panel/panel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2541,7 +2541,7 @@ function MdPanelPosition($injector) {
25412541
this._$window = $injector.get('$window');
25422542

25432543
/** @private {boolean} */
2544-
this._isRTL = $injector.get('$mdUtil').bidi() === 'rtl';
2544+
this._isRTL = $injector.get('$mdUtil').isRtl();
25452545

25462546
/** @private @const {!angular.$mdConstant} */
25472547
this._$mdConstant = $injector.get('$mdConstant');

src/components/slider/slider.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ function SliderDirective($$rAF, $window, $mdAria, $mdUtil, $mdConstant, $mdThemi
647647
var size = vertical ? sliderDimensions.height : sliderDimensions.width;
648648
var calc = (position - offset) / size;
649649

650-
if (!vertical && $mdUtil.bidi() === 'rtl') {
650+
if (!vertical && $mdUtil.isRtl(attr)) {
651651
calc = 1 - calc;
652652
}
653653

src/components/tabs/js/tabsController.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,6 @@ function MdTabsController ($scope, $element, $window, $mdConstant, $mdTabInkRipp
962962
}
963963

964964
function isRtl() {
965-
return ($mdUtil.bidi() === 'rtl');
965+
return $mdUtil.isRtl($attrs);
966966
}
967967
}

src/components/virtualRepeat/virtual-repeater.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ function VirtualRepeatContainerController($$rAF, $mdUtil, $mdConstant, $parse, $
125125
this.oldElementSize = null;
126126
/** @type {!number} Maximum amount of pixels allowed for a single DOM element */
127127
this.maxElementPixels = $mdConstant.ELEMENT_MAX_PIXELS;
128+
/** @type {string} Direction of the text */
129+
this.ltr = !$mdUtil.isRtl(this.$attrs);
128130

129131
if (this.$attrs.mdTopIndex) {
130132
/** @type {function(angular.Scope): number} Binds to topIndex on AngularJS scope */
@@ -385,13 +387,12 @@ VirtualRepeatContainerController.prototype.resetScroll = function() {
385387

386388

387389
VirtualRepeatContainerController.prototype.handleScroll_ = function() {
388-
var ltr = document.dir !== 'rtl' && document.body.dir !== 'rtl';
389-
if (!ltr && !this.maxSize) {
390+
if (!this.ltr && !this.maxSize) {
390391
this.scroller.scrollLeft = this.scrollSize;
391392
this.maxSize = this.scroller.scrollLeft;
392393
}
393394
var offset = this.isHorizontal() ?
394-
(ltr?this.scroller.scrollLeft : this.maxSize - this.scroller.scrollLeft)
395+
(this.ltr ? this.scroller.scrollLeft : this.maxSize - this.scroller.scrollLeft)
395396
: this.scroller.scrollTop;
396397
if (this.scrollSize < this.size) return;
397398
if (offset > this.scrollSize - this.size) {
@@ -405,7 +406,7 @@ VirtualRepeatContainerController.prototype.handleScroll_ = function() {
405406
var numItems = Math.max(0, Math.floor(offset / itemSize) - NUM_EXTRA);
406407

407408
var transform = (this.isHorizontal() ? 'translateX(' : 'translateY(') +
408-
(!this.isHorizontal() || ltr ? (numItems * itemSize) : - (numItems * itemSize)) + 'px)';
409+
(!this.isHorizontal() || this.ltr ? (numItems * itemSize) : - (numItems * itemSize)) + 'px)';
409410

410411
this.scrollOffset = offset;
411412
this.offsetter.style.webkitTransform = transform;

src/core/util/util.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,36 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
8989
return $options.getOption ? $options.getOption(optionName) : $options[optionName];
9090
},
9191

92+
/**
93+
* Determines the current 'dir'ectional value based on the value of 'dir'
94+
* attribute of the element. If that is not defined, it will try to use
95+
* a 'dir' attribute of the body or html tag.
96+
*
97+
* @param {Object=} attrs a hash object with key-value pairs of normalized
98+
* attribute names and their corresponding attribute values.
99+
* @returns {boolean} true if the element's passed in attributes,
100+
* the document, or the body indicates RTL mode, false otherwise.
101+
*/
102+
isRtl: function(attrs) {
103+
var dir = angular.isDefined(attrs) && attrs.hasOwnProperty('dir') && attrs.dir;
104+
105+
switch (dir) {
106+
case 'ltr':
107+
return false;
108+
109+
case 'rtl':
110+
return true;
111+
}
112+
113+
return ($document[0].dir === 'rtl' || $document[0].body.dir === 'rtl');
114+
},
115+
92116
/**
93117
* Bi-directional accessor/mutator used to easily update an element's
94118
* property based on the current 'dir'ectional value.
95119
*/
96-
bidi : function(element, property, lValue, rValue) {
97-
var ltr = !($document[0].dir == 'rtl' || $document[0].body.dir == 'rtl');
120+
bidi: function(element, property, lValue, rValue) {
121+
var ltr = !this.isRtl();
98122

99123
// If accessor
100124
if (arguments.length == 0) return ltr ? 'ltr' : 'rtl';
@@ -111,7 +135,7 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
111135
},
112136

113137
bidiProperty: function (element, lProperty, rProperty, value) {
114-
var ltr = !($document[0].dir == 'rtl' || $document[0].body.dir == 'rtl');
138+
var ltr = !this.isRtl();
115139

116140
var elem = angular.element(element);
117141

0 commit comments

Comments
 (0)