Bladeren bron

Merge pull request #240 from threema-ch/issue-239

Right-to-left support
Danilo Bargen 8 jaren geleden
bovenliggende
commit
a62c89b194
1 gewijzigde bestanden met toevoegingen van 48 en 29 verwijderingen
  1. 48 29
      src/directives/compose_area.ts

+ 48 - 29
src/directives/compose_area.ts

@@ -120,28 +120,36 @@ export default [
                 function submitText(): Promise<any> {
                     let text = '';
 
-                    // Extract text
-                    // tslint:disable-next-line: prefer-for-of (see #98)
-                    for (let i = 0; i < composeDiv[0].childNodes.length; i++) {
-                        const node = composeDiv[0].childNodes[i];
-                        switch (node.nodeType) {
-                            case Node.TEXT_NODE:
-                                // Append text, but strip leading and trailing newlines
-                                text += node.nodeValue.replace(/(^[\r\n]*|[\r\n]*$)/g, '');
-                                break;
-                            case Node.ELEMENT_NODE:
-                                const tag = node.tagName.toLowerCase();
-                                if (tag === 'img') {
-                                    text += node.alt;
-                                    break;
-                                } else if (tag === 'br') {
-                                    text += '\n';
+                    // Process a DOM node recursively and extract text.
+                    const visitChildNodes = (parentNode: HTMLElement) => {
+                        // tslint:disable-next-line: prefer-for-of (see #98)
+                        for (let i = 0; i < parentNode.childNodes.length; i++) {
+                            const node = parentNode.childNodes[i] as HTMLElement;
+                            switch (node.nodeType) {
+                                case Node.TEXT_NODE:
+                                    // Append text, but strip leading and trailing newlines
+                                    text += node.nodeValue.replace(/(^[\r\n]*|[\r\n]*$)/g, '');
                                     break;
-                                }
-                            default:
-                                $log.warn(logTag, 'Unhandled node:', node);
+                                case Node.ELEMENT_NODE:
+                                    const tag = node.tagName.toLowerCase();
+                                    if (tag === 'div') {
+                                        visitChildNodes(node);
+                                        break;
+                                    } else if (tag === 'img') {
+                                        text += (node as HTMLImageElement).alt;
+                                        break;
+                                    } else if (tag === 'br') {
+                                        text += '\n';
+                                        break;
+                                    }
+                                default:
+                                    $log.warn(logTag, 'Unhandled node:', node);
+                            }
                         }
-                    }
+                    };
+
+                    // Extract text
+                    visitChildNodes(composeDiv[0]);
 
                     return new Promise((resolve, reject) => {
                         let submitTexts = (strings: string[]) => {
@@ -194,7 +202,7 @@ export default [
                             updateView();
                         }).catch(() => {
                             // do nothing
-                            this.$log.warn('failed to submit text');
+                            $log.warn(logTag, 'Failed to submit text');
                         });
 
                         return true;
@@ -427,11 +435,20 @@ export default [
                     const emoji = this.textContent; // Unicode character
                     const formatted = ($filter('emojify') as any)(emoji, true, true);
 
-                    // Firefox inserts a <br> after editing content editable fields.
-                    // Remove the last <br> to fix this.
+                    // In Chrome in right-to-left mode, our content editable
+                    // area may contain a DIV element.
+                    const nestedDiv = composeDiv[0].childNodes.length === 1
+                        && composeDiv[0].childNodes[0].tagName.toLowerCase() === 'div';
+                    let contentElement;
+                    if (nestedDiv === true) {
+                        contentElement = composeDiv[0].childNodes[0];
+                    } else {
+                        contentElement = composeDiv[0];
+                    }
+
                     let currentHTML = '';
-                    for (let i = 0; i < composeDiv[0].childNodes.length; i++) {
-                        const node = composeDiv[0].childNodes[i];
+                    for (let i = 0; i < contentElement.childNodes.length; i++) {
+                        const node = contentElement.childNodes[i];
 
                         if (node.nodeType === node.TEXT_NODE) {
                             currentHTML += node.textContent;
@@ -440,8 +457,9 @@ export default [
                             if (tag === 'img') {
                                 currentHTML += getOuterHtml(node);
                             } else if (tag === 'br') {
-                                // not not append br if the br is the LAST element
-                                if (i < composeDiv[0].childNodes.length - 1) {
+                                // Firefox inserts a <br> after editing content editable fields.
+                                // Remove the last <br> to fix this.
+                                if (i < contentElement.childNodes.length - 1) {
                                     currentHTML += getOuterHtml(node);
                                 }
                             }
@@ -465,7 +483,7 @@ export default [
                         };
                     }
 
-                    composeDiv[0].innerHTML = currentHTML;
+                    contentElement.innerHTML = currentHTML;
                     cleanupComposeContent();
                     setCaretPosition(caretPosition.from);
 
@@ -550,7 +568,7 @@ export default [
                     return pos;
                 }
 
-                // define position of caret
+                // Update the current caret position or selection
                 function updateCaretPosition() {
                     caretPosition = null;
                     if (window.getSelection && composeDiv[0].innerHTML.length > 0) {
@@ -615,6 +633,7 @@ export default [
                 composeDiv.on('keydown', onTyping);
                 composeDiv.on('keyup mouseup', updateCaretPosition);
                 composeDiv.on('selectionchange', updateCaretPosition);
+
                 // When switching chat, send stopTyping message
                 scope.$on('$destroy', scope.stopTyping);