.next() jumps two steps instead of one, what's wrong? - javascript

I'm making a web-based quiz.
When I press an answer I want the count at the top to change to the next, however it keeps skipping one digit, jumping to the next (e.i. from I to III, instead of I to III).
What am I doing wrong?
Site: http://www.carlpapworth.com/friday-quiz/#
Html:
<ul id="count">
<li><h4>I</h4></li>
<li><h4>II</h4></li>
<li><h4>III</h4></li>
<li><h4>IV</h4></li>
<li><h4>V</h4></li>
<li><h4>VI</h4></li>
<li><h4>VII</h4></li>
<li><h4>VIII</h4></li>
<li><h4>IX</h4></li>
<li><h4>X</h4></li>
</ul>
JS:
$('#count li:first').addClass('cCurrent');
$('.qAnswers li a').click(qNext);
function qNext(){
$('.cCurrent').next('#count li').addClass('cCurrent');
$('.cCurrent:first').removeClass('cCurrent');
}

The js/custom.js script is mentioned twice in the <head>. You should remove one of them, otherwise the click events are registered twice.
Furthermore, the expression inside .next() looks somewhat odd (you don't need the #count in there and maybe not even li) and the function itself can be simplified to this:
function qNext()
{
$('#count .cCurrent')
.removeClass('cCurrent')
.next('li')
.addClass('cCurrent');
}
It removes the class of the currently highlighted <li>, then moves to the next <li> and applies the cCurrent class there.
Lastly, you shouldn't give your answers a class that gives away that the answer is correct or wrong. Your answers had something like this:
xxx
xxx
If someone would look at the source, it would be very obvious what to click.

I don't see anything wrong in your javascript, but your HTML page includes the same script twice. If the click event is registered twice, it probably causes your issue.
<script type="text/javascript" src='js/custom.js'></script>
<script type="text/javascript" src="js/jquery.easing.1.3.js"></script>
<script src='js/custom.js'></script>

I'm not that familiar with jquery specifics, but I would debug this with adding some trace, inna spirit of:
function qNext(){
// Output data on what is your current question
$('.cCurrent').next('#count li').addClass('cCurrent');
// Output something - so you know for sure that this is the line that does the double move
$('.cCurrent:first').removeClass('cCurrent');
}
And you can also try:
function qNext(){
// Output ...
$myObject = $('.cCurrent');
// Output ...
$myObject2 = $myObject.next('#count li');
// Output ...
$myObject2.addClass('cCurrent');
// Output ...
$('.cCurrent:first').removeClass('cCurrent');
}

the qnext function is working correctly
I assume the Problem is that theres also another click event, which does also slide one Question to the right, added to the answers by the slider (ulslide). Try to comment out this line and see if it works
nextButton: '.qAnswers a',

Related

What can cause click() method to fail?

I have an element (a checkbox), with this HTML:
<button type="button" class="_f_V1 noMargin o365button" aria-labelledby="_ariaId_28" role="checkbox" aria-checked="false">
<span class="_fc_3 owaimg checkboxImage wf-size-checkboxMultiselectSize ms-bg-color-white ms-border-color-neutralSecondaryAlt"> </span>
<span class="_fc_4 o365buttonLabel _fc_2" id="_ariaId_28" style="display: none;"></span>
</button>
Note it's a button element even though it behaves like an <input [type="checkbox"]>.
I aim to select and click on this element with the click() method. The selection is correct, but the click() method fails.
What I did:
document.querySelector('._f_V1.noMargin.o365button').click();
Yet nothing happens - the checkbox won't be checked.
Given this (first) element is but one of a list of similar elements, I've also tried:
(()=>{
document.querySelectorAll('button span').forEach((e)=>{
e.click()
});
})();
Again, neither the first, nor any other checkbox is selected.
From running querySelector() and querySelectorAll() (with their relevant selectors) in console, I get the elements I want (I don't get undefined), so it means my selections are correct.
Given the selections are correct, why would the click() method have no effect?
When I click with the mouse --- the checkbox is checked but when I use click() on the same element, it doesn't.
If you want to try to reproduce online, you need to have an Hotmail email account with messages that you've already deleted. If this is the case:
Go to "Deleted items".
Go to "recover deleted items".
a window will be opened with deleted conversations.
Near to each conversation there will be a checkbox (after mouseover). This is the element I'm having the trouble with.
Note: The mouseover just changes opacity of the checkboxes.
If the question is:
What can cause click() method to fail?
Then the Answer is: Kinda NOTHING! If the click-method is available for an HTMLElement then calling HTMLElement.click() can not "fail" (in that sense). What could happen is that calling click on this element will not have the desired effect/impact - which is the case for the questions author! "just for the sake of completeness..."
After deeper investigation, here is my conclusion.
The actual event handlers that are responsible for checking and unchecking (and all that is related to it) are callbacks "listen to" mousedown-events on these button._f_V1.noMargin.o365button-elements (boot.worldwide.0.mouse.js:37); so you will not get anywhere triggering click-events. One may ask: "how can you say so?". I can say so because I removed ALL other event listeners first traversing up two parents and then from there on all the way down with each and every child element except for the button where I left the mousedown-eventListener. And the functionality was still intact. After removing also this last event listener the functionality was gone. So I guess: yep I can say so :)
My next step was to trigger a mousedown-event on the button like this:
$('._f_V1.noMargin.o365button').each(function() {
$(this).mousedown();
})
But NO this doesn't work.
So what about hysterically triggering events on every maybe-relevant element like this:
var $El = $('._f_V1.noMargin.o365button').parent().parent();
$El.add( $El.find('*') ).each(function() {
$(this).mousedown().mouseup().click();
// may be one event is cancelling the result of another one out
// so I also tried $(this).mousedown()
});
NO - this also doesn't work.
So I came up with my last approach which didn't work either. Let’s mimic the attributes and properties from selected button. BTW the element that is actually responsible for making the "pseudo checkbox" look like checked/unchecked is the first span-childNode of the button-element. So if you type in the following code in the console of your browsers devtool everything will look exactly as it was properly clicked (or mousedowned so to say):
$('._f_V1.noMargin.o365button').each(function() {
$(this).trigger('mousedown').addClass('_f_V1 noMargin o365button _f_W1').attr('aria-checked', 'true').prop('aria-checked', true)
.children(':first').trigger('mousedown').addClass('_fc_3 owaimg ms-Icon--check wf-size-checkboxMultiselectSize ms-bgc-w ms-fcl-nsa-b ms-fcl-ns-b ms-border-color-neutralSecondaryAlt')
.parent().parent().parent().trigger('mousedown').attr('aria-selected', 'true').prop('aria-selected', true)
})
See the screen capture below where I pastet the above snippet straight into devtools console and the "pseudo checkbox" appear as they where clicked.
So what to do now? Ask another question! One that is much more specific. Something like: "How to [recover|deepDelete] all deleted messages in hotmail.com" Because this is what the intent of the question actually is - not sure about it but I guess.
Just want to emphasize this once more: In general the code from OP and also the code in this answer works. It does right, so to say. But it’s not able to achieve what the author wants to achieve.
Additionally here is a proof that the OPs code is actually working:
document.querySelector('._f_V1.noMargin.o365button').addEventListener(
'click', function() { console.log('jepp') }
);
document.querySelector('._f_V1.noMargin.o365button').click();
// BTW: yep HTMLElement.click() returns undefined
console.log(
'yep HTMLElement.click() returns: ',
document.querySelector('._f_V1.noMargin.o365button').click()
)
button {width: 100%; height: 100%; position: fixed}
<button type="button" class="_f_V1 noMargin o365button" aria-labelledby="_ariaId_28" role="checkbox" aria-checked="false">
<span class="_fc_3 owaimg checkboxImage wf-size-checkboxMultiselectSize ms-bg-color-white ms-border-color-neutralSecondaryAlt"> </span>
<span class="_fc_4 o365buttonLabel _fc_2" id="_ariaId_28" style="display: none;"></span>
</button>
function handelClick(){
if(this.getAttribute("aria-checked")=="true"){
this.setAttribute("aria-checked", "false");
}else{
this.setAttribute("aria-checked", "true");
}
}
var button=document.getElementsByTagName('button');
for (var i = 0; i < button.length; i++) {
button[i].addEventListener('click', handelClick);}
goto https://jsfiddle.net/7xnwpgbk/5/
it may help you
You can try it with jQuery
click method which will only work on jQuery collections created like:
jQuery( 'your whatever selector(s) here' ) // form here on you can call .click() now
So for your specific approach you can do:
jQuery('._f_V1.noMargin.o365button').click();
as well as:
jQuery('button span').click();
Since jQuery click method does only trigger an on click event on the first DOM element of a jQuery collection you can combine it with jQuery method each as follows:
jQuery('._f_V1.noMargin.o365button').each(function() {
$(this).click();
});
as well as:
jQuery('button span').each(function() {
$(this).click();
});

Passing parameter to javascript onclick without using HTML

I can't figure this out. I'm trying to create an onclick handler purely in Javascript.
What I plan to do here is inside this DIV, have a collection of items that I can click on. For now, these items will be numbers from 0 to 9 inclusive. When a number is clicked on, a system message consisting solely of that number should pop-up on the screen. I narrowed my problem down to just the onclick handler definition.
If I use this format:
item[n].onclick=function(n){
handler(n);
}
The handler will fire only when click a number which is correct, but the message that appears is something about mouse event.
If I use this format:
item[n].onclick=function(){
handler(n);
}
The handler will pass a value of -1 which in turn is printed as a message. I think it means "false".
How do I modify this:
item[n].onclick=function(){
handler(n);
}
so that 'n' being used as the handler parameter is the same as the number I click on the screen?
My code is the following:
<div ID="Itemset"></div>
function handler(n){
alert(n);
}
collections=document.getElementById('Itemset');
for(n=0;n<10;n++){
item[n]=document.createElement('DIV');
item[n].innerHTML=n;
collections.appendChild(item[n]);
item[n].onclick=function(n){
handler(n);
}
}
What I'm effectively trying to do if you want to understand it HTML wise is this:
<div ID="Itemset">
<div onclick="handler(0);">0</div>
<div onclick="handler(1);">1</div>
<div onclick="handler(2);">2</div>
<div onclick="handler(3);">3</div>
<div onclick="handler(4);">4</div>
<div onclick="handler(5);">5</div>
<div onclick="handler(6);">6</div>
<div onclick="handler(7);">7</div>
<div onclick="handler(8);">8</div>
<div onclick="handler(9);">9</div>
</div>
Except that I don't want to write out onclick="handler(n);" a million times.
Any advice? and feel free to point to another resource that has the answer I need if there is one.
UPDATE
I'm looking for something compatible with older browsers as well. I'm going to have to not go for the bind function because according to mozilla docs, it works for IE 9+. I'm looking for something that works for IE 7+ as well as other browsers. I might have to go for event listeners if there is no other alternative.
You have a closure issue here (see JavaScript closure inside loops – simple practical example), a simple solution is to use bind to use the current value of n to be a parameter of the handler function
item[n].onclick=handler.bind(item[n],n);
U can use addEventListener and ID for find clicked element...
document.getElementById("Itemset").addEventListener("click", function(e) {
// e.target is the clicked element!
// If it was a list item
var value_data = parseInt(e.target.textContent);
if(e.target && value_data > -1) {
alert("Malai test:: "+value_data);
//handler(value_data);
}
});
https://jsfiddle.net/malai/tydfx0az/
I found my answer here: https://bytes.com/topic/javascript/answers/652914-how-pass-parameter-using-dom-onclick-function-event
Instead of:
item[n].onclick=function(n){
handler(n);
}
I have to do:
item[n].onclick=new Function('handler('+n+')');
Funny thing is, the word function needs to be capitalized when making a new instance. It's awkward I have to go this route but it works in IE 7+
One alternative is :
function handler(){
alert(this.id);
}
function myFunction() {
var item=[];
collections=document.getElementById('Itemset');
for(n=0;n<10;n++){
item[n]=document.createElement('DIV');
item[n].innerHTML=n;
item[n].setAttribute("id","itemset"+n);
collections.appendChild(item[n]);
item[n].onclick=handler;
}
}
Insert dynamic ids to the elements and when you click on any element retrieve its id using this.id and do whatever you want to do with that value.
That's all.
Hope this helps.

Trying to target a list item a with CSS current class to emphasize when active

I tried some stuff I found in past questions but unfortunately it hasn't helped. I think the reason may be it is deeply buried in CSS classes and I'm just inexperienced and not targeting it accurately, despite my attempts to use Chrome's inspect element to find exactly where it is. This is the code I have:
.multilanguage-widget.readmore ul.display-posts-listing li.listing-item a.current {
font-weight: bold !important;
}
and this is the page example I'm trying to do it on here.
See the list of Capabilities to the right side. Please help, I've been struggling with this for quite a while now and all my attempts have been failing.
You could write a script that removes the class from all active elements and adds it to the one that was clicked on:
<script type="text/javascript">
function active(e) {
$$('.current').each(function(i) {
i.removeClassName('current');
});
e.addClassName('current');
};
</script>
You can then call this function from your onclick events:
<a class="title" href="http://lumistaging.designiscasual.com/biometrics/" onclick="active(this)">Biometric Authentication</a>
<a class="title" href="http://lumistaging.designiscasual.com/barcode/" onclick="active(this)">Barcode Authentication</a>
(etc...)
I haven't tested it, but your CSS should work as it is.
If your pages are consistent enough, you could use something like this:
<script>
$(document).ready(function(){
$('ul.display-posts-listing li').children('a').filter(function(){
return ($(this).html() == $('h1.entry-title').html())
}).addClass('current');
});
</script>
I would put this in the header.php just before the </head> tag.

JavaScript incrementing a variable

I'm trying to increment a variable in JavaScript by clicking on a link, it works the first time but then every other time if I click on it once it will show up 3 times, then 4, 5 and so on.
A screenshot of the console:
The numbers in the blue (right) are as expected, there is nothing wrong with this but as you can see on the left, each line is one click. the first log is fine but then it logs 1 three times, then 10 four times.
Here is the code thats doing the work.
$('.here').live('click', function(eve) {
eve.preventDefault();
var curpop = $(this).attr('rel')
++curpop
$('.pop').html(curpop);
console.log(curpop)
})
$(this).attr('rel') is just a number (in the blue, right, in the picture) once you click the link it is meant to increment the number.
Thanks for you help.
EDIT: I have set up the same thing in jsfiddle but it seems to work there, and all the suggestions still dont work on my project even though they should.
<h4 class='left'>Click
<a class="here" href="#" rel="1">here</a></h4>
<h4 class='right'>
<span class='pop'>
1
</span>
</h4>
This is the html, now there are multiple of these but are loaded via ajax, I am guessing that it would have something to do with the multiple instances of the class with no identifier to separate them?
More EDIT
As I suspected the problem was with the "multiple instances of the class with no identifier to separate them" so I just made each one like this:
<span id="<?php echo $thereID; ?>_span" class='pop'>
1
</span>
then
$('#' + thereID + '_span').html(curpop);
Thanks for all the help
Need to see more code, but typically I see JS beginners adding the event inside of the event. In other words, every time the link is clicked, another event handler is added.
At any rate, here's an example of incrementing a counter in a click handler: http://jsfiddle.net/GSuSk/
GO UP
<p>0</p>
<script>
$('#link').click(function(){
var v=$('p').text();
$('p').text(+(v)+1);
});
</script>
Why dont you try this kind of method? Look here for demo
Not sure with this limited amount of code, but if I'm not mistaken, I think one problem is that the variable is being created within live and really should initialize outside so that it only needs grab it once, then increment from there on without having to grab the new value each time. Here is how I re-arranged it.
http://jsfiddle.net/robx/nDbb8/1/
<script type="text/javascript">
$(function(){
$('.here li a').click(function(){
var current = parseInt($(this).attr('rel'));
var inc = current + 1;
console.log(inc);
$(this).attr('rel',inc);
});
});
</script>
<div >
<ul class='here'>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</ul>
</div>
I don't think you need the live function here ... the key is to use parseInt to cast the current value of the rel attribute as it's being evaluated as a string ... :-)

Using javascript to insert id into list elements

I am messing around with a deck of cards that I made.I have it set up so that there is a method that spits out cards by suit into a list, so if I want spades I get a <ol> of all of the spades cards. I am now trying to give each <li> element an id depending on what card it is. ace will be <li id="ace"><img src="ace_spades.gif"/></li> king will be <li id="king"><img src="king_spades.gif"/></li> for example.The list is in order from top to bottom akqj1098765432 . I tried doing this:
var card_id=["ace","king","queen","jack","ten","nine","eight","seven","six","five","four", "three","two"];
var counter=0;
while (counter<=12)
{
$(document).ready(function(){
$("li").eq(counter).attr("id", card_id[counter])
});
counter++;
}
but it doesn't work. I have not really done anything with javascript before besides simple jquery stuff. What am I getting wrong here?
Try this:
$(document).ready(function(){
var card_id = ["ace","king","queen","jack","ten","nine","eight","seven","six","five","four", "three","two"];
$.each(card_id, function(i,id){
$("li").eq(i).attr('id',id);
});
});
You should try to only have one $(document).ready() function and it's not necessary to use a while() loop.
I think you don't need to call $(document).ready() function in the while. Try this:
var card_id=["ace","king","queen","jack","ten","nine","eight","seven","six","five","four", "three","two"];
var counter=0;
while (counter<=12){
$("li").eq(counter).attr("id", card_id[counter]);
counter++;
}
You do not need the document ready function. Place your script just before </body> and after the jquery.js script. This is working for me.
Check working example at http://jsfiddle.net/H8MeG/2/
First of ID's in a webpage have to be unique. Some browsers might ignore id's of elements that have already been used. Other browsers might fail completely...
Second off. you shouldn't use .eq() like that.
You definitely shouldn't add 12 new $(document).ready() statements.
Here's a more reliable version and the example on jsfiddle
var card_id=["ace","king","queen","jack","ten","nine","eight","seven","six","five","four", "three","two"];
$("#spades li").each(function(index){
$(this).attr("class", card_id[index]);
$(this).text(card_id[index]);
});
I also added $(this).text(card_id[index]); so you see it actually works. Try to uses classes for multiple elements that share the same characteristic.
why are you messing with ids at all?
you know that the first item is the ace, the second the king, and so on.
ol.getElementsByTagName('li')[12]='deuce'

Categories

Resources