Button element is not retrieved at the first call - javascript

I've came across a curious thing while scripting in JavaScript and I'm not entirely sure if my way of understanding it is correct.
Basically I would like to click a button which brings up another one, if the second button is not brought up by the first I need to quit the loop.
var intervalID = window.setInterval(myfunc,1000);
function t(){
console.log('quit');
clearInterval(intervalID);
}
function myfunc(){
//first button
document.getElementsByClassName('hit')[0].click();
//try to retrieve the second one
var el = document.getElementsByClassName('hit_ok');
console.log(el.length);
//if it exists click it
if (el.length == 1){
el[0].click();
//otherwise exit
} else {
console.log('ready to quit');
window.setTimeout(t,50);
}
}
My problem is that the first instance returns always 0 in the if statements
I also tried the following:
function myfunc(){
document.getElementsByClassName('hit')[0].click();
var el = document.getElementsByClassName('hit_ok');
console.log(el);
if (el != null){
el[0].click();
} else {
console.log('ready to quit');
window.setTimeout(t,50);
}
}
and in fact it returns:
[] --> length: 0__proto__: HTMLCollection
VM3642:1 Uncaught TypeError: Cannot read property 'click' of undefined
instead of:
[span.hit_ok]
Which means that the first time it cant retrieve the button.
Clearly the second button is there since the first one is pressed.
HTML code:
//first button
<div class="try">
<input type="hidden" id="isHit" value="">
Try
</div>
//second button
<div class="msgbox_button">
<span class="hit_ok" onclick="remove();">OK</span>
</div>
Any ideas?
Regards,

What you do:
intervalID=window.setInterval();
This is valid js, but the script is started before the page has loaded, wich means the DOM is not created at that time.
What to do:
window.onload=function(){
var intervalID=window.Interval(...);
};
This starts the loop after the page has loaded

Related

jquery if (value)... else avoiding "duplicate selector"

I have a notification on PhpStorm that "Duplicate JQuery Selector" for a JQuery if...else conditional based on a value and then updating that value.
$(document).ready(function() {
$('#forgotten').click(function () {
if($('#button').val() === 'Login') {
$('#button').val('Send New Password');
}
else {
$('#button').val('Login');
}
return false;
});
});
PhpStorm tells me
Duplicated jQuery selector
Inspection info: Checks that jQuery selectors are used in an efficient way. It warns about duplicated selectors which could be cached and optionally about attribute and pseudo-selectors usage
Does this really matter? (I suspect not, it's micro-optimisation)
Is there a better way of writing this code (I suspect so)?
What is this better way?
Attempts:
if($('#button').val() === 'Login') {
$(this).val('Send New Password');
}
else {
$(this).val('Login');
}
The above code using this doesn't work; It seems that the JQuery isn't aware of what this is because it's not an invocation.
Attempt two is to use This useful answer:
$('#something')[$(this).val()=='X'?'show':'hide']();
But I can't see the syntax of how to apply this to swapping the value.
$('#button')[$(this).val() === 'Login'?$(this).val('Send New Password'):$(this).val('Login')];
The above attempt does not make the change expected (and does not give any console notices).
So, how do I do it; how do I write the original IF statement without repeating the reference?
Creating a jquery has (some, minor) overhead, so is not the most efficient. Your first code could be written as:
var btn = $("#button");
if (btn.val() === 'Login') {
btn.val('Send New Password');
}
else {
btn.val('Login');
}
while, in this case, it's a micro-optimisation, if you were doing this 1000s of times with very complicated selectors, it can save a lot of time to only run the jquery selection once.
Regarding your other attempts, using this will only make sense if this has relevant context, eg if inside an event:
$("#button").click(function() {
var btn = $(this);
...
In the case of .val() (and many other jquery functions (but not all)) a callback can be provided which is called for each entry in the jquery collection.
https://api.jquery.com/val/#val-function
A function returning the value to set. this is the current element. Receives the index position of the element in the set and the old value as arguments.
In your case, this becomes:
$("#button").val(function(i, v) { return v === "Login" ? "Send new" : "login" });
This will run the callback function on each item in the collection provided by the selector, so very useful if you want to run against multiple items with different results on each, example:
$(".button").val(function(i, v) { return v === "Login" ? "Send new" : "login" });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="button" class="button" value="Login"></input>
<input type="button" class="button" value="Login"></input>
<input type="button" class="button" value="Not Login"></input>
Whenever you call $("#button") jQuery searches the document and gets the corresponding DOM element. So you can try to assign the selection to a variable as followings to avoid the repetition of the search:
var btn = $('#button');
if(btn.val() === 'Login') {
btn.val('Send New Password');
}
else {
btn.val('Login');
}

understanding an eventListener solution from Eloquent JavaScript

Help would be really appreciated, I’ve been trying to figure this out for hours now.
So this was the solution to an exercise I was doing:
<!doctype html>
<tab-panel>
<div data-tabname="one">Tab one</div>
<div data-tabname="two">Tab two</div>
<div data-tabname="three">Tab three</div>
</tab-panel>
<script>
function asTabs(node) {
let tabs = Array.from(node.children).map(node => {
let button = document.createElement("button");
button.textContent = node.getAttribute("data-tabname");
let tab = {node, button};
button.addEventListener("click", () => selectTab(tab));
return tab;
});
let tabList = document.createElement("div");
for (let {button} of tabs) tabList.appendChild(button);
node.insertBefore(tabList, node.firstChild);
function selectTab(selectedTab) {
for (let tab of tabs) {
let selected = tab == selectedTab;
console.log(selected)
tab.node.style.display = selected ? "" : "none";
tab.button.style.color = selected ? "red" : "";
}
}
selectTab(tabs[0]);
}
asTabs(document.querySelector("tab-panel"));
</script>
the part that confused me is on line 13:
button.addEventListener("click", () => selectTab(tab));
Normally when adding event listeners, you wouldnt need to place a function call inside another function - it would be sufficient to say something like this:
button.addEventListener("click", selectTab(tab));
However when I do, an error comes up saying:
ReferenceError: tabs is not defined (line 15 in function selectTab)
called from line 7 in function Array.from.map.node
called from line 3 in function asTabs
called from line 25
and that’s where I’m lost.
Thanks for your time as always
Normally when adding event listeners, you wouldnt need to place a
function call inside another function - it would be sufficient to say
something like this:
button.addEventListener("click", selectTab(tab));
That isn't true.
The second argument to addEventListener needs to be a function. That function will be called when the event happens.
selectTab(tab) calls the selectTab function immediately (passing it the value of the tab variable). You can only do that if that function's return value it another function.
However when I do, an error comes up saying:
ReferenceError: tabs is not defined (line 15 in function selectTab)
tabs is defined then the Array.from call finished evaluating. The event listener is added as part of the evaluation of that. i.e. before the value has been assigned to tabs.

Javascript and JQuery Dom Global Variable Scope

I have problem with scope of the variable in the code
var ButtonPressed; //global SCOPE
$(document).ready(function()
{
function messageAlert()
{
$('#buttons').append('<input type="button" id="btn" value="Clickme" />');
return false;
}
messageAlert();
$('#btn').on("click", function()
{
ButtonPressed = 1;
});
}); //end document
//// UNDEFINED NOT WORKING
if (ButtonPressed === 1)
{
alert(ButtonPressed);
}
I try everything about scope tutorials but I can't show variable ButtonPressed=1 GLOBAL.
Any help ?
You are binding a click event to the button #btn to set the global variable ButtonPressed which will not be fired unless you click the button.
When your code executes and reaches the block (which is in the global scope) knowing that the button have not been clicked
if (ButtonPressed === 1)
{
alert(ButtonPressed);
}
The variable ButtonPressed will not be set because you haven't clicked the button so it will not alert any message.
In other words, the if statement runs before the click handler
Explaining your code. the execution goes this way ( 1 ) --> ( 2 ) --> ( 3 )
var ButtonPressed; // executed as soon as the script tag is hit -- ( 1 )
$(document).ready(function()
{
//...... //executed ONLY AFTER the DOM is ready - (3 )
});
if (ButtonPressed === 1) //executed as soon as the script tag is hit - ( 2 )
{
alert(ButtonPressed);
}
as the comments indicate, the var ButtonPressed is executed first, then the execution skips to the if check . Only after the DOM is completely ready then your code block inside the $(document).ready will execute.
So that means all the global scope code stuff will get executed first and then the one's inside the document ready
1) If your intention is to Show a alert when ever a button is clicked then do this
$('#btn').on("click", function()
{
ButtonPressed = 1;
alert(ButtonPressed);
// do all the stuff that should happen when a button is clicked
});
2) Else if your intention is to Check if a button was clicked?? then you can make use of the setInterval. using this you can check if a button was clicked or not for every say 1 secs. Like below.
var checkButtonStatus = setInterval(function(){
if (ButtonPressed === 1)
{
alert(ButtonPressed);
//do all your stuff as the button was clicked
clearInterval(checkButtonStatus ); // remove interval as you don't need to check again.
}
}, 1000);
Note: I would say option 2 is not efficient way of doing it, Go for option 1

Click toggle with jquery/javascript

I want to click a table element and to have it do x the first click and if clicked again perform Y
<td class='p' id='e1' onclick="myFunction2()"><img src='person2.png'/></td>
Thats what I have for my HTML for one click just now, but I wish to change that so that an item can be selected, then if clicked again for a deselect it would then trigger a different function.
I'm going to assume (you didn't say) that you want the function to be called to alternate with every click:
$('#e1').on('click', function() {
// retrieve current state, initially undefined
var state = $(this).data('state');
// toggle the state - first click will make this "true"
state = !state;
// do your stuff
if (state) {
// do this (1st click, 3rd click, etc)
} else {
// do that
}
// put the state back
$(this).data('state', state);
});
This uses jQuery's .data feature to store the button's click state in the button element itself.
Alternatively, you could use an external variable, but you should enclose the callback in a closure (in this case an immediately invoked function expression) to prevent the variable from becoming a global variable:
(function() {
var state;
$('#e1').on('click', function() {
state = !state;
if (state) {
// do this (1st click, 3rd click, etc)
} else {
// do that
}
});
})();
If the .on call and the state variable declaration are inside a jQuery document.ready handler that would have the same effect.
Pretty basic, let me know if this is close to what you want.
http://jsfiddle.net/WNJ75/6/
<div id="e1">Click Me</div>
.
(function() {
var click_track = 1;
$("#e1").click(function() {
if (click_track == 1)
alert("do something");
else if (click_track == 2) {
alert("do something else and reset click");
click_track = 0;
}
click_track++;
});
})();
demo: http://jsfiddle.net/HJwJf/
Link the toggle method with;
$("button").toggle(function(){
$("body").css("background-color","green");},
function(){
$("body").css("background-color","red");},
function(){
$("body").css("background-color","yellow");}
);
You could create a new atribute on the HTML element named, for example, "clickCount", and use it inside your event handler as a counter.
Let's say you have a button like this one:
<button data-click-count='0' onclick="myFunction(this)">My Button</button>
And you have a function like this:
function myFunction(elt) {
// Gets the clicks count
var count = $(elt).data("click-count");
// Adds one to the click counter
$(elt).data("click-count", ++count);
if (count == 1)
doSomething();
else if (count == 2)
doSomethingElse();
}
Every time you click the button, you'll see an alert with the number of clicks you've made.
You can use the same method and apply it to your case.
Using a state variable. The state variable will swap between the values 0 and 1 on each click. Making use of state we can execute the corresponding function in fn array.
<td class='p' id='e1'><img src='person2.png'/></td>
$("td#e1.p").each(function(){
var state = 1, fn = [myFunction1, myFunction2];
$(this).click(function(){
return fn[state = 1 - state].apply(this, arguments);
});
});
Also, it's preferably to use proper event binding than inline JavaScript.

How to capture clicked button in js functions?

I have to buttons like this:
<input type='submit' id='submit' class='processAnimation'>
<input type='reset' id='reset' class='processAnimation'>
Now I have two js function. First function is called when ajax request is started and seconf function is called when ajax request is completed.
this.showLoading = function () {
backupsource = $('.processAnimation').attr('class');
$('.processAnimation').removeAttr('class').addClass('disabled-btn processAnimation');
$('.processAnimation').attr( 'backupsource', backupsource );
}
this.hideLoading = function () {
backupsource = $('.processAnimation').attr('backupsource');
if( backupsource != undefined ) {
$('.processAnimation').removeAttr('class').addClass( backupsource );
$('.processAnimation').removeAttr('backupsource');
}
}
EDIT: Above two functions are working and moving flower replaced clicked button. When request is complete then button is back. Problem is that when I click one button it replace all buttons(class=procesAnimation) with moving flower.
Thanks
Since you haven't posted your click event binding I am going to take a quick guess and say that your selector is not set right or conflicts with another element. try something like this:
$('input').click(function(){
switch( $(this).attr('id') ){
case 'submit' :
ShowLoading();
break;
case 'reset' :
HideLoading();
break;
}
});
and change the syntax of how you initialize the two functions to the following:
function ShowLoading(){
//do your show loading procedure here
};
function HideLoading(){
//do your hide loading procedure here
};
This is using the code u have currently
$('.processAnimation').click(function (){
if($(this).attr('type')=='submit'){
//submit has been clicked
}else{
//reset has been clicked
}
});
but it looks like you should really be using ID's rather than class's
if you have jQuery it is simple
$('#submit').click(showLoading)
$('#reset').click(hideLoading)
Just two different binding of events.
or did I miss something? :)

Categories

Resources