I have a div with content in it. When the page loads, this function works fine. But when I update the div with content using javascript, this function fails to work.
Can anyone help me figure out what I should do to make this work?
$("textarea.indent").each(function(){
var indentWidth = $(this).siblings('[class=indent]').width();
if(indentWidth != null)
$(this).css('text-indent', (indentWidth+5)+'px');
});
Are you loading $("textarea.indent") dynamicly?
Jquery binds all events on document ready ie. when the page loads. That means that elements added after the page is done loading won't get bound to that event. To fix this you need to dynamicly bind your events as well. Like this..
$.ajax{
...
//Some ajax call
success: function(){
//Bind event
$("textarea.indent").each(function(){
var indentWidth = $(this).siblings('[class=indent]').width();
if(indentWidth != null)
$(this).css('text-indent', (indentWidth+5)+'px');
});
}
}
It doesn't have to be a ajax request thats add the elements, but my point still stands.
Related
I am working on a project that has a html page that has links to libraries- in addition it dynamically prints part of the page with Jquery replaceWith().
The dynamically printed part includes src to images, etc.
What is happening is the images are not loaded, so the page is not rendering immediately.
I need to somehow get the equivalent of a window.onload event that tells me when the page
has loaded all that stuff, so that I start the code, etc that affects the page.
I have tried tacking it on at the end of the script- that does not seem to work-
any suggestions/ideas anyone?
I have tried window.onload, etc, I am wondering if I attach
$("#content").ready() that would work vs load, or if I have to write a window onload inside the content that is written in by replaceWith(). I have actually tried some of this already and nothing seems to work, but I may be implementing it incorectly.
Thanks!
Note, No html , js appear at original post.
Try below (adjustable) pattern, i.e.g., assign different class to "original content" (.ocontent) , "new content" (.ncontent), check utilizing $.is()
var callback = function (status) {
if (status === false) {
console.log(status);
// new content ready
// do stuff
};
if (status === true) {
console.log(status);
// old content present
// do stuff
};
};
$.when($(".ocontents").replaceWith("<img class=ncontents />"))
.done(function(o) {
callback($("#content *").is(o));
});
jsfiddle http://jsfiddle.net/guest271314/6agJz/
See http://api.jquery.com/is/
im trying to do something here. I have a document which I set an array. Then, jquery takes this array and appends an iframe for each value:
<script>
var containers = new Array("test1", "test2");
</script>
This results is 2 iframes, identified by id with his name. Ok. perfect, working. Then, inside of each iframe, it calls a document. Inside this document, I have a function called play().
I am testing play() by returning an alert. Whenever I click on a button, it works:
$("#viewport .next").click(function(){
document.getElementById(containers[current]).contentWindow.play();
});
This works. Perfectly. But I it put this function to trigger on document ready, it doesnt works.
$(function() {
document.getElementById(containers[current]).contentWindow.play();
});
It returns to me:
Uncaught TypeError: Object [object Window] has no method 'play'
Whats am I doing wrong guys?
Thanks!
EDIT
Tried to apply onload on iframe. Didnt work.
var initialFrame = containers[qual];
initialFrame.onload = function() {
document.getElementById(initialFrame).contentWindow.play();
};
EDIT2
For some reason, it started working. Thanks!
Wait for the load event of the iframe first.
initialFrame.addEventListener("load", function() {
initialFrame.contentWindow.play();
});
You would generally listen for the iframe's load event like this:
$("#iframe").load(function(){
// iframe is loaded
});
... but I had trouble with this recently so I instead checked for the contents of the iframe over and over until it had loaded, like this:
function loadFrame() {
if($('body', $('#iframe').contents()).length != 1) {
setTimeout(loadFrame,500);
}
else {
// iframe is loaded
}
};
loadFrame();
Not sure if this is the best solution, but it works.
I populate many parts of my website using
$("#theDivToPopulate").load("/some/api/call.php", callBackToBindClickEventsToNewDiv);
Where /some/api/call.php returns a built list, div, or some other HTML structure to place directly into my target div. The internet has been running slow lately and I've noticed that the time between a button click (which kicks off these API calls) and the div populating is several seconds. Is there an easy way to globally wrap all the load calls so that a div containing "Loading..." is displayed before the call is even made and hidden once the API call is complete.
I can not simply put the code to hide the div into the callBackToBindClickEventsToNewDiv as some load events have different call backs. I would have to copy the code into each function which is ugly and defeats the purpose. I want the flow of any .load to go as follows:
1) dispplayLoadingDiv()
2) Execute API call
3) Hide loading div
4) do callback function.
The loading div must be hidden first as the callback contains some animations to bring the newly loaded div in nicely.
EDIT:
Expanding on jacktheripper's answer:
var ajaxFlag;
$(document).ajaxStart(function(){
ajaxFlag = true;
setTimeout(function (e) {
if(ajaxFlag) {
hideAllDivs();
enableDivs(['loading']);
}
}, 500);
}).ajaxStop(function(){
ajaxFlag = false;
var load = $("#loading");
load.css('visibility','hidden');
load.css('display','none');
load.data('isOn',false);
});
This way loading is only displayed if the page takes more than 500 MS to load. I found the loading flying in and out real fast made things kind of choppy for fast page loads.
Use the following jQuery:
$(document).ajaxStart(function(){
$('#loader').show();
}).ajaxStop(function(){
$('#loader').hide();
});
Where you have an element called #loader that contains what you want to show when an AJAX request is being performed. It could be a span with text, an image (eg a gif), or anything similar. The element should be initially set to display: none
You do not even need to call the function anywhere else.
Try this
$("#someButtonId").click(function(e){
e.preventDefault();
$("#theDivToPopulate").html("Loading...");
$.get("/some/api/call.php",function(data){
$("#theDivToPopulate").fadeOut(100,function(){
$("#theDivToPopulate").html(data).fadeIn(100,function(){
//Do your last call back after showing the content
});
});
});
});
I have a page with 3 buttons. >Logos >Banners >Footer
When any of these 3 buttons clicked it does jquery post to a page which returns HTML content in response and I set innerhtml of a div from that returned content . I want to do this so that If I clicked Logo and than went to Banner and come back on Logo it should not request for content again as its already loaded when clicked 1st time.
Thanks .
Sounds like to be the perfect candidate for .one()
$(".someItem").one("click", function(){
//do your post and load the html
});
Using one will allow for the event handler to trigger once per element.
In the logic of the click handler, look for the content having been loaded. One way would be to see if you can find a particular element that comes in with the content.
Another would be to set a data- attribute on the elements with the click handler and look for the value of that attribute.
For example:
$(".myElements").click(function() {
if ($(this).attr("data-loaded") == false {
// TODO: Do ajax load
// Flag the elements so we don't load again
$(".myElements").attr("data-loaded", true);
}
});
The benefit of storing the state in the data- attribute is that you don't have to use global variables and the data is stored within the DOM, rather than only in javascript. You can also use this to control script behavior with the HTML output by the server if you have a dynamic page.
try this:
HTML:
logos<br />
banner<br />
footer<br />
<div id="container"></div>
JS:
$(".menu").bind("click", function(event) {
event.stopPropagation();
var
data = $(this).attr("data");
type = $(this).attr("type");
if ($("#container").find(".logos").length > 0 && data == "logos") {
$("#container").find(".logos").show();
return false;
}
var htmlappend = $("<div></div>")
.addClass(type)
.addClass(data);
$("#container").find(".remover-class").remove();
$("#container").find(".hidde-class").hide();
$("#container").append(htmlappend);
$("#container").find("." + data).load("file_" + data + "_.html");
return false;
});
I would unbind the click event when clicked to prevent further load requests
$('#button').click(function(e) {
e.preventDefault();
$('#button').unbind('click');
$('#result').load('ajax/test.html ' + 'someid', function() {
//load callback
});
});
or use one.click which is a better answer than this :)
You could dump the returned html into a variable and then check if the variable is null before doing another ajax call
var logos = null;
var banners = null;
var footer = null;
$(".logos").click(function(){
if (logos == null) // do ajax and save to logos variable
else $("div").html(logos)
});
Mark nailed it .one() will save extra line of codes and many checks hassle. I used it in a similar case. An optimized way to call that if they are wrapped in a parent container which I highly suggest will be:
$('#id_of_parent_container').find('button').one("click", function () {
//get the id of the button that was clicked and do the ajax load accordingly
});
Imagine a normal page calling javscript in head. The trouble is some of the content isnt loaded untill i click on a link. Subsequently when this link loads the content it wont work. This is because i guess the javascript has already been run and therefor doesnt attach itself to those elements called later on. There is only standard html being called.
So for example this is the code which calls my external html.
$.get('content.inc.php', {id:id}, function(data){
$('#feature').children().fadeTo('fast', 0).parent().slideUp('slow', function(){
$(this).html(data).slideDown('slow');
});
});
If the html i was calling for example and H1 tag was already in the page the cufon would work. However because i am loading the content via the above method H1 tags will not be changed with my chosen font.This is only an example. The same will apply for any javascript.
I was wonering whether there is a way around this without calling the the javascript as well the html when its received from the above function
If you want to attach events to elements on the page that are dynamically created take a look at the "live" keyword.
$('H1').live("click", function() { alert('it works!'); });
Hope this is what you were looking for.
Does Cufon.refresh() do what you want?
As you said Cufon was just an example, I'd also suggest a more general:
$.get(url, options, function(html, status) {
var dom = $(html);
// call your function to manipulate the new elements and attach
// event handlers etc:
enhance(dom);
// insert DOM into page and animate:
dom.hide();
$target_element.append(dom); // <-- append/prepend/replace whatever.
dom.show(); // <-- replace with custom animation
});
You can attach event handlers to the data that you get via the get() inside of the callback function. For example
$.get('content.inc.php', {id:id}, function(data){
$('#feature').children().fadeTo('fast', 0).parent().slideUp('slow', function(){
$(this).html(data).find('a').click(function(e) {
// specify an event handler for <a> elements in returned data
}).end().slideDown('slow');
});
});
live() may also be an option for you, depending on what events you want to bind to (since live() uses event delegation, not all events are supported).
Andy try this. It will call the Cufon code after each AJAX request is complete and before the html is actually added to the page.
$.get('content.inc.php', {id:id}, function(data){
$('#feature').children().fadeTo('fast', 0).parent().slideUp('slow', function(){
$(this).html(data);
Cufon.replace('h1');
$(this).slideDown('slow');
});
});
JavaScript is not executed because of a security reason OR beccause jQuery is just setting this element's innerHTML to some text (which is not interpreted as a JavScript) if it's contained. So the security is the beside effect.
How to solve it?
try to find all SCRIPT tags in Your response and execute them as fallows:
var scripts = myelement.getElementsByTagName("SCRIPT");
var i = 0;
for (i = 0; i < scripts.length; i++)
eval(scripts[i].innerHTML);