简体   繁体   中英

How to get JavaScript running properly on mobile phones?

( http://www.learnwithjesse.com/white-hmong-to-green-hmong-converter/ ).

I have JavaScript that utilizes two HTML <textarea> elements, one for input values and one for output values. Input values are converted a different word and is outputted to the output box. For example, if I type in the word 'daj' in the input box and click on the convert button, it should output the converted word 'dlaaj' to the output box. It works fine in Chrome, Firefox, and Internet Explorer, but not on my Galaxy S5 Active; it outputs the same word I put in the input box. 'daj' still outputs 'daj' .

What I've tried so far: I've tried running on different phones, iPhone5, it doesn't output correctly. I've tried running the script on http://mobiletest.me which makes my computer act like mobile phone using Galaxy S5 and it runs properly.

How can I get it to output properly on mobile phones?

<p class="welcome" id="greeting">White Hmong to Green Hmong Converter</p>
<p class="content">
</p>

<form>
<input type="button" value="Convert White Hmong to Green Hmong" onClick="clicked(0)" /><input type="button" value="Converter Green Hmong to White Hmong" onClick="clicked(1)" />
<br>
<br>
<textarea rows="7" cols="68" id="whiteHmongInput" >
Input</textarea>
<br>
<br>
<textarea rows="7" cols="68" id="greenHmongInput" >
Output</textarea>
</form>


<script>

function clicked(number) {

  var n = -1;
  var list = [];
  var list2 = [];
  var NUMBERWORDS = 90;

  list[0] ="cab";
  list[1] ="cia";
  list[2] ="dab";
  list[3] ="daj";
  list[4] ="dej";
  list[5] ="dev";
  list[6] ="dib";
  list[7] ="duab";
  list[8] ="fiav";
  list[9] ="hais";
  list[10] ="hla";
  list[11] ="hlab";
  list[12] ="hlad";
  list[13] ="hmaim";
  list[14] ="hmaiv";
  list[15] ="hmaj";
  list[16] ="hmaiv";
  list[17] ="hmob";
  list[18] ="hmog";
  list[19] ="hmoo";
  list[20] ="hmoob";
  list[21] ="hmood";
  list[22] ="hmoog";
  list[23] ="hmoov";
  list[24] ="hmos";
  list[25] ="hmov";
  list[26] ="hnas";
  list[27] ="hnais";
  list[28] ="hneev";
  list[29] ="hnyab";
  list[30] ="hnov";
  list[31] ="iav";
  list[32] ="kos";
  list[33] ="liab";
  list[34] ="liaj";
  list[35] ="liam";
  list[36] ="loos";
  list[37] ="los";
  list[38] ="mloos";
  list[39] ="mus";
  list[40] ="npib";
  list[41] ="nqhaiv";
  list[42] ="nyaiv";
  list[43] ="pa";
  list[44] ="pab";
  list[45] ="pad";
  list[46] ="pag";
  list[47] ="pam";
  list[48] ="piam";
  list[49] ="piav";
  list[50] ="qaib";
  list[51] ="rhiam";
  list[52] ="siab";
  list[53] ="siav";
  list[54] ="thab";
  list[55] ="tiab";
  list[56] ="tias";
  list[57] ="tiav";
  list[58] ="tsam";
  list[59] ="tshaj";
  list[60] ="txiav";
  list[61] ="txiab";
  list[62] ="vaj";
  list[63] ="xa";
  list[64] ="xaj";
  list[65] ="xya";
  list[66] ="yiag";
  list[67] ="zaj";
  list[68] = "txoj";
  list[69] = "nco";
  list[70] = "dua";
  list[71] = "tus";
  list[72] = "txog";
  list[73] = "cas";
  list[74] = "tos";
  list[75] = "qab";
  list[76] = "yaj";
  list[77] = "pov";
  list[78] = "niaj";
  list[79] = "hmo";
  list[80] = "hnub";
  list[81] = "iab";
  list[82] = "pom";
  list[83] = "niaj";
  list[84] = "Ziag";
  list[85] = "ya";
  list[86]= "tas";
  list[87]= "nws";
  list[88] = "rau";
  list[89] = "li";

  list2[0] ="caab";
  list2[1] ="ca";
  list2[2] ="dlaab";
  list2[3] ="dlaaj";
  list2[4] ="dlej";
  list2[5] ="dlev";
  list2[6] ="dlib";
  list2[7] ="dluab";
  list2[8] ="fav";
  list2[9] ="has";
  list2[10] ="hlaa";
  list2[11] ="hlaab";
  list2[12] ="hlaad";
  list2[13] ="maim";
  list2[14] ="maiv";
  list2[15] ="maaj";
  list2[16] ="maiv";
  list2[17] ="mob";
  list2[18] ="mog";
  list2[19] ="moo";
  list2[20] ="moob";
  list2[21] ="mood";
  list2[22] ="moog";
  list2[23] ="moov";
  list2[24] ="mog";
  list2[25] ="mov";
  list2[26] ="naag";
  list2[27] ="nais";
  list2[28] ="neev";
  list2[29] ="nyab";
  list2[30] ="nov";
  list2[31] ="av";
  list2[32] ="kaus";
  list2[33] ="lab";
  list2[34] ="laj";
  list2[35] ="lam";
  list2[36] ="loog";
  list2[37] ="lug";
  list2[38] ="noog";
  list2[39] ="moog";
  list2[40] ="pib";
  list2[41] ="qhav";
  list2[42] ="yav";
  list2[43] ="paa";
  list2[44] ="paab";
  list2[45] ="paad";
  list2[46] ="paag";
  list2[47] ="choj";
  list2[48] ="puag";
  list2[49] ="pav";
  list2[50] ="qab";
  list2[51] ="rag";
  list2[52] ="sab";
  list2[53] ="sav";
  list2[54] ="hab";
  list2[55] ="tab";
  list2[56] ="tag";
  list2[57] ="tav";
  list2[58] ="tsaam";
  list2[59] ="tshaaj";
  list2[60] ="txav";
  list2[61] ="txab";
  list2[62] ="vaaj";
  list2[63] ="xaa";
  list2[64] ="xaaj";
  list2[65] ="xyaa";
  list2[66] ="yag";
  list2[67] ="zaaj";
  list2[68] = "txuj";
  list2[69] = "ncu";
  list2[70] = "dlua";
  list2[71] = "tug";
  list2[72] = "txug";
  list2[73] = "caag";
  list2[74] = "tog";
  list2[75] = "qaab";
  list2[76] = "yaaj";
  list2[77] = "puv";
  list2[78] = "naj";
  list2[79] = "mo";
  list2[80] = "nub";
  list2[81] = "ab";
  list2[82] = "pum";
  list2[83] = "naj";
  list2[84] = "Zag";
  list2[85] = "yaa";
  list2[86]= "tag";
  list2[87]= "nwg";
  list2[88] = "rua";
  list2[89] = "le";

  var s = document.getElementById("whiteHmongInput").value;
  var choppedIntoLines = s.split(/\r\n|\r|\n/g);
  var choppedIntoWords;
  //Splits Lines Into Words
  document.getElementById("greenHmongInput").value ="";
  for(var i = 0; i < choppedIntoLines.length; i++) {
    choppedIntoWords = choppedIntoLines[i].split(" ");
    //Splits each Line to words, then match words to see if white hmong if so convert to green word
    for(var o = 0; o < choppedIntoWords.length; o++) {
      choppedIntoWords[o].toLowerCase();
      if (number == 0){
        n = list.indexOf(choppedIntoWords[o].valueOf());  //tries to find the index of a word if i exist, returns -1 if it doesn't
        if ( n != -1){
          choppedIntoWords[o] = list2[n];
        }
        n = -1; //Basically if n = -1 it means the white hmong word coulnd't be found.
      }
      if (number == 1 ){
        n = list2.indexOf(choppedIntoWords[o].valueOf());  //tries to find the index of a word if i exist, returns -1 if it doesn't
        if ( n != -1){
          choppedIntoWords[o] = list[n];
        }
        n = -1; //Basically if n = -1 it means the white hmong word couldn't be found.
      }
    }
    //Recombines words to line of Words.
    choppedIntoLines[i]  = "";
    for (var p = 0; p < choppedIntoWords.length; p++) {
      choppedIntoLines[i] += choppedIntoWords[p] + " ";
    }
    //Recombines lines and Output to Green Hmong Section
    document.getElementById("greenHmongInput").value += choppedIntoLines[i]+"\n";
  }
}
</script>

I suspect the reason your code is not working on mobile is not because of the mobile browser, but the keyboard on your mobile device. Most mobile keyboards will automatically capitalize the first letter you type, so when you type daj in it automatically comes out Daj .

There is a bug in the code that prevents it form working with words that have any capital letters.

Fixing the current code

The line choppedIntoWords[o].toLowerCase(); does nothing. In JavaScript strings are immutable , toLowerCase does not alter the string, it returns a new string. Since you never assigned the result of toLowerCase to a variable, the result was immediately discarded.

The quick fix would be to just assign the result of toLowerCase to the array element you are calling it on: choppedIntoWords[o] = choppedIntoWords[o].toLowerCase(); .

Better yet, move the toLowerCase call into the comparison, leaving the original value untouched, this will preserve the capitalization of any words that are not being replaced.

list.indexOf(choppedIntoWords[o].toLowerCase()) // .valueOf() is not needed here

(Another subtle bug, word 84 in the arrays (Ziag/Zag), both words are capitalized which will screw up the comparisons even after the toLowerCase bug is fixed.)

That said, I would rewrite it to work a little differently to make it more maintainable.

A better way of doing it

Instead of trying to keep two lists of words in sync, it would be much easier to store the word pairs as two-element arrays inside of another array. This way when adding/removing/editing any of the words you can do it all in one place.

At run-time, you could then generate two objects to act as look-up tables for the white-to-green and green-to-white conversions. Using these objects to look up the conversions should also be much faster than doing .indexOf on an array. In this particular situation, efficiency probably does not matter that much but it is a bonus that the conversion will happen (ever so slightly) faster.

<p class="welcome" id="greeting">White Hmong to Green Hmong Converter</p>
<p class="content">
</p>

<form>
<button type="button" id="white-to-green">Convert White Hmong to Green Hmong</button>
<button type="button" id="green-to-white">Convert Green Hmong to White Hmong</button>
<br>
<br>
<textarea rows="7" cols="68" id="input" placeholder="Type in Hmong words here"></textarea>
<br>
<br>
<textarea rows="7" cols="68" id="output" placeholder="Converted words will appear here"></textarea>
</form>

<script>
// Storing the white and green words in a single array that made up of
// two-element arrays containing each word pair will be much more
// maintainable than trying to keep two different lists in sync.
var hmongWords = [
    // white first, green second
    ["cab", "caab"],
    ["cia", "ca"],
    ["dab", "dlaab"],
    ["daj", "dlaaj"],
    // ...
    ["tas", "tag"],
    ["nws", "nwg"],
    ["rau", "rua"],
    ["le", "li"]

  ],
  // these objects will act as look-up tables for the conversions
  whiteToGreen = {},
  greenToWhite = {},

  elInput = document.getElementById("input"),
  elOuput = document.getElementById("output"),
  elWhiteToGreen = document.getElementById("white-to-green"),
  elGreenToWhite = document.getElementById("green-to-white"),

  convert = function (text, lookupTable) {
    var lines = text.split(/\r\n|\r|\n/),
      processWord = function (word) {
        // Look for the word in the look up object.
        // If the object has a property that is the word we are looking for,
        // that value will be returned. If the word is not in the look-up
        // object, undefined is returned. Since undefined is falsey the
        // second half of the or statement will return the original word
        return lookupTable[word.toLowerCase()] || word;
      },
      processLine = function (line) {
        // Split the line up based on whitespace and process them,
        // join the resulting array with spaces and return the converted line
        return line.split(/\s/).map(processWord).join(' ');
      };

    // Map will return a new array of lines that have been processed by
    // processLine. Join the new lines with a newline and return the string
    return lines.map(processLine).join('\n');
  },
  convertWhiteToGreen = function (text) {
    // just calls convert with the whiteToGreen look-up object
    return convert(text, whiteToGreen);
  },
  convertGreenToWhite = function (text) {
    // just calls convert with the greenToWhite look-up object
    return convert(text, greenToWhite);
  },
  makeListener = function (converter) {
    // this returns a function that will be used as an event listener
    return function () {
      // grab text from the input box, runs it through the
      // converter function that was provided when makeListener was called
      // and puts the output into the output box
      elOuput.value = converter(elInput.value);
    };
  };

// build the look-up tables
hmongWords.forEach(function (wordPair) {
  whiteToGreen[wordPair[0]] = wordPair[1];
  greenToWhite[wordPair[1]] = wordPair[0];
});

// Attach the event listeners to the buttons.
// makeListener returns a function that uses the function you pass to it 
// to convert the text.
elWhiteToGreen.addEventListener('click', makeListener(convertWhiteToGreen), false);
elGreenToWhite.addEventListener('click', makeListener(convertGreenToWhite), false);
</script>

You can see my version in action here

My code uses the forEach and map methods to loop over the arrays that split creates instead of for loops. This avoids the need for a counter variable and instead allows us to provide each item in the array a meaningful name ( word , line , etc) instead of referring to an item in the array by its index.

Something else you might notice is that the convert function uses the logical or ( || ) operator. The logical or statement short-circuits if the first operand is truthy. So if a value is found in the look-up object, it is returned. If the value is not found in the object the second operand, the original word is returned. You have to be careful when using this technique in some situations, for instance when a valid option might be falsy such as 0 or an empty string. But in this situation lookupTable[word.toLowerCase()] will either return a non-empty string, which is always truthy or undefined which is always falsy.

You might have noticed that I used the words "truthy" and "falsy" instead of true and false this has to do with how implicit type conversion is handled in JavaScript. If something is "truthy" it will be converted to true when in a context that a Boolean value is needed. Likewise "falsy" values are values that will be converted to false in a context where a Boolean value is needed.

In the HTML instead of putting the placeholder text as a value in the textarea s, I used the placeholder attribute.

Here are a few articles that might help understanding some of the techniques I've used if they are new to you:

Another thing I used in my code but didn't discus is closures. They are a kind of big and important topic in JavaScript here is some stuff to help with them:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM