Orthography Profiles with JavaScript

This fiddle illustrates how sequences can be manipulated with the help of orthography profiles implemented in JavaScript.

by LinguList

HTML

<h1>
Orthography Profiles with JavaScript
</h1>

<table>
  <tr>
    <td>
      <label for="opin">Input String: </label>
    </td>
    <td>
      <input id="opin" type="text" placeholder="your string here" onkeyup="activate(this.value)"/>
    </td>
  </tr>
  <tr>
    <td>
      <label for="opout_grapheme">Output (Grapheme): </label>
    </td>
    <td>
      <span id="opout_grapheme"/>
    </td>
  </tr>
    <tr>
    <td>
      <label for="opout_ipa">Output (IPA): </label>
    </td>
    <td>
      <span id="opout_ipa"/>
    </td>
  </tr>
</table>

CSS

.segment {
  display: table-cell;
  background-color: lightgray;
  padding: 2px;
  border: 1px solid black;
  width: 30px;
}

JavaScript

/* Function segmentizes a word when a profile is given.
 */
function segmentize(word, profile) {
  /* normalize according to NFD */
  word = word.normalize('NFD');
  if (word.length == 0) {
    return [word];
  }
  
  /* define queue and output*/
  var queue = [[[], word, '']];

  /* define variables */
  var segmented, current, rest; 

  /* main loop */
  while (queue.length > 0) {
    [segmented, current, rest] = queue.splice(0, 1)[0];
  
    /* A: check if the current segment occurs in the profile */
    if (current in profile && !(rest)) {
      return segmented.concat([current]);
    }
    /* B: check for non-specified characters in profile */
    else if (current.length == 1 && !(current in profile)) {
      if (rest) {
	      queue.push([segmented.concat([current]), rest, '']);
      }
      else {
	      return segmented.concat([current]);
      }
    }
    /* C: check for next smaller string */
    else if (!(current in profile)) {
      queue.push(
        [
          segmented, 
          current.slice(0, current.length-1), 
          current[current.length-1] + rest
        ]
      );
    }
    /* D: if current in profile, proceed with rest */
    else {
      queue.push(
        [
          segmented.concat([current]), 
          rest, 
          ''
        ]
      );
    }
  }
}

/* convert a segmented sequence into another orthography */
function convert(segments, profile, column){
  var output = [];
  var i;
  for (i=0; i<segments.length; i++) {
    if (segments[i] in profile) {
      output.push(profile[segments[i]][column]);
    }
    else {
      output.push('«' + segments[i] + '»');
    }
  }
  return output;
}


var profile = {
  "th": {"grapheme": "th", "ipa": "tʰ"},
  "ph": {"grapheme": "ph", "ipa": "pʰ"},
  "kh": {"grapheme": "kh", "ipa": "kʰ"},
  "a": {"grapheme": "a", "ipa": "a"},
  "i": {"grapheme": "i", "ipa": "i"},
  "u": {"grapheme": "u", "ipa": "u"},
  "aa": {"grapheme": "aa", "ipa": "aː"},
  "ii": {"grapheme": "ii", "ipa": "iː"},
 ...