Creating closures in a loop in JavaScript - javascript

I have this scenario:
<html>
<head>
<script type="text/javascript" src="jquery-1.4.4.js"></script>
<script type="text/javascript">
var actions = {
'view' : function(){alert("view");},
'history': function(){alert("history");},
'renewal': function(){alert("renewal");}
}
for(var action in actions){
$('.' + action).live('click', function(e){
e.preventDefault();
if(actions[action])
actions[action]();
});
}
</script>
</head>
<body>
<a class="view" href="#">view</a>
<a class="history" href="#">history</a>
<a class="renewal" href="#">renewal</a>
</body>
</html>
I think a closure is created, since clicking a link always alerts "renewal" and I am not able to fix it.

Why dont you try using the classname in the click event?
I'm no jQuery expert, but something like this:
$('.' + action).live('click', function(e)
{
e.preventDefault();
if(actions[this.className])
actions[this.className]();
});

It is indeed. You can replace
for(var action in actions){
$('.' + action).live('click', function(e){
e.preventDefault();
if(actions[action])
actions[action]();
});
}
with
for(var action in actions){
$('.' + action).live('click', function(e){
e.preventDefault();
var currentAction = $(e.target).attr('class');
if(actions[currentAction])
actions[currentAction]();
});
}
By the way, the problem is not that there is a closure. Indeed, if there was not a closure, the value of the variable action would not be rembered at all! The problem is that all the functions in the loop refer to the same variable action, that at the end of the loop will have the value renewal.

There are better ways of doing this, but to make your solution work:
for(var action in actions){
(function(myAction){
$('.' + myAction).live('click', function(e){
e.preventDefault();
if(actions[myAction])
actions[myAction]();
});
})(action);
}
You are going to find out that live is not going to cancel the default action, You are going to want to use delegate

That's not what happens. Instead, your event handler function references the action variable, which will always have the value 'renewal', since that 's the last item in the list after the loop is done. The best way to go about it is to replace the loop with something like that:
for(var action in actions) {
$('.' + action).live('click', function(e){
e.preventDefault();
var action = $(e.currentTarget).attr('class');
if(actions[action]) actions[action]();
});
}

Related

Get HTML from global variable (common) declaration

How can I get the HTML of the clicked anchor tag from global variable properties?
For example, I have Google, Yahoo, Apple etc. links and onClick of any link I need to alert this HTML.
I can achieve this by variable declaration inside function, but I have 3,000+ functions in same page with different class/id which I have difficulties to do so.
Google<br>
Yahoo<br>
Apple<br>
Samsung
<!-- and so on... -->
var myHtml = $(this).html();
$(document).on('click', '.action', function() {
alert(myHtml);
});
I can do this by below code, but need to add the same code for all the functions
var myHtml;
$(document).on('click', '.action.g', function() {
myHtml = $(this).html()
alert(myHtml);
});
FIDDLE
This works smoothly
$('.action').on('click', function(event){
alert(event.target.text);
});
Her is a working Fiddle
Try this, as suggested by #Rory
var myHtml;
$(document).on('click', '.action', function() {
myHtml = $(this).html()
alert(myHtml);
});
Hope this helps
Use onclick on the links
function a(e) {
alert($(e).html())
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Google<br>
Yahoo<br>
Apple<br>
Samsung

How to know which anchor is clicked in jquery?

I have this code:
HTML:
<ul class="dropdown-menu" role="menu" id="document_dropdown">
<li><a class="notify" href="toSomewhere" id="1">Item1</a></li>
<li><a class="notify" href="toSomewhere" id="2">Item1</a></li>
<li><a class="notify" href="toSomewhere" id="3">Item1</a></li>
<li><a class="notify" href="toSomewhere" id="4">Item1</a></li>
</ul>
JQuery:
$(document).ready(function () {
$('#document_dropdown .notify').click(function(){
var id = $(this).attr("id");
alert(id);
});
});
What I want to achieve is to see which anchor is clicked and return the id of that anchor so that I can use it in another script. So far it doesn't do anything. What might be wrong with my code? Can anyone help me with this? Thank you very much.
The code you have will work fine, although this.id is a more succinct method of retrieving a native property from an element. If you wish to stop the clicking of the link causing the browser to make an HTTP request, you would need to add preventDefault() to your logic.
You cannot return anything from an event handler, so instead if you need to pass information around you would need to either store it in a global variable, or call another function with that value as a parameter.
$('#document_dropdown .notify').click(function(e){
e.preventDefault();
var id = this.id;
alert(id);
doSomething(id);
});
function doSomething(id) {
alert('You clicked #' + id);
}
Example fiddle
you just need to do this :
$(document).ready(function () {
$('#document_dropdown .notify').click(function(){
var id = this.id;
alert(id);
});
});
Thats it.
The event handler cannot return anything. You need to call another script function and pass the ID as as argument.
$(document).ready(function () {
$('#document_dropdown .notify').click(function(evt){
var id = this.id;
alert(id);
anotherScriptFunction(id);
evt.preventDefault();
});
});
You can pass in the event handler like this:
$(document).ready(function () {
$('#document_dropdown .notify').click(function(e){
var id = e.target.id;
alert(id);
});
});
In this way, e.target is the element you have clicked on. You can wrapper it into a jQuery element through $(e.target).

Append to a.href id from input field

I am trying to append to a link with id a value that is entered from the input text field. I came this far searching stackoverflow but id doesn't work!
<script type="text/javascript">
jQuery(function(){
$("#txt_name").keypress(function() {
var value = $("#txt_name").val();
});
$("a#coupon_link").attr("href", function(i) {
return href + '&discount_code='.text(value);
});
});
</script>
and this is how the html looks like
<form>
<fieldset>
<input id="txt_name" type="text" value="discount" />
</fieldset>
</form>
<a id="coupon_link" href="https://www.e-junkie.com/ecom/gb.php?c=cart&i=XXXXXX&cl=YYYYYY&ejc=2" target="ej_ejc" class="ec_ejc_thkbx" onClick="javascript:return EJEJC_lc(this);"><img src="http://www.e-junkie.com/ej/ej_add_to_cart.gif" border="0" alt="Add to Cart"/></a>
You probably meant this:
$(function() {
$("#coupon_link").on('click', function(e) {
e.preventDefault(); // apparently not needed
location.href = $(this).attr('href') + '&discount_code=' + encodeURIComponent($('#txt_name').val());
});
});
You don't have to update the value of #txt_name on keypress; you only have to use the value when the link is pressed.
Fix your code like this :
$(function(){
$("#txt_name").keypress(function() {
var value = $("#txt_name").val();
var link = $("#coupon_link");
var originalHref = link.attr('originalHref');
if (!originalHref) {
originalHref = link.attr("href");
link.attr("originalHref", originalHref)
}
link.attr("href", originalHref + '&discount_code='+value);
});
});
A few things to note :
never add anything to a selector when you're targeting an element by ID
your value variable wasn't in the same scope
the return of val can be directly concatenated, you don't need to try to change it to text
you don't need to pass a function to attr in your case
you're trying to make the href grow with every key stroke. This is a bad idea. The solution I propose is to keep the original href
if you're not sure the original href has yet some parameters (i.e. has '?') you should test it (I let you do that)
Overall a much cleaner solution wouldn't be to change the link but to build the href on click on the link :
$("#coupon_link").click(function(e) {
location = this.href + '&discount_code=' + $('#txt_name').val();
});
Not sure to understand, but it looks like a scope issue try this javascript :
<script type="text/javascript">
jQuery(function(){
var value = 0;
$("#txt_name").keypress(function() {
value = $("#txt_name").val();
$("a#coupon_link").attr("href", function(i) {
return href + '&discount_code=' + encodeURIComponent(value);
});
});
});
</script>
Try this:
jQuery(function(){
$("#txt_name").keypress(function() {
var value = $("#txt_name").val();
$("a#coupon_link").attr("href", '&discount_code=' + String(value));
});
});
This isnt working because the href isnt being changed as the function is called before a keypress event is triggered. Look into replacing keypress with blur and update the href when blur() is called
i think you need this:
<script type="text/javascript">
$(function(){
$("#txt_name").keypress(function() {
var value = $("#txt_name").val();
$("a#coupon_link").attr("href",href+'&discount_code='+value.toString);
});
});
</script>
look at href don't know where you have that var, if it is needed ok else remove that
You probably need to change the href when a key has been pressed, not only on page load. To do so you will have to do the replacing of the href inside the keyup function, like so:
$(function(){
var link = $("a#coupon_link");
link.data('href', link.attr("href"));
$("#txt_name").on('keyup', function() {
link.attr("href", link.data('href') + '&discount_code='+ this.value);
});
});
So as to not append the &discount_code=*** several times, you need to store the original href somewhere, like in a data attribute.
this one worked for me getting value from input field and append it to the existing link using jquery.
$('#qty').on('keyup', function() {
var theQty = 0;
theQty = $("#qty").val();
var oldHref=$("a#buybtn").attr("href");
$("a#buybtn").attr("href",oldHref+ '&qty=' + String(theQty));
});

html + jquery ( Bind onclick event for execute action before onclick )

I have a question about "event click" and "order of execution".
I make a example here ( The HTML is generated by a external javascript ) :
HTML:
Comment​
JavaScript:
$(document).ready(function(){
$('#comments-replybutton').click(function(){
alert('2 attach event');
});
});​
I want that when do click in "Comment" first execute the action of jquery (bind event).
Is this possible?
I believe you're looking for preventDefault().
More here.
$(document).ready(function(){
$('#comments-replybutton').click(function(e){
e.preventDefault();
alert('2 attach event');
});
});​
$(document).ready(function(ev){
$('#comments-replybutton').click(function(ev){
alert('2 attach event');
ev.stopPropagation();
});
});​
You mean, like this?
Edit after comment
You can also name your function to unbind:
var myEventHandler = function myFunction(ev){
$(this).unbind(myFunction);
alert('attach event 2');
ev.stopPropagation();
}
$('#comments-replybutton').bind('click', myEventHandler);
// $(something).click(fn) is just a shorthand to $(something).bind('click', fn);
Edit 2
I guess you can kill off the original event easily, just by saying document.getElementById('comments-replybutton').onclick = "" or something similar. You can re-attach it by copying before:
var original_event_handler = $('#comments-replybutton')[0].onclick;
$('#comments-replybutton')[0].onclick = "";
$('#comments-replybutton').click(original_event_handler);
A bit dirty, but I'm too lazy to look it up :S preventDefault won't help you here, though.
http://jsfiddle.net/C37ka/
try this:
$(document).ready(function(){
$('#comments-replybutton').unbind('click').click(function(){
alert('2 attach event');
});
});​
and if you need also to execute the inline statement at the end, you will need something like this:
$(document).ready(function(){
var initialEvent = $('#comments-replybutton')[0].onclick;
$('#comments-replybutton').click(function(){
alert('2 attach event');
}).click(initialEvent);
});​

How to pass a variable from a link to a jQuery function

I would like a jQuery function to know which link was clicked to call it, i.e. I would like the link's id value to be passed to the jQuery function.
Is this possible? If so what is the neatest way to do it.
Sure. Inside the click() event handler you can refer to the element clicked by this.
$("a").click(function() {
alert(this.id);
...
});
or
$("a").click(function() {
alert($(this).attr("id"));
...
});
$("a").click(function() {
var linkid = $(this).attr("id");
// use linkId here
});
Don't forget to cancel default behaviour, or you won't achieve nothing.
$("a").click(function(e) {
e.preventDefault();
var linkid = $(this).attr("id");
//do whatever here
});
$("a").click(function() {
alert($(this).attr("id"));
...
});
i can say this same..

Categories

Resources