Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why transliteration in not working when I am selection the second input box?

<div class="row" v-for="(book, index) in Subsequent" :key="index">
    <div class="col-md-8">
        <div class="form-group label-floating">
            <label class="control-label"> Details</label>
            <input type="text" class="form-control" v-model="book.seizuredetails" id="transliterateTextarea2">
        </div>
    </div>
</div>
<a @click="addNewRow">Add Another</a>
</div>

I am getting transliteration in the first input box. (no problem in the first case)

So, when I clciking on Add Another I am able to have a new input box. But in that transliteration is not working.

My transliteration script is

  <script type="text/javascript">

      // Load the Google Transliterate API
      google.load("elements", "1", {
          packages: "transliteration"
      });

      function onLoad() {
          var options = {
              sourceLanguage: google.elements.transliteration.LanguageCode.ENGLISH,
              destinationLanguage: [google.elements.transliteration.LanguageCode.MALAYALAM],
              shortcutKey: 'ctrl+g',
              transliterationEnabled: true
          };

          // Create an instance on TransliterationControl with the required
          // options.
          var control = new google.elements.transliteration.TransliterationControl(options);

          // Enable transliteration in the textbox with id
          // 'transliterateTextarea'.
          var ids = [ "transliterateTextarea", "transliterateTextarea1", "transliterateTextarea2" ];
          control.makeTransliteratable(ids);
      }
      google.setOnLoadCallback(onLoad);
  </script>

So, When click on add another, how can I able to give that input area a new transliteration id.

Please help me to have a solution.

like image 617
Wanderer Avatar asked Apr 18 '18 06:04

Wanderer


1 Answers

Basically you would get the makeTransliteratable code and place it in a method. After that, you would call such method on any input you want to make transliterable.

There are some gotchas, though.

The first one is how to tell if google transliteration has loaded or not. I'm using a Promise (window.googleIsloaded) and await window.googleIsLoaded; inside the method to guarantee it only executes after google has been loaded.

The second gotcha is much worse: when transliterating, google sets the value of the <input> directly, and doesn't emit any event upon doing it. Since there's no event, Vue can't update the v-model property. To overcome that, I have created a Proxy that intercepts any calls to the inputs and emits an input event whenever google sets the value directly, which allows Vue to pick the change up. The downside is that the Proxy API is not available in IE.

JSFiddle demo here.


Update:

Alright, I've come up with a workaround to work in all IE versions Vue support and was also able to turn it into a Vue custom directive.

So all you gotta do is add v-transliterate="options" to the <input> or <textarea>, being options your object or property containing the configurations for transliteration of that specific <input>/<textarea>. Example:

<input type="text" v-model="somevar" v-transliterate="options">

Demo JSFiddle here. Code:

<script src="https://unpkg.com/vue"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>
  // Load the Google Transliterate API
  google.load("elements", "1", {
    packages: "transliteration"
  });

  Vue.directive('transliterate', function (el, binding) {
      var control = new google.elements.transliteration.TransliterationControl(binding.value);
      // a getter for each property google transliterate reads and a setter for each it modifies
      var inputOrTextareaProxy = {
          get getAttribute() { return el.getAttribute.bind(el); },
          get addEventListener() { return el.addEventListener.bind(el); },
          get blur() { return el.blur.bind(el); },
          get focus() { return el.focus.bind(el); },
          get tagName() { return el.tagName; },
          get type() { return el.type; },
          get id() { return el.id; },
          get style() { return el.style; },
          get selectionStart() { return el.selectionStart; },
          get selectionEnd() { return el.selectionEnd; },
          get value() { return el.value; },
          set value(v) { el.value = v; el.dispatchEvent(new CustomEvent('input')); },
          get nodeType() { return el.nodeType; },
          get ownerDocument() { return el.ownerDocument; },
          get scrollTop() { return el.scrollTop; },
          set scrollTop(v) { el.scrollTop = v; }
      };
      control.makeTransliteratable([inputOrTextareaProxy]);
  });
</script>

<div id="app">
  <div class="row" v-for="(book, index) in Subsequent" :key="index">
    <div class="col-md-8">
      <div class="form-group label-floating">
        <label class="control-label"> Details</label>
        <input type="text" class="form-control" v-model="book.seizuredetails" v-transliterate="options"> (Type "World." with the dot!) {{ book.seizuredetails }}
      </div>
    </div>
  </div>
  <a @click="addNewRow">Add Another</a>
</div>
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!',
    Subsequent: [
        {seizuredetails: ''}
    ],
    options: {
      sourceLanguage: google.elements.transliteration.LanguageCode.ENGLISH,
      destinationLanguage: [google.elements.transliteration.LanguageCode.MALAYALAM],
      shortcutKey: 'ctrl+g',
      transliterationEnabled: true
    }
  },
  methods: {
    addNewRow: function() {
        this.Subsequent.push({seizuredetails: ''})
    }
  }
})
like image 91
acdcjunior Avatar answered Nov 05 '22 16:11

acdcjunior