Home > front end >  I want to make it work multiple times with one function
I want to make it work multiple times with one function

Time:11-18

When the button is clicked, the addQuery("to be execution") function is executed, and the value contained in the button attribute "value='class name'" is added to the class that has the class contained in the function addQuery("to be execution") do.

  <div class="test1">test 1</div>
  <div class="test2">test 2</div>

  <button class="addQuery" value='push-down' onclick='addQuery(".test1")'>button</button>
  <button class="addQuery" value='push-up' onclick='addQuery(".test2")'>button</button>

  <script type="text/javascript" src="./script.js"></script>
const addQueryclass = document.getElementsByClassName("addQuery");
for (let i = 0; i < addQueryclass.length; i  ) {
  function addQuery(cwillrun) {
    const toadd = addQueryclass[i].value;
    document.querySelector(cwillrun).className  = ` ${toadd}`;
  }
}

In JavaScript there should be only one function, in HTML each element should have a different class value.

E.g

  <div class="test1">test 1</div>

  <button class="addQuery" value='push-down' onclick='addQuery(".test1")'>button</button>

<!--When the button is clicked it should be something like this:  -->
  <div class="test1 push-down">test 1</div>

  <button class="addQuery" value='push-down' onclick='addQuery(".test1")'>button</button>

Can you please solve it with basic javascript without using a framework?

CodePudding user response:

If I correctly understand what you trying to do it would be something like this

[...document.getElementsByClassName('addQuery')].forEach(el => {
  el.addEventListener('click', e => {
    e.preventDefault;
    
    document
      .getElementsByClassName(el.dataset.target)[0]
      .classList.add(el.dataset.value)
    ;
  });
});
<div class="test1">test 1</div>
<div class="test2">test 2</div>

<button class="addQuery" data-target="test1" data-value="push-down">
  button 1
</button>
<button class="addQuery" data-target="test2" data-value="push-up">
  button 2
</button>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

If I understand you correctly, you have two buttons, each with a value. When the user clicks on a button, its value is added to a corresponding div.

The short answer

First, we'll change the function's parameters list to accept a button, then send the button itself as an argument to the function via the onclick attribute, and finally, add the button's value to the div's classes list.

Notice you should not manually add the new class to className. This way, the class will be added every time the user clicks on the button. Instead, we will simply use the classList.add() function which takes care of this automatically.

// I have added basic CSS so we have a visual indication for the class adding

const addQueryclass = document.getElementsByClassName("addQuery");

function addQuery(button, cwillrun) {
  document.querySelector(cwillrun).classList.add(button.value);
}
.push-down, .push-up { font-weight: bold; }
<div class="test1">test 1</div>
<div class="test2">test 2</div>

<button class="addQuery" value='push-down' onclick='addQuery(this, ".test1")'>button</button>
<button class="addQuery" value='push-up' onclick='addQuery(this, ".test2")'>button</button>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

The long answer

As said in the comments, using the onclick attribute inline is bad practice. We do not want to mix HTML (presentation) and JavaScript (behavior). That is why the better way would be to separate them, by writing the entire event handling logic in the JavaScript file.

When we used the onclick attribute, we simply sent the corresponding item's class as an argument. Since in our new approach we are not using the onclick attribute, we need to store these classes somewhere else: in our case, a data-attribute.

for (const button of document.getElementsByClassName("addQuery")) {
  button.addEventListener("click", () => {
    document.querySelector(button.dataset.class).classList.add(button.value);
  });
}
.push-down, .push-up { font-weight: bold; }
<div class="test1">test 1</div>
<div class="test2">test 2</div>

<button class="addQuery" value="push-down" data-class=".test1">button</button>
<button class="addQuery" value="push-up" data-class=".test2">button</button>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Something to consider is that test1 and test2 are classes and not ids. This suggests that you have other items with the same classes (if not, it will be smarter to change those to ids). But since we are using querySelector(), only the first corresponding item will be affected.

for (const button of document.getElementsByClassName("addQuery")) {
  button.addEventListener("click", () => {
    document.querySelector(button.dataset.class).classList.add(button.value);
  });
}
.push-down, .push-up { font-weight: bold; }
<div class="test1">test 1</div>
<div class="test1">test 1</div>
<div class="test2">test 2</div>
<div class="test2">test 2</div>

<button class="addQuery" value="push-down" data-class=".test1">button</button>
<button class="addQuery" value="push-up" data-class=".test2">button</button>
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

If we want all of them to be affected, we should use querySelectorAll() instead (or document.getElementsByClassName), loop through them, and apply our logic to each and every one.

for (const button of document.getElementsByClassName("addQuery")) {
  button.addEventListener("click", () => {
    document.querySelectorAll(button.dataset.class).forEach(item => {
      item.classList.add(button.value)
    });
  });
}
.push-down, .push-up { font-weight: bold; }
<div class="test1">test 1</div>
<div class="test1">test 1</div>
<div class="test2">test 2</div>
<div class="test2">test 2</div>

<button class="addQuery" value="push-down" data-class=".test1">button</button>
<button class="addQuery" value="push-up" data-class=".test2">button</button>
<iframe name="sif5" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Another thing to consider is that we are only adding classes to the divs. If we want to remove them when clicking again, we could replace classList.add() with classList.toggle().

for (const button of document.getElementsByClassName("addQuery")) {
  button.addEventListener("click", () => {
    document.querySelectorAll(button.dataset.class).forEach(item => {
      item.classList.toggle(button.value)
    });
  });
}
.push-down, .push-up { font-weight: bold; }
<div class="test1">test 1</div>
<div class="test2">test 2</div>

<button class="addQuery" value="push-down" data-class=".test1">button</button>
<button class="addQuery" value="push-up" data-class=".test2">button</button>
<iframe name="sif6" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

One final thought

This is only one basic way to go. There are many improvements we can make to this code. I strongly suggest that whatever strategy you choose to go for, you then post your final code at Code Review, and get further feedback.

CodePudding user response:

function addQuery(element) {
  console.log(document.getElementById(element).innerHTML);
  if (isNaN(document.getElementById(element).innerHTML)) document.getElementById(element).innerHTML = 0;
  document.getElementById(element).innerHTML = parseInt(document.getElementById(element).innerHTML)   1;
}
<div id="test1">1</div>
<div id="test2">test 2</div>

<button class="addQuery" value='push-down' onclick='addQuery("test1")'>button</button>
<button class="addQuery" value='push-up' onclick='addQuery("test2")'>button</button>
<iframe name="sif7" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

you can try here. https://jsfiddle.net/k43xds9r/

  • Related