Why does this javascript code prevent my browser from ever loading? - javascript

I'm learning javascript and jquery and have written a very basic script inside my file. I'm experiencing two problems...
The browser never finishes loading the document, it just sits there with the loading icon animating in the tab. Any ideas?
I can't seem to debug this using firebug. When I set a breakpoint anywhere in the document load function, it never hits. Any ideas?
Here's my code...
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link media="screen" type="text/css" href="default.css" rel="stylesheet">
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function()
{
var strMarkup = "";
var strXMLFile = "";
//Parse XML and generate accordion elements
var arrayAccordianElements = ParseXML(strXMLFile);
});
function ParseXML(strPath)
{
var arrayEvents = new Array();
arrayEvents[0] = "test1";
arrayEvents[1] = "test2";
arrayEvents[2] = "test3";
//Return the accordian elements
return arrayEvents;
}
</script>
</head>
<body>
hello
</body>
</html>
As you experts can see, my webpage should simply display "hello" after processing some javascript that creates an array inside of a function. Do you see any problems? I apologize if they're obvious problems, I'm a noob :)
Thanks in advance for all your help!

Runs fine for me in Safari 4.0.3. Make sure your path to jQuery is correct? If it is incorrect and there's something misconfigured and jQuery fails to load, that will hang indefinitely.

Code-wise I don't see anything that would cause an infinite loop at all. However, knowing firefox etc, there may be a variety of things out of your control. Start with restarting the browser. Profile the script with Firebug (Console > Profile > Reload the page > Press profile again), and see what part takes most time.
One thing, probably unrelated, close your link tag. is sufficient.

Related

Is it possible to use javascript to modify a script element?

Is there a way to use javascript to modify a script element?
Like for example:
HTML:
<script id="something" src="/js/file.js"></script>
Javascript:
var something = document.getElementById("something");
something.src = "/js/anotherfile.js"
Is it possible? Because I have a bit of code that works like that and it sort of doesn't work
To be specific, here's the code:
<!DOCTYPE html>
<html>
<head>
<title>MyohTheGod's Website</title>
<link rel="icon" type="image/x-icon" href="/supercorn.gif" defer>
</link>
<link id="css" href="/css/dark.css" rel="stylesheet" type="text/css">
</link>
<script src="/js/particles.js" defer></script>
<script src="/js/header.js"></script>
<script src="/js/theme.js"></script>
<script>window.alert("Welcome to the Home of MyohTheGod. You can play games, check out our web proxies, and more. Also, please do check out the About page. Press OK to continue...");</script>
</head>
<body>
-snip-
</body>
<script id="foot" src="/js/footer.js"></script>
</html>
<script>
-snip-
</script>
var css = document.getElementById("css");
var foot = document.getElementById("foot");
function toggleDLmode(m) {
-snip-
if (dlmodebool) {
css.href = "/css/dark.css"
foot.src="/js/dark-footer.js"
} else {
css.href = "/css/index.css"
foot.src="/js/footer.js"
}
}
-snip-
It is working, do you inspect it? It does changed, but maybe you're thinking, "hm why this /js/anotherfile.js is not downloaded?". Well because of the script tag is already rendered and already downloaded, so you can't do that. What you can do though add NEW script tag.
Maybe this will help How to dynamically change the script src?. This links would explain more why your code "does not work".
There certainly is. You can use document.scripts which returns an collection that you can iterate through like an array. You can change the code using the innerHTML property very much like a normal element. See here https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
Edited to add: If you've got a html page with multiple script tags, the document.script collection has each script in the order they appear. The code below will log out the source (src tag) or the actual javascript for each script element.
You can also 'write' javascript by setting the innerHTML property.
IMHO it's a bit of a solution that's looking for a problem but at least it gives you access to the number of scripts you have.
[...document.scripts].forEach(script => {
if (script.src != '') {
console.log("Script source:" + script.src);
} else {
console.log(script.innerHTML);
}
});

How can I change my code to be able to calculate different urls instead of the current page

I'm trying to calculate the load time and page size of different URLs/Pages similar to the developer tools performance tab but in javascript. But the current code only calculates its current page instead of a different URL. Is there any way for me to do this because with my research I have no luck.
<html>
<head>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<script type="text/javascript">
var start = new Date().getTime();
function onLoad() {
var now = new Date().getTime();
var latency = now - start;
alert("page loading time: " + latency+"\n"+"Start time:"+start+"\n"+"End time:"+now);
alert("Load_size:"+document.getElementsByTagName("html")[0].outerHTML.length + "KB");
}
</script>
</head>
<body onload="onLoad()">
<!- Main page body goes from here. -->
</body>
</html>
It will not be possible to read the runtime parameters of a page outside the page your javascript is running on.
Part of the security model is to avoid being able to inspect the runtime of other pages. This is called the "sandbox". You'll need to build a plugin that breaks the sandbox to inspect the domLoad / domReady and other performance events.
Good news though, you probably have one built in! The console for modern browsers shows all those events in the timeline tab.
If you're trying to make a service that attempts to evaluate the runtime of other pages, you'll need to load those in a virtual web browser on the server and interpret the results using selenium or something similar.
You can try this to calculate the load time of a page:
<script type="text/javascript">
$(document).ready(function() {
console.log("Time until DOMready: ", Date.now()-timerStart);
});
$(window).load(function() {
console.log("Time until everything loaded: ", Date.now()-timerStart);
});
</script>
edit: this will only work on pages where this JS code will run, so if you cant insert code onto the page you wont be able to run it.

jQuery not functioning right after publish to test server

I have the following jQuery in a user control using a Telerik RadGrid:
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.4.js"></script>
<script type="text/javascript">
var warnMessage = "You have attempted to leave this page. If you have made any changes to the fields without clicking the Save and Continue button, your changes will be lost. Are you sure you want to exit this page?";
$(document).ready(function () {
$('input:not(:button,:submit),textarea,select').change(function () {
window.onbeforeunload = function () {
if (warnMessage != null) return warnMessage;
}
});
$('input:not(:button,:submit),textarea,select').on('DOMNodeRemoved', function () {
window.onbeforeunload = function () {
if (warnMessage != null) return warnMessage;
}
});
$('input:submit').click(function (e) {
warnMessage = null;
});
});
</script>
What it's meant to do is to keep a user from clicking away from the page using several of these controls without saving their changes. When I run this in VS2013, it works fine, triggering the pop-up when anything is added/updated/deleted in the RadGrid and the user attempts to leave the page without saving. However after publishing to the test server,the .click is never hit, so when a user tries to add another entry to the grid, the warning message fires again, and the on DOMNodeRemoved never works. Is there something I'm doing wrong in the code? Or is there something wrong with the server? I'm new to jQuery, so any help would be greatly appreciated. I will post more info if needed.
After looking at the console fo rthe test-server site, I found I was getting an "object doesn't support property or method 'addeventlistener'" error. I went to the Master page of the site and added a meta to check for the compatibility mode and that fixed it right up.
<head runat="server">
<title></title>
<link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
<link rel="SHORTCUT ICON" href="favicon.ico" type="image/x-icon"/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<script type="text/javascript" src="/Scripts/modernizr.js"></script></head>
UPDATE
After looking into this issue more, it's not that JQuery wasn't working per se, it was that the functionality did not exist for my solution to work in IE9.

Why scripts at the end of body tag

I know this question was asked many times, but I haven't found answer. So why its recommended to include scripts at the end of body tag for better rendering?
From Udacity course https://www.udacity.com/course/ud884 - rendering starts after DOM and CSSOM are ready. JS is HTML parse blocking and any script starts after CSSOM is ready.
So if we got:
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>CRP</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- content -->
<script src="script.js"></script>
</body>
</html>
CRP would be:
CSSOM ready > JS execute > DOM ready > Rendering
And if script is at head:
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>CRP</title>
<link rel="stylesheet" href="styles.css">
<script src="script.js"></script>
</head>
<body>
<!-- content -->
</body>
</html>
CRP would be the same:
CSSOM ready > JS execute > DOM ready > Rendering
This question is only about "sync" scripts (without async/defer attribute).
Scripts, historically, blocked additional resources from being downloaded more quickly. By placing them at the bottom, your style, content, and media could download more quickly giving the perception of improved performance.
Further reading: The async and defer attributes.
In my opinion, this is an outdated practice. More recently, the preference is for JavaScript to separate any code that requires the DOM to be present into a "DOMContentLoaded" event listener. This isn't necessarily all logic; lots of code can initialize without access to the complete DOM.
It's true that this causes a small moment when only the script file is being retrieved, and nothing else (for instance, images). This small window can be skipped by adding the async attribute, but even without it I recommend putting script tags in the head so that the browser knows as soon as possible to load them, rather than saving them (and any future JS-initiated requests) for last.
It is a best practice to put JavaScript tags just before the
closing tag rather than in the section of your HTML.
The reason for this is that HTML loads from top to bottom. The head
loads first, then the body, and then everything inside the body. If we
put our JavaScript links in the head section, the entire JavaScript
file will load before loading any of the HTML, which could cause a few
problems.
1.If you have code in your JavaScript that alters HTML as soon as the
JavaScript file loads, there won't actually be any HTML elements
available for it to affect yet, so it will seem as though the
JavaScript code isn't working, and you may get errors.
2.If you have a lot of JavaScript, it can visibly slow the loading of your page
because it loads all of the JavaScript before it loads any of the
HTML. When you place your JavaScript links at the bottom of your HTML
body, it gives the HTML time to load before any of the JavaScript
loads, which can prevent errors, and speed up website response time.
One more thing: While it is best to include your Javascript at the end
of your HTML , putting your Javascript in the of your
HTML doesn't ALWAYS cause errors. When using jQuery, it is common to
put all of your code inside a "document ready" function:
$("document").ready(function(){ // your code here });
This function basically says, don't run any of the code inside until
the document is ready, or fully loaded. This will prevent any errors,
but it can still slow down the loading time of your HTML, which is why
it is still best to include the script after all of the HTML.
Images placed below the script tag will wait to load until the JS script loads. By placing the script tag at the bottom you load images first, giving the appearance of a faster page load.
I think it depends on your website or app. Some web apps are based on JavaScript. Then it does not make sense to include it at the bottom of the page, but load it immediately. If JavaScript just adds some not so important features to some content based page, then better load it at the end. Loading time will almost be the same, but the user will see the important parts earlier (before the page finished loading).
It’s not about a whole site loading faster, but giving a user the impression of some website loading faster.
For example:
This is why Ajax based websites can give a much faster impression. The interface is always the same. Just some content parts will alter.
This was an extremely useful link. For any given webpage, a document object model is created from the .html. A CSS object model is also created from .css.
We also know that JS files also modify objects. When the browser encounters a tag, the creation of DOM and CSS object models are immediately halted when the script is run because it can edit everything. As a result, if the js file needed to extract information from either of the trees (DOM and CSS object model), it would not have enough information.
Therefore, script srces are generally at the end of the body where most of the trees have already been rendered.
Not sure if this helps,
But from this resource script-tag-in-web the inline script is always render blocking even if kept at the end of body tag.
Below inline script is first render blocking.Browser will not paint anything on screen till the long for loop is executed
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link href="style.css" rel="stylesheet" />
<title>Critical Path: Script</title>
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg" /></div>
<script>
let word = 0
for(let i =0; i<3045320332; i++){
word += i;
}
var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = word + 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);
</script>
</body>
</html>
But'index.js' below is not initial render blocking, the screen will be painted , then once external 'index.js' is finished running the span tag will be updated.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link href="style.css" rel="stylesheet" />
<title>Critical Path: Script</title>
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg" /></div>
<script type="text/javascript" src="./index.js">
</script>
</body>
</html>
index.js
let word = 0
for(let i =0; i<3045320332; i++){
word += i;
}
var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = word + 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);

Accessing jQuery objects in the module pattern

Really getting in to javascript and looking around at some patterns. One I have come accross is the module pattern. Its seems like a nice way to think of chucks of functionality so I went ahead and tried to implement it with jQuery. I ran in to a snag though. Consider the following code
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>index</title>
<script type="text/javascript" charset="utf-8" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
var TestClass2 = (function(){
var someDiv;
return {
thisTest: function ()
{
someDiv = document.createElement("div");
$(someDiv).append("#index");
$(someDiv).html("hello");
$(someDiv).addClass("test_class");
}
}
})();
TestClass2.thisTest();
});
</script>
</head>
<body id="index" onload="">
<div id="name">
this is content
</div>
</body>
</html>
The above code alerts the html content of the div and then adds a class. These both use jQuery methods. The problem is that the .html() method works fine however i can not add the class. No errors result and the class does not get added. What is happening here? Why is the class not getting added to the div?
Ah, now that you've updated your question I can better answer your question. You should change the append to appendTo considering you're wanting to move the newly created element inside of the already present #index.
$(document).ready(function() {
var TestClass2 = (function() {
var someDiv = $("#name");
return {
thisTest: function() {
someDiv = document.createElement("div");
$(someDiv)
.html("hello")
.addClass("test_class")
.appendTo("#index");
}
}
})();
TestClass2.thisTest();
});
Hope this helps!
I copied and pasted your code and it works for me.
Make sure you're not simply viewing source to see if the class is applied because doing so simply shows you the HTML that was sent from the server - any DOM updates that occur through JavaScript will not be reflected.
To view the live DOM, use a tool like Firebug or WebKit's Inspector (comes built-in to Safari and Chrome).
Your code works great!
http://jsfiddle.net/lmcculley/p3fDX/

Categories