Bug 1346085 - Part 3: RTL support for date/time input box. r?mossop, gandalf draft
authorJessica Jong <jjong@mozilla.com>
Wed, 05 Apr 2017 15:02:37 +0800
changeset 556021 271c033f1655bad80e4f08a455d2df5a070ccc10
parent 556020 1e115b7276b7cdb6103123396b9fdb9cbe2874a9
child 622760 d19e0a7a55b3875e973cc186753d3e95c60803c5
push id52407
push userjjong@mozilla.com
push dateWed, 05 Apr 2017 08:14:48 +0000
reviewersmossop, gandalf
bugs1346085
milestone55.0a1
Bug 1346085 - Part 3: RTL support for date/time input box. r?mossop, gandalf Set the .dir property of the input box wrapper to `rtl` if this is a RTL locale. MozReview-Commit-ID: D2qJVjvzxNW
toolkit/content/widgets/datetimebox.xml
--- a/toolkit/content/widgets/datetimebox.xml
+++ b/toolkit/content/widgets/datetimebox.xml
@@ -84,21 +84,18 @@
                 break;
               case "month":
                 fragment.appendChild(this.mMonthField);
                 break;
               case "day":
                 fragment.appendChild(this.mDayField);
                 break;
               default:
-                // Remove bidirectional formatting characters, we'll handle
-                // directions on our own.
-                let value = this.stripDirFormattingChars(part.value);
                 let span = document.createElementNS(HTML_NS, "span");
-                span.textContent = value;
+                span.textContent = part.value;
                 fragment.appendChild(span);
                 break;
             }
           });
 
           root.appendChild(fragment);
         ]]>
         </body>
@@ -595,21 +592,18 @@
                   fragment.appendChild(span);
                   fragment.appendChild(this.mMillisecField);
                 }
                 break;
               case "dayPeriod":
                 fragment.appendChild(this.mDayPeriodField);
                 break;
               default:
-                // Remove bidirectional formatting characters, we'll handle
-                // directions on our own.
-                let value = this.stripDirFormattingChars(part.value);
                 let span = document.createElementNS(HTML_NS, "span");
-                span.textContent = value;
+                span.textContent = part.value;
                 fragment.appendChild(span);
                 break;
             }
           });
 
           root.appendChild(fragment);
         ]]>
         </body>
@@ -1085,17 +1079,17 @@
   <binding id="datetime-input-base">
     <resources>
       <stylesheet src="chrome://global/content/textbox.css"/>
       <stylesheet src="chrome://global/skin/textbox.css"/>
       <stylesheet src="chrome://global/content/bindings/datetimebox.css"/>
     </resources>
 
     <content>
-      <html:div class="datetime-input-box-wrapper"
+      <html:div class="datetime-input-box-wrapper" anonid="input-box-wrapper"
                 xbl:inherits="context,disabled,readonly">
         <html:span class="datetime-input-edit-wrapper"
                    anonid="edit-wrapper">
           <!-- Each of the date/time input types will append their input child
              - elements here -->
         </html:span>
 
         <html:button class="datetime-reset-button" anonid="reset-button"
@@ -1105,16 +1099,30 @@
 
     <implementation implements="nsIDateTimeInputArea">
       <constructor>
       <![CDATA[
         this.DEBUG = false;
         this.mInputElement = this.parentNode;
         this.mLocales = window.getAppLocalesAsBCP47();
 
+        this.mIsRTL = false;
+        let intlUtils = window.intlUtils;
+        if (intlUtils) {
+          this.mIsRTL =
+            intlUtils.getLocaleInfo(this.mLocales).direction === "rtl";
+        }
+
+        if (this.mIsRTL) {
+          let inputBoxWrapper =
+            document.getAnonymousElementByAttribute(this, "anonid",
+                                                    "input-box-wrapper");
+          inputBoxWrapper.dir = "rtl";
+        }
+
         this.mMin = this.mInputElement.min;
         this.mMax = this.mInputElement.max;
         this.mStep = this.mInputElement.step;
         this.mIsPickerOpen = false;
 
         this.mResetButton =
           document.getAnonymousElementByAttribute(this, "anonid", "reset-button");
         this.mResetButton.style.visibility = "hidden";
@@ -1201,16 +1209,23 @@
             // Used to store the non-formatted number, clered when value is
             // cleared.
             field.setAttribute("rawValue", "");
             // Minimum digits to display, padded with leading 0s.
             field.setAttribute("mindigits", aMinDigits);
             // Maximum length for the field, will be advance to the next field
             // automatically if exceeded.
             field.setAttribute("maxlength", aMaxLength);
+
+            if (this.mIsRTL) {
+              // Override the numeric field with "ltr", so that it stays in the
+              // same order even when it's empty (with placeholder).
+              field.style.unicodeBidi = "bidi-override";
+              field.style.direction = "ltr";
+            }
           }
 
           return field;
         ]]>
         </body>
       </method>
 
       <method name="updateResetButtonVisibility">
@@ -1398,30 +1413,16 @@
 
       <method name="isEmpty">
         <parameter name="aValue"/>
         <body>
           return (aValue == undefined || 0 === aValue.length);
         </body>
       </method>
 
-      <method name="stripDirFormattingChars">
-        <parameter name="aString"/>
-        <body>
-        <![CDATA[
-          // Strip bidirectional formatting characters.
-          // http://www.unicode.org/reports/tr9/#Directional_Formatting_Characters
-          let str = aString.replace(
-            /[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g, "");
-
-          return str;
-        ]]>
-        </body>
-      </method>
-
       <method name="getFieldValue">
         <parameter name="aField"/>
         <body>
         <![CDATA[
           if (!aField || !aField.classList.contains("numeric")) {
             return undefined;
           }