JavaScript incrementing a variable - javascript

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 ... :-)

Related

A function with changing variable, dependent on a class

So, first some background.
I have 9 types of rooms that are displayed as thumbnails with the name. What I want to do is that on click "Additional Information" - the rooms with disappear and the expanded version of a chosen room type will appear with the description and bigger picture. Also, there is an ability to go next and previous in the expanded view. I do not have a problem with this expansion and previous/next. BUT!
Here is what I am trying to achieve: if the code looks approximately like
<ul id="room_holder">
<li><div class="room 1">Additional Info</div></li>
<li><div class="room 2">Additional Info</div></li>
and so on...
And the expandable area will look something like:
<div id="expandable">
<div id="picture">Blah-blah-blah, some description, etc</div>
</div>
So, basically, what I can't figure out is how to get the needed slide to show when the correspondint thumbnail is pressed. I know I can do the .addClass method, and copy the code 9 times, for each of the numbers (1-9). But I believe it is 9 times more compact if I have some sort of function, that gets the second class name (the number) by using .split(' ')[1] and then using it as part of the variable in the part which opens the corresponding expandable view. So, my question is: how do I do this? I am a newbie with javascript, but try to learn on the go!
Oh, and the codepen that I've been trying to deal with is:
http://codepen.io/godban/pen/QbZmxz
Firstly, you should use data-* attribute instead of classes (new in HTML5) data attributes, w3school :
<ul id="room_holder">
<li><div class="room" data-room="1">Additional Info</div></li>
<li><div class="room" data-room="2">Additional Info</div></li>
Then, use the click function from jQuery .click( handler ), use it this way to know which one has been clicked :
$(".room").click(function(event){
var target = event.currentTarget;
var room = $(target).data("room");
alert(room);
});

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

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',

How can I dynamically set an id within a Javascript loop?

I have a list of Questions, and each of those Questions has a list of Answers (which can be any integer from 1-5). I would like to dynamically create a chart for each Question, using the count of all answers that match a specific "rank"; i.e. all the answers that were a '1', '2', '3', etc.
So what I've done is set a for loop that creates an element for each question; this element is used as a placeholder for the chart. (As an aside, I am using flot charts).
The problem I'm having is trying to name the placeholders dynamically; what I really want is to create something that ends up looking like this:
<div id='chart1'/>
<div id='chart2'/>
etc
The closest I've managed is this:
<div id="'chart'#currentQuestion"/>
which of course gives an id like this: 'chart'1
Later, when I try to append the chart to the div I've created, the following doesn't work:
$("#'chart'"+i).append(div); //where i is the current loop counter
If I use
$("#chart"+i).append(div);
it correctly finds the element 'chart1', 'chart2' etc; but I'm struggling to name the div to match.
Can anyone help? It seems trivial unless you know how to solve it :-)
Edit: As requested, here is the relevant HMTL:
<div id="'chart#currentQuestion'">CHART</div>
SOLVED:
Like this: id="chart#(currentQuestion)" (via a colleague) Thanks for your efforts.
You haveen't close your div correctly. try this code
<div id='chart1' style="border:dashed">
</div>
<br />
<div id='chart2' style="border:dotted">
</div>
<script type="text/javascript" src="jquery_library.js">
</script>
<script type="text/javascript">
function fnc(value){
$("#chart"+value).append('1');
}
</script>
<input type="button" onclick="fnc(1)" value="for div1"/>
<input type="button" onclick="fnc(2)"value="for div2" />
You are using razor syntax, so here how it should be.
// Define your counter
#{long i = 0;}
// On document ready dynamically add your items
$("document").ready(function(){
// Create red divs starting by zero
// after 5 divs stop creating red divs
#for (i = 0;i<5;i++){
#:$("#form").append('<div id="chart' + #(i) + '">Red</div>');
}
});
// I made a button for action, you can choose other ways to invoke this function
$("#form>input").click(function(){
// Your counter is at 4 now
// lets change it to 2
#(i = 2;) // Now your counter is at 2
// Put a blue div into 2nd div starting by 0
$("#chart"+#(i)).append('<div class="blue">blue</div>');
});
this is how you use razor syntax with scripts

What's wrong with this jquery loop?

To summarise briefly what I'm trying to do: I'm providing the facility for a user to view a gallery of thumbnail images, each with a corresponding download link. When the download link is clicked, I present the user with a confirmation div, and assuming the user clicks 'agree', they'll be able to proceed with the download of the full size version of the thumbnail.
To do this, I'm using a repeater to generate the thumbnails. I'm creating a unique id for each link within the 'ItemCreated' event, along with a unique hidden field that stores the relative path for the destination file for that thumbnail.
When the user clicks on the 'Download' link for the appropriate thumbnail, my code should select the 'agree' link, and update it's target path with the hidden field value of the item that was clicked (I hope that made sense?). This basically means whenever a 'Download' button is clicked, the 'agree' link is updated to direct you to the correct file.
The problem that I'm having however is that my 'agree' link never gets updated - it seems to point to the same file for every thumbnail.
Here's a snippet of the rendered thumbnail list:
<div class="download-listing">
<div class="download">
<img src="/img/thumb0.jpg" alt="" />
<div id="downloadLink0" class="dl">Download</div>
<input type="hidden" id="hf0" value="/GetImage.ashx?path=/img/0.jpg" class="hf" />
</div>
<div class="download">
<img src="/img/thumb1.jpg" alt="" />
<div id="downloadLink1" class="dl">Download</div>
<input type="hidden" id="hf1" value="/GetImage.ashx?path=/img/1.jpg" class="hf" />
</div>
<div class="download">
<img src="/img/thumb2.jpg" alt="" />
<div id="downloadLink2" class="dl">Download</div>
<input type="hidden" id="hf2" value="/GetImage.ashx?path=/img/2.jpg" class="hf" />
</div>
</div>
<input id="count" type="hidden" value="3" />
<!-- Hidden popup -->
<div id="popup">
<p><a id="close" class="bClose action">I disagree</a><a id="file-link" class="action" href="#">I agree</a></p>
</div>
Hopefully you can see from the above code that I'm trying to extract the hidden field path from the download that's clicked, and then update the #file-link 'href' with this value.
The Javascript/Jquery I'm using (and this is where the problem seems to be) is the following:
<script type="text/javascript">
$(document).ready(function () {
for (var i = 0; i < $("#count").val(); i++) {
var index = i;
$("#downloadLink" + index).click(function () {
$('#file-link').attr('href', $('#hf' + index).val());
$('#popup').bPopup();
});
}
});
</script>
However, none of this is working! What seems to be happening is that every download link points to the same path - the last one in the list. I can't figure out where I'm going wrong. Is there something obvious I'm missing?
I appreciate any help given!
Thanks
Isn't it easier to do this:
$(function(){
$(".download .dl").click(function(){
$('#file-link').attr('href', $(this).next("input").val());
$('#popup').bPopup();
});
});
Try Something like this...
$("div[id*='downloadLink']").click(function () {
$('#file-link').attr('href',$(this).siblings('img').attr('src'));
$('#popup').bPopup();
});
After a click on any download link, this code will pass the associated image href path to the file-link element.
here is the working fiddle
I'd recommend against using all those input fields. It just creates a bunch of unnecessary markup. Why not store the #count value simply in a JavaScript variable? And the inputs that contain the image paths could be removed as well. You could store that info in an attribute on each download link, named something like "data-path". For example:
<div id="downloadLink0" class="dl" data-path="/GetImage.ashx?path=/img/0.jpg">Download</div>
Now, going back to your original problem, the above markup would solve the issue quite easily:
$('.dl').click(function(){
$('#file-link').attr('href', $(this).attr('data-path')); //could also do $(this).data('path') if using jQuery 1.6 or later
$('#popup').bPopup();
});
Other people have already suggested different ways to achieve what you want, but nobody explained why your current code doesn't work.
The reason it currently doesn't work is because of how scope works in Javascript. There is no block scope* and so your index variable is defined once, and updated every time the loop runs, until in the end it has the maximum (last) value. Then whenever your event handler is run, index still has this value, and the last item will be used.
So, in JS, the easiest way to get a new scope is to use a closure. Here's an example adapted from your code:
$(document).ready(function () {
for (var i = 0; i < $("#count").val(); i++) {
var fn = (function(index) {
return function () {
$('#file-link').attr('href', $('#hf' + index).val());
$('#popup').bPopup();
};
})(i);
$("#downloadLink" + i).click(fn);
}
});
This is not as good a way to solve your actual problem as some of the other answers. However, it demonstrates the concept of creating a scope: you're calling a function that takes one parameter, index, for which you pass the loop iterator variable i. This means that the function inside it (which it returns) can now always access the value of this parameter. The inner function gets stored in fn, which then gets passed as the click handler.
If this looks really tricky, here's a more in-depth look at function and scope in Javascript.
*Note that proposed new versions of Javascript/Ecmascript may add block scoped variables. It is not currently implemented in a cross-browser fashion, however.
You should probably calculate it from the event source (#downloadLinkn), by getting n from the end of the 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