I am working on js script loading techniques and want to show a custom loader while all my content/resources are loading. Below is working as far as I can tell to load js scripts in order but my web app is throwing some errors after it starts.
My question is: how is the below script (which is called as a <script> right after jQuery at the bottom of my HTML) different from simply having all these js scripts called as <script>'s in the head of the HTML? Why errors on one but not the other?
$(document).ready(function(){
jLoader(scripts[0]);
});
var i = 0;
function jLoader (script){
return $.ajax({
method: "GET",
dataType: "script",
url: script,
context: document.body,
cache:true,
}).done(function() {
console.log(script + ' loaded!');
step();
}
});
}
function step(){
i = i + 1;
jLoader(scripts[i]);
}
var scripts = ['js/materialize.js','http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.js','js/leaflet.awesome-markers.js',
'js/bouncemarker.js','https://cdn.firebase.com/js/client/2.3.1/firebase.js','js/geofire.min.js','js/myScript.js'];
There is a closing curly brace too much after step();
When you put the variable definitions on top it should work::
var i = 0;
var scripts = ['http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.js','https://cdn.firebase.com/js/client/2.3.1/firebase.js'];
$(document).ready(function(){
jLoader(scripts[0]);
});
function jLoader (script){
return $.ajax({
method: "GET",
dataType: "script",
url: script,
context: document.body,
cache:true,
}).done(function() {
console.log(script + ' loaded!');
step();
});
}
function step(){
i = i + 1;
jLoader(scripts[i]);
}
At least here it does: http://jsfiddle.net/adweqcm2/
But remember: in production environments it is recommendable to concatenate your scripts.
Related
I have one html page which contains a jquery function.
<script>
function loadCustomers() {
$.ajax({
type: 'GET',
url: 'http://localhost:8080/cache/getCustomers',
dataType: 'json',
success: function(data) {
var rows = [];
$.each(data,function(id,value) {
rows.push('<tr><td><a href="clientSiteInfo.html?client=">'+id+'</td><td>'+value+'</td></tr>');
});
$('table').append(rows.join(''));
}
});
};
window.onload = loadCustomers;
</script>
I have linked another html page for each row. When each rows populated, the id values has to be passed to the clientSiteInfo.html page.
In the clientSiteInfo.html page i have another jquery function similar to above.
<script>
function loadSites() {
$.ajax({
type: 'GET',
url: 'http://localhost:8080/cache/getSite?clientName='+${param.client},
dataType: 'json',
success: function(data) {
var rows = [];
$.each(data,function(id,value) {
rows.push('<tr><td>'+id+'</td><td>'+value.machine+'</td><td>'+value.state+'</td></tr>');
});
$('table').append(rows.join(''));
}
});
};
window.onload = loadSites;
</script>
in the GET url I try to read client parameter. But it is not passing from my initial page.
What Im doing wrong here? I look for simple solution
jQuery doesn't have a native way to read the url parameters. However, javascript works just fine:
function getParameterByName(name) {
const match = RegExp(`[?&]${name}=([^&]*)`).exec(window.location.search);
return match && decodeURIComponent(match[1].replace(/\+/g, ' ') );
}
In your code you would just call it as getParameterByName('client')
I have a script like this.
The jQuery ajax loads all my files with no issues.
The ajax_load_books.php file have lot of css and js(inline edit, sliders etc.) files in it.
The problem is:
How to load all the files before the success function so that the user can see the loader_div message untill all the files are loaded.
In other words - Load all the js/css files and proceed with the success function.
Even I have checked with .load() function. Could someone redefine the below code .
<script type="text/javascript">
$(document).ready(function () {
$(".form-control").change(function () {
var id = $(this).val();
var dataString = 'id=' + id;
$.ajax({
type: "POST",
url: "ajax_load_books.php",
data: dataString,
cache: false,
beforeSend: function () {
$("#loader_div").show();
},
success: function (html) {
$("#loader_div").hide();
$("#txtHint").html(html);
}
});
});
});
</script>
Thanks,
Kimz
For the css files, you can find them using jQuery.parseHTML() function, but the <script> will be stripped with this so instead we would have to use regex for the <script> tags.
Try:
<script type="text/javascript">
$(document).ready(function () {
$(".form-control").change(function () {
var id = $(this).val();
var dataString = 'id=' + id;
$("#loader_div").show();
$.ajax({
type: "POST",
url: "ajax_load_books.php",
data: dataString,
cache: false,
beforeSend: function () {
//parsing <link>
var $str = $('<output>');
//loading html into fake tag
$str.load("ajax_load_books.php");
//now $str includes all your page code
temp = $.parseHTML(str);
$.each(temp, function (i, el) {
//finding the <link> tag
if (el.nodeName == 'LINK') {
//appending it to the <head> tag
$('head').append("<link rel='stylesheet' href='" + el.getAttribute('href') + "'>");
}
});
//for script we will use regex
var pattern = /<script[^>]+?>.*?<\/script>/gi;
var matches = str.match(pattern);
var scripts = "";
for (var i in matches) {
scripts += matches[i];
}
//appending script tag to <head>
$('head').append(scripts);
},
success: function (html) {
$("#loader_div").hide();
$("#txtHint").html(html);
}
});
});
});
</script>
Demo
There is a drawback with this, your stylesheets and script code will repeat. If the above code causes issue running because of the repetition, you should place the code of beforeSend() before the AJAX and have a parameter sent from your AJAX function indicating that when an AJAX is called with this parameter, to execute all the HTML except the stylesheets and js scripts.
I'm putting multiple 2 JS scripts in 1 file, and although they worked well independently when wrapped around the when in html file, the 2nd one simply doesn't work when I calls them from an outside JS file.
Here's the JS code:
// start of open the name div
$(function() {
$('.reply_submit_name_open').click(function(){
$(this).siblings('.reply_submit_name').fadeIn();
$(this).fadeOut();
});
$('.check_author').click(function(){
if($('.check_author').is(":checked")) {
$('.name_input').val($(this).val());
$('.name_input').attr('readonly', true);
} else {
$('.name_input').attr('readonly', false);
}
});
});
// end of opening name div
// start of posting replies
var base_url = '<?php print base_url();?>';
var interview_id = '<?php echo $this->uri->segment(3)?>';
$(function() {
$('.reply_button').click(function(){
var this_a = $(this);
var reply = $(this).parents().siblings('textarea').val();
var username =$(this).siblings().find('input').val();
var parent_comment_id=$(this).closest('form').attr('id');
var last_reply_id=$(this).closest('.reply_form_div').siblings('.replies').children().last('.comment').attr('id');
$.ajax({
type:"POST",
url: base_url + "comment_upload/reply_upload",
data:{parent_comment_id : parent_comment_id, interview_id: interview_id, reply:reply, username: username},
dataType: "json",
success: function(data,status){
if(data.state == 'succ') {
this_a.html('Success');
$('.reply_button').closest('.reply_form_div').siblings('.replies').append(data.new_reply);
} else {
this_a.html('Bad');
}
}
});
});
});
// end of posting replies
What's the cause? Appreciate any advice.
You've got a bunch of PHP in there that certainly won't be evaluated if you move this to an external .js file, unless you've configured your server to run all .js files through php.
I'm creating a dynamic-form infrastructure. This infrastructure will get a certain XML which will include all of the form data, from the order in the page to validators.
The dynamic page may also contain fields which will require some sort of validation. The validation is not only trivial (such as "numeric"\"alphanumeric"), it might be something more complicated.
That's why I want to pass in my XML the validators javascripts.
When developing on traditional Web Application, it's simple to plant this code in the page header. But I don't know how to do so when using MVC3, since it's not a normal client-server application.
It's important to explain - in my controller, I pass this dynamic-form class the xml file, it does all it should, and in the end, I plant the result in ViewBag.table.
Anyone know how can I can plant the javascript code from the controller to view header?
EDIT:
I tried thw following:
$(document).ready(function () {
$.ajax({
url: '#Url.Action("SetJScript", "MyPages")',
type: 'POST',
success: function (result) {
var myscript = document.createElement('script');
myscript.setAttribute('type', 'text/javascript');
myscript.innerHTML = '$( document ).ready( function ( e ){' + result + '});';
document.getElementsByTagName('head').item(0).appendChild(myscript);
}
});
and also:
$(document).ready(function () {
$.ajax({
url: '#Url.Action("SetJScript", "MyPages")',
type: 'POST',
success: function (result) {
var myscript = document.createElement('script');
myscript.setAttribute('type', 'text/javascript');
myscript.innerHTML = "function test() {alert('aa');}";
document.getElementsByTagName('head').item(0).appendChild(myscript);
}
});
or change the:
myscript.innerHTML = "function test() {alert('aa');}";
to:
myscript.innerHTML += "function test() {alert('aa');}";
so it will be added to the existing "$documnet.ready" function.
None of it worked.
I kept getting "Unknown error"
Thank you all.
Hope it helps..
$(document).ready(function () {
$.ajax(
{ url: '#Url.Action("SetJScript", "MyPages")',
type: 'POST',
success: function(result)
{ var myscript = document.createElement('script');
myscript.setAttribute('type','text/javascript');
myscript.innerHTML = 'function test() {alert("aa");}';
document.getElementsByTagName('head').item(0).appendChild(myscript);
} //end of success
});
});
I am using jQuery to insert an HTML shell into a page, and populate the shell with XML. Here is the XML in question
<minorPropCategory title="Test Title 1">
<minorProp>FLV</minorProp>
<minorProp>BLV</minorProp>
<minorProp>RLV</minorProp>
</minorPropCategory>
<minorPropCategory title="Test Title 2">
<minorProp>LAS</minorProp>
<minorProp>ILV</minorProp>
<minorProp>BIL</minorProp>
</minorPropCategory>
So first, what I do is import an HTML snippet for each minorPropCategory, and add the title using this code
$(xml).find('minorPropCategory').each(function(){
var minorHeader=$(this).attr("title");
var minorId=$(this).attr("title").replace(/ /g,'');
var minorModuleContainerCode = "minorModuleContainer.html";
//names the div with a unique ID
minorDiv = $("<div id='"+minorId+"minorModuleContainer' class='minorModuleGroupContainer'>");
//Sets loading message in case it takes longer than usual to load
minorDiv.html("Loading......");
//After minorModuleContainerCode.html code loads, starts populating module
minorDiv.load(minorModuleContainerCode,"t",
function(){
$("#"+minorId+"minorModuleContainer").find(".minorModuleHeader").html(minorHeader);
}
);
$("#minorModuleContainer").append(minorDiv);
Then, what I want to do is add another HTML snippet, and then populate it. This is where I am having a problem. I can try it like this
//Create the actual minor modules
$(this).find('minorProp').each(function(){
var minorPropCode = $(this).text();
var minorModuleCode = "minorModule.html";
minorModuleDiv = $("<div id='"+minorPropCode+"minorModule' class='minorModule'>");
minorModuleDiv.html("Loading......");
minorModuleDiv.load(minorModuleCode,"b",
function(){
$.ajax({
type: "GET", url: minorPropCode+".xml", dataType: "xml",
success: function(xml3) {
$("#"+minorPropCode+"minorModule").find(".minorPropLogo").attr(
{
src:$(xml3).find('smallImage').text(),
alt:$(xml3).find('smallImageAlt').text()
}
);
}
});
});
$("#"+minorId+"minorModuleContainer").append(minorModuleDiv);
});
});
But it never shows up on the page, because I don't think it is firing at the proper time. Alternatively, I tried moving the creation of the minor modules into the .load function of it's parent, but I run into another problem. The code looks like this.
//MINOR MODULE CODE
$(xml).find('minorPropCategory').each(function(){
var minorHeader=$(this).attr("title");
var minorId=$(this).attr("title").replace(/ /g,'');
var minorModuleContainerCode = "minorModuleContainer.html";
//names the div with a unique ID
minorDiv = $("<div id='"+minorId+"minorModuleContainer' class='minorModuleGroupContainer'>");
//Sets loading message in case it takes longer than usual to load
minorDiv.html("Loading......");
//After minorModuleContainerCode.html code loads, starts populating module
minorDiv.load(minorModuleContainerCode,"t",
function(){
$("#"+minorId+"minorModuleContainer").find(".minorModuleHeader").html(minorHeader);
$(this).find('minorProp').each(function(){
alert("minorPropFired");
var minorPropCode = $(this).text();
var minorModuleCode = "minorModule.html";
minorModuleDiv = $("<div id='"+minorPropCode+"minorModule' class='minorModule'>");
minorModuleDiv.html("Loading......");
minorModuleDiv.load(minorModuleCode,"b",
function(){
$.ajax({
type: "GET", url: minorPropCode+".xml", dataType: "xml",
success: function(xml3) {
alert("test");
$("#"+minorPropCode+"minorModule").find(".minorPropLogo").attr(
{
src:$(xml3).find('smallImage').text(),
alt:$(xml3).find('smallImageAlt').text()
}
);
}
});
});
$("#"+minorId+"minorModuleContainer").append(minorModuleDiv);
});
The problem is, that the line with "$(this).find('minorProp').each(function(){" doesn't fire because "this" has changed. I guess, by now, my noob is showing. I feel like I am doing this in the wrong way. Any help would be appreciated. Thanks.
Posted below is the full .js file of what I am trying to do.
// JavaScript Document<script language="JavaScript" type="text/javascript">
$(document).ready(function(){
//gets the code for the ad from the URL. Using URL jQuery add-on to make this super-easy
var adCode = $.url.param("adCode");
if (adCode != null){
//gets the ad code's XML file
$.ajax({
type: "GET", url: adCode+".xml", dataType: "xml",
success: function(xml) {
//Set the header image
$("#headerImg").attr(
{
src:$(xml).find('headerImage').text(),
alt:$(xml).find('headerImageAlt').text()
}
);
//set the header text
$("#headerText").html($(xml).find('adText').text());
//set the top image
$("#topImg").attr(
{
src:$(xml).find('topImage').text(),
alt:$(xml).find('topImageAlt').text()
}
);
//MAJOR MODULE CODE - This code reads all of the major modules, then adds a majorModule div, and populates it
//Gets all majorProps from ad XML
$(xml).find('majorProp').each(function(){
var propCode=$(this).text();
var majorModuleCode = "majorModule.html";
//names the div with a unique ID
div = $("<div id='"+propCode+"majorModule' class='majorModule'>");
//Sets loading message in case it takes longer than usual to load
div.html("Loading......");
//After majorModule.html code loads, starts populating module
div.load(majorModuleCode,"t",
function(){
//Get the XML for the prop, which contains prop specific stuff
$.ajax({
type: "GET",
url: propCode+".xml",
dataType: "xml",
success: function(xml2) {
$("#"+propCode+"majorModule").find(".propImg").attr(
{
src:$(xml2).find('smallImage').text(),
alt:$(xml2).find('smallImageAlt').text()
}
);
$("#"+propCode+"majorModule").find(".propLogoImg").attr(
{
src:$(xml2).find('smallLogo').text(),
alt:$(xml2).find('name').text()
}
);
$("#"+propCode+"majorModule").find(".viewCalendarLinkA").attr(
{
href:"https://www.harrahs.com/AvailabilityCalendar.do?propCode="+propCode+"&showHotDeal=Y"
}
);
$("#"+propCode+"majorModule").find(".learnMoreLinkA").attr(
{
href:$(xml2).find('homeLink').text()
}
);
$("#"+propCode+"majorModule").find(".propText").html(
$(xml2).find('bodyText').text()
);
}
});
//Get the lowest rate for the prop
$.ajax({
type: "GET",
url: "lowest_rate\\"+propCode+".xml",
dataType: "xml",
success: function(xml3) {
$("#"+propCode+"majorModule").find(".roomRate").html(
"$"+($(xml3).find('roomtype').filter(
function (index) {
return $(this).attr("lowest") == "Y";
}).text()).slice(0, -3)
)
}
});
}
);
$("#mainModuleContainer").append(div);
});
//MINOR MODULE CODE
$(xml).find('minorPropCategory').each(function(){
var minorHeader=$(this).attr("title");
var minorId=$(this).attr("title").replace(/ /g,'');
var minorModuleContainerCode = "minorModuleContainer.html";
//names the div with a unique ID
minorDiv = $("<div id='"+minorId+"minorModuleContainer' class='minorModuleGroupContainer'>");
//Sets loading message in case it takes longer than usual to load
minorDiv.html("Loading......");
//After minorModuleContainerCode.html code loads, starts populating module
minorDiv.load(minorModuleContainerCode,"t",
function(){
$("#"+minorId+"minorModuleContainer").find(".minorModuleHeader").html(minorHeader);
}
);
$("#minorModuleContainer").append(minorDiv);
//Create the actual minor modules
$(this).find('minorProp').each(function(){
var minorPropCode = $(this).text();
var minorModuleCode = "minorModule.html";
minorModuleDiv = $("<div id='"+minorPropCode+"minorModule' class='minorModule'>");
minorModuleDiv.html("Loading......");
minorModuleDiv.load(minorModuleCode,"b",
function(){
$.ajax({
type: "GET", url: minorPropCode+".xml", dataType: "xml",
success: function(xml3) {
$("#"+minorPropCode+"minorModule").find(".minorPropLogo").attr(
{
src:$(xml3).find('smallImage').text(),
alt:$(xml3).find('smallImageAlt').text()
}
);
}
});
});
$("#"+minorId+"minorModuleContainer").append(minorModuleDiv);
});
});
}
});
}
});
To fix this problem just before running minorDiv.load do something like this
var elem = $(this);
minorDiv.load(minorModuleContainerCode,"t", function(){
$("#"+minorId+"minorModuleContainer").find(".minorModuleHeader").
html(minorHeader);
// replace $(this) with elem here
elem.find('minorProp').each(function(){
...
}
...
}
This will keep the reference to correct object in your nested functions.