The Issues of Coordinate Systems (or: Mirroring XY, Oh My!)

Coordinates and Mirroring, Oh My!

I’ve spent a lot of my Physics education dealing with calculations. Calculating positions of objects as they move in space, particles in some electric field, planets around a certain star, and more, more and some more. In Physics, Mathematics is the language we use to represent reality, perform predictions, and validate them.

So it was only natural that when I deal with flips and mirroring when it comes to Right-to-Left vs. Left-to-Right support, I expected to handle these with ease. After all, after transforming relative frames and different types of physical field coordinates to one another, what’s transforming cartesian to mirror-cartesian?

Well, apparently it’s something.

Computer Coordinate System

Computer software, and especially web-based content, is originally meant to be read in English; left to right, top to bottom. When an application loads on any screen, it isn’t necessarily clear what the size of the visible content would be, especially with the advent of mobile devices of all shapes and sizes.

It makes sense, then, to start your coordinate system origin at the top-left corner, where the page begins to load, and go onwards from there — to the right, and to the bottom. So, going right on the axis increases X, and going down from the axis increases Y.

It makes perfect sense for computers to behave this way. Really. I get it. So.. what’s the problem, you ask?

The Problem

Eh. This difference between +y and -y makes using real-life calculation inside computer applications all that much more complicated. Whenever we deal with mathematics in physics and in the real world, we take our coordinate system as starting from the bottom-left corner. That means that going right on the origin increases the value of X, and going up from the origin increases the value of Y.

That’s exactly a horizontal mirror of what Computers expect.

This can be handled by flipping the value of y, of course ,but it is still the source of many a-frustrations, especially when programming applications that invlove physical formulas, the more elaborate the more complicated to keep track of. Also, this makes multiplications and additions — and the calculation of vector combinations – rather annoying.

But the issue becomes even more elaborate when we deal with complex positioning of elements that are nested in one another or are dynamically positioned. Not only do we need to deal with a flipped y, we also need to deal with dynamic calculations involving relative positioning.

Practical vs Conceptual

This problem of the flipped y axis is more an annoyance than an actual practical issue. Even if we deal with position calculations purely mathematically, there are ways to convert the Real World coordinates into computer-driven coordinates with some (quite basic) transformation function that mirrors the y’ values.

The main problem, though, is conceptual.

For example, when I work on improving RTL support in the new Visual Editor in MediaWiki, part of the issues I deal with are the locations of popups. The locations for these popups are often calculated dynamically, depending on where your marker is located.

You would think that this won’t cause any problem to an RTL content. After all, the x=10 position is still x=10 even in an RTL language. Whatever positions are calculated should remain in place even if the directionality of the page changed.

Not quite.

Relative Positioning

HTML elements are often relatively placed, especially when they’re nested inside other elements. For example, consider this HTML snippet:

<div id="master" style="position: absolute; width: 150px; height: 70px; left:0px;">
	Blah Blah Blah
   <div id="child" style=" position: relative; width: 50px; height: 50px; left: 150px;">Box</div>

Aligned Left

The ‘child’ div is nested inside its ‘master’ div. The master is pushed all the way to the left, since it has “left=0” style value. The child has ‘left=150’, which would mean that the actual position of the child (assuming no other margins or any other parent positioning) is 150px from the left edge.

However, consider this:

<div id="master" style="position: absolute; width: 150px; height: 70px; right:0px;">
	Blah Blah Blah
   <div id="child" style=" position: relative; width: 50px; height: 50px; left: 150px;">Box</div>

Aligned Right

Now the parent div is pushed all the way to the right of the screen, because of its “right:0” style. But the child div is still placed 150px from the left — this time, however, since it’s placed 150px to the left of its parent, it would be aaaaaaaaaaaall the way to the right +150px – essentially outside the screen.

Of course ,you can correct some of those problems with relative positioning, but relative positioning isn’t always what you need or want. And in the case of VisualEditor, many of the elements are surrounded by multiple other <div> elements that have their own calculated position values relative to the marker and the rest of the text. That’s on purpose, and it shoud stay this way.

Directionality Switching

So, why is the above example so important? Here’s why: When you switch content between LTR to RTL, you switch the directionality of the page. The ‘left’ style in the ‘master’ div above often has to be changed to ‘right’ so logical positions of text and buttons work out. Or, if you use something like CSSJanus, it may change automatically.

Example Bug: Visual Editor Link Popup in RTL

One of the bugs that I am trying to tackle in VisualEditor right now is the problem of the missing popup link in RTL wikis. If you edit an article and insert a link in LTR wiki (like English) a little popup will materialize, allowing you to change the target of the link and choose whether it is external or Wiki-Internal. Very cool and very useful.

In RTL, however, that link doesn’t pop up. It was fairly clear from the get-go that this is a CSS issue, some positioning problem that occurs when the page is “flipped” right-to-left instead of left-to-right — and, indeed, that is the case. While the parent’s position (defined in a CSS class) was flipped to be “right:0” in RTL, the popup itself still had a dynamically calculated “left” value. This conflict essentially put the entire popup at the outside of the screen.

The solution involved a simple change of popup direction style to the right, and recalculation of the distance from the new origin (right instead of left). Recalculating right to left when the marker is concerned is relatively easy. It looks something like this:

// Pseudocode:
if (langauge == 'rtl') {
   popup.right = window.innerWidth - popup.left;
   popup.left = '';

That solved the issue of the main popup, but it didn’t solve the issue of the subpopup. In VisualEditor, the link inspector is comprised of two popups: The main one involving the input in which you can enter your target page (inside the wiki or external http url) and a sub-popup that includes a list of suggestions.

Both popups have dynamically calculated values to the “left” in the LTR version. Both were changed to the ‘right’ with the above pseudocode. But what fixed the main popup, didn’t fix the sub-popup.

The sub popup appeared skewed, almost at the right place but not entirely, mocking me with its imperfect positioning.

Link popup and its suggestions sub-popup

Link popup and its suggestions sub-popup after RTL fix. It appears — but not quite right

The Solution

It took me a while (and some gentle coaxing from my mentors) to realize what was happening, and when I did, it seemed rather obvious.

The main popup calculates its position in relation to the marker, and the sub-popup calculates its position in relation to the first popup — both popups are inside a parent div that is, also, dynamically placed.

The mirroring should not be calculated in relation to the entire screen, because the positions (left or right) are set in relation to whatever container div holds the popups and not in relation to the entire screen.

The only reason I didn’t notice this fact with the main popup is that its skew’yness wasn’t all that evident, it appeared a little to the right but still inside the selected word. But when the second popup is misaligned, it’s noticeable.

The mirroring should be done in relation to whatever container holds the popup, and not assume that the position is mirrored across the entire screen.

The new code, then, is something like this:

// Pseudocode:
if (langauge == 'rtl') {
   popup.right = parentContainer.innerWidth - popup.left;
   popup.left = '';

And here’s the visual result:

Much better!

Much better!

The RTL/LTR Vertigo

Regardless of the actual solution, this problem raised an important issue: LTR to RTL switches can involve some dynamic calculations that may be somewhat messy, and when we switch the directionality of an entire page, some elements in it may flip (those who have CSS classes, mostly) and some may not (those who have dynamically calculated positions that are injected inline).

That means that examining the code and trying to calculate the transformation of the mirroring can be a truly confusing experience, one that I hereby name “The LTR/RTL Vertigo“.

Some elements flip, some don’t, some values require change, some don’t, some are relative to their parents and some relative to a grand-parent or the content box itself. And then, of course, there’s the fact that the x/y axis are the mirror of what I am used to from my Physics background. Did I say Vertigo already?

But don’t worry, this condition is mostly harmless, mostly temporary, and is mostly solved with a quick break from the screen and exposure to the summer sun to remind oneself that there is, in fact, a world out there.


So, until next time – Beware the RTL/LTR Vertigo, think of relative positioning, calculate your math mirrored, and go outside a little. It’s actually kinda nice.




Tags: , ,

Trackback from your site.