mobile/android/chrome/content/Linkify.js

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 const LINKIFY_TIMEOUT = 0;
     7 function Linkifier() {
     8   this._linkifyTimer = null;
     9   this._phoneRegex = /(?:\s|^)[\+]?(\(?\d{1,8}\)?)?([- ]+\(?\d{1,8}\)?)+( ?(x|ext) ?\d{1,3})?(?:\s|$)/g;
    10 }
    12 Linkifier.prototype = {
    13   _buildAnchor : function(aDoc, aNumberText) {
    14     let anchorNode = aDoc.createElement("a");
    15     let cleanedText = "";
    16     for (let i = 0; i < aNumberText.length; i++) {
    17       let c = aNumberText.charAt(i);
    18       if ((c >= '0' && c <= '9') || c == '+')  //assuming there is only the leading '+'.
    19         cleanedText += c;
    20     }
    21     anchorNode.setAttribute("href", "tel:" + cleanedText);
    22     let nodeText = aDoc.createTextNode(aNumberText);
    23     anchorNode.appendChild(nodeText);
    24     return anchorNode;
    25   },
    27   _linkifyNodeNumbers : function(aNodeToProcess, aDoc) {
    28     let parent = aNodeToProcess.parentNode;
    29     let nodeText = aNodeToProcess.nodeValue;
    31     // Replacing the original text node with a sequence of
    32     // |text before number|anchor with number|text after number nodes.
    33     // Each step a couple of (optional) text node and anchor node are appended.
    34     let anchorNode = null;
    35     let m = null;
    36     let startIndex = 0;
    37     let prevNode = null;
    38     while (m = this._phoneRegex.exec(nodeText)) {
    39       anchorNode = this._buildAnchor(aDoc, nodeText.substr(m.index, m[0].length));
    41       let textExistsBeforeNumber = (m.index > startIndex);
    42       let nodeToAdd = null;
    43       if (textExistsBeforeNumber)
    44         nodeToAdd = aDoc.createTextNode(nodeText.substr(startIndex, m.index - startIndex));
    45       else
    46         nodeToAdd = anchorNode;
    48       if (!prevNode) // first time, need to replace the whole node with the first new one.
    49         parent.replaceChild(nodeToAdd, aNodeToProcess);
    50       else
    51         parent.insertBefore(nodeToAdd, prevNode.nextSibling); //inserts after.
    53       if (textExistsBeforeNumber) // if we added the text node before the anchor, we still need to add the anchor node.
    54         parent.insertBefore(anchorNode, nodeToAdd.nextSibling);
    56       // next nodes need to be appended to this node.
    57       prevNode = anchorNode; 
    58       startIndex = m.index + m[0].length;
    59     }
    61     // if some text is remaining after the last anchor.
    62     if (startIndex > 0 && startIndex < nodeText.length) {
    63       let lastNode = aDoc.createTextNode(nodeText.substr(startIndex));
    64       parent.insertBefore(lastNode, prevNode.nextSibling);
    65       return lastNode;
    66     }
    67     return anchorNode;
    68   },
    70   linkifyNumbers: function(aDoc) {
    71     // Removing any installed timer in case the page has changed and a previous timer is still running.
    72     if (this._linkifyTimer) {
    73       clearTimeout(this._linkifyTimer);
    74       this._linkifyTimer = null;
    75     }
    77     let filterNode = function (node) {
    78       if (node.parentNode.tagName != 'A' &&
    79          node.parentNode.tagName != 'SCRIPT' &&
    80          node.parentNode.tagName != 'NOSCRIPT' &&
    81          node.parentNode.tagName != 'STYLE' &&
    82          node.parentNode.tagName != 'APPLET' &&
    83          node.parentNode.tagName != 'TEXTAREA')
    84         return NodeFilter.FILTER_ACCEPT;
    85       else
    86         return NodeFilter.FILTER_REJECT;
    87     }
    89     let nodeWalker = aDoc.createTreeWalker(aDoc.body, NodeFilter.SHOW_TEXT, filterNode, false);
    90     let parseNode = function() {
    91       let node = nodeWalker.nextNode();
    92       if (!node) {
    93         this._linkifyTimer = null;
    94         return;
    95       }
    96       let lastAddedNode = this._linkifyNodeNumbers(node, aDoc);
    97       // we assign a different timeout whether the node was processed or not.
    98       if (lastAddedNode) {
    99         nodeWalker.currentNode = lastAddedNode;
   100         this._linkifyTimer = setTimeout(parseNode, LINKIFY_TIMEOUT);
   101       } else {
   102         this._linkifyTimer = setTimeout(parseNode, LINKIFY_TIMEOUT);
   103       }
   104     }.bind(this);
   106     this._linkifyTimer = setTimeout(parseNode, LINKIFY_TIMEOUT); 
   107   }
   108 };

mercurial