Getting content of a script file using Javascript - javascript

I have the following script element in my web page:
<script src="default.js" type="text/javascript"></script>
Using JavaScript, I want to be able to retrieve the content of the script file. I know I could use an ajax request to get the data but then I am getting something from the server that I already have locally.
So what I would prefer to do is retrieve the content from the DOM (if that's possible) or something that has the same result.
Cheers
Anthony
UPDATE
I was trying to simplify the question, maybe a bad a idea, I thought this way would cause less questions.
The real situation I have is as follows, I actually have
<script type="text/html" class="jq-ItemTemplate_Approval">
...
html template that is going to be consumed by jQuery and jTemplate
...
</script>
Now this works fine but it means each time the page loads I have to send down the template as part of the HTML of the main page. So my plan was to do the following:
<script src="template.html" type="text/html"></script>
This would mean that the browser would cache the content of template.html and I would not have to send it down each time. But to do this I need to be able to get the content from the file.
Also in this case, as far as I know, requesting the content via ajax isn't going to help all that much because it has to go back to the server to get the content anyway.

If I understand you correctly, you don't want to use Ajax to load an html template text, but rather have it loaded with the rest of the page. If you control the server side, you can always include the template text in an invisible div tag that you then reference from Javascript:
<div id="template" style="display:none;">
...template text...
</div>
<script>
// pops up the template text.
alert(document.getElementById("template").innerHTML);
</script>
If you are just looking for to load the template so that you can have it cached, you can put the contents in a variable like this:
<script>
var template = "template text..";
</script>
or you can load it using ajax and store the template in a variable so it is accessible. It's pretty trivial in jquery:
var template;
$.get("template.html", function(data){
template = data;
});

unless you load a script as literal text in the page, it does not exist as text. It is interpreted by the browser and melded into the runtime, with any other scripts.
If you want the source you have to fetch it again,if with Ajax get the responseText.
It will come from the browser cache, and doesn't have to be downloaded again.

I think what you want to do is to assign a variable inside template.js. Then you have the variable available for use wherever you want in jquery. Something like:
var tpl = "<div> ... </div>"
Wouldn't this be a simpler solution to your problem? We do this in Ext JS. I think this will work for you in jQuery.

You could get the attribute of the src of the script and then use XHR to get the contents of the JS file. It's a much cleaner way of doing it IMO. e.g.:-
if(window.XMLHttpRequest) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.status == 200 && xhr.readyState == 4) {
var sourceCode = xhr.responseText;
alert('The source code is:-\n'+sourceCode);
}
}
xhr.open("GET",document.getElementById('scriptID').src,true);
xhr.send(null);
}

Using an iFrame & HTML5 Local Storage
Save the templates for rendering later...
not stoked about the iFrame, but it seems to be working pretty good (haven't ran performance tests yet)
Put the iFrame on the page you want the template on (index.html)
<html>
<head>
<iframe src="mustache.Users.html" onload="this.remove();" class="hidden" id="users_template"></iframe>
</head>
</html>
Make sure the src attribute is set
hide the element until you can get rid of it after it loads
Put this body wrapper around your template (mustache.Users.html)
(don't worry it won't show up in the template)
<body onload="localStorage.setItem('users_template',this.document.body.innerHTML);">
<ul class="list-group" id="users" >
{{#users}}<li>{{name}}</li>{{/users}}
</ul>
</body>
replace 'users_template' with whatever name for your variable
the 'onload' attribute saves the template into localStorage during load
Now You can access your templates from anywhere
localStorage.getItem('users_template')
OR
window.localStorage.getItem('users_template')

What is in the JavaScript file? If it's actual code, you can run functions and reference variables in there just like you had cut and paste them into the webpage. You'll want to put the include line above any script blocks that reference it.
Is this what your looking to accomplish?

Why not use Ajax (well Ajah because its html :-))?
when the server is set up correctly and no no-cache or past expires headers are sent, the browser will cache it.

The way that most JavaScript import files work is they include a script, that immediately calls a function with a parameter of certain text, or of another function. To better illustrate, say you have your main index.html file, set it up like this:
<html>
<head>
</head>
<body>
<script>
let modules = {};
function started(moduleName, srcTxt) {
modules[moduleName] = (srcTxt) //or something similar
}
</script>
<!--now you can include other script tags, and any script tags that will be included, their source can be gotten (if set up right, see later)-->
<script src="someOtherFile.js"></script>
</body>
</html>
now make that other file, someOtherFile.js, and right away when its loaded, simply call that "started" function which should already be declared in the scope, and when thats done, then whatever text is passed, from the file, is stored in the main index.html file. You can even stringify an entire function and put it in, for example:
started("superModule", (function() {
/*
<?myCustomTemplateLanguage
<div>
{something}Entire Javascript / html template file goes here!!{/something}
</div>
?>
*/
}).toString());
now you can access the inner content of the function, and get all the text in between the comments, or better yet, then do other parsing etc, or make some other kind of parsing identifiers at the beginning and end of the comments, as shown above, and get all text in between those

Related

How to pass element ID variable to jQuery load function

I am fairly new to Jquery and HTML so please bear with me. I have my index.html with a call to jquery-1.9.1.min.js and I want to create a script that would load an outside html file. Index.html is a fairly long file so I want to break up the section for cleaner code and make it easier to modify.
<html class="no-js">
<main>
<section id="testLoad"></section>
</main>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.9.1.min.js"><\/script>')</script>
<script>$("#testLoad").load("test.html #part-1"); </script>
</body>
</html>
As you can see from the code above it loads the html file fine. What I want to do is set "#part-1" as a variable so that I can call the load script again but call a different ID from another part of the file.
I would also be open to different methods aside from this load function. All I need is to call an external html file (there are about 30 different sections) so it can display that sections data. If I do it this way is there a way to create a header file so that all of these section can have access to the same style sheet?
You'd put your load function inside a named function and pass in an argument:
function loadStuff(divId) {
$("#testLoad").load("test.html #" + divId + '');
}
In your event handler you'd call it:
$(document).ready(function() {
loadStuff('someId');
});
You could also pass in the target ID in a similar manner.
As others have pointed out, this isn't the ideal way to do what's essentially client-side templating.
It seems like you want to be able to combine multiple different "partial" html files, and for this I would recommend you look into Angular which excels at exactly this.
Not sure why you are loading the JQuery js file the way you are. That really doesn't look safe.
Another thing you can do is create an "iffy" as some people call it where it is a script that is automatically called when the page is loaded.
<script>
(function (){
//code goes here
}())
</script>
This code will run when that page is loaded.

How to replace entire page after Javascript code done executing?

I am using a JS script to run some calculations on a page. I then use selenium to grab the text out of the results div.
results = json.loads(driver.find_element_by_id("results").text)
I would very much prefer to avoid using selenium and use requests instead:
results = json.loads(get(<url goes here>).text)
In order to accomplish this I would need to somehow replace the entire page (including JS) with the results in the form of a simple JSON string (no HTML tags). In other words:
<html>
<head>
...
</head>
<body>
<div id="results">{"blah":"1234", "test":"4567", ...}</div>
...
<script>
...
</script>
</body>
</html>
becomes a plain text string suitable for get(...).text
{"blah":"1234", "test":"4567", ...}
This string is modified by the JS code that runs after the page loads. Which means that the results would have to be stored and then used to create an entirely new page devoid of any HTML or JS. The original page replaces itself entirely.
An alternative would be to use JS to replace the entire <html>...</html> block and then erase itself.
Not sure this is possible.
Yes, I could probably use something like:
page = get(<url goes here>)
page.json()
...
I was hoping for an approach that removes everything from the page except the results.
Using python for the selenium part.
EDIT 1:
Here's code that shows how the page works.
https://jsfiddle.net/pkLu7uqz/
The idea is to end-up with a page that has nothing but the JSON string in it. No HTML, CSS, JS at all. Just a single line of text.
You can use document.write in JavaScript. If you call it after the page was loaded, all the content will be replaced by whatever you write.
Run your calculations on JavaScript, and then write the results using document.write. The only thing is that you will need to call it asynchronously so the page has finished loading by the time it's called; otherwise it will just append the text to the document (right after the script).
A simple way would be to call it with a setTimeout:
<html>
<head>
...
</head>
<body>
...
<script>
// run calculations here
...
// get the results into a variable
results = RESULT_OF_THE_CALCULATIONS;
// write the variable using a setTimeout of 1 millisecond
setTimeout('document.write(results)', 1);
</script>
</body>
</html>

Force JS cache clearing without server-side coding

I'm looking to clear the cache on some JavaScript files on my login page. Our web language is pretty archaic, and I'm stuck using it. No PHP, Rails, or anything fun or fancy.
Looking to clear cache on JS files
1. I can't use server-side code.
2. I can't manually append a query string.
3. I found the meta tags mentioned, but noticed that strictly referred the caching the HTML.
My only thought was to use JavaScript in the header to manipulate the text of the HTML document before it loads the files in the tags that occur further down the page. Though I was unable to get this to work successfully. Any ideas?
I'm assuming you currently have something like this in your code:
<script type="text/javascript" src="/site/js/script.js"></script>
If you can't change that, you're stuck. The browser is going to load that as soon as it sees the tag. There's not a reliable way to stop the browser from doing that, or to manipulate the tag before the browser acts on it.
If you can change it, though, the most obvious solution to me is to take it out, and instead dynamically inject a script tag with a cache-busting URL. For example (untested, but you get the idea):
<script>
var scriptUrl = "/site/js/script.js",
cacheBustingUrl = scriptUrl + "?" + Date.now(),
newScriptElement = document.createElement("script")
;
newScriptElement.setAttribute("src", cacheBustingUrl);
document.body.appendChild(newScriptElement);
</script>
This should append a new script element like <script src="/site/js/script.js?1404918388711"></script> to the end of the page, which the browser will load like any other script tag.
If you already have jQuery, by the way, this is a little more succinct:
<script>
var scriptUrl = "/site/js/script.js",
cacheBustingUrl = scriptUrl + "?" + Date.now()
;
$("<script>").attr("src", cacheBustingUrl).appendTo(document.body);
</script>

refreshing javascript by renaming src attribute

I want to refresh the output of the script below. Is this json? Do I need to add a crossdomain policy in my site?
<div id="nowplaying">
<script src="http://s4.total-streaming.com/xml.php?station=1269&get=js"></script>
</div>
Edit:
This is what I'm trying based on #alexn advise, but still doesn't refresh.
<div id="nowplaying">
<script id="nowplaying-script" src="http://s4.total-streaming.com/xml.php?station=1269&get=js"></script>
<script>
setInterval(function () {
$('#nowplaying-script').attr('src', 'http://s4.total-streaming.com/xml.php?station=1269&get=js');
}, 1000);
</script>
</div>
Note Firebug: Resource interpreted as script but transferred with MIME type text/html. xml.php:-1
No, it's plain JavaScript. The script will simply output a string. You don't need any cross-domain policies to use this.
To refresh the content, just re-assign the src attribute of your script tag to the same url. You can use setTimeout to do this on a specified interval. Something like this should do it, you need to ad an id attribute to your script tag. The following will refresh every 5:th second.
setInterval(function() {
var element = document.getElementById("nowplaying-script");
element.setAttribute("src", "http://s4.total-streaming.com/xml.php?station=1269&get=js");
}, 5000);
(This is untested)
I would lean towards this being a cache problem.
How about you try this plugin (or look into how it works): http://plugins.jquery.com/project/reload
It essentially would allow you to do this:
setInterval(function () {
$('#nowplaying-script').reload();
}, 1000);
If you don't want to use the plugin, all it's doing is appending the current date to the URI params.
Another thing I noticed is that the script you are loading contains document.write. Even if you managed to get it to reload, it's not going to do what your expecting it to do.
In fact, calling document.write on a already loaded HTML page will cause your page to turn blank and contain only the content passed to document.write.
Now I'm not sure if your script is running on the same hostname as the script you are loading, if isn't you going to need a JSONP API instead of an a script that writes into the page.
If they do not offer a JSONP API, a more hackish way to solve this problem would be to write a server-side script that acts as a proxy. It essentially would load http://s4.total-streaming.com/xml.php?station=1269&get=js, parse it server-side using a substr or RegEx and return back the text that you want, in this case the name of the song currently playing.
Another way to solve this problem would be to overwrite the document.write method and have it print the content into the div instead of onto the screen like this:
document.write = function(songName) {
$('#nowplaying').text(songName);
};
Personally I wouldn't use this solution, but it will work if the other solutions are too complex for you to setup. Keep in mind all calls to document.write on that given page will print the content into your #nowplaying element. You should probably move your SCRIPT tag out of the #nowplaying element too if you use the above solution.

How do I get the original innerHTML source without the Javascript generated contents?

Is it possible to get in some way the original HTML source without the changes made by the processed Javascript? For example, if I do:
<div id="test">
<script type="text/javascript">document.write("hello");</script>
</div>
If I do:
alert(document.getElementById('test').innerHTML);
it shows:
<script type="text/javascript">document.write("hello");</script>hello
In simple terms, I would like the alert to show only:
<script type="text/javascript">document.write("hello");</script>
without the final hello (the result of the processed script).
I don't think there's a simple solution to just "grab original source" as it'll have to be something that's supplied by the browser. But, if you are only interested in doing this for a section of the page, then I have a workaround for you.
You can wrap the section of interest inside a "frozen" script:
<script id="frozen" type="text/x-frozen-html">
The type attribute I just made up, but it will force the browser to ignore everything inside it. You then add another script tag (proper javascript this time) immediately after this one - the "thawing" script. This thawing script will get the frozen script by ID, grab the text inside it, and do a document.write to add the actual contents to the page. Whenever you need the original source, it's still captured as text inside the frozen script.
And there you have it. The downside is that I wouldn't use this for the whole page... (SEO, syntax highlighting, performance...) but it's quite acceptable if you have a special requirement on part of a page.
Edit: Here is some sample code. Also, as #FlashXSFX correctly pointed out, any script tags within the frozen script will need to be escaped. So in this simple example, I'll make up a <x-script> tag for this purpose.
<script id="frozen" type="text/x-frozen-html">
<div id="test">
<x-script type="text/javascript">document.write("hello");</x-script>
</div>
</script>
<script type="text/javascript">
// Grab contents of frozen script and replace `x-script` with `script`
function getSource() {
return document.getElementById("frozen")
.innerHTML.replace(/x-script/gi, "script");
}
// Write it to the document so it actually executes
document.write(getSource());
</script>
Now whenever you need the source:
alert(getSource());
See the demo: http://jsbin.com/uyica3/edit
A simple way is to fetch it form the server again. It will be in the cache most probably. Here is my solution using jQuery.get(). It takes the original uri of the page and loads the data with an ajax call:
$.get(document.location.href, function(data,status,jq) {console.log(data);})
This will print the original code without any javascript. It does not do any error handling!
If don't want to use jQuery to fetch the source, consult the answer to this question: How to make an ajax call without jquery?
Could you send an Ajax request to the same page you're currently on and use the result as your original HTML? This is foolproof given the right conditions, since you are literally getting the original HTML document. However, this won't work if the page changes on every request (with dynamic content), or if, for whatever reason, you cannot make a request to that specific page.
Brute force approach
var orig = document.getElementById("test").innerHTML;
alert(orig.replace(/<\/script>[.\n\r]*.*/i,"</script>"));
EDIT:
This could be better
var orig = document.getElementById("test").innerHTML + "<<>>";
alert(orig.replace( /<\/script>[^(<<>>)]+<<>>/i, "<\/script>"));
If you override document.write to add some identifiers at the beginning and end of everything written to the document by the script, you will be able to remove those writes with a regular expression.
Here's what I came up with:
<script type="text/javascript" language="javascript">
var docWrite = document.write;
document.write = myDocWrite;
function myDocWrite(wrt) {
docWrite.apply(document, ['<!--docwrite-->' + wrt + '<!--/docwrite-->']);
}
</script>
Added your example somewhere in the page after the initial script:
<div id="test">
<script type="text/javascript"> document.write("hello");</script>
</div>
Then I used this to alert what was inside:
var regEx = /<!--docwrite-->(.*?)<!--\/docwrite-->/gm;
alert(document.getElementById('test').innerHTML.replace(regEx, ''));
If you want the pristine document, you'll need to fetch it again. There's no way around that. If it weren't for the document.write() (or similar code that would run during the load process) you could load the original document's innerHTML into memory on load/domready, before you modify it.
I can't think of a solution that would work the way you're asking. The only code that Javascript has access to is via the DOM, which only contains the result after the page has been processed.
The closest I can think of to achieve what you want is to use Ajax to download a fresh copy of the raw HTML for your page into a Javascript string, at which point since it's a string you can do whatever you like with it, including displaying it in an alert box.
A tricky way is using <style> tag for template. So that you do not need rename x-script any more.
console.log(document.getElementById('test').innerHTML);
<style id="test" type="text/html+template">
<script type="text/javascript">document.write("hello");</script>
</style>
But I do not like this ugly solution.
I think you want to traverse the DOM nodes:
var childNodes = document.getElementById('test').childNodes, i, output = [];
for (i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeName == "SCRIPT")
output.push(childNodes[i].innerHTML);
return output.join('');

Categories

Resources