On a static element, to fake a click, I use
$(selector).click();
But how can I do the same thing on a dynamic element (resulted from an ajax call)?
The same...:
$(selector).click();
Why didn't you try it first?
P.S. it is not called fake a click, it's called trigger the click event.
$(selector).trigger('click'); == $(selector).click();
Update
You need to bind that element a callback to the event in order it to work:
$(selector).click(function(){...});
$(selector).click();
If you want it to have the the click callback you assigned to the static elements automaticlly, you should use on\ delegate (or live but it's deprecated) when you attach the click callback.
$('body').on('click', 'selector', function(){...})
instead if body use the closest static element the holds that selector elements.
See my DEMO
within your ajax success function try your code:
$(selector).click();
Basing this on your previous question : How can I select a list of DOM objects render from an AJAX call?
$(document).ready(function(){
var listItems = $('#myList li a');
var containers = $('#myContainer > div');
listItems.click(function(e){//do someting
});
etc...
If the elements you are trying to attach a click handler to are supposed to be inside any of the two variables above then you WILL have to update those variables after the elements are inserted into the DOM, as it is right now only elements that exists during first page load will be inside those variables.
That is the only reason I can think of why something like :
$(document).on('click', listItems, function(e) {//do something
});
will not work!
Don't know if I understand (I'm french sorry...)
But try :
$(selector).live('click',function(){}); // deprecated it seems
Demo of gdoron with live() : http://jsfiddle.net/Rx2h7/1/
use on() method of jquery,
staticElement.on('click', selector, function(){})
on method generates click event on dynamically created element by attaching it to the static element present in the DOM .
For further reference check this out -- https://api.jquery.com/on/
Related
I have been trying to manipulate content that is loaded into jQuery UI tabs via AJAX.
As you can imagine, these elements are "future" DOM elements and aren't manipulated by normal $(".someClass")functions.
I've read using .live() for event handling is now deprecated using jQuery 1.7+ and is replaced by the new .on() method.
My issue is that the div I want to hide, when it loads in an AJAX tab, must be manipulated after the initial DOM load and is not bound to a click event at first.
My functions, which are currently wrapped in $() are below.
I think I have the syntax correct for links that use a click handler, but I'm not sure of the correct way to ".hide()" my "hiddenStory" div at load.
I also think that the functions themselves shouldn't be wrapped in an overall $()?
Any help or advice would be greatly appreciated.
$(function(){
// this .hiddenStory div below is what I want to hide on AJAX load
// need syntax and/or new methods for writing this function
$(".hiddenStory").hide();
// this is a function that allows me to toggle a "read more/read less" area
// on the "hiddenStory" div
$(".showMoreOrLess").on('click', (function() {
if (this.className.indexOf('clicked') != -1 ) {
$(this).removeClass('clicked');
$(this).prev().slideUp(500);
$(this).html("Read More" + "<span class='moreUiIcon'></span>");
}
else {
$(this).addClass('clicked');
$(this).prev().slideDown(500);
$(this).html("See Less" + "<span class='lessUiIcon'></span>");
}
}));
});
// prevents default link behavior
// on BBQ history stated tab panes with
// "showMoreOrLess" links
$('.showMoreOrLess').click(function (event)
{
event.preventDefault();
// here you can also do all sort of things
});
// /prevents default behavior on "showMoreOrLess" links
Could you set the display: none via CSS and override it when you wanted to show the element's content? Another option, if you have to do it this way would be to add the `$(".hiddenStory").hide() in the callback from the AJAX load that is populating the element. For example:
$(".hiddenStory").load("http://myurl.com", function(){
$(".hiddenStory").hide();
}
);
If you aren't using the .load method, you should have some sort of call back to tie into (e.g. success if using $.ajax...)
I have an ajax action link which is appending a partial to a div.
$('#hypNewCriteria').click(newClick);
...
var newClick = (function ()
{
console.log('newClick');
$.ajax(this.href, {
success: function (result)
{
...
}
}
On the first page load and on every partial that is returned I am (probably unnecessarily), am executing via a document.ready
$('#hypNewCriteria').click(newClick);
... subsequent clicks on the actionlink; the number of partial views returned increases by 1 each time. After 7 clicks, it returns 8 partials. I expect only 1 partial to append.
I suspect the .click(newClick) event is appending. Is there a way to set just one click event or clear the event before I set another?
You can use jQuery's unbind() method to unbind events.
http://api.jquery.com/unbind/
I would also look into the live() jQuery method. This binds an event to all current and future elements that are added to a page, useful for pages that load partials or add items that require events to be added all the time.
Try .one():
$('#hypNewCriteria').one('click', newClick);
I'm having a hard time understanding the syntax of the .delegate function of jquery. Let's say I have the following:
$(".some_element_class").delegate("a", "click", function(){
alert($(this).html());
});
I know that the a element is the element to which the click event is applied. I know that once we click on that a element, the event click will be triggered and the callback function will be called. But what is the purpose of what comes before the .delegate? In this case, what is the purpose of .some_element_class? How do I read the above including the .some_element_class? Also, in the example above, what does $(this) represent? Does it represent the a element or does it represent .some_element_class?
Please somebody, shed some light on this.
Thank you
This reduces event binding.
This basically sets an event on a tags ONLY within the elements with class .some_element_class without actually binding an event to a tags directly.
http://api.jquery.com/delegate/
http://api.jquery.com/on/
As of jQuery 1.7, .delegate() has been superseded by the .on() method.
For earlier versions, however, it remains the most effective means to
use event delegation. More information on event binding and delegation
is in the .on() method. In general, these are the equivalent templates
for the two methods:
$(elements).delegate(selector, events, data, handler); // jQuery 1.4.3+
$(elements).on(events, selector, data, handler); // jQuery 1.7+
$(".some_element_class").on("a", "click", function(){
alert($(this).html());
});
"...what is the purpose of what comes before the .delegate?"
A delegate is bound to .some_element_class element.
That delegate is triggered for every click that takes place inside .some_element_class
That delegate tests what was clicked, so your handler function will only run if...
the actual element clicked matches the "a" selector, or
any ancestor of the actual element clicked that is a descendant of .some_element_class matches the "a" selector.
<div class="some_element_class"> <!-- delegate handler is here -->
<div>won't trigger your handler</div>
<a>will trigger your handler</a>
<a><span>will trigger</span> your handler</a>
</div>
So you can see that only one handler is bound to the container. It analyzes all clicks inside the container, and if the element clicked (or one of its nested ancestors) matches the selector argument, your function will run.
Because there's just one enclosing handler, it will work for future elements added to the container...
<div class="some_element_class"> <!-- delegate handler is here -->
<div>won't trigger your handler</div>
<a>will trigger your handler</a>
<a><span>will trigger</span> your handler</a>
<!-- this element newly added... -->
<a><span>...will also trigger</span> your handler</a>
</div>
"Also, in the example above, what does $(this) represent?"
this will represent the element that matched the "a" selector.
it means delegate() is invoked on the .some_event_class. and the a is selector string, click is event type string & function() is eventhandler function. delegate() method is used to handle the "live event" and for static events bind() is used. I hope this helps. feel free to ask if you have any doubts
Differences between bind() & delegate()
//Static event handlers for static links
$("a").bind("",linkHandler);
//Live event handlers for dynamic parts of the document
$(".dynamic").delegate("a", "mouseover", linkHandler);
Summary: they are just methods that bind event handlers to specific document elements.
The a is actually just a filtering selector, what will happen is that a normal click event is bound to .some_element_class, and anytime the event fires, the event target is traversed up to .some_element_class to see if there is an element that matches the filtering selector (tagname a). If it does, your callback is fired with this set to the first element that matched a selector in the bubbling path.
You can do something similar with bind:
$(".some_element_class").bind("click", function (e) {
var matches = $(e.target).closest("a", this);
if (matches.length) {
yourcallback.call(matches[0], e);
}
});
I am currently trying to make a bookmarklet that adds, among other things, a DIV element to the page.
I'm doing this by adding the HTML code to body.innerHTML and that works fine. On this DIV element is a button that should allow to hide the added DIV. I therefore tried to add via JavaScript a JavaScript function to the innerHTML called function hideDiv().
The new JavaScript is added to the body and it looks fine. But it doesn't work.
Short example:
javascript:var b = document.body.InnerHTML; b=b+'<input type="button" onclick="javascript:alert("hello")"/>'; document.body.innerHTML = b;
This bookmarklet should add a button that shows an alert if its clicked. It adds the button but nothing happens when clicking on it.
Is this a general issue? Can JavaScript add (working) JavaScript to a page?
I think you should set an id and then just add the function to the element. Like this:
javascript:var b = document.body.InnerHTML; b=b+'<input type="button" id="test"/>'; document.body.innerHTML = b; document.getElementById('test').onclick = function () { alert('hi')}
The javascript: prefix is only used in href attributes (or action for forms). It is NOT used in onclick or any other events. Remove the javascript: and your code should work fine.
I have ~400 elements on a page that have click events tied to them (4 different types of buttons with 100 instances of each, each type's click events performing the same function but with different parameters).
I need to minimize any impacts on performance that this may have. What kind of performance hit am I taking (memory etc) by binding click events to each of these individually (using JQuery's bind())? Would it be more efficient to have an inline onclick calling the function on each button instead?
Edit for clarification :):
I actually have a table (generated using JQGrid) and each row has data columns followed by 4 icon 'button' columns- delete & three other business functions that make AJAX calls back to the server:
|id|description|__more data_|_X__|_+__|____|____|
-------------------------------------------------
| 1|___data____|____data____|icon|icon|icon|icon|
| 2|___data____|____data____|icon|icon|icon|icon|
| 3|___data____|____data____|icon|icon|icon|icon|
| 4|___data____|____data____|icon|icon|icon|icon|
I am using JQGrid's custom formatter (http://www.trirand.com/jqgridwsiki/doku.php?id=wiki:custom_formatter) to build the icon 'buttons' in each row (I cannot retrieve button HTML from server).
It is here in my custom formatter function that I can easily just build the icon HTML and code in an inline onclick calling the appropriate functions with the appropriate parameters (data from other columns in that row). I use the data in the row columns as parameters for my functions.
function removeFormatter(cellvalue, options, rowObject) {
return "<img src='img/favoritesAdd.gif' onclick='remove(\"" + options.rowId + "\")' title='Remove' style='cursor:pointer' />";
}
So, I can think of two options:
1) inline onclick as I explained above
--or--
2) delegate() (as mentioned in below answers (thank you so much!))
Build the icon image (each icon type has its own class name) using the custom formatter.Set the icon's data() to its parameters in the afterInsertRow JQGrid event. Apply the delegate() handler to buttons of specific classes (as #KenRedler said below)
> $('#container').delegate('.your_buttons','click',function(e){
> e.preventDefault();
> var your_param = $(this).data('something'); // store your params in data, perhaps
> do_something_with( your_param );
> }); //(code snippet via #KenRedler)
I'm not sure how browser-intensive option #2 is I guess...but I do like keeping the Javascript away from my DOM elements :)
Because you need not only a general solution with some container objects, but the solution for jqGrid I can suggest you one more way.
The problem is that jqGrid make already some onClick bindings. So you will not spend more resources if you just use existing in jqGrid event handler. Two event handler can be useful for you: onCellSelect and beforeSelectRow. To have mostly close behavior to what you currently have I suggest you to use beforeSelectRow event. It's advantage is that if the user will click on one from your custom buttons the row selection can stay unchanged. With the onCellSelect the row will be first selected and then the onCellSelect event handler called.
You can define the columns with buttons like following
{ name: 'add', width: 18, sortable: false, search: false,
formatter:function(){
return "<span class='ui-icon ui-icon-plus'></span>"
}}
In the code above I do use custom formatter of jqGrid, but without any event binding. The code of
beforeSelectRow: function (rowid, e) {
var iCol = $.jgrid.getCellIndex(e.target);
if (iCol >= firstButtonColumnIndex) {
alert("rowid="+rowid+"\nButton name: "+buttonNames[iCol]);
}
// prevent row selection if one click on the button
return (iCol >= firstButtonColumnIndex)? false: true;
}
where firstButtonColumnIndex = 8 and buttonNames = {8:'Add',9:'Edit',10:'Remove',11:'Details'}. In your code you can replace the alert to the corresponding function call.
If you want select the row always on the button click you can simplify the code till the following
onCellSelect: function (rowid,iCol/*,cellcontent,e*/) {
if (iCol >= firstButtonColumnIndex) {
alert("rowid="+rowid+"\nButton name: "+buttonNames[iCol]);
}
}
In the way you use one existing click event handler bound to the whole table (see the source code) and just say jqGrid which handle you want to use.
I recommend you additionally always use gridview:true which speed up the building of jqGrid, but which can not be used if you use afterInsertRow function which you considered to use as an option.
You can see the demo here.
UPDATED: One more option which you have is to use formatter:'actions' see the demo prepared for the answer. If you look at the code of the 'actions' formatter is work mostly like your current code if you look at it from the event binding side.
UPDATED 2: The updated version of the code you can see here.
You should use the .delegate() method to bind a single click handler for all elements ,through jQuery, to a parent element of all buttons.
For the different parameters you could use data- attributes to each element, and retrieve them with the .data() method.
Have you considered using delegate()? You'd have one handler on a container element rather than hundreds. Something like this:
$('#container').delegate('.your_buttons','click',function(e){
e.preventDefault();
var your_param = $(this).data('something'); // store your params in data, perhaps
do_something_with( your_param );
});
Assuming a general layout like this:
<div id="container">
<!--- stuff here --->
<a class="your_buttons" href="#" data-something="foo">Alpha</a>
<a class="your_buttons" href="#" data-something="bar">Beta</a>
<a class="your_buttons" href="#" data-something="baz">Gamma</a>
<a class="something-else" href="#" data-something="baz">Omega</a>
<!--- hundreds more --->
</div>