really basic stuff here. I'd like to give a click function a name and assign some parameters to it. The goal is code reusability such that I can write only one generic function for common tasks such as for enabling users to delete various data.
Here's a jsfiddle to show you what I mean.
And here's that code:
the HTML:
<button>delete this</button>
<div data-id="3" class="delete">something bad</div>
<div data-id="4" class="delete">something else bad</div>
and the JS:
// this function would be loaded on my site's template and therefore would be available across my entire site.
function deleteThis(data_id){
$('button').on('click', 'button', function(){
$('div[data-id="'+data_id+'"]').hide();
});
}
var clicked_id=3;
function deleteThis(clicked_id);
// this function would be called on the various pages where users can delete things and this variable, clicked_id, would be assigned=3 by the user's action on that page.
How do I give this button click event a name?
update thanks all! the $('button') should have been $(document.body) or the button's parent element. It works if you make that simple change. You can also do it as Michael Buen suggests below.
Just refactor your code, put the delete functionality on its own function
<button>delete this</button>
<div data-id="3" class="delete">something bad</div>
<div data-id="4" class="delete">something else bad</div>
$('button').on('click', function() { deleteImmediately(3) });
function deleteImmediately(id) { -- refactored code
$('div[data-id='+id+']').hide();
}
Live test: http://jsfiddle.net/e2kuj/2/
In your fiddler, the (function deleteThis(){})() is making it private and you are trying to access it as a global!
I think you're misunderstanding events. deleteThis only makes sense if it's in the handler.
corrected HTML: (don't use custom attributes for referencing HTML - They're slower)
<button>delete this</button>
<div id="del_3" class="delete">something bad</div>
<div id="del_4" class="delete">something else bad</div>
JS: (untested)
var deleteTargetId = 'del_3'; //clicked_id renamed for clarity
function deleteThis(targetId){
$('#'+targetId).remove(); //removes rather than hides the html
}
$('button').click( function(){
deleteThis(deleteTargetId);
} );
Now you could swap deleteTarget and the HTML with that ID would get yoinked.
However, if this is homework, I'm wondering if you understand the assignment. The var named 'clicked_id' suggests the idea is to click the divs to make them disappear and use delegation. That one's easy.
You'll need to understand event delegation and event bubbling to see what's going on here. Basically when something is clicked, the event then fires on the parent element and then that parent element's parent element, all the way up to the HTML tag. This happens with all events and doesn't cause the trouble you might think because containers are rarely assigned listeners for events. Links and buttons are more typically end point nodes or at most contain a span or an image. Usually when bubbling causes a problem it's because somebody's doing something awful with HTML or they should've been using delegation in the first place.
'on' is the new piss-poor name for the once appropriately named and less confusion-prone 'delegate' jquery method. Essentially anything in the body with the class 'delete' triggers the handler. We don't care about the ID since the idea is to kill the div that was clicked and 'this' gives us a reference to it. This is unusual behavior for JQ, since most methods would have 'this' point at the 'body' but it's obviously a more useful thing to point at for event delegation.
$('body').on('click', '.delete', function(e){
$(this).remove(); //this refers to the originally clicked element
} );
//note: not the solution you asked for, but possibly the one you needed.
It was almost right. I updated it -> http://jsfiddle.net/fz5ZT/41/
function deleteThis(id){
$('button').click(function(){
$('div[data-id="'+id+'"]').hide();
});
};
deleteThis(3);
you can remove the element in a different way:
$('button').on('click', function(){
$(this).next("div").remove();
});
http://jsfiddle.net/fz5ZT/46/
You could just use $('button').on('click', 'button', clickHandler); to reference the clickHandler function.
I am big fan of such things since apart from being reusable it has the following advantages.
I will be able to just send across a patch in case there's a bug in the clickHandler
Someone can augment my method which is not possible with anonymous methods
Readable, and also useful to see the stack trace in case of errors
Hope that helps.
Update:
function clickHandler(ev) {
ev.preventDefault();
// ... handler code
}
Related
I'm using underscore to create some elements and appending them to a div with jQuery.
At the bottom of the page I'm using jQuery's .on() to respond to clicks on the elements.
$('.pickup').on('click',
function(e) {
alert("hello");
}
);
Via some user interaction (in Google maps), I've got to add more elements to the div and want them to respond to clicks as well. For some reason they do not. I've pared it all down on jsfiddle:
http://jsfiddle.net/thunderrabbit/3GvPX/
When the page loads, note that clicking on the lines in output will alert('hello') via jQuery.
But click the [add] button and the new lines do not respond to clicks.
My HTML
<div id="unit_2225" class="pickup">
<span>Click me; I was here first</span>
</div>
<script type="text/template" id="unit-template">
<div class="unit-item">
<span class="pickup">
<span>click us (<%= unit_id %>) via underscore</span>
</span>
</div>
</script>
<div id="divID">
</div>
<button>add</button>
My Javascript
var addUnitToDiv = function(key,val) {
console.log(val);
var template = _.template($('#unit-template').html(),val);
$('#divID').append(template);
}
var unit_ids = [{unit_id:'hello'},
{unit_id:'click'},
{unit_id:'us'},
{unit_id:'too'},
{unit_id:112}];
$.each(unit_ids, addUnitToDiv);
var unit_pids = [{unit_id:'we'},
{unit_id:'wont'},
{unit_id:'respond'},
{unit_id:'to'},
{unit_id:'clicks'},
{unit_id:358}];
createMore = function() {
$.each(unit_pids, addUnitToDiv);
}
$('.pickup').on('click','span',function() {
alert("hello");
});
$('button').click(createMore);
I found a similarly worded question but couldn't figure out how to apply its answer here.
Instead of binding events directly to the elements, bind one event to their container element, and delegate it:
$("#divID").on("click", ".pickup", function () {
// Your event handler code
});
DEMO: http://jsfiddle.net/3GvPX/3/
In this case, the event handler is only executed for elements inside of the container #divID that have the class "pickup".
And in your scenario, the elements are being added to the element with an id of "divID". Thus, where the two selectors came from.
This is handy because, as you've found out, dynamically adding elements doesn't magically bind event handlers; event handlers bound normally with .on() are only executed (bound) on those present at the time of binding.
It could even help if you change the delegated selector to "span.pickup" (if you know the elements will always be a <span> like in your template), so that the DOM is filtered by the tag name first.
Reference:
http://api.jquery.com/on/#direct-and-delegated-events
Working demo http://jsfiddle.net/u2KjJ/
http://api.jquery.com/on/
The .on() method attaches event handlers to the currently selected set of elements in the jQuery object. You can attach the handler on the document level.
Hope it fits the need, :)
code try the code changed below
$(document).on('click','.pickup',function() {
alert("hello");
});
So I'm currently using .append() to add a feature to all of the posts on a webpage, but when additional posts are loaded on the page, the appended features aren't included in the new content — I'm trying to come up with a way to make sure all of the new content has the appended feature too.
$(this).append('<div id="new_feature></div>');
Something like this?
$(this).live().append('<div id="new_feature></div>');
Maybe there's a way to make it constantly appending in a loop perhaps?
There is DOMNodeInserted event:
$('button').click(function() {
$('#appendme').append($('<div class="inner">').text(Math.random()));
})
$('#appendme').on('DOMNodeInserted','.inner',function() {
console.log(this);
});
DEMO
update: this seems not works in IE, try propertychnage event handler also ($('#appendme').on('DOMNodeInserted,propertychange') but i not sure, have no IE to check this right now.
update2: Domnode* seems deprecated according to mdn, they tell to use MutationObserver object instead
update3: seems here is no very crossbrowser solution for MutationEvents, see this answer, so my suggestion would be use code above, if event supported and fallback to setTimeOut or livequery option.
update4:
If you depend only on .append() you can patch jQuery.fn.append() like this:
jQuery.fn.append=function() {
return this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 ) {
this.appendChild( elem );
$(elem).trigger('appended');
}
});
};
$('button').click(function() {
$('#appendme').append($('<div class="inner">').text(Math.random()));
})
$('#appendme').on('appended','.inner',function() {
console.log(this);
});
DEMO2
may be more correct is to spoof jQuery.fn.domManip like here
jQuery documentation:
Use of the .live() method is no longer recommended since later versions of jQuery offer better methods that do not have its drawbacks.
You can use setTimeout() function that can check for new <div>s every n milliseconds.
$(function(){
setInterval("Check4NewDivs();",1000);
});
So say this is a div with class="comment newdiv", so when it appears on the page for the first time, it has the class newdiv that will let the function know it was just dynamically created.
function Check4NewDivs(){
$(".comment .newdiv").each(function(){
$(this).append('<div class="new_feature"></div>').removeClass("newdiv");
});
}
It's append not appened.
live is a deprecated event handler. It's not used this way. use on instead.
http://api.jquery.com/live/
So, the following code will run when you click selector.
$(document).on('click', 'selector', function() {
$(this).append('<div id="new_feature></div>');
});
No, there is no standard way to do it like that. There was a proposal of the events that would be fired whenever the DOM elements are inserted etc., but you cannot rely on that.
Instead rely on either:
(preferably) callbacks - just invoke function ensuring existence of such appended snippets, whenever you pull something (but after you successfully pull it from server and insert into DOM, not sooner), or
constant checks - like using in setInterval() or setTimeout(), but this would be unnecessary processing and you will never get instant append, unless you will perform processing-heavy checks all the time,
use the on load function:
$(item).on('load',function(){
$(this).append('<div id="new_feature"></div>');
});
This will add append the item as a callback once the item has been loaded. I would also choose some sort of dynamic ID creator rather than always append stuff with the same ID, but thats just me.
you must bind to an element that already exists on the page. i have written an example where i make appended content live.
DEMO on JSFiddle
HTML
<div id="container">
<div id="features">
</div>
<br />
<a href='#' id='clickme'>click me to add feature</a>
</div>
JS
$(function() {
$('#clickme').on('click', function(e) {
$('#features').append('<div class="new_feature">new feature</div>');
});
$('#features').on('click', '.new_feature', function() {
alert('i am live.');
});
});
I'm not really a developper. I prefer to design my websites ... So, for my actual project, i must developping some "basic" scripts.
I've met a problem with this:
<script type="text/javascript">
$("button").click(function toggleDiv(divId) {
$("#"+divId).toggle();
});
;
</script>
Into Head-/Head
LINK
<div> id="myContent">Lorem Ipsum</div>
It works for IE8. (Miracle). But not the others browsers...
The idea is that when u click on "LINK" a windows appears and when you click again, the window close.
Any idea ?
Thanks for u time !
One of the problems is you're mixing two different styles of binding event handlers: one of them is good (the jQuery method), the other is bad (the javascript: protocol in your href attribute) - the two don't work together in any way. Another problem is that your selector is completely incorrect (it's looking for a button) for the HTML you've provided (you never create a button).
I'd suggest using a HTML5 data-* attribute to specify the id for the <div> on your <a> element:
LINK
<div id="mycontent">Lorem ipsum</div>
Then use the following jQuery code:
$('a').click(function(e) {
e.preventDefault(); // e refers to the event (the click),
// calling preventDefault() will stop you following the link
var divId = $(this).data('divid');
$('#' + divId).toggle();
});
Note that I've used this in the above code; what this refers to depends on the context in which you use it, but in the context of a jQuery event handler callback function, it will always refer to the element that triggered the event (in this case, your <a> element).
If you extract toggleDiv from the handler, it ought to work. You will probably also need to return false to keep the href from trying to go anywhere.
<script type="text/javascript">
function toggleDiv(divId) {
$("#"+divId).toggle();
return false;
}
</script>
I've just begun to play around with Dojo. I simply wanted to display a dialog when an item in a Dijit ComboButton's DropDownMenu is clicked. I tried using dojo.connect to associate the onclick event with a function which would simply display a dialog with the text contained in the item, with no luck.
I've managed to get it working in a horrible way. All the work is now actually written to the onclick attribute manually. I'm clearly misunderstanding something here. This is what I currently have:
JS:
require(["dijit/form/Button", "dijit/form/FilteringSelect", "dijit/DropDownMenu", "dijit/MenuItem"]);
//if the following is defined inside dojo.ready, nothing happens
function getmail(text)
{
alert('No mail from '+text);
}
dojo.ready(function(){
//the following does nothing:
dojo.connect(dojo.query(".dijitMenuItemLabel"), "onclick", function(evt) {
console.log("mail item clicked");
alert('Blah');
//dojo.stopEvent(evt);
});
});
HTML:
<form method="POST">
<div data-dojo-type="dijit.form.ComboButton" id="getmail">
<span>Get All Mail</span>
<div data-dojo-type="dijit.DropDownMenu">
<div data-dojo-type="dijit.MenuItem"
data-dojo-props="onClick:function(){getmail(dojo.trim(dojo.query('.dijitMenuItemLabel', this.domNode)[0].innerHTML))}">
Yahoo</div>
<div data-dojo-type="dijit.MenuItem">Google</div>
</div>
</div>
</form>
What does it look like I am clearly misunderstanding about Dojo?
(Or maybe I'm making simple JavaScript mistakes)
JSFiddle
You should be able to do it with something like
var myButton = dijit.byId('getmail');
myButton.on('click', function(){ alert('clicked') });
My guess is that you confused dojo.byId and dijit.byId when you fetched your button - regular DOM nodes work when you conenct a lowercase 'onclick' but widgets fire a camel case 'onClick' event (the distinction is because dijits fire with some keyboard events, for accessibility).
However, for newer versions of Dojo it is probably best to stay away from dojo.connect and instead just use simpler ".on" API I showed.
Ah, and before I forget, it also looks like you could have forgotten to run the Dojo parser (or set parseOnLoad to true) so the button was never created. Can you provide a fully executable example on JSFiddle?
I am dynamically creating a hyperlink in the c# code behind file of ASP.NET. I need to call a JavaScript function on client click. how do i accomplish this?
Neater still, instead of the typical href="#" or href="javascript:void" or href="whatever", I think this makes much more sense:
var el = document.getElementById('foo');
el.onclick = showFoo;
function showFoo() {
alert('I am foo!');
return false;
}
Show me some foo
If Javascript fails, there is some feedback. Furthermore, erratic behavior (page jumping in the case of href="#", visiting the same page in the case of href="") is eliminated.
The simplest answer of all is...
My link
Or to answer the question of calling a javascript function:
<script type="text/javascript">
function myFunction(myMessage) {
alert(myMessage);
}
</script>
My link
With the onclick parameter...
<a href='http://www.google.com' onclick='myJavaScriptFunction();'>mylink</a>
The JQuery answer. Since JavaScript was invented in order to develop JQuery, I am giving you an example in JQuery doing this:
<div class="menu">
Example
Foobar.com
</div>
<script>
jQuery( 'div.menu a' )
.click(function() {
do_the_click( this.href );
return false;
});
// play the funky music white boy
function do_the_click( url )
{
alert( url );
}
</script>
I prefer using the onclick method rather than the href for javascript hyperlinks. And always use alerts to determine what value do you have.
<a href='#' onclick='jsFunction();alert('it works!');'>Link</a>
It could be also used on input tags eg.
<input type='button' value='Submit' onclick='jsFunction();alert('it works!');'>
Ideally I would avoid generating links in you code behind altogether as your code will need recompiling every time you want to make a change to the 'markup' of each of those links. If you have to do it I would not embed your javascript 'calls' inside your HTML, it's a bad practice altogether, your markup should describe your document not what it does, thats the job of your javascript.
Use an approach where you have a specific id for each element (or class if its common functionality) and then use Progressive Enhancement to add the event handler(s), something like:
[c# example only probably not the way you're writing out your js]
Response.Write("My Link");
[Javascript]
document.getElementById('uxAncMyLink').onclick = function(e){
// do some stuff here
return false;
}
That way your code won't break for users with JS disabled and it will have a clear seperation of concerns.
Hope that is of use.
Use the onclick HTML attribute.
The onclick event handler captures a
click event from the users’ mouse
button on the element to which the
onclick attribute is applied. This
action usually results in a call to a
script method such as a JavaScript
function [...]
I would generally recommend using element.attachEvent (IE) or element.addEventListener (other browsers) over setting the onclick event directly as the latter will replace any existing event handlers for that element.
attachEvent / addEventListening allow multiple event handlers to be created.
If you do not wait for the page to be loaded you will not be able to select the element by id. This solution should work for anyone having trouble getting the code to execute
<script type="text/javascript">
window.onload = function() {
document.getElementById("delete").onclick = function() {myFunction()};
function myFunction() {
//your code goes here
alert('Alert message here');
}
};
</script>
<a href='#' id='delete'>Delete Document</a>