I have the following in my javascript file:
var divId = "divIDer";
jQuery(divId).ready(function() {
createGrid(); //Adds a grid to the html
});
The html looks something like:
<div id="divIDer"><div>
But sometimes my createGrid() function gets called before my divIder is actually loaded onto the page. So then when I try to render my grid it can't find the proper div to point to and doesn't ever render. How can I call a function after my div is completely ready to be used?
Edit:
I'm loading in the div using Extjs:
var tpl = new Ext.XTemplate(
'<div id="{divId}"></div>');
tpl.apply({
});
You can use recursion here to do this. For example:
jQuery(document).ready(checkContainer);
function checkContainer () {
if($('#divIDer').is(':visible'))){ //if the container is visible on the page
createGrid(); //Adds a grid to the html
} else {
setTimeout(checkContainer, 50); //wait 50 ms, then try again
}
}
Basically, this function will check to make sure that the element exists and is visible. If it is, it will run your createGrid() function. If not, it will wait 50ms and try again.
Note:: Ideally, you would just use the callback function of your AJAX call to know when the container was appended, but this is a brute force, standalone approach. :)
Thus far, the only way to "listen" on DOM events, like inserting or modifying Elements, was to use the such called Mutation Events. For instance
document.body.addEventListener('DOMNodeInserted', function( event ) {
console.log('whoot! a new Element was inserted, see my event object for details!');
}, false);
Further reading on that: MDN
The Problem with Mutation Events was (is) they never really made their way into any official spec because of inconcistencies and stuff. After a while, this events were implemented in all modern browser, but they were declared as deprecated, in other words
you don't want to use them.
The official replacement for the Mutation Events is the MutationObserver() object.
Further reading on that: MDN
The syntax at present looks like
var observer = new MutationObserver(function( mutations ) {
mutations.forEach(function( mutation ) {
console.log( mutation.type );
});
});
var config = { childList: true };
observer.observe( document.body, config );
At this time, the API has been implemented in newer Firefox, Chrome and Safari versions. I'm not sure about IE and Opera. So the tradeoff here is definitely that you can only target for topnotch browsers.
To do something after certain div load from function .load().
I think this exactly what you need:
$('#divIDer').load(document.URL + ' #divIDer',function() {
// call here what you want .....
//example
$('#mydata').show();
});
Through jQuery.ready function you can specify function that's executed when DOM is loaded.
Whole DOM, not any div you want.
So, you should use ready in a bit different way
$.ready(function() {
createGrid();
});
This is in case when you dont use AJAX to load your div
inside your <div></div> element you can call the $(document).ready(function(){}); execute a command, something like
<div id="div1">
<script>
$(document).ready(function(){
//do something
});
</script>
</div>
and you can do the same to other divs that you have.
this was suitable if you loading your div via partial view
Related
I am pretty new to JavaScript so I don't know the ins and outs of the language but I do have some knowledge of it. I created a self invoked function that would sort an array of zip-codes and then output it to a div element in the html file.
Unfortunately, the output isn't going into the div element because the function is executed before the html elements is ready, therefor it doesn't exist.
Is there anyway that I could access the div element within the function without having to use Window.Load, etc?
Thank you! click on the link below to view my function.
Screenshot of function
Is there anyway that I could access the div element within the
function without having to use Window.Load, etc?
Just move that code to the end of your html - after elements in question.
For example after </body>
From what I know, you can't access the DOM if it doesn't exist in that moment.
I know I know, don't use window.onload. But I assure you this is different than waiting for the DOM to load and then follow up with your calculations.
You can have a function evaluate something, then actually hang on the result and wait, and then finally fill the innerHTML when the DOMContentLoaded event has fired... or perhaps something of similar flavour, have a look at this.
<script>
const calculations = (function () {
// Super smart calculations...
var output = "Result of smart calculations";
function findWhereOutputGoes() {
return document.getElementById('output-div');
}
return {
output: output,
findWhereOutputGoes: findWhereOutputGoes,
}
})();
document.addEventListener('DOMContentLoaded', function(){ // Fires as soon as DOM has loaded
calculations.findWhereOutputGoes().innerHTML = calculations.output;
});
</script>
<div id="output-div">
</div>
I'm trying to call EasyUI's draggable everytime I dynamically create new HTML elements. I have the draggable method enclosed like so:
function initializedrag() {
console.log("initializedrag called")
$(".item").draggable({
revert:true,
proxy:'clone',
onStartDrag:function(){
$(this).draggable('options').cursor = "not-allowed";
$(this).draggable('proxy').css('z-index',3);
},
onStopDrag:function(){
$(this).draggable('options').cursor="move";
}
});
console.log("end of initializedrag")
}
And I use load to load in a new html site that contains a div with some li items and a tags that have a class of .item, like so, when the page is ready:
$(function() {
console.log("ready");
$("#shop").load("shopcontent/cat1.html");
initializedrag();
...
});
Through the console.logs, it's calling the function fine, however, the drag functionality isn't actually working. The exact same draggable works when I have a element that is already on the page, and draggable on page load. However, I need it to work whenever I call the initializedrag function.
What's going on here?
FIXED!
It was quite simple really, I just enclosed the initializedrag() in a function that gets called when the content is loaded!
So instead of:
$("#shop").load("shopcontent/cat1.html");
initializedrag();
I did:
$("#shop").load("shopcontent/cat1.html", function() {
initializedrag();
});
Which is odd because I put the contents of initializedrag() in a function just like above yesterday, but it didn't work :)
I am using this code to show loader effect while image load:
$(function(){
jQuery('figure').append('<div class="loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>');
jQuery('.img').load(function(){
jQuery('.loader').remove();
});
});
But I want this code in a function so that I can call it on any image. JSFIDDLE
What you are passing to $() is already a function which is anonymous.
If you want to call it somewhere else you can simply give it a name like
function showSoader(){
jQuery('figure').append('<div class="loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>');
jQuery('.img').load(function(){
jQuery('.loader').remove();
});
}
You can bind it to ready like $(showSoader) and call it anywhere else like showSoader().
If you want to generalize it to work with multiple elements, simply specify a parameter to access the element:
function showSoader(selector){
var $elm = $(selector);
$elm.append('<div class="loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>');
$elm.find('.img').load(function(){
$elm.find('.loader').remove();
});
}
Which you call call like showSoader("#myImgContainer")
worth noticing:
Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load()
shortcut is to execute a function when an image (or collection of
images) have completely loaded. There are several known caveats with
this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache
JQuery
jQuery.fn.extend({
loadImage: function() {
return this.each(function() {
var loading= jQuery('<div class="loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>').insertBefore(jQuery(this));
jQuery(this).load(function(){
loading.remove();
}).error(function() {
loading.remove();
});
});
}
});
$(".img").loadImage();
DEMO
I use pie.js (http://css3pie.com/) a library that allows me to have css3 on ie6+. I apply pie.js on document.ready :
$(document).ready(function(){
if (window.PIE) {
$('.vexClass, #vexId').each(function(){
PIE.attach(this);
});
}
});
My problem is when the dom was modified the elements for which I have apply pie.js are not rendering well so I must load my function that apply pie.js to my elements when the dom is modified and only for section that was modified using OnSubtreeModified or another technique ... For example I have a panel that is displayed when dom was loaded, in that panel I have a button that is expanding another panel with buttons and other elements for which I want to apply pie.js, so for main panel all elements for which I have applied pie.js are rendered ok but the elements from expanded panel, pie.js is not applied :|
So how can I inject that pie.js when dom is modified for expanded panel?
Thank's.
If you are using wicket the only way to do that is through Wicket.Ajax.registerPostCallHandler
Add this in your project, every time when a ajax request is done your pie will be applied.
window.document.ready = function() {
Wicket.Ajax.registerPostCallHandler(pieStarter);
}
function pieStarter() {
if (window.PIE) {
go();
}
}
function go() {
$(''.vexClass, #vexId'').each(function() {
PIE.attach(this);
});
}
Do you get your data from an Ajax call? If so, you need to add the pie in the callback. There is no possibility (at least afaik) to add anything on something that you don't have at a given time.
If you need to add the pie in the callback, you should make an separate function for that. You can give a dom node to the function and it checks for every child node if pie is applied, and if not it does so.
You can't use the DOMSubtreeModified event since older versions of IE - which you are targeting - don't support this. You can, however, work around this by using this answer Detect changes in the DOM together with this script:
$(document).ready(function () {
function applyPIE() {
if (window.PIE) {
$('.vexClass, #vexId').not('[data-pie=attached]').each(function(){
PIE.attach(this);
$(this).attr('data-pie', 'attached');
});
}
}
onDomChange(function(){
alert('document updated, applying PIE now');
applyPIE();
});
$('#link').click(function () {
$('body').append('<h4>added content</h4>');
});
applyPIE();
});
It creates a local function applyPIE() which is called on document ready and every time the DOM changes - filtering out already processed elements. You may want to expand the .vexClass, #vexId set of selectors to match your needs.
JSFiddle: http://jsfiddle.net/hongaar/y3FaM/1/
Seems to me like this should work (based on answers to other questions here on SM), but I'm not getting any results...
Here's my code in the head of the page:
Second edit:
<script type="text/javascript">
function capitalizeFirstLetter(string){
return string.charAt(0).toUpperCase() + string.slice(1);
}
$(document).delegate('#sun, #mon, #tue, #wed, #thu, #fri, #sat', 'pageshow' , function() {
var days = ['sun','mon','tue','wed','thu','fri','sat'],
output = [],//create an output buffering variable
d = new Date();
for(var x=0; x<days.length; x++){
//rather than manipulate the DOM every iteration of the loop we add a string of HTML to an array
output.push('<li>' + capitalizeFirstLetter(days[x]) + '</li>');
}
//now we add the buffered data to the listview and either refresh or initialize the widget
var $cNav = $('#custom-navbar')
$cNav.append(output.join(''));
//if the listview has the `ui-listview` class then it's been initialized, and the widget needs to be refreshed, otherwise it needs to be initialized
if ($cNav.hasClass('ui-navbar')) {
$cNav.navbar('refresh');
} else {
$cNav.navbar();
}
});
</script>
And here's my code in the body:
<div data-role="content">
<div data-role="navbar" style="margin: -10px 0 15px 0;">
<ul id="custom-navbar"></ul>
</div>
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script type="text/javascript">
$(document).delegate('#sun', 'pageshow' , function() {
alert("!");
var days = ['sun','mon','tue','wed','thu','fri','fri','sat'],
output = [];//create an output buffering variable
for(var x=0; x<days.length; x++){
alert(days[x]);
//rather than manipulate the DOM every iteration of the loop we add a string of HTML to an array
output.push('<li><a data-ajax="false" href="#' + days[x] + '">' + days[x] + '</a></li>');
}
//now we add the buffered data to the listview and either refresh or initialize the widget
var $cNav = $('#custom-navbar')
$cNav.append(output.join(''));
//if the listview has the `ui-listview` class then it's been initialized, and the widget needs to be refreshed, otherwise it needs to be initialized
if ($cNav.hasClass('ui-listview')) {
$cNav.listview('refresh');
} else {
$cNav.listview();
}
});
</script>
<script src="../js/jquery.mobile-1.0.1.js"></script>
Since this code runs each pageshow event, you will be getting multiple listings when users navigate to, away, and then back to the page. You could use the pageinit event instead: http://jquerymobile.com/demos/1.1.0-rc.1/docs/api/events.html
Update
The error in your page comes from here:
$('ul#custom-navbar').append('<li/>', {
.append('<a/>', {
'href' = "#" + days[x],
'data-ajax' = "false",
'text' = days[x]
});
});
Do you see it? You've got an extra , { and are missing a bit of syntax to make this make sense. You're also using equal signs where you should be using colons (since you're setting properties of an object):
$('ul#custom-navbar').append(
$('<li/>').append('<a/>', {
'href' : "#" + days[x],
'data-ajax' : "false",
'text' : days[x]
})
);
This creates a list-item, then appends a link to it with some attributes set.
Note that you can copy my code, paste it over your code (in your document) and it will work fine. I've tested it using my console.
In a general sense, you should learn to use your console, it will help you an amazing amount. For instance I found the error on your page in about 30 seconds...
Well, from the jQuery Mobile website they directly recommend not binding to $(document).ready() due to their use of some ajax magic behind the scenes and instead recommend performing something similar to what you're doing but with pageinit instead of pageshow. From what I can see in the documentation they should be (for this) functionally equivalent. Have you tried binding pageshow or pageinit after loading jqm?
http://jquerymobile.com/demos/1.1.0-rc.1/docs/api/events.html
Important: Use pageInit(), not $(document).ready()
The first thing you learn in jQuery is to call code inside the
$(document).ready() function so everything will execute as soon as the
DOM is loaded. However, in jQuery Mobile, Ajax is used to load the
contents of each page into the DOM as you navigate, and the DOM ready
handler only executes for the first page. To execute code whenever a
new page is loaded and created, you can bind to the pageinit event.
This event is explained in detail at the bottom of this page.
I guess 'pageshow' event is of jquery mobile framework. If am right, then you should add jquery mobile script tag before your script.
Well firstly use
$('ul#custom-navbar').listview();
not $('ul#custom-navbar').listview('refresh'); this won't work if the element isn't initialized
But If you added the html attr data-role="listview" on the ul, the on pageshow jQM will automatically init the listview, if so and then you added elements to it, then you would need to run $('ul#custom-navbar').listview('refresh'); I recommend you do this instead.
Also you need to put the $('ul#custom-navbar').listview(); within your live function like someone else mentioned, jQM isn't loaded when you call it, and you should be using the pageinit event, pageshow also fires when you navigate back to the page (thru the back button etc), you don't want to init it twice. Read up on those two, optimally you'd be using both to cleanly handle JS.
PS: I'm glad you are properly listening to the pageinit/pageshow events and not using document.ready, also I suggest starting those listeners in the mobileinit handler, e.g.
$(document).bind("mobileinit", function(){//your pageinit/pageshow listeners here and also the .live function is deprecated now, use $(document).on('pageinit pageshow', 'div:jqmData(role="page"), div:jqmData(role="dialog")', function(oEvent){