JQuery ClueTip with ColdFusion - Javascript $(document).ready() misfire [duplicate] - javascript

Yesterday I had an issue where a .on('click') event handler I was assigning wasn't working right. Turns out it's because I was was trying to apply that .on('click') before that element existed in the DOM, because it was being loaded via AJAX, and therefore didn't exist yet when the document.ready() got to that point.
I solved it with an awkward workaround, but my question is, if I were to put a <script> tag IN the ajax loaded content and another document.ready() within that, would that second document.ready() be parsed ONLY once that ajax content is done being loaded? In other words, does it consider that separately loaded ajax content to be another document, and if so, does having another document.ready() within that ajax-loaded HTML work the way I think it does?
Alternatively; what would be a better way to handle this situation? (needing to attach an event listener to a DOM element that doesn't yet exist on document.ready())

To answer your question: No, document.ready will not fire again once a ajax request is completed. (The content in the ajax is loaded into your document, so there isn't a second document for the ajax content).
To solve your problem just add the event listener to the Element where you load the ajax content into it.
For example:
$( "div.ajaxcontent-container" ).on( "click", "#id-of-the-element-in-the-ajax-content", function() {
console.log($( this ));
});
For #id-of-the-element-in-the-ajax-content you can use any selector you would use in $("selector"). The only difference is, only elements under div.ajaxcontent-container will be selected.
How it works:
As long as div.ajaxcontent-container exists all elements (if they exist now or only in the future) that match the selector #id-of-the-element-in-the-ajax-content will trigger this click-event.

Javascript in the resulting ajax call will not be excecuted (by default) due to safety. Also, you can't directly bind event to non-existing elements.
You can bind an event to some parent that does exist, and tell it to check it's children:
$(document).ready(function(){
$(document).on('eventName', '#nonExistingElement', function(){ alert(1); }
// or:
$('#existingParent').on('eventName', '#nonExistingElement', function(){ alert(1); }
});
Always try to get as close to the triggering element as you can, this will prevent unnessesary bubbling through the DOM
If you have some weird functions going on, you could do something like this:
function bindAllDocReadyThings(){
$('#nonExistingElement').off().on('eventName', function(){ alert(1); }
// Note the .off() this time, it removes all other events to set them again
}
$(document).ready(function(){
bindAllDocReadyThings();
});
$.ajaxComplete(function(){
bindAllDocReadyThings();
});

try this, that is not working because your control is not yet created and you are trying to attach a event, if you use on event it will work fine. let me know if you face any issues.
$(document).ready(function(){
$(document).on('click', '#element', function (evt) {
alert($(this).val());
});
});

The answer here is a delegated event:
JSFiddle
JSFiddle - Truly dynamic
jQuery
$(document).ready(function(){
// Listen for a button within .container to get clicked because .container is not dynamic
$('.container').on('click', 'input[type="button"]', function(){
alert($(this).val());
});
// we bound the click listener to .container child elements so any buttons inside of it get noticed
$('.container').append('<input type="button" class="dynamically_added" value="button2">');
$('.container').append('<input type="button" class="dynamically_added" value="button3">');
$('.container').append('<input type="button" class="dynamically_added" value="button4">');
$('.container').append('<input type="button" class="dynamically_added" value="button5">');
});
HTML
<div class="container">
<input type="button" class="dynamically_added" value="button1">
</div>

I'm working on a code-base with a friend that has a similar requirement. The delegated event handler option is definitely best if all you want is to attach event handlers. An alternative, especially if you need to do other DOM processing in your $(document).ready function, is to put the code you want run into a script element at the end of your code. Basically, instead of:
<script type="text/javascript">
$(document).ready(function() {
// Your code here
});
</script>
<!-- rest of dynamically loaded HTML -->
Try swapping the script and the rest of the HTML around so you have:
<!-- rest of dynamically loaded HTML -->
<script type="text/javascript">
// Your code here
</script>
This forces the browser to only process your code once it has loaded every other DOM element in the dynamically loaded HTML. Of course this means you'll have to make sure the inserted HTML does not have unintended UI consequences by using CSS/HTML instead of JS. Its an old Javascript trick from years gone by. As a bonus, you don't need jQuery for this anymore.
I should mention that in Chromium v34, putting a second $(document).ready call inside a <script> tag in the dynamically loaded HTML seems to wait for dynamically loaded DOM to load and then runs the function as you described. I'm not sure this behaviour is standard though as it has caused me great grief when trying to automate tests with this kind of code in it.

JQuery AJAX .load() has a built-in feature for handling this.
Instead of simply $('div#content').load('such_a_such.url'); you should include a callback function. JQuery .load() provides room for the following:
$('div#content').load('such_a_such.url',
{ data1: "First Data Parameter",
data2: 2,
data3: "etc" },
function(){ $('#span1').text("This function is the equivalent of");
$('#span2').text("the $(document).ready function.");
}
);
However, you do not need to include the data argument.
$( "#result" ).load( "ajax/test.html", function() {
alert( "Load was performed." );
});
http://api.jquery.com/load/

Related

jQuery event not firing (advanced)

For a dynamic added element via ajax or any after page load, I know that we have to use the .on like
$(document).on('click', '#dynamically-added-element', function() {
// do something
console.log('Hello World!');
});
I even wrapped mine with (function($){})(jQuery); to make sure no conflict; and to make sure everything should be run/loaded in proper order, I also have $(document).ready(function(){});.
Now that event was originally meant to run on Page A and it works well, but when I made and try it run on Page B having the same id for the main container and have the same child html, it doesn't work.
So I've done some experiment/tests and both works.
(1) So what I've done, I wrote exact same event listener through my browser's console with just console.log and click the target element, it works!
(2) On the same .js script, I've added exact same event listener with just console.log but wrapped it inside setTimeout(function(){}, 5000);, after 5 seconds, I clicked the target element and it worked!
So my question now is, why my original code doesn't work? Why these tests works? So what's the solution?
Also, my html elements aren't loaded dynamically, it's loaded on page load, generated via server side PHP.
Edit:
This info might be useful.
running in magento
js script is being included on head (that's why $(document).ready is really important).
jquery script is being loaded before my custom script.
Page A and Page B are on different pages.
It's not an ajax generated element nor js/jquery added element on the fly; it's generated on postback with php code
(3) My third experiment works as well. But I don't want this to be my solution if possible, nor using javascript inline onclick. So what I did, I added a whole new script block inside the php file where that 'part' of the page is being included, with exact same code and it works. But the thing is, I have now two identical event listener.
So now I have 2 identical event listener (regardless if the other one doesn't work - only for Page B), 1 from within (internal) and 1 from external .js file.
<script type="text/javascript">
(function($) {
$(document).ready(function() {
$(document).on('click', '#the-container a', function(e) {
e.preventDefault();
var target = $(this).attr('href');
});
});
})(jQuery);
</script>
Just write you document.on outside of the document.ready that should work and comment your "e.preventDefault();". It worked on the fiddle when I changed it.
<script type="text/javascript">
$(document).on('click', '#the-container a', function(e) {
//e.preventDefault();
var target = $(this).attr('href');
});
</script>
jQuery event handlers are attached to the elements themselves not the selector, if you are instantiating an event handler to an element selector before the element has been loaded, it is not attaching a listener to anything.
For example this will not work:
$.get('http://example.api.com',
function(data){
$node = $('<p></p>')
$node.text(data)
$node.addClass('elementToListen')
$('body').append($node)
})
// this gets executed before the ajax request completes. So no event
// listener gets attached
$('.elementToListen').on('click',function(e){'do somthing'})
because the event listener has been set up before any of the elements have been added to the DOM.
While this will work:
$.get('http://example.api.com',
function(data){
$node = $('<p></p>')
$node.text(data)
$node.addClass('elementToListen')
// here it is getting executed after the AJAX request in the
// success callback
$node.on('click',function(e){'do somthing'})
$('body').append($node)
})

Jquery Onclick functionality not working for div, as specific loaded after sometime

For <div class="editdiv">Test</div>. Jquery click functionality is added in document.ready function . But editdiv loading in page dynamically with delay.
So when I click on the div. Function is not calling. By using timeout function is working fine.
I need a different approach to solve this functionality.
If your .editdiv is loaded dynamically after your js loading so your click event can't detect it and it will not work, instead you should use event delegation on() to deal with fresh DOM :
$('body').on('click', '.editdiv', function(){
//Your click event code
})
If you want to avoid setTimeout you could use delay with queue callback method :
$('div.scroll-area-blue')
.delay(5000)
.queue(function() {
$(this).enscroll({
showOnHover: false,
verticalScrolling: true,
verticalTrackClass: 'vertical-track-blue',
verticalHandleClass: 'vertical-handle-blue'
});
});
If you will use setTimeout better to use it like :
setTimeout( enscrollDiv, 5000);
function enscrollDiv(){
$('div.scroll-area-blue').enscroll({
showOnHover: false,
verticalScrolling: true,
verticalTrackClass: 'vertical-track-blue',
verticalHandleClass: 'vertical-handle-blue'
});
}
Hope this helps.
It is really difficult to understand whats going wrong from your question. What I guess is you are loading a specific div using Ajax or similar technologies - meaning the div is not available initially.
The way jQuery works is that, it only binds the event to the elements only available at the time the part is executed.
If a <div id='myDiv'></div> is not present when $('#myDiv').click(function(){}) is called, it won't work.
One workaround is to do it like this:
$('body').on('click','#myDiv',function(){});
This registers the click on body and then checks if the clicked element is having a id 'myDiv' or not. We can expect the <body></body> to be present always. So the problem we had with previous code won't happen here.
maybe you're loading the javascript codes before the html elements(tags) are loaded.
try adding the script which includes "document.ready()" before the end tag of the body when all html tags have already finished loading.
I'm hitting targets in the dark. Hope it works for you. It's difficult to generate any solution without analyzing the problematic code......

how to use jquery in included html?

sorry for the title...
so i separated the index.html into divs then i called the contant using :
<script>$(function(){$("#work_bunch").load("wb.html"); });</script>
and it works fine but i wont to use jquery on the elements in wb.html
i used this in index :
<script type="text/javascript" src="java_scripts/wb_op.js"></script>
what ever i write in the .js file it seems to work fine in the index
but i can't select any element in wb.html
for example (if img5 is an element wb.html) :
$("#img5").mouseover(function(){
$(img5).fadeOut(2000);
});
You need to use event delegation:
$(document).on('mouseover', '#element_in_wb_page', function() {
// your function
});
In your case:
$(document).on('mouseover', '#img5', function() {
$(this).fadeOut(2000);
});
Delegate the event:
$("#work_bunch").on("mouseover", "#img5", function(){
$(this).fadeOut(2000);
});
When DOM was ready your elements were not there they come into view afterwards so at the time of DOM ready all the events were bound to existing elements. If any element is generated dynamically or put into the view via ajax any event will not be bound to them.
So the solution to cater this issue is to try to delegate the event to the closest static parent whenever possible, although you can delegate to document also but that is way expensive in lookup of that dom elements.
explaining syntax:
$(parentToDelegate).on(event, selector, callbackFn);
If you are including .js in head tag, then you need to make use document.ready()
$(document).ready(function() {
$("#img5").mouseover(function(){
$(this).fadeOut(2000);
});
});
here is what i found to be more general solution
use
$(window).load(function() {
// executes when complete page is fully loaded, including all frames, objects and images
});
instead of
$(document).ready(function() {
// executes when HTML-Document is loaded and DOM is ready
});
because:
- The document ready event executes already when the HTML-Document is loaded.
- The window load event executes a bit later when the complete page is fully loaded, including all frames, objects and images.
use delegate method on if content added dynamically
$("#work_bunch").on("mouseover", "#img5", (function(){
$(this).fadeOut(2000);
});
and typo issue $(img5) to $("#img5")

Extra function tag needed?

In this example someone shows a jQuery onclick event.
My shows this:
$(function() {
$('.post').on('click', function() {
SOME STUFF
});
});
But what are the first and last line doing?
if i remove the lines, it's not working:
$('.post').on('click', function() {
SOME STUFF
});
But why? In the linked example is a second commenter. He shows this way (without first/last line).
Can someone explain this?
It is a shortcut for $( document ).ready(...)
See http://api.jquery.com/ready/
Quoting the doc :
While JavaScript provides the load event for executing code when a page is rendered, this event does not get triggered until all assets such as images have been completely received. In most cases, the script can be run as soon as the DOM hierarchy has been fully constructed. The handler passed to .ready() is guaranteed to be executed after the DOM is ready, so this is usually the best place to attach all other event handlers and run other jQuery code. [...]
All three of the following syntaxes are equivalent:
* $( document ).ready( handler )
* $().ready( handler ) (this is not recommended)
* $( handler )
That is short for document.ready. It waits until the entire document is loaded and the element with class .post can be found and bound to.
If you omit that part, the jQuery function will not find the element and your event will not work.
The first and last lines create an anonymous function. In computer programming, an anonymous function is a function defined, and possibly called, without being bound to an identifier.
In the example here it is used to set the event listener that is loaded onload of the page.
$(function() {
$('.something').on('click', function() {
alert('hello');
$(this).addClass('classOne');
});
});
$(function(){});
is jQuery short hand for
$(document).ready(function() {});
which ensures your document is ready for manipulation before executing anything within it. In many ways its similar to the browser window.onready event. See jQuery docs..
The risk if you don't wrap your jQuery code in either of these forms of the functions is that you will try and manipulate elements before they have been created by the browser. Your code is not guaranteed to fail, but you could, at the very least, get inconsistent behaviour.

How to avoid multiple loading of jQuery functions?

I am using following code on my page which I am loading in ajax.
$(document).ready(function() {
$('#button_id').click(function() {
//Do Something
});
});
Now When I click on the button action happens multiple times. I know that its happening because I am loading the ajax page multiple times.
Please help me solve this.
You can use .off() to remove existing listeners:
$(function() {
$('#button_id').off('click').click(function() {
//Do Something
});
});
If I am wrong about your implementation I apologize. Your problem may exist because the binding is created on first page load and then on subsequent ajax loads with new scripts being inserted and creating duplicate bindings. You should prevent any bindings from being generated on ajax loads to prevent duplicate bindings unless you are good with cleanup.
If the button you are clicking on exists in the ajax loaded area then you should use delegation to ensure that the click handlers still work.
For example:
$( "body" ).on( "click", "#button_id", function() {
//do something
});
This will add a binding to the body element, but more specifically to the id #button_id. A click event on the button will propagate and bubble up to the body element (or whatever parent element you choose).
This makes it so that dynamic elements can be inserted in the DOM and only one event handler is needed to listen for it.
No need for .on() or .off() calls for individual ajax loads. This allows your bindings to be much cleaner.
Of course, if your button is not likely to exist on the page all the time then it would not be a good idea to keep extra bindings. Only create these types of binding if they are always needed to prevent optimization issues.
A cleaner solution would be to remove that code from the ajax loaded HTML and use one single event handler in the master page
I guess your problem is the event is firing many times.
To fire only once try this:
$(document).ready(function() {
$('#button_id').on("click",function(e) {
e.preventDefault(); // This prevents the default non-js action (very used for anchors without links or hashes)
e.stopPropagation(); // Prevent the bubling of the event and spread more times
//Do Something
});
});
If doesn't work with e.stopPropagation(); try with e.stopInmediatePropagation();
Adding documentation for the last method I suggested. It could solve your problem.
http://api.jquery.com/event.stopimmediatepropagation/

Categories