0

Is there a possibility to toggleText() for each element of the array separately?

Right now, when clicked, the values are changed for every single element at the same time and I'd like to go over them one by one as they're clicked.

$(function() {
    var jap = ["kau", "matsu", "shiru"];
    var eng = ["to buy", "to wait", "to know"];
    var tds = [$('#td1'), $('#td2'), $('#td3')]
    
    for (i = 0; i < tds.length; i++) {
        $(tds[i]).on('click', function(){
            for(i = 0; i < tds.length; i++) {
            $(tds[i]).toggleText(jap[i], eng[i]);
            }
        });
     }
});

Ideally, I'd like to change the text inside a table cell on each individual click for each array element.

-- edit:

Here's the HTML with the table:

<table>
    <tbody id="tb">
         <tr>
            <td>Godan Verbs</td>
            <td>V2</td>
            <td>Ichidan Verbs</td>
            <td>V2</td>
            <td>Irregular Verbs</td>
            <td>V2</td>
          </tr>
          <tr>
             <td>kau</td>
             <td>kai-</td>
             <td>taberu</td>
             <td>tabe-</td>
             <td>kuru</td>
             <td>ki-</td>
           <tr>
              <td>matsu</td>
              <td>machi-</td>
              <td>miru</td>
              <td>mi-</td>
              <td>suru</td>
              <td>shi-</td>
          </tr>
          <tr>
              <td>shiru</td>
              <td>shiri-</td>
              <td>oshieru</td>
              <td>oshie-</td>
          </tr>
          <tr>
              <td>kaku</td>
              <td>kaki-</td>
              <td>neru</td>
              <td>ne-</td>
           </tr>
           <tr>
               <td>oyogu</td>
               <td>oyogi-</td>
               <td>kangaeru</td>
               <td>kangae-</td>
            </tr>
            <tr>
                <td>hanasu</td>
                <td>hanashi-</td>
                <td>okiru</td>
                <td>oki-</td>
             </tr>
             <tr>
                 <td>shinu</td>
                 <td>shini-</td>
                 <td>sakeru</td>
                 <td>sake-</td>
              </tr>
              <tr>
                  <td>yomu</td>
                  <td>yomi-</td>
                  <td>kotaeru</td>
                  <td>kotae-</td>
               </tr>
               <tr>
                   <td>asobu</td>
                   <td>asobi-</td>
                   <td>iru</td>
                   <td>i-</td>
                </tr>
        </tbody>                
 </table>

Here's additional meaning of the words I'd like to display:

const jap2en = {"kau":"to buy", "matsu":"to wait", "shiru":"to know", "kaku":"to write", "oyogu":"to swim", "hanasu":"to talk", "shinu":"to die", "yomu":"to read", "asobu":"to play", "taberu": "to eat", "miru": "to look", "oshieru": "to teach", "neru": "to sleep", "kangaeru": "to think", "okiru": "to get up", "sakeru": "to avoid", "kotaeru": "to answer", "iru": "to be/exist", "kuru": "to come", "suru": "to do"};

I also added ids to the tds that are supposed to show the meaning like this for each individual td:

<td id="td1">kau</td>
<td>kai-</td>
<td id="td2">taberu</td>
// and so on

and changed the js code to this:

const $tds = $("#tb td[id]");
$("#tb").on("click", "td[id]", function() { ... }

However, as I mentioned in the comment, that one fragment changes the structure of the table and makes tds appear in wrong places. This fragment specifically:

$tds.each(function(i) {
    $(this).text(jpArr[i])
    $(this).data("lang","ja")
 })

If removed, the code works but the cells require two clicks to show the meaning.

1
  • 1
    You might want to have a look at the jQuery Learning Center because your setup is overly complicated. And if you go the jQuery-way your problem will also be solved. Commented May 28, 2021 at 7:37

2 Answers 2

2

You have jQuery - use its power

It is not recommended to loop to add eventListeners in JavaScript, jQuery or not.

const jap2en = {"kau":"to buy", "matsu":"to wait", "shiru":"to know", "kaku":"to write", "oyogu":"to swim", "hanasu":"to talk", "shinu":"to die", "yomu":"to read", "asobu":"to play", "taberu": "to eat", "miru": "to look", "oshieru": "to teach", "neru": "to sleep", "kangaeru": "to think", "okiru": "to get up", "sakeru": "to avoid", "kotaeru": "to answer", "iru": "to be/exist", "kuru": "to come", "suru": "to do"};
const jpArr = Object.keys(jap2en); // just the Japanese keys
const en2jap = Object.fromEntries(Object.entries(jap2en).map(a => a.reverse())); // makes a reverse lookup

$(function() {
  const $tds = $("#tb td");
  $("#tb").on("click", "td", function() { // delegation
    const text = $(this).text();
    const lang = $(this).data("lang");
    const langArr = lang === "ja" ? jap2en : en2jap;
    const langText = langArr[text];
//    console.log(text,lang,langText,langArr[text])
    if (langText) {
      $(this).text(langText);
      $(this).data("lang",lang === "ja" ? "en" :"ja" );
    }  
  });
  $tds.each(function(i) {
    $(this).data("lang","ja")
  }) 
});
td {
  border: 1px solid black;
  padding: 3px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <table>
      <thead>
        <tr>
          <th>Godan Verbs</th>
          <th>V2</th>
          <th>Ichidan Verbs</th>
          <th>V2</th>
          <th>Irregular Verbs</th>
          <th>V2</th>
        </tr>
      </thead>
      <tbody id="tb">
        <tr>
          <td>kau</td>
          <td>kai-</td>
          <td>taberu</td>
          <td>tabe-</td>
          <td>kuru</td>
          <td>ki-</td>
        </tr>
        <tr>
          <td>matsu</td>
          <td>machi-</td>
          <td>miru</td>
          <td>mi-</td>
          <td>suru</td>
          <td>shi-</td>
        </tr>
        <tr>
          <td>shiru</td>
          <td>shiri-</td>
          <td>oshieru</td>
          <td>oshie-</td>
        </tr>
        <tr>
          <td>kaku</td>
          <td>kaki-</td>
          <td>neru</td>
          <td>ne-</td>
        </tr>
        <tr>
          <td>oyogu</td>
          <td>oyogi-</td>
          <td>kangaeru</td>
          <td>kangae-</td>
        </tr>
        <tr>
          <td>hanasu</td>
          <td>hanashi-</td>
          <td>okiru</td>
          <td>oki-</td>
        </tr>
        <tr>
          <td>shinu</td>
          <td>shini-</td>
          <td>sakeru</td>
          <td>sake-</td>
        </tr>
        <tr>
          <td>yomu</td>
          <td>yomi-</td>
          <td>kotaeru</td>
          <td>kotae-</td>
        </tr>
        <tr>
          <td>asobu</td>
          <td>asobi-</td>
          <td>iru</td>
          <td>i-</td>
        </tr>
      </tbody>
    </table>


simpler version

const jap = ["kau", "matsu", "shiru"];
const eng = ["to buy", "to wait", "to know"];

$.fn.extend({ // extending jQuery to have a toggleText
  toggleText: function(a, b) {
    return this.text(this.text() == b ? a : b)
  }
});

$(function() {
  $("#tb").on("click", "tr", function() { // delegation
    const idx = $(this).index();
    $(this).find("td").eq(0).toggleText(jap[idx], eng[idx]);
  });
});
td {
  border: 1px solid black;
  padding: 3px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
  <thead>
    <tr>
      <th>Godan Verbs</th>
      <th>V2</th>
      <th>Ichidan Verbs</th>
      <th>V2</th>
      <th>Irregular Verbs</th>
      <th>V2</th>
    </tr>
  </thead>
  <tbody id="tb">
    <tr>
      <td>kau</td>
      <td>kai-</td>
      <td>taberu</td>
      <td>tabe-</td>
      <td>kuru</td>
      <td>ki-</td>
    </tr>
    <tr>
      <td>matsu</td>
      <td>machi-</td>
      <td>miru</td>
      <td>mi-</td>
      <td>suru</td>
      <td>shi-</td>
    </tr>
    <tr>
      <td>shiru</td>
      <td>shiri-</td>
      <td>oshieru</td>
      <td>oshie-</td>
    </tr>
    <tr>
      <td>kaku</td>
      <td>kaki-</td>
      <td>neru</td>
      <td>ne-</td>
    </tr>
    <tr>
      <td>oyogu</td>
      <td>oyogi-</td>
      <td>kangaeru</td>
      <td>kangae-</td>
    </tr>
    <tr>
      <td>hanasu</td>
      <td>hanashi-</td>
      <td>okiru</td>
      <td>oki-</td>
    </tr>
    <tr>
      <td>shinu</td>
      <td>shini-</td>
      <td>sakeru</td>
      <td>sake-</td>
    </tr>
    <tr>
      <td>yomu</td>
      <td>yomi-</td>
      <td>kotaeru</td>
      <td>kotae-</td>
    </tr>
    <tr>
      <td>asobu</td>
      <td>asobi-</td>
      <td>iru</td>
      <td>i-</td>
    </tr>
  </tbody>
</table>

Sign up to request clarification or add additional context in comments.

12 Comments

That's great. Thank you for your time and help.
Do you perhaps have any idea why this fragment: ` $tds.each(function(i) { $(this).text(jpArr[i]) $(this).data("lang","ja") }) ` breaks the structure of a table? tds are all mixed up when I apply this code. When I remove the mentioned fragment, then it's structured as expected, but it requires two clicks to show the meaning of the word.
I set the text to the value of the lookup table and then set the data-attribute to whatever the current language in the cell is
The loop is to set the value of the cell to begin with so we do not have to fill the table by hand. Show YOUR html if you want my code to work with your html
Let me edit my initial question and include the html
|
0

Try this

If you want to achieve on every click the corresponding text based on index of array to toggle then i believe you have to just get rid of the inner for loop you have used.

also you just have to save the ids without $ and ()

which makes it like this

$(function() {
    var jap = ["kau", "matsu", "shiru"];
    var eng = ["to buy", "to wait", "to know"];
    var tds = ['#td1', '#td2', '#td3'];
    
    for (i = 0; i < tds.length; i++) {
        $(tds[i]).on('click', function(){                
            $(this).toggleText(jap[i], eng[i]);                
        });
     }
});

EDIT

i just made it working like this (looping event listeners though i guess):

$(function() {
  var jap = ["kau", "matsu", "shiru"];
  var eng = ["to buy", "to wait", "to know"];
  var tds = ['#td1', '#td2', '#td3'];

  $("td").each(function(index, value) {
    $(this).on('click', function() {
      var textToToggle = $(this).text() == jap[index] ? eng[index] : jap[index];
      $(this).text(textToToggle);
    });
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
  <tr>
    <td id="td1">kau</td>
    <td id="td2">matsu</td>
    <td id="td3">shiru</td>
  </tr>
</table>

2 Comments

Please test your code. Click edit, then [<>] and create a stacksnippet. You will see you lack a closure over the i and the i is now a global variable
It is NOT recommended to loop to add eventlisteners - especially not now it is as easy in plain JS as in jQuery

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.