I'm using an external JavaScript file to access DOM objects with in my documents. The problem is that jQuery doesn't seem to have access if it's an externally loaded file. My code looks like:
<html>
<head>
</head>
<body>
<div id="domToChange" someAttribute="hi"></div>
<script src="officialJqueryLibrary"></script>
<script src="myJS.js"></script>
</body>
</html>
///////// myJS.js file
// Returns undefined
$('#domToChange').attr('someAttribute');
The DOM selector doesn't seem to find my div when the JavaScript file is loaded externally. However everything works when I place it inside the HTML document itself. How can I give DOM access to my JavaScript file?
You should wrap all your DOM related code into
$(function() {
//Code
});
Then the code gets executed when the DOM is fully loaded.
Try getting the value for your attribute, like so:
$('#domToChange').attr('someattribute');
//or
$('#domToChange').attr('someAttribute'); // i know you've tried this, but pls check demo
Demo here. On my machine, browser Chrome Version 28.0.1500.95 m, it just works fine.
OK, this is a hit and miss kind of thing (but I believe it be an accurate explanation), but the real explanation for why it is happening lies here.
You need to understand that jQuery is an object that is initialized. So the jQuery object takes time to initiatize. As it says,
is very important to make the distinction between jQuery object and native DOM elements. Native DOM methods and properties are not present on the jQuery object, and vice versa.
So it is not necessary that the jQuery object gets initialized at the same time the DOM gets initialized.
Also, all scripts that are passed have a defer attribute. This is mostly browser dependent.
As it says,
When set, this boolean attribute provides a hint to the user agent that the script is not going to generate any document content (e.g., no "document.write" in javascript) and thus, the user agent can continue parsing and rendering.
And it can sometimes delay the execution of the script. Hence the different result according to different people.
You have to enclose the code like this:
$(function(){
$('#domToChange').attr('someAttribute');
});
So that the code is executed when the DOM is ready.
Related
I was going through jQuery ready event and found the following:
The handler passed to .ready() is guaranteed to be executed after the DOM is ready, so this is usually the best place to attach all other event handlers and run other jQuery code. When using scripts that rely on the value of CSS style properties, it's important to reference external stylesheets or embed style elements before referencing the scripts.
I guess this implies that if I set any CSS property after running the jQuery code, its value won't be reflected in the jQuery code. However, the code extracts the value correctly. Am I missing something? Here is my code:
<head>
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script>
$(document).ready(function() {
var theColor = $('p').css('color');
$('p').text(theColor);
});
</script>
</head>
<body>
<p>Some Text!</p>
<style>
p{ color: rgb(29,65,92); }
</style>
</body>
From my understanding the text should not have changed to rgb(29,65,92) in this case but it did. What's the explanation here?
EDIT: If the code return correct value because it is wrapped in ready then what does the following statement mean?
When using scripts that rely on the value of CSS style properties,
it's important to reference external stylesheets or embed style
elements before referencing the scripts.
Both your script and your CSS are internal to the document (i.e., not external), so the DOMContentLoaded warning does not apply.
What the jQuery documentation is pointing out is that if you have external scripts that rely on computed CSS values, those values aren't guaranteed to be available at the time DOMContentLoaded fires. Instead, you'd want to add a handler for load.
Your code does not return rgb(29,65,92) when I run it in Safari, opera and IE. These three browsers display Some Text! for <p> as defined in your HTML. They are ignoring your jQuery code. It works fine in Chrome and Firefox. So, I think the order in which you write your style and script matters in most cases for your page to be consistent across browsers.
When using scripts that rely on the value of CSS style properties,
it's important to reference external stylesheets or embed style
elements before referencing the scripts.
This probably means, it might work if you dont do this, but it is important to do this probably considering cross browser compatibility`
As the title says, if I remove a script tag from the DOM using:
$('#scriptid').remove();
Does the javascript itself remain in memory or is it cleaned?
Or... am I completely misunderstanding the way in which browsers treat javascript? Which is quite possible.
For those interested in my reason for asking see below:
I am moving some common javascript interactions from static script files into dynamically generated ones in PHP. Which are loaded on demand when a user requires them.
The reason for doing this is in order to move the logic serverside and and run a small script, returned from the server, clientside. Rather than have a large script which contains a huge amount of logic, clientside.
This is a similar approach to what facebook does...
Facebook talks frontend javascript
If we take a simple dialog for instance. Rather than generating the html in javascript, appending it to the dom, then using jqueryUI's dialog widget to load it, I am now doing the following.
Ajax request is made to dialog.php
Server generates html and javascript that is specific to this dialog then encodes them as JSON
JSON is returned to client.
HTML is appended to the <body> then once this is rendered, the javascript is also appended into the DOM.
The javascript is executed automatically upon insertion and the dynamic dialog opens up.
Doing this has reduced the amount of javasript on my page dramatically however I am concerned about clean up of the inserted javascript.
Obviously once the dialog has been closed it is removed from the DOM using jQuery:
$('#dialog').remove();
The javascript is appended with an ID and I also remove this from the DOM via the same method.
However, as stated above, does using jQuery's .remove() actually clean out the javascript from memory or does it simple remove the <script> element from the DOM?
If so, is there any way to clean this up?
No. Once a script is loaded, the objects and functions it defines are kept in memory. Removing a script element does not remove the objects it defines. This is in contrast to CSS files, where removing the element does remove the styles it defines. That's because the new styles can easily be reflowed. Can you imagine how hard it would be to work out what a script tag created and how to remove it?
EDIT: However, if you have a file that defines myFunction, then you add another script that redefines myFunction to something else, the new value will be kept. You can remove the old script tag if you want to keep the DOM clean, but that's all removing it does.
EDIT2: The only real way to "clean up" functions that I can think of is to have a JS file that basically calls delete window.myFunction for every possible object and function your other script files may define. For obvious reasons, this is a really bad idea.
If your scripts have already executed removing the DOM elements are not going to get rid of them. Go to any page with JavaScript, open up your preferred javascript console and type $("script").remove(). Everything keeps running.
And this demonstrates #Kolink answer:
http://jsfiddle.net/X2mk8/2/
HTML:
<div id="output"></div>
<script id="yourDynamicGeneratedScript">
function test(n) {
$output = $("#output")
$output.append("test " + n + "<br/>")
}
test(1);
</script>
Javascript:
$("script").remove();
// or $("#yourDynamicGeneratedScript").remove();
test(2);
test(3);
test(4);
function test(n) {
$output = $("#output")
$output.append("REDEFINED! " + n + "<br/>")
}
test(5);
test(6);
test(7);
I need to use a javascript file that is server generated and which creates some html. But I am not happy with the html it creates. I fixed most of this in CSS, but the last problem is that the hrefs point to the wrong place. Is there any way to change these hrefs? I tried putting some scripting after the original call, but it did not work:
<script type="text/javascript" src="http://widget.seekandfind.com/publications?id=dd15fc98d1a83f5e1bcecf3f378a1269c00de96f"></script>
<script type="text/javascript">
var element = document.getElementsByClassName('saf-links')[1].getElementsByTagName('a')[0];
element.setAttribute("href","index.htm");
</script>
Thank you for any suggestions.
It is most likely your JS is firing before the other JS has fully written to the DOM.
You probably need to use a listener (like using the jQuery doTimeout plugin with a loop, or if you are not using jQuery, making your own with a setTimeout() closure/loop) that waits until the HTML elements are ready to be addressed.
Test for an element you know should exist from the called script result and then proceed to modify it once it is available.
Is it really necessary to wait for the "ready" (or "window.onload") events if your code only manipulates DOM elements that have already been parsed entirely?
The jQuery documentation for the "ready()" function demonstrates how you could wait to perform actions until the DOM is entirely ready but the example is for code (script tags) that are listed before the DOM elements in question. But it seems that code which appears after the necessary DOM elements in an HTML document has access to them since, presumably, the DOM is built as the browser parses the document.
For example, is it safe to assume that the following code is reliable in all situations or is it still necessary (or beneficial somehow) to use a ready/onload handler?
<body>
<div id="foo"/>
<script type="text/javascript">
var foo = document.getElementById('foo');
foo.innerHTML = 'The element #foo is loaded!';
</script>
</body>
This SO question is very similar but I wanted to bump it to see if there is any more information.
If your JavaScript code is below the DOM elements and only modifies them exclusively, you don't need to wait for the DOM ready event.
However, keep in mind editing a DOM element which contains a script element (or more specifically, before the element's closing tag) used to cause big problems in IE6 (thanks T.J. Crowder) and IE7.
However, this requires inline scripts which can be a maintenance problem. It is preferred to have your JavaScript stored externally (and many speak of the benefits of including them before the closing body tag) for many benefits such as ease of maintenance and fine grained cache control.
in your case it is fine because the browser will render your code line by line and in your code id="foo" comes first so it will get that div....but suppose you wrote this script in head tag then the script will run first and it wont get the div with id="foo" because its not yet loaded..its better to write in document.ready method
Yes, it's safe if you js code is after dom but usually it's not relly good idea to mix html and js.
Document is loaded in linear fashion so your code works correctly.
Sometimes programmers do not use document ready for performance purpose when the javascript is not depends on the DOM below it. Here is some example.
Based on a click event on the page, via ajax I fetch a block of html and script, I am able to take the script element and append it to the head element, however WebKit based browsers are not treating it as script (ie. I cannot invoke a function declared in the appended script).
Using the Chrome Developer Tools I can see that my script node is indeed there, but it shows up differently then a script block that is not added dynamically, a non-dynamic script has a text child element and I cannot figure out a way to duplicate this for the dynamic script.
Any ideas or better ways to be doing this? The driving force is there is potentially a lot of html and script that would never be needed unless a user clicks on a particular tab, in which case the relevant content (and script) would be loaded. Thanks!
You could try using jQuery... it provides a method called .getScript that will load the JavaScript dynamically in the proper way. And it works fine in all well known browsers.
How about calling eval() on the content you receive from the server? Of course, you have to cut off the <script> and </script> parts.
If you're using a library like jQuery just use the built-in methods for doing this.
Otherwise you'd need to append it to the document rather than the head like this:
document.write("<scr" + "ipt type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js\"></scr" + "ipt>");
In all honesty, I have no idea why the script tag is cut like that, but a lot of examples do that so there's probably a good reason.
You'll also need to account for the fact that loading the script might take quite a while, so after you've appended this to the body you should set up a timer that checks if the script is loaded. This can be achieved with a simple typeof check on any global variable the script exports.
Or you could just do an eval() on the actual javascript body, but there might be some caveats.
Generally speaking though, I'd leave this kind of thing up to the browser cache and just load the javascript on the page that your tabs are on. Just try not to use any onload events, but rather call whatever initializers you need when the tab is displayed.