jQuery two different ids trigger the same function - javascript

There are 2 ids #firstTableTotal, #secondTableTotal and 1 function contentchanged. How to make both ids(#firstTableTotal, #secondTableTotal) use the same function(contentchanged). I tried with the following codes but the result is not as expected.
$('#firstTableTotal').trigger('contentchanged');
$('#secondTableTotal').trigger('contentchanged');
$(document).on('contentchanged', '#firstTableTotal #secondTableTotal', function()
{alert("Calculations go here");
});

As mentioned already you are trigerring the event even before binding it... Also another problem is with your selectors... There must be a comma between each ID.. Else the meaning would be a parent child combination.
It should be
'#firstTableTotal, #secondTableTotal'
Right now what you have actually means select the element with ID secondTableTotal which is the child of a element with ID firstTableTotal.. Which is not the case in your code.
Your aim is to target both the elements. So place a comma between them. This makes the selector choose two different elements.

That is because you are triggering the event even before it is bound.
Also use a comma to separate the 2 different selectors
$(document).on('contentchanged', '#firstTableTotal, #secondTableTotal',

If contentchanged is an event:
var myFunc = function(){
alert("Calculations go here");
};
$('#firstTableTotal').on('contentchanged', myFunc);
$('#secondTableTotal').on('contentchanged', myFunc);
//Some time later
$('#firstTableTotal').trigger('contentchanged');
$('#secondTableTotal').trigger('contentchanged');
If contentchanged is in fact a function:
var contentchanged = function(){
alert("Calculations go here");
};
$('#firstTableTotal').on('some_event', contentchanged);
$('#secondTableTotal').on('some_event', contentchanged);
//Some time later
$('#firstTableTotal').trigger('some_event');
$('#secondTableTotal').trigger('some_event');

if you have a function called contentChanged:
var contentchanged= function () { //do something}
then you can simply add a listener to each DOM node.
$('#firstTableTotal').on(eventNameHere, contentchanged);
$('#secondTableTotal').on(eventNameHere, contentchanged);
It is best to attach the listeners to the node directly, that way when the nodes are removed from the DOM, the listeners will also be garbage collected. If you add the listener to the window, like you are currently doing, you will need to manually remove it in order for garbage collection to occur.

Related

why doesn't my jquery click function work after changing element values?

So I'm making a small quiz app with object oriented JS using Object.create cloning method. I have an ol, and a function called showVals() that populates it with lis. That seems to be working fine. What I'm having trouble with is: my li click function to give the attr of ".selected' class seems to work intitially, but after I click to proceed and qn2.showVals() is called it is no longer giving the lis a class of selected when clicked.
The data for qn2 is there. Everything looks normal, except for the click function no longer working (giving the lis the class).
$(document).ready(function(){
qn1.showVals();
qn1.setAns(1); // calling question1 answer for now
$('li').click(function(){
$('li').removeAttr("class");
$(this).attr({"class": "selected"});
});
$('.proceed').click(function(e){
e.preventDefault();
if ($('.selected').html() == qn1.ctAns) {
if (confirm("You are correct")){
qn2.showVals();
qn2.setAns(3);
};
};
});
});
var qn1 = {
title:"The Mouth of Sauron",
qn: "How did 'The mouth of Sauron' meet his demise?",
img: "images/mouth-sauron.gif",
ans: ["Shot in the back", "Beheaded", "Drowned in a swamp", "Sacrificed"],
setAns: function(x) {
this.ctAns = this.ans[x]; //setting correct answer
},
showVals: function(){
$('#slide-title').text(this.title);
$('.question-box > p').text(this.qn);
$('#obj-img').attr("src", this.img);
$('ol').html('<li>'+this.ans[0]+'</li>'+'<li>'+this.ans[1]+'</li>'+
'<li>'+this.ans[2]+'</li>'+'<li>'+this.ans[3]+'</li>')
}
}
var qn2 = Object.create(qn1);
qn2.title = "Golemn";
qn2.qn = "What this dude's name?";
qn2.ans= ["Golemn", "Gimli", "Goober", "Poop"]
qn2.img = "images/golemn.gif";
This is likely because your li elements are dynamically added.
You should try using jQuery on(), which allows you to bind an event handler to the parent element which must already exists in your DOM, and then you can specify the child/descendant selector that will call the event handler. This child element may still be non-existent at the time you do the event binding. In such a case, you call on() like:
$('ol').on('click', 'li', function () {...});
where ol already exists.
Alternatively, you could always bind your click handler to your dynamically generated li elements after you have added them to your DOM. Although I think that is more processor-time consuming as I assume you have to do this for all quiz questions you ask your user.

is this javascript code correct?

I am trying to remove a class when clicking on an element with a specific class. I made this javascript and it does work. But is this correct syntax to do it this way Can this be more efficient?
// Clear notifications alerts
$(document).on('click', '.js-clear-notifications', function() {
$('.AlertNotifications').remove();
});
// clear inbox alerts
$(document).on('click', '.js-clear-inbox', function() {
$('.AlertInbox').remove();
});
Your javascript code is correct, provided that you load jQuery as well.
Furthermore you have the most efficient solution, where you use a single event handler to handle events that originate on multiple elements.
The alternative would be:
$('.js-clear-notifications').on('click', function() {
$('.AlertNotifications').remove();
});
Which attaches as many event handlers as there are elements in the jQuery object. Slightly less efficient, though probably you would never notice except in extreme cases.
To me a more proper way to do it is something like this:
...
$('.js-clear-inbox').on('click', function() {
$('.AlertInbox').remove();
});
...
I will also suggest to have more specific selectors i.e.
$('div .js-clear-inbox')
I hope that this helps.
I am editing this in response to the feedback in the comments.
If what you want is to remove all elements with AlertNotifications class, which is what your code does, then what you have is correct.
If what you want is to remove only the class, which is what the text of the post said, you want removeClass, not remove:
$('.js-clear-notifications').on('click',function() {
$(this).removeClass('AlertNotificitions');
}
The new way, if you have already defined the variable, the proper way to delete it from the DOM would be:
var elem = document.getElementById("myDiv");
elem.remove();
But if you are just beginning out, .remove would be your best opinion.

jQuery override an on() event with another on() event

I have 2 files, file 1 (head.tpl) contains this default function operation
$(document).on("click", "#blackout", function(){
closeSkyBox();
});
That is the default operation I want to run, and it works.
On my second page, I would like to override the operation that is in head.tpl with this:
$(document).on("click", "#blackout", function(){
closeSkyBox(function(){
pev_for_country = '';
});
});
So, now when I test the code, each one runs, so If I were to place an alert (for testing reasons) I get two alert boxes. How can I make it so only the one in the second page runs, and the one in head.tpl is disabled. Then when I don't override it say on a third page, the one in head.tpl runs?
Looks like you're looking for jQuery's .off
$(document)
.off('click', '#blackout')
.on('click', '#blackout', function () {
// ...
});
You can use .off to remove all event handlers, but you should be cautious: what if other libraries add event handlers that you don't want to remove subscribe to this event? Also, if you add an additional event handler at a later date, this would obliterate it.
A better approach, I think, is to create a function that you can override:
function blackoutClick() {
closeSkyBox();
}
And set up your click handler:
$(document).on("click", "#blackout", function(){
blackoutClick();
});
Or, as Paul pointed out in the comments below, you don't even need to wrap that handler in an anonymous function, you can just use the cleaner:
$(document).on("click", "#blackout", blackoutClick );
Then, in your second page, you can just modify that function:
function blackoutClick() {
closeSkyBox(function(){
pev_for_country = '';
});
I believe another way to do it is also to set the event to null...
$(document).on('click', '#blackout', null);
before you re-set it on your second page.

Passing argument to JS function from link onclick

I have a link that looks like this:
<a id="mylink" onclick="deleteHike( 3 );" href="javascript:void(0);">Yes</a>
It is able to call this JavaScript:
window.onload = function()
{
//Get a reference to the link on the page
// with an id of "mylink"
var a = document.getElementById("mylink");
//Set code to run when the link is clicked
// by assigning a function to "onclick"
a.onclick = function( hike_id )
{
// Somecode her
// But when I try to use the hike_id it displays as [object MouseEvent]
}
}
But the value that comes in is [object MouseEvent], not the number that I was expecting. Any idea why this happens and how to fix this? :)
Thanks!
You are trying to assign the function to your link in two different and conflicting ways.
Using the eval-ed function string, onclick = "function(value)", works but is deprecated.
The other way of binding the click handler in the onload event works too, but if you want a particular value to be passed, you'll have to change your script a bit because the value as given in the initial onclick is completely lost when you set the onclick to a new function.
To make your current method work, you don't need an onload handler at all. You just need this:
function deleteHike(hike_id) {
// Some code here
}
To do it the second way, which I recommend, it would look like this:
<a id="mylink" href="javascript:void(0);">Yes</a>
with this script:
function deleteHike(e, hike_id) {
// Some code here
// e refers to the event object which you can do nifty things with like
// - learn the actual clicked element if it was a parent or child of the `this` element
// - stop the event from bubbling up to parent items
// - stop the event from being captured by child items
// (I may have these last two switched)
}
function getCall(fn, param) {
return function(e) {
e = e || window.event;
e.preventDefault(); // this might let you use real URLs instead of void(0)
fn(e, param);
};
}
window.onload = function() {
var a = document.getElementById("mylink");
a.onclick = getCall(deleteHike, 3);
};
The parameter of a DOM event function is the event object (in Firefox and other standards-compliant browsers). It is nothing in IE (thus the need to also grab window.event). I added a little helper function for you that creates a closure around your parameter value. You could do that each time yourself but it would be a pain. The important part is that getCall is a function that returns a function, and it is this returned function that gets called when you click on the element.
Finally, I recommend strongly that instead of all this, you use a library such as jQuery because it solves all sorts of problems for you and you don't have to know crazy JavaScript that takes much expertise to get just right, problems such as:
Having multiple handlers for a single event
Running JavaScript as soon as possible before the onload event fires with the simulated event ready. For example, maybe an image is still downloading but you want to put the focus on a control before the user tries to use the page, you can't do that with onload and it is a really hard problem to solve cross-browser.
Dealing with how the event object is being passed
Figuring out all the different ways that browsers handle things like event propagation and getting the clicked item and so on.
Note: in your click handler you can just use the this event which will have the clicked element in it. This could be really powerful for you, because instead of having to encode which item it was in the JavaScript for each element's onclick event, you can simply bind the same handler to all your items and get its value from the element. This is better because it lets you encode the information about the element only in the element, rather than in the element and the JavaScript.
You should just be able to declare the function like this (no need to assign on window.onload):
function deleteHike(hike_id)
{
// Somecode her
// But when I try to use the hike_id it displays as [object MouseEvent]
}
The first parameter in javascript event is the event itself. If you need a reference back to the "a" tag you could use the this variable because the scope is now the "a" tag.
Here's my new favorite way to solve this problem. I like this approach for its clarity and brevity.
Use this HTML:
<a onclick="deleteHike(event);" hike_id=1>Yes 1</a><br/>
<a onclick="deleteHike(event);" hike_id=2>Yes 2</a><br/>
<a onclick="deleteHike(event);" hike_id=3>Yes 3</a><br/>
With this JavaScript:
function deleteHike(event) {
var element = event.target;
var hike_id = element.getAttribute("hike_id");
// do what you will with hike_id
if (confirm("Delete hike " + hike_id + "?")) {
// do the delete
console.log("item " + hike_id + " deleted");
} else {
// don't do the delete
console.log("user canceled");
}
return;
}
This code works because event is defined in the JavaScript environment when the onclick handler is called.
For a more complete discussion (including why you might want to use "data-hike_id" instead of "hike_id" as the element attribute), see: How to store arbitrary data for some HTML tags.
These are alternate forms of the HTML which have the same effect:
<a onclick="deleteHike(event);" hike_id=4 href="javascript:void(0);">Yes 4</a><br/>
<button onclick="deleteHike(event);" hike_id=5>Yes 5</button><br/>
<span onclick="deleteHike(event);" hike_id=6>Yes 6</span><br/>
When you assign a function to an event on a DOM element like this, the browser will automatically pass the event object (in this case MouseEvent as it's an onclick event) as the first argument.
Try it like this,
a.onclick = function(e, hike_id) { }

Issue with selectors & .html() in jquery?

The function associated with the selector stops working when I replace it's contents using .html(). Since I cannot post my original code I've created an example to show what I mean...
Jquery
$(document).ready(function () {
$("#pg_display span").click(function () {
var pageno = $(this).attr("id");
alert(pageno);
var data = "<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
});
});
HTML
<div id="pg_display">
<span id="page1">1</span>
<span id="page2">2</span>
<span id="page3">3</span>
</div>
Is there any way to fix this??...Thanks
Not sure I understand you completely, but if you're asking why .click() functions aren't working on spans that are added later, you'll need to use .live(),
$("#someSelector span").live("click", function(){
# do stuff to spans currently existing
# and those that will exist in the future
});
This will add functionality to any element currently on the page, and any element that is later created. It keeps you have having to re-attach handlers when new elements are created.
You have to re-bind the event after you replace the HTML, because the original DOM element will have disappeared. To allow this, you have to create a named function instead of an anonymous function:
function pgClick() {
var pageno = $(this).attr("id");
alert(pageno);
var data="<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
$("#pg_display span").click(pgClick);
}
$(document).ready(function(){
$("#pg_display span").click(pgClick);
});
That's to be expected, since the DOM elements that had your click handler attached have been replaced with new ones.
The easiest remedy is to use 1.3's new "live" events.
In your situation, you can use 'Event delegation' concept and get it to work.
Event delegation uses the fact that an event generated on a element will keep bubbling up to its parent unless there are no more parents. So instead of binding click event to span, you will find the click event on your #pg_display div.
$(document).ready(
function()
{
$("#pg_display").click(
function(ev)
{
//As we are binding click event to the DIV, we need to find out the
//'target' which was clicked.
var target = $(ev.target);
//If it's not span, don't do anything.
if(!target.is('span'))
return;
alert('page #' + ev.target.id);
var data="<span id='page1'>1</span><span id='page2'>2</span><span id='page3'>3</span>";
$("#pg_display").html(data);
}
);
}
);
Working demo: http://jsbin.com/imuye
Code: http://jsbin.com/imuye/edit
The above code has additional advantage that instead of binding 3 event handlers, it only binds one.
Use the $("#pg_display span").live('click', function....) method instead of .click. Live (available in JQuery 1.3.2) will bind to existing and FUTURE matches whereas the click (as well as .bind) function is only being bound to existing objects and not any new ones. You'll also need (maybe?) to separate the data from the function or you will always add new span tags on each click.
http://docs.jquery.com/Events/live#typefn

Categories

Resources