Handling multi-line HTML inside Javascript - javascript

I am using Javascript to define a button behaviour on a web page. The behaviour I am after is to insert some new HTML somewhere on my page, but I would like to use the MVC extension method Html.EditorFor to define the new HTML which will be inserted.
What I would like to do is the following:
$("#myButton").click(function() {
$("#(Html.EditorFor(x => x.SomeModelProperty))").insertBefore(<somewhere>);
});
The problem I'm encountering is that the MvcHtmlString returned by the call to EditorFor renders as multi-line HTML, resulting in invalid Javascript:
$("<div>
<label for="ModelData_SomeModelProperty">SomeModelProperty</label>
</div>
<div> ....
In an ideal world, I could get EditorFor to somehow render all of the above on a single line, or use some kind of special Javascript syntax to define a multi-line string (like using single quotes in C#), but so far I'm drawing a blank.
I've tried calling ToHtmlString and hand-editing the resulting string to remove line-breaks, and I'm aware that I can escape the new lines in Javascript using a /, but the problem with doing so is that I then have to handle the escaped HTML, which looks a little like the following:
$("<div>
<label for="ModelData_SomeModelProperty">SomeModelProperty</label>
</div>
<div> .... (you get the idea)
I was just wondering whether anyone had tried anything similar and might have a more elegant approach?

One way would be to get it written into a hidden div in html instead of directly into the javascript. Then you can just read it from the dom to use in you script.
So you page would have a
<div style="display:none" id="hiddenArea">
...insert whatever you want in here
with newline or whatever...
</div>
And then in your javascript:
$("#myButton").click(function() {
var source = $("#hiddenArea").html();
$(source).insertBefore(<somewhere>);
});

You could maybe create a HTML helper so you much more control on what's returned and how it is formatted.
http://www.codeproject.com/Tips/720515/Custom-HTML-Helper-for-MVC-Application

Related

How to replace html tags with our own tags

In my MVC web application, I have a text area inside View, in that user will put HTML text so in that text, I want to replace html tags with my own custom tags.
For Example:
HTML tag:
<input type='text' name='MyList.First_Name' data-val='true' data-val-required='Please enter first name' />
Replace with:
[~TextFieldTag|MyList.First_Name|||0|data-val=>true|data-val-required=>Please enter first name|~]
Can anyone suggest what is the best approach to do this?
I was going to recommend a simple string replacement at first, but given the seemingly complicated nature of your replacements, that might not be the best approach.
Probably the best approach would be to take the HTML, convert it to DOM elements, which can be done simply by throwing it into an elements innerHTML:
document.querySelector('button').addEventListener('click', () => {
document.querySelector('#renderSpace').innerHTML = document.querySelector('textarea').value;
});
Add some HTML:
<textarea></textarea>
<button>Press Me</button>
<div id="renderSpace"></div>
You can position the area you render it inside of off-screen so users don't actually see it.
From there, I would walk the DOM tree (basically, start at the root, then look at all of its children, then their children, etc., recursively), reading off any properties that you deem appropriate and then writing your string replacement as you go along.
That does require that they have entered valid HTML (which is generally a requirement, but can be difficult to rely on users to enter), so you'll want to have some good, user-friendly, error handling in there.

Format code that is displayed in div

I'm building a Javascript based UI that generates code based on the UI. I got the code generation working. the code is saved in a string. I tried formatting it, indenting it, but I don't know how anymore. Is there a way to put out the code formatted?
For example if I have this string:
"<body><div><h1>Hi</h1></div></body>"
being output like this:
<body>
<div>
<h1>
Hi
</h1>
</div>
</body>
right now I'm outputing like this:
$(".output").text(string);
Take a look at code tag in html. Show your string wrapped by code tags
<code>your string</code>
Or use text area. https://jsfiddle.net/sureshatta/k1atgn6o/1/
If you are trying to achived the formatted output please have a look at Template literals
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
.text() use for Change the Text of any Tag.
$(".output").text(string);
.html() is use for Add the String with the Tag.
$(".output").html(string);
If you want to display code that is correctly indented and colorized, you can use a library to do that, such as highlighjs.
I'm not sure it does auto indentation, but the algorithm for that isn't that hard: just add newline and enough spaces when opening a new html tag (recursion will make this way easier).
Also, you can use js-beautify.

Why replace backslash code doesn't work in JS?

My code in JSP file looks like this :
<s:form namespace="/user" action="list" method="POST" id="filterListForm" theme="simple"
onsubmit="document.getElementById('filterSearchText').value=document.getElementById('filterSearchText').value.replace(/\\/g,'')">
It won't replace the backslash char. I've tried the following, none of them work :
replace('/\\/g','')
replace(/\\\\/g,'')
replace(\/\\\/g,'')
But if I change it to the following, it works :
<s:form namespace="/user" action="list" method="POST" id="filterListForm" theme="simple"
onsubmit="replaceBackslash()">
<script type="text/javascript">
function replaceBackslash() { document.getElementById('filterSearchText').value=document.getElementById('filterSearchText').value.replace(/\\/g,''); }
</script>
Why ? Is there a way to make it work in the first case ?
You want:
var replaced = original.replace(/\\/g, '');
In a regular expression literal, all you need to do is double the backslash to quote it.
As to why it doesn't work when you try passing the code in via a JSP tag, well that would probably be JSP mangling the string for you. It might work to do this:
<s:form ... onsubmit=' ... .replace(/\\\\/g, "") ... ' >
but I don't have a good way to try that at the moment.
edit — actually I'm finding this challenging. It probably depends on what your tag library does. My framework (Stripes) likes to HTML-escape attribute values, so it's hard to pass through something like \ (well, impossible).
(This isn't really a solution, just a recommendation of a general practice that happens to solve this problem, too.)
Bottom line: Go with separated Javascript. If you feel it's too much work to completely separate it out into a different file (even though that would help you cleanly avoid all issues such as this), at least put it all in a script tag at the bottom. It helps separate layout and logic, and it keeps all the Javascript in one known place, making it easier to understand and maintain. You don't even need onclick/onsubmit attributes, you can assign those in Javascript too (usually keyed on html #id attributes). If you use the on[event] attributes anyway, just call one sensibly named function, and put the function's implementation in your main script.

Passing apostrophe to javascript function

I am not finding a solution on this one using JavaScript (to utilize localStorage) in a JSP.
Trying to pass something with apostrophe. I have done a .replaceAll() and replaced the ' with ' and it still passes it as an '.
I have also tried a .split("'") and replaced the apostrophe with:
(\' , ' , \', '' , ''' and '\'')
All of these just pass an apostrophe to the function (what I see when I hover over the link) like this:
Save job
With a and b being the two split substrings but with no effect. I do notice that spaces are converted into %20, but that's little comfort. Any other ideas?
Your JSP code is irrelevant. Decide what HTML you want to produce and produce it.
The following are all valid HTML markup:
<a href="saveJob('Bob\'s Question')"> …
<a href="saveJob("Bob&apos;s Question")"> …
<a href="saveJob('He said "Go Away"')"> …
<a href='saveJob("He said \"Go Away\"")"> …
… and the following are invalid:
<a href="saveJob('Bob's Question')"> <!-- JS string ends early -->
<a href="saveJob("Bob's Question")"> <!-- HTML attribute ends early -->
<a href="saveJob('Bob&apos;s Question')"> <!-- JS string ends early -->
<a href="saveJob('He said "Go Away"')"> <!-- HTML attribute ends early -->
You cannot use your HTML attribute delimiter in your attribute value except as an HTML entity. You cannot use your JavaScript string delimiter in your JavaScript string unless you escape it, even if you use an HTML entity to describe it.
In general, you should not be putting JavaScript in your HTML (you should attach event handlers to your markup programmatically, from script), and you especially shouldn't be abusing an HTML anchor as a JavaScript trigger (either use an HTML anchor to a valid URL and let JavaScript hijack the link if enabled, or use a <button> or other element to invoke script-only side effects).
As you've noticed, such manual string escape tasks can be quite tricky; covering apostrophes won't even get you all the way: what if there's a newline in the string? That would break the script as well.
I would recommend converting your data to a JSON object, perhaps using JSON-taglib. This should take care of all required escaping for you.
The Phrogz solution
<a href="saveJob("Bob&apos;s Question")">
works fine if you have only apostrophes in your text.
If your text contains both apostrophes and quotes, you can use a hidden div (div with style='display:none;') for the text, pass the id of the div to saveJob instead of passing the text itself, and get the text inside saveJob by using
document.getElementById(myId).innerHTML

How can I use literal DOM markup as a Prototype Template?

Prototype's Template class allows you to easily substitute values into a string template. Instead of declaring the Template source-string in my code, I want to extract the source-string from the DOM.
For example, in my markup I have an element:
<div id="template1">
<img src="#{src}" title="#{title}" />
</div>
I want to create the template with the inner contents of the div element, so I've tried something like this:
var template = new Template($('template1').innerHTML);
The issue is that Internet Explorer's representation of the innerHTML omits the quotes around the attribute value when the value has no spaces. I've also attempted to use Element#inspect, but in Internet Explorer I get back a non-recursive representation of the element / sub-tree.
Is there another way to get a Template-friendly representation of the sub-tree's contents?
Looks like you can embed the template source inside a textarea tag instead of a div and retrieve it using Element#value.
Certainly makes the markup a little weird, but it still seems reasonably-friendly to designers.
Additionally, as Jason pointed out in a comment to the original question, including the img tag in the textarea prevents a spurious request for an invalid image.
Resig to the rescue:
You can also inline script:
<script type="text/html" id="user_tmpl">
<% for ( var i = 0; i < users.length; i++ ) { %>
<li><%=users[i].name%></li>
<% } %>
</script>
Quick tip: Embedding scripts in your
page that have a unknown content-type
(such is the case here - the browser
doesn't know how to execute a
text/html script) are simply ignored
by the browser - and by search engines
and screenreaders. It's a perfect
cloaking device for sneaking templates
into your page. I like to use this
technique for quick-and-dirty cases
where I just need a little template or
two on the page and want something
light and fast.
and you would use it from script like
so:
var results = document.getElementById("results");
results.innerHTML = tmpl("item_tmpl", dataObject);

Categories