I asked half this question already but as i began debugging and messing around with code i noticed some other issues. On my website, http://www.yokaproject.com/, for arguments sake this is what i want you to do. Click on the art tab first, youll notice two logs to the console one for script length, other is ajax call, 5 and 1 respectively. I dont understand why it logs 5, i have 4 known scripts. Then click the next tab, music, it will log 8 twice for script length, and ajax call twice, why? Further it will keep adding in this pattern. I have this very simple request, please work with me on this. Im not saying write code for me or give me everything, just help direct me so i can actually learn my mistake and how to correct it. In fact i would even chat with someone and work on this issue, i just really want to write better JS. That being said here is my code(ignore my script check function meant to comment that out):
*This is just my ajax function, please check my website to see further details, http://www.yokaproject.com/index.html
function handlersAttached(){
$('.header a').on('click', ajaxLoad);
}
handlersAttached();
function ajaxLoad(e) {
console.log($("script").length);
console.log("ajax called");
e.preventDefault();
var url = $(this).attr("href");
var that = $(this);
that.off('click'); // remove handler
$.ajax({
url: url,
dataType: "html",
type: "GET",
cache: false
}).done(function(data){
$("#container").html(data);
})
};
At the first click $(scripts) returned following tags:
<script async="" src="https://www.google-analytics.com/analytics.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="../assets/instafeed.js-master/instafeed.min.js"></script>
<script type="text/javascript" src="../assets/load_scripts.js"></script>
<script>/*google analytics stuff*/</script>
At the next one the following:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="../assets/instafeed.js-master/instafeed.min.js"></script>
<script src="../assets/load_scripts.js"></script>
<script async="" src="https://www.google-analytics.com/analytics.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="../assets/instafeed.js-master/instafeed.min.js"></script>
<script type="text/javascript" src="../assets/load_scripts.js"></script>
<script>/*google analytics stuff*/</script>
It seems that first three of them are appending to DOM tree every time your ajax call performed. Furthermore, load_scripts.js is among them itself, so next clicks will produce more ajax calls and more triggered handlers with console.log respectively.
Solution: do not include scripts in ajax response or, at least, do not append them to DOM tree. Depends on what you're trying to achieve :)
Related
In my parent.htm there's a dropdown list, which is filled dynamically from the database using a JQuery function updateMyList() in parent.js.
If the user wants to add another option to the list, the form child.htm is loaded inside <div id="overlay"> of the parent.htm. To insert new data an AJAX request is called from child.js, which is included in child.htm.
If the request was successful, child.htm is unloaded via $("#overlay").html("") from child.js. When this happens, i'd like to call parent.js's updateMyList(), but i can't find a way to trigger it.
Using opener from inside child.js didn't work (TypeError: opener is null) and i can't find a way to tell if $("#overlay").html() has been changed back to "".
Any help would be greatly appreciated!
Sorry if this is a double post, i'm running out of ideas for search terms...
edit: here's a simplified code:
parent.htm:
<head>
<script type="text/javascript" src="js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="parent.js"></script>
<script>
$(document).ready(function () {
$('#new-option').click(function(){
$("#overlay").load("child.htm");
});
});
</script>
</head>
parent.js:
$(document).ready(function(){
function updateMyList(){
//send AJAX and write options
});
// and do much more...
});
child.htm:
<head>
<script type="text/javascript" src="js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="js/child.js"></script>
</head>
child.js:
$(document).ready(function(){
// do more stuff
$('#save-option').click(function(){
$.post("./inc/savenewoption.php", {
//save user entries
}, function(data){
alert(data);
})
.done(function() {
updateMyList(); // <- this won't work
$("#overlay").html("");
});
});
});
It doesn't work because updateMyList() is inside a different function (one of your $(document).ready() ones). In my experience the only reason you put code into a $(document).ready() function is because Javascript can fire before the document has completely loaded. Trying to fire Javascript on elements before they are in the document will cause errors.
The updateMyList() function doesn't fire until the ajax request is complete, so it should be safe to have it located outside $(document).ready().
I'm developing a web application that because of performance concerns is heavily reliant on Ajax functionality. I'm attempting to make parts of each page available while longer running modules load.
The issue is that I want to kick off the Ajax requests as soon as possible (in the head of the document). This part works fine; the issue is on rare occasion, the Ajax call will come back before the area that I want to load the Ajax data into is present on the page. This causes the data to not be loaded.
To get around the issue I started using script tags below each of my containers that resolve a JQuery promise to let the code know that the area is available.
EDIT: I want to load the data into the area as soon as it becomes available (before full document load).
The current pseudo code looks like this:
<head>
<script>
var areaAvailablePromise = new $.Deferred();
$.when(areaAvailablePromise, myAjaxFunction()).then(function(){
// load data into the element.
});
</script>
</head>
<!-- much later in the document -->
<div class="divIWantToLoadAjaxContentInto"></div>
<script>
areaAvailablePromise.resolve();
</script>
My question is: is there ANY better way to handle this situation? Every one knows that inline scripts are blocking and are bad for performance. Also, I feel that this is going to lead to cluttered code with micro-script tags all over the place.
Put your (whole) <script> tag just after the element.
HTML is parsed from top to bottom, so the element will be loaded already.
No. There really is no better way to my knowledge.
<!doctype html>
<html>
<head>
<script src="jquery.min.js"></script>
<script src="q.min.js"></script>
<script>
var elD = Q.defer();
var dataP = Q($.ajax(…));
Q.spread([elD.promise, dataP], function (el, data) {
…
}).done();
</script>
</head>
<body>
…
<div id="foo"></div>
<script>elD.resolve($("#foo"));</script>
…
</body>
</html>
you can use:
$(document).ready( handler )
(recommended)and also has contracted form:
$(handler)
exemple:
$(function(){
alert("OK");
})
read more: http://api.jquery.com/ready/
I was wondering what a good way to load an external web page (same server) would be. I have tried .load() and .get() however, The external page has a php script that spits out information every few seconds, the .load() and .get() only load it after the php is done. I have tried iFrame with does load it displaying the information being outputted by the PHP script. However, I don't really like to use iFrames. Thanks!
If your goal is for the PHP information (that is spit out every few seconds) to be updated on your site, then what you want to do is use AJAX, inside a setInterval routine.
See this post for the basics of AJAX -- it really is simpler than you might think. (You might first want to look at the simple examples linked at bottom).
Once you've got a simple ajax exchange happening, put that into a function called, for example, doAjax() -- and then create a setInterval, like this:
setInterval('doAjax();',60000);
Here is an important note when considering setInterval
Following is a simple copy/paste(able) example that will let you see exactly what I mean:
HTML/javascript: index.php
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<style>
#timeDiv{width:40%;height:200px;background:wheat;padding:10px;}
</style>
<script type="text/javascript">
$(document).ready(function() {
doAjax();
window.setInterval(function(){
doAjax();
},2000);
}); //END document.ready
function doAjax() {
$.ajax({
type: "POST",
url: "your_php_processor.php",
success: function(myData) {
$('#thetime').html(myData);
}
});
}
</script>
</head>
<body>
<div id="timeDiv">
The time is: <span id="thetime"></span>
</div>
</body>
</html>
Now, the PHP side... your_php_processor.php
<?php
$d = date("h:i:s");
echo $d;
When a page first loads we can use window.onload to make sure that all resources have loaded before we do something.
My question is, if we modify the DOM (e.g. inserting some html based on an ajax request), is there any event that will fire when the document is in the 'loaded' state again? (e.g. when the html inserted contains multiple images).
(Solution with jQuery would be fine).
The short answer:
NO.
The long answer:
if you know what you are looking for you can use mutation observers (https://developer.mozilla.org/en-US/docs/DOM/MutationObserver). it is only support in new browser, and in some version of chrome it has memory leaks when used with closures.
BTW,
document.ready doesn't tell you if all (or any..) of the resources were loaded. it only tell you well, that the dom is ready (that is the load function, which will only fire after all resources (well, any resources that isn't requested using a javascript) were downloaded).
You can use .done().
Description: Add handlers to be called when the Deferred object is resolved.
Also there is jQuery plugin See Here
I would say YES (I do not know if this is supported by all browsers. I use it in safari and chrome)
Testcase you can find here : http://maakmenietgek.nl/testcases/domready/ Please note that I cannot get it work in a fiddle, that's why a standalone testcase
The index.html looks like this
<!DOCTYPE html>
<head>
<title>Testcase</title>
<script src="jquery-1.8.2.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#clickme').click(function() {
$.get('ajaxdata.html', function(data) {
$('#addhere').html(data);
});
});
})
</script>
</head>
<body>
<p id="clickme">clickme</p>
<div id="addhere">
</div>
</body>
</html>
The data loaded with the $.get call looks like this
<p>added data</p>
<script type="text/javascript">
$(document).ready(function() {
alert('added data');
});
</script>
The alert shows after the html has been added to the DOM
Greetings all,
I am attempting to explicitly load the effects.js and builder.js Scriptaculous libraries on a page, using this code:
<script type="text/javascript" src="/javascripts/scriptaculous.js?load=builder,effects"></script>
This works like a charm in FF 3.0.x, IE7 and Opera 9.6.x. It does not work in Firefox 2.0.x, however. The libraries never become loaded. In order to get them to load in FF 2.0.x, I must explicitly reference them with two extra <script /> tags, i.e.:
<script type="text/javascript" src="/javascripts/scriptaculous.js?load=builder,effects"></script>
<script type="text/javascript" src="/javascripts/builder.js"></script>
<script type="text/javascript" src="/javascripts/effects.js"></script>
Does anyone happen to know what the discrepency between FF 2.0 and 3.0 is that causes this behavior? Is there a better solution to my problem?
Thanks for your help!
I've had too much coffee today, so I figure I will give this a go.
One possibility is the load function in scriptaculous.js does not correctly do the processing to include the libraries passed to it as parameters (scriptaculous.js?load=builder,effects).
Try putting in an alert to see if the load function in scriptaculous.js is being entered into, if it is, then the process probably doesn't do what it's supposed to on FF2:
load: function() {
alert('In the load function!');
...rest of code here...
If it isn't, then (maybe) firefox 2 does not want to execute load.
The last part of load seems to do the work for including other libs:
$A(document.getElementsByTagName("script")).findAll( function(s) {
return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
}).each( function(s) {
var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
var includes = s.src.match(/\?.*load=([a-z,]*)/);
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});
From the above code, I can see that the includes variable should parse out the library names, see if that's being assigned anything, replace it with something like:
var includes = s.src.match(/\?.*load=([a-z,]*)/);
alert(includes[0] + ' ' + includes[1]);
That should give you a better idea of what's going on. While this is an interesting little problem, I would definitely go with the solution you proposed:
<script type="text/javascript" src="/javascripts/scriptaculous.js"></script>
<script type="text/javascript" src="/javascripts/builder.js"></script>
<script type="text/javascript" src="/javascripts/effects.js"></script>