I'm using jQuery FileTree. After a file upload via javascript ajax (old school javascript xmlhttp request, not jQuery), I invoke the fileTree using the following code:
$('#jstree').fileTree({
script: '/ajax/file_tree2/' + path,
multiFolder: true,
expandSpeed: 250,
collapseSpeed: 250
});
...which produces a nice graphic file tree that I can click around in (the path variable is the new folder, being used as a URI segment variable, and I've simply copied the server-side connector jQueryFileTree.php code into a public function in a CodeIgniter controller class. This is extra information that I don't think has anything to do with the problem, just FYI).
But, for some reason when I make a second call by uploading a new file (without having to reload the page), the file tree doesn't update or refresh. I want to refresh the tree structure when I upload new files for different folders.
I've tried to clear the #jstree element itself, using a loader gif:
$('#jstree').html('<img src=\"'+$("#base_url").html()+'/assets_/images/loading/loading36.gif\" />');
...or even just clearing the html:
$('#jstree').html('');
I've tried commands that are part of other widget-type libraries, like 'destroy' or 'refresh':
$('#jstree').fileTree.destroy();
$('#jstree').fileTree({
refresh: true,
script: '/ajax/file_tree2/' + path,
multiFolder: true,
expandSpeed: 250,
collapseSpeed: 250
});
These either do nothing or return a js error.
I downloaded the raw source of v2.1.4 (467904a3ab5c13df094ffe01ddb0d0fea24c5d6a) and modified line 203 from:
if (!data) {
to
if (!data || (Object.prototype.toString.call(args) === '[object Object]' && args.reload)) {
Now, if I want to reload the fileTree, I just pass "reload: true" in the arguments array.
If I have a script tag like this:
<script
id = "myscript"
src = "http://www.example.com/script.js"
type = "text/javascript">
</script>
I would like to get the content of the "script.js" file. I'm thinking about something like document.getElementById("myscript").text but it doesn't work in this case.
tl;dr script tags are not subject to CORS and same-origin-policy and therefore javascript/DOM cannot offer access to the text content of the resource loaded via a <script> tag, or it would break same-origin-policy.
long version:
Most of the other answers (and the accepted answer) indicate correctly that the "correct" way to get the text content of a javascript file inserted via a <script> loaded into the page, is using an XMLHttpRequest to perform another seperate additional request for the resource indicated in the scripts src property, something which the short javascript code below will demonstrate. I however found that the other answers did not address the point why to get the javascript files text content, which is that allowing to access content of the file included via the <script src=[url]></script> would break the CORS policies, e.g. modern browsers prevent the XHR of resources that do not provide the Access-Control-Allow-Origin header, hence browsers do not allow any other way than those subject to CORS, to get the content.
With the following code (as mentioned in the other questions "use XHR/AJAX") it is possible to do another request for all not inline script tags in the document.
function printScriptTextContent(script)
{
var xhr = new XMLHttpRequest();
xhr.open("GET",script.src)
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log("the script text content is",xhr.responseText);
}
};
xhr.send();
}
Array.prototype.slice.call(document.querySelectorAll("script[src]")).forEach(printScriptTextContent);
and so I will not repeat that, but instead would like to add via this answer upon the aspect why itthat
Do you want to get the contents of the file http://www.example.com/script.js? If so, you could turn to AJAX methods to fetch its content, assuming it resides on the same server as the page itself.
Update: HTML Imports are now deprecated (alternatives).
---
I know it's a little late but some browsers support the tag LINK rel="import" property.
http://www.html5rocks.com/en/tutorials/webcomponents/imports/
<link rel="import" href="/path/to/imports/stuff.html">
For the rest, ajax is still the preferred way.
I don't think the contents will be available via the DOM. You could get the value of the src attribute and use AJAX to request the file from the server.
yes, Ajax is the way to do it, as in accepted answer. If you get down to the details, there are many pitfalls. If you use jQuery.load(...), the wrong content type is assumed (html instead of application/javascript), which can mess things up by putting unwanted <br> into your (scriptNode).innerText, and things like that. Then, if you use jQuery.getScript(...), the downloaded script is immediately executed, which might not be what you want (might screw up the order in which you want to load the files, in case you have several of those.)
I found it best to use jQuery.ajax with dataType: "text"
I used this Ajax technique in a project with a frameset, where the frameset and/or several frames need the same JavaScript, in order to avoid having the server send that JavaScript multiple times.
Here is code, tested and working:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<script id="scriptData">
var scriptData = [
{ name: "foo" , url: "path/to/foo" },
{ name: "bar" , url: "path/to/bar" }
];
</script>
<script id="scriptLoader">
var LOADER = {
loadedCount: 0,
toBeLoadedCount: 0,
load_jQuery: function (){
var jqNode = document.createElement("script");
jqNode.setAttribute("src", "/path/to/jquery");
jqNode.setAttribute("onload", "LOADER.loadScripts();");
jqNode.setAttribute("id", "jquery");
document.head.appendChild(jqNode);
},
loadScripts: function (){
var scriptDataLookup = this.scriptDataLookup = {};
var scriptNodes = this.scriptNodes = {};
var scriptNodesArr = this.scriptNodesArr = [];
for (var j=0; j<scriptData.length; j++){
var theEntry = scriptData[j];
scriptDataLookup[theEntry.name] = theEntry;
}
//console.log(JSON.stringify(scriptDataLookup, null, 4));
for (var i=0; i<scriptData.length; i++){
var entry = scriptData[i];
var name = entry.name;
var theURL = entry.url;
this.toBeLoadedCount++;
var node = document.createElement("script");
node.setAttribute("id", name);
scriptNodes[name] = node;
scriptNodesArr.push(node);
jQuery.ajax({
method : "GET",
url : theURL,
dataType : "text"
}).done(this.makeHandler(name, node)).fail(this.makeFailHandler(name, node));
}
},
makeFailHandler: function(name, node){
var THIS = this;
return function(xhr, errorName, errorMessage){
console.log(name, "FAIL");
console.log(xhr);
console.log(errorName);
console.log(errorMessage);
debugger;
}
},
makeHandler: function(name, node){
var THIS = this;
return function (fileContents, status, xhr){
THIS.loadedCount++;
//console.log("loaded", name, "content length", fileContents.length, "status", status);
//console.log("loaded:", THIS.loadedCount, "/", THIS.toBeLoadedCount);
THIS.scriptDataLookup[name].fileContents = fileContents;
if (THIS.loadedCount >= THIS.toBeLoadedCount){
THIS.allScriptsLoaded();
}
}
},
allScriptsLoaded: function(){
for (var i=0; i<this.scriptNodesArr.length; i++){
var scriptNode = this.scriptNodesArr[i];
var name = scriptNode.id;
var data = this.scriptDataLookup[name];
var fileContents = data.fileContents;
var textNode = document.createTextNode(fileContents);
scriptNode.appendChild(textNode);
document.head.appendChild(scriptNode); // execution is here
//console.log(scriptNode);
}
// call code to make the frames here
}
};
</script>
</head>
<frameset rows="200pixels,*" onload="LOADER.load_jQuery();">
<frame src="about:blank"></frame>
<frame src="about:blank"></frame>
</frameset>
</html>
related question
.text did get you contents of the tag, it's just that you have nothing between your open tag and your end tag. You can get the src attribute of the element using .src, and then if you want to get the javascript file you would follow the link and make an ajax request for it.
In a comment to my previous answer:
I want to store the content of the script so that I can cache it and use it directly some time later without having to fetch it from the external web server (not on the same server as the page)
In that case you're better off using a server side script to fetch and cache the script file. Depending on your server setup you could just wget the file (periodically via cron if you expect it to change) or do something similar with a small script inthe language of your choice.
if you want the contents of the src attribute, you would have to do an ajax request and look at the responsetext. If you where to have the js between and you could access it through innerHTML.
This might be of interest: http://ejohn.org/blog/degrading-script-tags/
I had a same issue, so i solve it this way:
The js file contains something like
window.someVarForReturn = `content for return`
On html
<script src="file.js"></script>
<script>console.log(someVarForReturn)</script>
In my case the content was html template. So i did something like this:
On js file
window.someVarForReturn = `<did>My template</div>`
On html
<script src="file.js"></script>
<script>
new DOMParser().parseFromString(someVarForReturn, 'text/html').body.children[0]
</script>
You cannot directly get what browser loaded as the content of your specific script tag (security hazard);
But
you can request the same resource (src) again ( which will succeed immediately due to cache ) and read it's text:
const scriptSrc = document.querySelector('script#yours').src;
// re-request the same location
const scriptContent = await fetch(scriptSrc).then((res) => res.text());
If you're looking to access the attributes of the <script> tag rather than the contents of script.js, then XPath may well be what you're after.
It will allow you to get each of the script attributes.
If it's the example.js file contents you're after, then you can fire off an AJAX request to fetch it.
It's funny but we can't, we have to fetch them again over the internet.
Likely the browser will read his cache, but a ping is still sent to verify the content-length.
[...document.scripts].forEach((script) => {
fetch(script.src)
.then((response) => response.text() )
.then((source) => console.log(source) )
})
Using 2008-style DOM-binding it would rather be:
document.getElementById('myscript').getAttribute("src");
document.getElementById('myscript').getAttribute("type");
You want to use the innerHTML property to get the contents of the script tag:
document.getElementById("myscript").innerHTML
But as #olle said in another answer you probably want to have a read of:
http://ejohn.org/blog/degrading-script-tags/
If a src attribute is provided, user agents are required to ignore the content of the element, if you need to access it from the external script, then you are probably doing something wrong.
Update: I see you've added a comment to the effect that you want to cache the script and use it later. To what end? Assuming your HTTP is cache friendly, then your caching needs are likely taken care of by the browser already.
I'd suggest the answer to this question is using the "innerHTML" property of the DOM element. Certainly, if the script has loaded, you do not need to make an Ajax call to get it.
So Sugendran should be correct (not sure why he was voted down without explanation).
var scriptContent = document.getElementById("myscript").innerHTML;
The innerHTML property of the script element should give you the scripts content as a string provided the script element is:
an inline script, or
that the script has loaded (if using the src attribute)
olle also gives the answer, but I think it got 'muddled' by his suggesting it needs to be loaded through ajax first, and i think he meant "inline" instead of between.
if you where to have the js between and you could access it through innerHTML.
Regarding the usefulness of this technique:
I've looked to use this technique for client side error logging (of javascript exceptions) after getting "undefined variables" which aren't contained within my own scripts (such as badly injected scripts from toolbars or extensions) - so I don't think it's such a way out idea.
Not sure why you would need to do this?
Another way round would be to hold the script in a hidden element somewhere and use Eval to run it. You could then query the objects innerHtml property.
I have a page1 which has a wrapper with articles.
<div id="wrapper">
<article>...</article>
<article>...</article>
<article>...</article>
<article>...</article>
</div>
I am loading new articles from page2 with Ajax and appending them to the wrapper
$.ajax({
url : page_to_load,
success : function (data) {
$('article',data).appendTo('#wrapper');
}
});
But some of this new articles might need specific scripts that were not loaded in page1 but would be loaded if accessed directly page2.
So the problem is some of the content in new articles breaks as they are missing those scripts.
What is the best solution? I can think of checking the new loaded page scripts and compare them with the already loaded and download the new ones, but I have no idea of how to do this.
EDIT
I noticed if I set the dataType to 'html' I cant search for the scripts, although they are there:
$('script',data)//doesn't match anything
But if I do:
console.log(data);
I can see the whole page with <html> and <script> tags
There is no problem actually, if you append HTML to the Dom then script calls will be interpreted as if the page was loaded directly, just make sure you use the same parameters as the shorthand jquery $.POST method.
I actually do this all the time and the <script src=""> are called and interpreted correctly
Just make sure you're accessing the scripts from the right scope as if the html was hardcoded on page1.
If this doesn't work, then check with the web inspector if the scripts are loaded or not.
Working solution:
$.ajax({
url : page_to_load,
success : function (data) {
// load the scripts
var dom = $(data);
dom.filter('script').each(function(){
var scriptSrc = $(this).attr('src');
if(!$('script[src="'+ scriptSrc +'"]').length && scriptSrc !== undefined) {
var script = $("<script/>");
script.attr('src', scriptSrc);
$("head").append(script);
}
});
// load the articles
$('article',data).appendTo('#wrapper');
}
});
Not sure but maybe you could add a script in the AJAX call - I'm not sure of this because I haven't tried it:
Proxy.Scripts.Add(new ScriptReference(AddVersion("/Pages/Items/SearchList/SearchList.Grid.js" )));
This workflow should work :
After every page request :
Get all the script tags in the loaded page.
Loop over the scripts
If it's not loaded yet , load it.
Here is the code snippet :
$.ajax({
url : 'http://localhost',
success : function (data) {
$('article',data).appendTo('#wrapper');
$.each($.parseHTML(data,null,true),function(){
if($(this)[0].tagName == "SCRIPT"){
var src = $(this).attr('src');
if($('script[src="'+ src +'"]').length){
$.getScript(src);
}
});
}
});
Disable async.
$.ajax({
url : page_to_load,
async: false,
success : function (data) {
$('article',data).appendTo('#wrapper');
}
});
you can use RequireJS or HeadJs library for calling js files.
RequireJS is a JavaScript file and module loader and HeadJS, a small library for Responsive Design, Feature Detections & Resource Loading
HeadJs is great and useful, try it.
When simply loading your script with a <script /> tag, you can retrieve the script URL like this:
var scriptURL = Array.prototype.pop.call ( // get the last...
document.getElementsByTagName ('script') // ...script tag on the page...
).src.split ('?') [0]; // ...take 'src' attribute...
// ...and strip the query string
This is a bit of a hack, but can be very useful sometimes, for a number of reasons (e.g., when there are other resource files script relies on and you don't want to hardcode the path). It works because at the time of execution the last <script /> tag existing on the page is your script.
I'm not sure if that is so when loading scripts with RequireJS. Is there a similar way in RequireJS to retrieve the script URL from inside the module definition?
You can require the module module, which commonly used to pass the special config settings:
define(['module'], function (module) {
console.log(module)
}
This will give you an object holding the id and the uri to the module
To get the URL of current module you can use the below script in requirejs.
define([module/hello], function (hello) {
var currentUrl = location.href;
var moduleUrl = url+require.toUrl("module/hello.js");
alert(moduleUrl);
});
$.ajax({ url: "plugin.js", dataType: 'script', cache: true, success: function() {
alert('loaded');
}});
1) I can't get the script to load, probably due to incorrect path, but how do I determine the correct path? The above code is in init.js, plugin.js is also in the same folder.
2) Can I load multiple plugins at once with the same request? eg. plugin.js, anotherplugin.js?
root
|
|_ html > page.html
|
|_ static > js > init.js, plugin.js
Thanks for your help
You need to use getScript, not ajax. Ajax is for loading data, not for executing code.
If you need to load multiple files, try something like this:
var scripts = ['plugin.js', 'test.js'];
for(var i = 0; i < scripts.length; i++) {
$.getScript(scripts[i], function() {
alert('script loaded');
});
}
1) The path will be relative to the page it's loaded from (not the path of your init script) since that's the url the browser will be at when it executes the ajax request.
Edit: Based on your edit, the path to load your script from is either /static/js/plugin.js (if it'll be deployed at the root of your domain), or ../static/js/plugin.js to be safe (assuming all pages that it'll be loaded from will be in /html).
2) No. If they're in different files, they'll need to be different requests. You could merge them into one file on the server-side though...
As an update, the better way to do this with jQuery 1.9.x is to use Deferreds-methods (i.e. $.when), such as follows:
$.when(
$.getScript('url/lib.js'),
$.getScript('url/lib2.js')
).done(function() {
console.log('done');
})
The .done() callback function has a number of useful params.
Read the documentation: http://api.jquery.com/jQuery.when/
Check out the jQuery .getScript function, which will load the script and include it in the current document.
1) The path should be /static/js/plugin.js, relative to your document.
2) No. Each file is loaded by a single HTTP request.
I would check Firebug's net tab to see if it was loaded correctly, and the path it is trying to load from.
The path will be from the document where the JavaScript was included.
I also keep a config object like this (PHP in this example)
var config = { basePath: '<?php echo BASE_PATH; ?>' };
Then you could do
var request = config.basePath + 'path/to/whatever.js';
You can use '../' to set the script path as base path. Then add the relative path for the
$.getScript("../plugin.js").done(function(script, textStatus ) {
alert("loaded:" + textStatus);
}).fail(function(script, textStatus ) {
alert("failed: " + textStatus);
});