Right-to-left Support in APEX 5.0

This post contains statements about possible future functionality. These are not official statements. They are speculative, subject to change, and should not be relied upon.

Right-to-left direction support (RTL) was not a stated goal or feature for APEX 5.0. That hasn’t stopped a number of people from asking about it; why no RTL support?, how do I create an app using RTL direction? For someone building an APEX app in a right-to-left language the Universal Theme doesn’t seem very universal.

Although RTL is not a 5.0 feature it doesn’t mean we completely ignored the issue. Here I will describe and demo what can be done today and hint at future possibilities. It isn’t a ready to use solution but should help get you started. We intend to improve RTL support over time including some out of the box capabilities in Universal Theme in a future patch release. Think of what I demo here as a progress report.

A great thing about APEX is that it allows you to create your own HTML templates for many of the building blocks of a web page. This puts you in control of the overall structure of the pages. It is what has made it possible for people to create their own RTL templates and themes. But more and more complex widgets such as menus, trees, or calendars are making a shift from customizable templates to fixed markup that is under the control of a JavaScript widget. This is the only reasonable way to ensure robust, dynamic, usable, accessible UI controls.

I remember way back at the beginning of 5.0, when we were collecting requirements for the new page designer menus, Joel was telling me how people create their own RTL themes but complained about the interactive reports action menu because it didn’t behave correctly (for example sub menus would open on the right rather than the left). This made it very clear to me that where APEX takes control of the markup it also has the responsibility to support RTL direction.

Joel said “if its not too much trouble could you make the new menu support RTL?”. It turns out that it isn’t too much trouble. I’ll start by describing general techniques we used, which may benefit people creating their own widgets or APEX plug-ins.

For all new widgets created for 5.0 that had even a remote chance of being used in customer created apps, now or in the future, we tried to make them direction aware. I believe it is important to make applications that can be used by everyone, which is why I try to learn as much as I can about internationalization, accessibility, and usability. However, I only speak English so if I got any of this direction functionality wrong please let me know.

What does it take to make a widget direction aware? The markup usually remains the same. The direction attribute (for example dir="rtl") is typically put at or near the top of the HTML document and the browser takes care of laying out the document in the specified direction. It is both the behavior and style that needs some adjusting.

The first thing is that the widget has to do is detect the direction and then set a flag or take some action to modify its behavior. Detection is simply a matter of checking the direction style of the widget root element. In a jQuery UI widget that looks like this:


if ( this.element.css("direction") === "rtl" ) {...

This works even when the dir attribute is on a distant ancestor element because the direction property is inherited. Detecting the direction like this means that there is no need for the widget to have a direction option.

All the APEX widgets that are direction aware work this way except for the new calendar, which determines the rtl direction setting from the language. The new APEX calendar is a wrapper around the jQuery FullCalendar plug-in and this is just how that plug-in works. I’m not sure if there is any advantage to tightly associating the direction with the language as the calendar does but since HTML treats language and direction independently it seemed to make the most sense to do the same for the APEX widgets.

I found that the most common impact the direction has on the widget is in keyboard handling (and for good accessibility most complex or composite widgets need keyboard handling). The behavior of the left and right arrow keys needs to be reversed or at least aware of the direction.

The style changes are typically related to properties that have a right and left aspect such as float or border-left, border-right. The direction is not easily detectable with CSS selectors so the widget upon detecting the rtl direction will add class u-RTL to the root element.

For example if the foobar widget has a rule like


.foobar-part {
    float: left;
    …
}

You would add another rule


.u-RTL .foobar-part {
    float: right;
}

That’s all there is to it. The specific needs of each widget are different but that is the general idea.

In APEX 5.0 the widgets that support RTL are: menu, tree view, icon list, splitter, region display selector, and calendar.

To demonstrate how these widgets behave I created a Demo RTL app that you can try or download. I started with a new app using Universal Theme. I switched the navigation to use the top menu since that is the easiest way to show the RTL support in the menu widget. I made use of many of the menu features including shortcut keys to better demonstrate how it handles RTL. Then I created a number of pages to demonstrate the left-to-right behavior. Once they were working I made a copy of each page to do the same thing but in the right-to-left direction.

Because Universal Theme doesn’t yet have support for RTL I created a new page template as a copy of Standard and called it Standard RTL. Only three changes were needed.
I added attribute dir="rtl" to the header element with class t-Header and the div element with class t-Body and added class u-RTL to the body element.

The following shows the changed elements:


<body class="t-PageBody t-PageBody--hideLeft t-PageBody--hideActions no-anim u-RTL #PAGE_CSS_CLASSES#" #ONLOAD# id="t_PageBody">
...
<header class="t-Header" id="t_Header" dir="rtl">
...
<div class="t-Body" dir="rtl">

For each of the RTL pages I changed the page template to Standard RTL. I only updated the Standard template but the same could be done for any of the other page templates. For now this is probably the best option. The plan is that in the future when Universal Theme supports RTL it will use the existing page templates and not introduce a new set of RTL specific page templates.

The reason I didn’t add dir="rtl" to the body is that for some reason doing so causes pop up menus to break.

This change is enough to put most of the widgets into RTL mode. For calendar there is a little trick I used to set the isRTL option without changing the language. See the JavaScript code on page 9 of the demo app for details. But just changing the direction doesn’t magically make everything work because Universal Theme has many styles that are specific to left-to-right. The purpose of adding class u-RTL to the body is so that specific CSS rules can be added to override properties as needed. I only fixed up one thing; the region headings. The rest is left as an exercise for the reader. Or you can wait until Universal Theme supports RTL out of the box. At this point I discovered that the menu widget had a number of style problems in RTL mode. These were regressions introduced late in the development cycle when we made some improvements in the menu markup. So I added CSS to fix those problems.

To add fix up rules I created a file called UT_RTL_fixup.css and uploaded it under Static Application Files. Then added it to Cascading Style Sheets File URLs on the User Interface Details for the Desktop UI. I did this so that I didn’t have to unsubscribe the theme. This will make it easier to refresh the theme later. If you were creating your own theme you would add this file to the theme CSS files or simply include the rules with all the rest of the theme CSS.


/* Fix up some UT and APEX RTL styles */
/* UT region headings */
.u-RTL .t-Region-headerItems--title {
    text-align: right;
}
/* UT nav menu bar */
.u-RTL .t-Header .a-MenuBar-item {
    float: right;
}
/* Menu fixes */
.u-RTL .a-Menu-labelContainer {
    float: right;
    margin-left: 20px;
    margin-right: 0;
    text-align: right;
}

.u-RTL .a-Menu .a-Menu-item a, .u-RTL .a-Menu .a-Menu-item a:hover,
.u-RTL .a-Menu .a-Menu-item a:active, .u-RTL .a-Menu .a-Menu-item a:visited,
.u-RTL .a-Menu .a-Menu-item label, .u-RTL .a-Menu .a-Menu-label {
    padding: 0 0 0 12px;
}

.u-RTL .a-Menu-accelContainer {
    float: left;
    margin-left: 0;
    margin-right: -20px;
    text-align: left;
}

Interactive Reports are included in the demo because they include menus. The Action and search menus use the menu widget and they work fine in RTL direction. Notice that the column heading pop ups are not menus and they are not in the desired RTL direction. Neither are any of the IR dialogs. Clearly there is more work to be done here. A little custom CSS and JavaScript could probably fix most problems but I didn’t go any further at this point.

I previously introduced the icon list widget including an example using it in the RTL direction. I included icon list in this demo as well on the Region Display Selector page.

The most complex page is the Split Page that demonstrates the splitter widget. Like the icon list the splitter widget is undocumented and unsupported. I have not yet described how to use the splitter. This page uses a special page template with LTR and RTL versions and some JavaScript initialization code. I was trying to push the limits of what can be done by putting fixed size pages, splitter, and multiple resizable interactive reports with fixed headers all together. These pages have a few issues. The point is that, as you can see, the splitter widget is direction aware.

The tree widget is direction aware and I previously mentioned that it is used for side navigation menu. I did not include an example of side navigation in this RTL demo because as you can probably tell the tree is customized with CSS to look different when used for side navigation. In addition the collapsible column that the tree is in has its own code and style that would need to be updated. I am not familiar enough with the side navigation to attempt getting it to work for this demo.

If you are creating a right-to-left theme I hope this has provided you with helpful information. If you have been patiently waiting for RTL support in APEX I hope this has demonstrated some good faith effort on our part.

3 thoughts on “Right-to-left Support in APEX 5.0

  1. Hi John,
    What about JS dynamic positioning in Interactive Report.
    We want to show popup regions (for example download popup region) in right side! may you explain about it?
    Best Regards
    Mahdi

  2. Hi John,
    Nice post, something to be considered in the new patch that, we need to switch from LTR to RTL and vise versa, many application are not only RTL, they are basically LTR and customers asked for translation to RTL, so you can’t change the template for the page on the fly and surely you don’t want to create two pages with different templates for the same function.
    Regards
    Omar

Comments are closed.