Jump to content

Why does window.load function triggers "click" event of elements?


Go to solution Solved by kicken,

Recommended Posts

Hi, I prepared a code :

<html>
  <head>
    <style>
      	.inn {
        vertical-align: top;
        display: inline-block;
        margin: 7px;
        text-align: left;
        padding: 10px;
        border-radius: 30px;
        text-shadow: 0 0 black;
        background-color: #ff5722;
        border-style: solid none none solid;
        border-width: 5px;
        border-top-color: red;
        border-left-color: #ff1800;
        box-shadow: 4px 4px #7a5858;
	    background-image: linear-gradient(to top, rgba(0,0,0,0) , rgb(255,255,255,.1) );
      }

      .inn:hover {
        vertical-align: top;
        color: #4340ff;
        display: inline-block;
        padding: 10px;
        margin: 7px;
        text-align: left;
        border-radius: 30px;
        background-color: #f97950;
        border-style: solid none none solid;
        border-width: 5px;
        border-top-color: #b10000;
        border-left-color: #910303;
        box-shadow: 4px 4px #ffffff;
        background-image: linear-gradient(to top, rgba(0,0,0,0) , rgb(255,255,255,.1) );
      }
      .inText {
        color : black;
      }

      .inn:hover .inText {
        position : relative ;
        top : 2px;
      }

      .inTextHover {
        position : relative ;
        top : 2px;
      }
	</style>
  </head>
  <body>
    <div class="navbar">
            <div class="inn">
                <div class="inText">button1</div>
            </div>
            <div class="inn">
                <div class="inText">button2</div>
            </div>
            <div class="inn">
                <div class="inText">button3</div>

            </div>
    </div>

    <script>
    var toggleButton ;	
    var toggleOn;
    var btns ;

    window.addEventListener("load",load);

    function load() {
        console.log("loaded?");

        btns = Array.from( document.getElementsByClassName("inText") ); // get all buttons to collection object then to an array
        sessionStorage.setItem("clickCounter",Number(0));

        // add click eventlistener to all buttons > 
        loadListeners(btns)  ;
    }

    function loadListeners(btns)  {
        btns.forEach((item,index,arr) => {
            item.addEventListener('click',toggleBtn(item,index,arr),false );
        });
    }
      
    function toggleBtn(item,index,arr) {
      // change botton's class :
      if(item.className =="inText" ) {  // change inText divs' classes
        console.log("yes");
        sessionStorage.setItem("clickCounter",Number(sessionStorage.clickCounter)+1);
        if(sessionStorage.clickCounter %2 ==1) {
          item.className="inTextHover";
          console.log("click counter : "+sessionStorage.clickCounter);
        }
      }
	}
    </script>
  </body>
</html>
  

when I load page, I am sawing that, window.load have already triggered the "click" event of divs. Why? I used "addEventListener" function, not a custom function. What is wrong? Thanks.

Edited by eaglehopes
  • Solution
10 minutes ago, eaglehopes said:
item.addEventListener('click',toggleBtn(item,index,arr),false )

In that line, you are not assigning the toggleBtn function as an on-click event handler.  You are executing that function now and assigning whatever value it returns (which is nothing) as your on-click handler.

You need to wrap it an anonymous function which is passed to addEventListener as the click handler.

item.addEventListener('click', function(){
    toggleBtn(item,index,arr);
}, false)

 

1 hour ago, kicken said:

In that line, you are not assigning the toggleBtn function as an on-click event handler.  You are executing that function now and assigning whatever value it returns (which is nothing) as your on-click handler.

You need to wrap it an anonymous function which is passed to addEventListener as the click handler.

item.addEventListener('click', function(){
    toggleBtn(item,index,arr);
}, false)

 

Thanks kicken, actually it worked! However, I think, I did not do anything extra what is done in : w3school example by assigning a function to an event. What is the difference btw mine code and the example code? Is it due to parameters which I supplied to my function ? 

Edited by eaglehopes
word correction

Yes, I found that, it is due to extra parameters I gave... I do not like javascript's "hidden parameter" feature! In other languages there is no such thing, but in javascript, sometimes even I did not sent any parameter, function can have it!

function loadListeners()  {
	btns.forEach((item,index,arr) => {
    console.log("item type is "+typeof(item));
		item.addEventListener('click',toggleBtn,false );
	});
}

function toggleBtn(item) {
	// write the parameter to console to see what it is !
	console.log(item); // it is an PointerEvent whose type is "click"
}

I changed my code above, and put a parameter named "item" to the toggleBtn functon definition itself (not sent anything inside addEventListener function). I got item as PointerEvent whose type is "click"! I have lot to learn about javascript's these kind of "strange" features. 

59 minutes ago, eaglehopes said:

I do not like javascript's "hidden parameter" feature!

There's no hidden parameter feature reference.  The issue you have is a very common one among new developers, and that's knowing the difference between a function reference, and executing a function.

function myFunction(){
   //do stuff
}

thing.addEventListener('click', myFunction   );   //<- pass a reference to myFunction
thing.addEventListener('click', myFunction() );   //<- execute myFunction now, pass it's return value.

addEventListener wants a callback function, which needs to be passed as a function reference.  To do that, you only supply the name of the function (or an inline anonymous function).  Adding the parenthesis after the function name causes that function to be executed rather than referenced.

When you're passing a function reference, you cannot pass any parameters along with that reference, which is what you were trying to do.  In order to supply parameters, you need to use the anonymous inline function as a wrapper.  The anonymous function is passed as the real event handler callback, and when the event occurs and the anonymous function is executed, it in turn executes your desired event handler with the proper parameters.

 

  • Like 1

I always tried to avoid using "function as wrapper" since, as far as I understood that wrapper code is for more specific situations, not general cases. That was my mistake! Very good explanation ! Thanks kicken, I do not know "pass by reference" and advantage/necessity of using function as wrapper.

Edited by eaglehopes
grammer correction

I have been developing an online trivia game for years now and I have finally wrapped this around my head. (Well, at least I think 😂 )

HTML

                    <div id="answers">
                        <button class="buttonStyle" id="ans1"></button>
                        <button class="buttonStyle" id="ans2"></button>
                        <button class="buttonStyle" id="ans3"></button>
                        <button class="buttonStyle" id="ans4"></button>
                    </div>

JavaScript

// Function to handle the event when an answer is selected.
const pickAnswer = (answerIndex) => {
    return () => {
        choice = answerIndex;
        checkAnswer();
        // Only show the next button if the next question exists
        if (index < triviaData.length - 1) {
            nextButton.style.display = "block"; // show the next button after an answer is chosen
        }
    };
};

// The `startGame` function takes an object as an argument with properties: ans1, ans2, ans3, ans4, id, question.
// These properties represent the answers to the current question, the question's id, and the question itself, respectively.
const startGame = ({ ans1, ans2, ans3, ans4, id, question }) => {
    // This line sets the id of the current question to the "data-record" attribute of the element with id "currentQuestion".
    document.querySelector("#currentQuestion").setAttribute("data-record", id);

    // This line sets the display number of the current question (index + 1) to the text content of the element with id "currentQuestion".
    document.querySelector("#currentQuestion").textContent = (index + 1).toString();

    // This line sets the text content of the element with id "question" to the question itself.
    document.querySelector("#question").textContent = question;

    // This loop iterates over each of the answer buttons.
    answerButtons.forEach((button, index) => {
        // This line checks if there was a previous "pickAnswer" event listener attached to the button,
        // and if so, removes it.
        const previousPickAnswer = button.__pickAnswer__;
        if (previousPickAnswer) {
            button.removeEventListener("click", previousPickAnswer);
        }

        // This line creates a new "pickAnswer" event listener, and attaches it to the button.
        const newPickAnswer = pickAnswer(index + 1);
        button.addEventListener("click", newPickAnswer, false);
        button.__pickAnswer__ = newPickAnswer;

        // This line sets the text content of the button to the corresponding answer (ans1, ans2, ans3, ans4)
        // with a "📷" character at the beginning.
        button.textContent = `📷 ${[ans1, ans2, ans3, ans4][index]}` || "";

        // If there's no corresponding answer, the button is disabled (its pointer events are set to "none").
        // Otherwise, the button is enabled (its pointer events are set to "auto").
        if (![ans1, ans2, ans3, ans4][index]) {
            button.style.pointerEvents = "none";
        } else {
            button.style.pointerEvents = "auto";
        }
    });
};

I comment the script out and I think it's self-explanatory. OK, I'm tired as this is the latest I have stayed up. 🤣

Edited by Strider64
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.