How to print </script> as text using Javascript - javascript

Hi i am trying to assing this value to a variable in javascript but always get an error. I have no clue what is going on, my statement is something like:
var a = "</script>";
I tried everything but it does not work, what should i do instead??

You need to hide that from the HTML parser:
var a = '</' + 'script>';
If you don't, then the surrounding HTML parser — which knows nothing at all about JavaScript syntax — thinks that that's the end of the script block. After it sees the opening tag for the block, it literally scans for </script> (ignoring case of course).
(edit — though basically right I think, my claim that browsers are searching strictly for </script> is probably somewhat overstated; I suspect that they look for anything that's recognizable as a closing tag. The basic point still stands of course.)

I may be misunderstanding your question but if you are trying to output '' on the screen for the reader (human) to view, then you can use:
var a = "</script>";
Note that this won't work for executable scripts however - it won't be interpreted as a html/script tag.

Related

How do I get document.getElementsByTagName('').innerHTML to make text between 2 tags?

I'm trying to use JavaScript to include a footer on several webpages, so if I want to change the footer, I only have to change it in one place. PHP is not available on this server and neither are server side inserts (SSI), but Perl, Python, and Tcl are available. I have been trying with document.getElementsByTagName('footer').innerHTML = "text"; but it doesn't produce text. I copied this code from dev.mozilla, and it tells me how many tags I have:
var footer = document.getElementsByTagName('footer');
var num = footer.length;
console.log('There is ' + num + ' footer in this document');
So, I don't know what's wrong with the innerHTML script. I also tried with paragraph tags and got the same results in both cases.
I reccoment using textContent instead. Se why here.
To see how it works, paste the following into your browser console while you're on StackOverflow and hit enter.
document.querySelector('.site-footer').textContent = 'Custom footer content.'
note: use querySelector with a class instead of getElementByTagName
Cheers! 🍻
Before asking this question, I had searched for Python includes without any luck, so I stopped there, but after asking this question, I thought that I should search for Perl/Ruby includes. Today, I found out that I can use the Perl use function, so I could study that and try to implement it although I am completely new to Perl. Ruby also appears capable, perhaps even more. I have no experience with Ruby either, but maybe I should start there.
I just figured out that getElementsByTagName() results in an array, so I have to refer to the footer's index with [0]:
var footerTags = document.getElementsByTagName('footer');
footerTags[0].innerHTML = "test";

Javascript Getting text from inside parenthesis

I have a large string of HTML (and javascript). I need to get text that is inside document.write()
<script>
$('.navigation').html();
window.jQuery || document.write("<script src='//cdn.shopify.com/s/files/1/0967/6522/t/2/assets/jquery.min.js?15152727378558387064'> $('.link').attr('href',url) \x3C/script>")
$('.button').html();
</script>
Currently I am finding the index of document.write then deleting any text before it.
strIndex = scriptHtml.indexOf('document.write(');
scriptHtml = scriptHtml.substr(strIndex);
This will Leave me with a string like this.
document.write("<script src='//cdn.shopify.com/s/files/1/0967/6522/t/2/assets/jquery.min.js?15152727378558387064'> $(".link").attr('href',url) \x3C/script>")
$('.button').html();
</script>
I need to find the first bracket in this new string and then know where the matching bracket ends so that i can get the string inside it.
I have tried some regex but cannot make one that works.
\(([^)]+)\)
The above regex does not work as it will match to:
("<script src='//cdn.shopify.com/s/files/1/0967/6522/t/2/assets/jquery.min.js?15152727378558387064'> $(".link")
as it just searches for an opening and closing bracket without considering how many have been opened.
Has anyone got an idea of how i can get the text i want or think of a better way i can get the text inside document.write?
Thanks
Regular Expressions are simply not the right tool for matching parenthesis that can nest, as they lack the mechanisms that would allow you to do this properly (in this case, recursion). See this answer for more information.
That said, in the example code you posted, simply matching the string document.write along with its quote marks will work (assuming you put the whole code into a variable named str):
console.log(str.match(/document\.write\("([^"]*)"\)/)[1]);
However, I strongly advise against this, as there are many, many possible cases in which parsing it this way will fail and accounting for all possibilities is very complex and really depends on how much you know about (or have control of) the possible inputs.

Can the string "</script>" cause any problems when returned as part of some JSON data?

There are no inline scripts involved, whatsoever. I have an external file script, which fetches some JSONP from twitter. Let's suppose that a property of the object represented in the returned JSONP was a string that contained somewhere in it the substring "</script>". Could this cause any problems on its own, without getting added to the DOM at all? (It gets scrubbed clean well before that point.)
I can't see why it would, but HTML parsing is notoriously whacky and quirky, so who knows? I know that if you want to have a string literal within an inline script, you need to break it up, like var slashScriptContainingString = 'foo</scr' + 'ipt>bar'; Again, I feel like it should be fine, but just checking to see if anyone knows why it might not be.
<!doctype html>
<script src="file.js"></script>
File.js:
var f = function(twobj) {
console.log(twobj);
doOtherStuffWith(twobj);
}
<script src="https://api.twitter.com/statuses/user_timeline/user.json?callback=f"></script>
Returned JSONP:
f(["this is an object, returned as part of the JSONP response, except it contains a string literal with the substring \"</script>\". Is this a problem? Note: I haven't said anything about injecting this string in the DOM in any way shape or form. I can't think of a reason why it might be, but I'd just like to be sure."]);
No, string literals can contain whatever you want. As long as you are not blindly trying to set the innerHTML of something, a string is just a string. The example you have posted is safe.
The reason that you need to split up your </script> tag in your JavaScript source is that you are missing CDATA blocks. Without them, technically everything in your inline JavaScript needs to be properly escaped for HTML. (< becomes <, etc.) Browsers are nice to you and let it slide, but </script> inside inline JavaScript becomes ambiguous. You should be using CDATA blocks to keep things like this from happening.
<script type="text/javascript">
//<![CDATA[
...code...
//]]>
</script>
See this question for more details: When is a CDATA section necessary within a script tag?

ASP.NET inline server tags

I'd like to start by saying that my code is working perfectly, this is more a "how best to do it" kind of question.
So I have code like this in my .aspx file:
function EditRelationship() {
var projects=<%= GetProjectsForEditRelationship() %>;
// fill in the projects list
$('#erProjectsSelect').empty();
for(var i in projects)
$('#erProjectsSelect').append('<option value='+projects[i][0]+'>'+projects[i][1]+'</option>');
var rels=<%= GetRelationshipsForEditRelationship() %>;
// etc
}
Again, it's working fine. The problem is that VS2008 kinda chokes on code like this, it's underlining the < character in the tags (with associated warnings), then refusing to provide code completion for the rest of the javascript. It's also refusing to format my document anymore, giving parsing errors. The last part is my worst annoyance.
I could put some of these in evals I guess, but it seems sorta dumb to add additional layers and runtime performance hits just to shut VS up, and it's not always an option (I can't remember off the top of my head where this wasn't an option but trust me I had a weird construct).
So my question is, how do you best write this (where best means fewest VS complaints)? Neither eval nor ajax calls fit this imo.
If your aim is to reduce VS complaints, and if you are running asp.net 4 (supporting Static client Ids), maybe a strategy like the following would be better?
Create a ASP:HiddenField control, set its ClientIdMode to "Static"
Assign the value of GetRelationshipsForEditRelationship() to this field on page load
In your javascript, read the value from the hidden field instead, I assume you know how to do this.
It's more work than your solution, and you will add some data to the postback (if you perform any) but it won't cause any VS complaints I guess :)
You could do this from your page in the code-behind
ClientScript.RegisterArrayDeclaration("projects", "1, 2, 3, 4");
or to construct something like JSON you could write it out
ClientScript.RegisterClientScriptBlock(GetType(), "JSONDeclarations", "your json stuff");
UPDATE Based on my comment
<script id="declaration" type="text/javascript">
var projects=<%= GetProjectsForEditRelationship() %>;
var rels=<%= GetRelationshipsForEditRelationship() %>;
</script>
<script type="text/javascript">
function EditRelationship() {
// fill in the projects list
$('#erProjectsSelect').empty();
for(var i in projects)
$('#erProjectsSelect').append('<option value='+projects[i][0]+'>'+projects[i][1]+'</option>');
}
</script>
I don't have VS2008 installed to test with, so take this with a grain of salt, but have you tried something like this?
var projects = (<%= GetProjectsForEditRelationship() %>);
Something like that might trick the JavaScript parser into ignoring the content of your expression.
For what it's worth, VS2010 correctly parses and highlights your original code snippet.
Is it an option to move this to VS2010? I just copied and pasted your code and the IDE interpreted it correctly.
The best solution is to put javascript in a separate file and avoid this entirely. For this particular function, you're doing server-side work. Why not build the list of options that you intend to add dynamically in codebehind, put them in a hidden div, and then just have jQuery add them from the already-rendered HTML?
If you have a situation where you really want to dynamically create a lot javascript this way, consider using ScriptManager in codebehind to set up the variables you'll need as scripts and register them, then your inline script won't need to escape
ScriptManager.RegisterClientScript("projects = " + GetProductsForEditRelationship());
(Basically, that is not the complete syntax, which is context dependent). Then refer to "projects" in your function.
(edit)
A little cleaner way to do this on a larger scale, set up everything you need like this in codebehind:
string script = "var servervars = {" +
"GetProductsForEditRelationship: " + GetProductsForEditRelationship() +
"GetRelationshipsForEditRelationship: " + GetRelationshipsForEditRelationship() +
"}"
and refer to everything like:
servervars.GetProductsForEditRelationship
If you do this a lot, of course, you can create a class to automate the construction of the script.

Creating an export function with JavaScript?

I'm trying to set up an export function in JavaScript for a packaged web app that turns a string stored in localStorage into a plain text file for downloading. As JavaScript does not have access to the computer's file-system, I'd like to set it up so that it create a blank text file (or, failing that, a simple HTML page) and open in in the web-browser; as it wouldn't be accessing any file-systems I was hoping this would be possible.
I was thinking of using a Data URI scheme to open the localStorage as plain text, such as the following:
function exportFile() {
window.open("data:text/plain;charset=utf-8," + localStorage.WebAppData);
};
But it's much slower than I expected, which I guess is because it's sticking the whole document in the URL box. Though probably not an issue with the code, some web browsers, like Google Chrome, won't let me save the resulting file. (And for some reason all the line-breaks have turned into spaces....)
Any suggestions to fix these problems or better ways of doing a similar function will be greatly appreciated!
Did you try something like:
window.open("data:text/plain;charset=utf-8," + localStorage.WebAppData);
For the download, I guess you need a round trip to a server, that will set a mime/type that will make the download box to pop up.
EDIT:
If you use localStorage, may be window.postMessage is available in your environment and could help for speed.
In order to retain line-breaks in the data exported with window.open you may wrap up your data with encodeURI:
var data1 = "Line \n break. And \r\n another one";
window.open("data:application/octet-stream, " + encodeURI(data1));
Otherwise you may export your data encoded in base64 with the btoa function:
var data1 = "Line \n break. And \r\n another one";
window.open("data:application/octet-stream;base64, " + btoa(data1));
Not really a solution, rather a work-around, but your question and the answer by #Mic lead me down this route:
Just use data:text/html as then you can put in line breaks using <br />
I tried everything else (all combinations of unicode characters, etc, ) to get line breaks in text/plain but couldn't get them to show up. document.write() and document.body.textContent(), etc also suffer from the same problem. Line breaks just get ignored.
Since Chrome won't let you save the popup window anyway, the only way to get text out of it is copy and paste so there is no benefit of using text/plain over text/html
In web browsers that will let you save the page (Firefox) you can choose to save the page as text, rather than HTML and so you still get the same end result.
EDIT: This approach works in Chrome, but not Firefox
win = window.open("", "win")
win.document.body.innerText = "Line \n breaks?"
Have to use innerText though. InnerHTML or textContent remove the line breaks. This works on both:
win = window.open("", "win")
win.document.body.innerHTML = "<pre>Line \n breaks?</pre>"
So perhaps you could just wrap everything in <pre> tags? Although I guess both of these have the same "problem" as the ` suggestion in that it's actually creating a HTML document rather than a text/plain one.

Categories

Resources