Suppress rendering of html from template-literals within another template-literal - javascript

I'd like to display some html code that is within a template literals within another template literal.
I am using <pre><code> tags to attempt this.
The problem I'm having at the moment is that the browser renders the html rather than its code. For example it displays an actual input box in place of displaying the code, e.g. <input ...
I'd like to apply some reversible process using javascript to the templateliteral variable so that the html is displayed literally (it should display all orange on black text in the below snippet), and so that the original code can be easily got back.
What might be a good way to do this?
Here is an example of the problem (it should display all orange on black text):
let templateliteral = `let inner = { content : \`
<style>
#exampleDivInTemplateLiteral { background-color:lightblue;color:white; }
</style>
<div id="exampleDivInTemplateLiteral">
<b>this is some text.</b>
<input id="exampleInput" placeholder="example input">\</input>
</div>\`}`
document.getElementById("exampleDiv").innerHTML = '<pre><code>' + templateliteral + '<pre></code>'
<div id="exampleDiv" style="background-color:black;color:orange;">
<div>
Note this is specific to template literals within template literals.
Posting in edited form so I can post answer

I used createElement and innerText (in place of innerHTML):
let templateliteral = `let inner = { content : \`
<style>
#exampleDivInTemplateLiteral { background-color:lightblue;color:white; }
</style>
<div id="exampleDivInTemplateLiteral">
<b>this is some text.</b>
<input id="exampleInput" placeholder="example input">\</input>
</div>\`}`
let divel = document.getElementById("exampleDiv")
let preel = document.createElement("pre");
let codeel = document.createElement("code");
preel.appendChild(codeel)
divel.appendChild(preel)
codeel.innerText = templateliteral
<div id="exampleDiv" style="background-color:black;color:orange;">
<div>

Related

I can't use '\n" in javascript, I don't know why it isn't work

As I know, writing a new line is "\n", so I tried many times but it wasn't working. This is my source code and screen shot of result
var ary3 = new Array('seven','eight', 'nine');
for (var i =0; i<ary3.length ; i++){
document.getElementById('demo3').innerHTML += i+"'\nth element\n[enter image description here][1] : " + ary3[i]+"\n";
}
<h1>Show me the array object's entry</h1>
<div id = 'demo3'></div>
<br>
Whitespace is generically collapsed to at most a single space in HTML. Example
<div>a
b c</div>
Will appear as just a b c
You have a few options
Use pre
<pre>a
b</pre>
Will appear as
a
b
Use white-space: pre; CSS on your div
<div style="white-space: pre;">a
b</div>
Will break line breaks
Insert <br/> for `\n' as in
var someString = "a\nb\nc";
someElement.innerHTML = someString.replace(/\n/g, "<br/>");
As for your specific example of looping you also have the option to insert separate elements
function insertDivWithText(parent, text) {
var div = document.createElement("div");
div.appendChild(document.createTextNode(text));
parent.appendChild(div);
}
var demo3 = document.querySelector("#demo3");
var ary3 = ['seven','eight', 'nine'];
for (var i = 0; i < ary3.length ; ++i) {
var div = document.createElement("div");
insertDivWithText(demo3, i + "th element");
insertDivWithText(demo3, "[enter image description here][1] : " + ary3[i]);
}
<h1>Show me the array object's entry</h1>
<div id = 'demo3'></div>
<br>
Also note that using .innerHTML with user data is likely going to expose you to scripting vulnerabilities. Consider using document.createTextNode or element.textContent or element.innerText
The problem is that the newline from JS will be rendered as plain space. HTML is responsible for new line showing, but HTML will not pay attention to simple new line in text. You can check your HTML using developer's tools. You will see that JS made new lines:
derveloper tools
To make new line work, you should add <br /> tag
var ary3 = new Array('seven','eight', 'nine');
for (var i =0; i<ary3.length ; i++){
document.getElementById('demo3').innerHTML += i+"'<br/>\nth element<br/>\n[enter image description here][1] : " + ary3[i]+"<br/>\n";
}
<h1>Show me the array object's entry</h1>
<div id = 'demo3'></div>
<br>
You are writing HTML, DOM, so you have to use <br> tag, not newline.
If you are trying to create a HTML new line, use <br>.
Html code for new line is <br>.
As in:
document.getElementById('demo3').innerHTML += i+"'nth element<br>[enter image description
Your output is html. In html, use the <br /> tag to break the line.

Adding "literal HTML" to an HTML widget with data from a datasource?

When creating an HTML widget in FreeBoard, the following text is displayed:
Can be literal HTML, or javascript that outputs HTML.
I know I can do the following to return HTML with data, but if I want to do something more complex I'd prefer to use literal HTML
return html with data
return "<div style='color: red'>This is a red timestamp: " + datasources["DS"]["Timestamp"] + "</div>"
literal html with no data
<div style='color: red'>
This is red text.
</div>
<div style='color: blue'>
This is blue text.
</div>
Both of those work. My question is, how can I insert data from a datasource into the literal html example?
For more context, here is what is at the top of the editor:
This javascript will be re-evaluated any time a datasource referenced here is updated, and the value you return will be displayed in the widget. You can assume this javascript is wrapped in a function of the form function(datasources) where datasources is a collection of javascript objects (keyed by their name) corresponding to the most current data in a datasource.
And here is the default text:
// Example: Convert temp from C to F and truncate to 2 decimal places.
// return (datasources["MyDatasource"].sensor.tempInF * 1.8 + 32).toFixed(2);
I don't know the freeboard framework, but a generic solution would be to use HTML5 templates, if your browser support requirements allow it.
function supportsTemplate() {
return 'content' in document.createElement('template');
}
if (supportsTemplate()) {
alert('browser supports templates');
} else {
alert('browser does not support templates');
}
var template = document.querySelector('#timestamp-template');
var timestamp = template.content.querySelector('.timestamp');
timestamp.innerHTML = new Date().toLocaleString();
var clone = document.importNode(template.content, true);
var output = document.querySelector('#output');
output.appendChild(clone);
<template id="timestamp-template">
<div style='color: red' class="timestamp">
This is default red text.
</div>
<div style='color: blue'>
This is blue text.
</div>
</template>
<div id="output"></div>
You would obviously need to adapt this strategy to support whatever data sources and transforms your project needs.
Failing support for HTML5 template elements, you could also use <script type="text/template">.
Here is an example of how to insert a Datasource into an HTML widget:
var LVL = datasources["GL"]["Level"];
return `<div style="width: 200px; height: 200px;background:rgb(242,203,56);"></style>
<svg width=200 height=`+LVL+`><rect width=100% height=100% fill=grey></svg>
</div>`;

Replace text, and replace it back

I am using this code to replace text on a page when a user clicks the link. I would like a way to replace it back to the initial text using another link within the replaced text, without having to reload the page. I tried simply adding the same script within the replaced text and switching 'place' and 'rep_place' but it didn't work. Any ideas? I am sort of a novice at coding so thanks for any advice.
<div id="place">
Initial text here
<SCRIPT LANGUAGE="JavaScript">
function replaceContentInContainer(target,source) {
document.getElementById(target).innerHTML = document.getElementById(source).innerHTML;
}
</script>
<div class="text" onClick="replaceContentInContainer('place', 'rep_place')">
<u>Link to replace text</u></div></div>
<div id="replacements" style="display:none">
<span id="rep_place">
Replacement text here
</div></span>
Where do you store the original text? Consider what you're doing in some simpler code...
a = 123;
b = 456;
a = b;
// now how do you get the original value of "a"?
You need to store that value somewhere:
a = 123;
b = 456;
temp = a;
a = b;
// to reset "a", set it to "temp"
So in your case, you need to store that content somewhere. It looks like the "source" is a hidden element, it can just as easily hold the replaced value. That way values are swapped, not just copied. Something like this:
function replaceContentInContainer(target,source) {
var temp = document.getElementById(target).innerHTML;
document.getElementById(target).innerHTML = document.getElementById(source).innerHTML;
document.getElementById(source).innerHTML = temp;
}
So replace them you simply call:
replaceContentInContainer('place', 'rep_place')
Then to swap them back:
replaceContentInContainer('rep_place', 'place')
Note that this will replace the contents of the "source" element until they're swapped back again. From the current code we can't know if that will affect anything else on the page. If so, you might use a different element to store the original values. That could get complex quickly if you have a lot of values that you need to store.
How's this? I store the initial content in an element of an array called initialContent.
<div id="place">
Initial text here [replace]
</div>
<div id="replacements" style="display:none">
<span id="rep_place">
Replacement text here [revert]
</span>
</div>
<SCRIPT LANGUAGE="JavaScript">
var initialContent = [];
function replaceContentInContainer(target,source) {
initialContent[target] = document.getElementById(target).innerHTML;
document.getElementById(target).innerHTML = document.getElementById(source).innerHTML;
}
function showInitialContent(target) {
document.getElementById(target).innerHTML = initialContent[target];
}
</SCRIPT>
Working example: http://jsbin.com/huxodire/1/
The main changes I did were the following:
I used textContent instead of innerHTML because the later replaces the whole DOM contents and that includes removing your link to replace the text. There was no way to generate that event afterwards.
I closed the first div or else all the text would be removed with the innerText including the text that works as a link.
You said you wanted to replace back to the original text, so I used a variable to hold the last value only if this existed.
Hope this helps, let me know if you need more assistance.
The div tags were mixed up and wiping out your link after running it. I just worked with your code and showed how you could switch.
<div id="place">
Initial text here
</div>
<SCRIPT LANGUAGE="JavaScript">
function replaceContentInContainer(target,source) {
document.getElementById(target).innerHTML =
document.getElementById(source).innerHTML;
}
</script>
<div class="text" onClick="replaceContentInContainer('place', 'rep_place')">
<u>Link to replace text</u></div>
<div class="text" onClick="replaceContentInContainer('place', 'original_place')">
<u>Link to restore text</u></div>
<div id="replacements" style="display:none">
<span id="rep_place">
Replacement text here
</span>
<span id="original_place">
Initial text here
</span>
</div>

How to insert a large block of HTML in JavaScript?

If I have a block of HTML with many tags, how do insert it in JavaScript?
var div = document.createElement('div');
div.setAttribute('class', 'post block bc2');
div.innerHTML = 'HERE TOO MUCH HTML that is much more than one line of code';
document.getElementById('posts').appendChild(div);
How do I do it right?
Template literals may solve your issue as it will allow writing multi-line strings and string interpolation features. You can use variables or expression inside string (as given below). It's easy to insert bulk html in a reader friendly way.
I have modified the example given in question and please see it below. I am not sure how much browser compatible Template literals are. Please read about Template literals here.
var a = 1, b = 2;
var div = document.createElement('div');
div.setAttribute('class', 'post block bc2');
div.innerHTML = `
<div class="parent">
<div class="child">${a}</div>
<div class="child">+</div>
<div class="child">${b}</div>
<div class="child">=</div>
<div class="child">${a + b}</div>
</div>
`;
document.getElementById('posts').appendChild(div);
.parent {
background-color: blue;
display: flex;
justify-content: center;
}
.post div {
color: white;
font-size: 2.5em;
padding: 20px;
}
<div id="posts"></div>
This answer does not use backticks/template literals/template strings (``), which are not supported by Internet Explorer.
Using HTML + JavaScript:
You could keep the HTML block in an invisible container (like a <script>) within your HTML code, then use its innerHTML at runtime in JS
For example:
// Create a temporary <div> to load into
var div = document.createElement('div');
div.setAttribute('class', 'someClass');
div.innerHTML = document.getElementById('blockOfStuff').innerHTML;
// You could optionally even do a little bit of string templating
div.innerHTML = div.innerHTML
.replace(/{VENDOR}/g, 'ACME Inc.')
.replace(/{PRODUCT}/g, 'Best TNT')
.replace(/{PRICE}/g, '$1.49');
// Write the <div> to the HTML container
document.getElementById('targetElement').appendChild(div);
.red {
color: red
}
<script id="blockOfStuff" type="text/html">
Here's some random text.
<h1>Including HTML markup</h1>
And quotes too, or as one man said, "These are quotes, but
'these' are quotes too."<br><br>
<b>Vendor:</b> {VENDOR}<br>
<b>Product:</b> {PRODUCT}<br>
<b>Price:</b> {PRICE}
</script>
<div id="targetElement" class="red"></div>
Idea from this answer: JavaScript HERE-doc or other large-quoting mechanism?
Using PHP:
If you want to insert a particularly long block of HTML in PHP you can use the Nowdoc syntax, like so:
<?php
$some_var = " - <b>isn't that awesome!</b>";
echo
<<<EOT
Here's some random text.
<h1>Including HTML markup</h1>
And quotes too, or as one man said, "These are quotes, but 'these' are quotes too."
<br><br>
The beauty of Nowdoc in PHP is that you can use variables too $some_var
<br><br>
Or even a value contained within an array - be it an array from a variable you've set
yourself, or one of PHP's built-in arrays. E.g. a user's IP: {$_SERVER['REMOTE_ADDR']}
EOT;
?>
Here's a PHP Fiddle demo of the above code that you can run in your browser.
One important thing to note: The <<<EOT and EOT; MUST be on their own line, without any whitespace before them!
Why use Nowdoc in PHP?
One huge advantage of using Nowdoc syntax over the usual starting and stopping your PHP tag is its support for variables. Consider the normal way of doing it - shown in the example below:
<?php
// Load of PHP code here
?>
Now here's some HTML...<br><br>
Let's pretend that this HTML block is actually a couple of hundred lines long, and we
need to insert loads of variables<br><br>
Hi <?php echo $first_name; ?>!<br><br>
I can see it's your birthday on <?php echo $birthday; ?>, what are you hoping to get?
<?php
// Another big block of PHP here
?>
And some more HTML!
</body>
</html>
Contrast that to the simplicity of Nowdoc.
Despite the imprecise nature of the question, here's my interpretive answer.
var html = [
'<div> A line</div>',
'<div> Add more lines</div>',
'<div> To the array as you need.</div>'
].join('');
var div = document.createElement('div');
div.setAttribute('class', 'post block bc2');
div.innerHTML = html;
document.getElementById('posts').appendChild(div);
If I understand correctly, you're looking for a multi-line representation, for readability? You want something like a here-string in other languages. Javascript can come close with this:
var x =
"<div> \
<span> \
<p> \
some text \
</p> \
</div>";
The easiest way to insert html blocks is to use template strings (backticks). It will also allow you to insert dynamic content via ${...}:
document.getElementById("log-menu").innerHTML = `
<a href="#">
${data.user.email}
</a>
<div class="dropdown-menu p-3 dropdown-menu-right">
<div class="form-group">
<label for="email1">Logged in as:</label>
<p>${data.user.email}</p>
</div>
<button onClick="getLogout()" ">Sign out</button>
</div>
`
Add each line of the code to a variable and then write the variable to your inner HTML. See below:
var div = document.createElement('div');
div.setAttribute('class', 'post block bc2');
var str = "First Line";
str += "Second Line";
str += "So on, all of your lines";
div.innerHTML = str;
document.getElementById('posts').appendChild(div);
If you are using on the same domain then you can create a seperate HTML file and then import this using the code from this answer by #Stano :
https://stackoverflow.com/a/34579496/2468603
By far the easiest way is to use the insertAdjacentHTML() method.
w3schools article
Just make sure to wrap you LARGE CODE INTO A SINGLE DIV like a wrapper, then it doesn't matter how long it is.
HTML:
<div id='test'></div>
JS:
const arr = ['one', 'two', 'three'];
let mapped = arr.map(value=> {
return `
<div>
<hr />
<h1>${value}</h1>
<h3>this is it</h3>
</div>
`
});
document.querySelector('#test').innerHTML = mapped.join('');

jquery - Dynamically generate url

I am trying to dynamically create a url slug when a user types into an input. Unwanted characters should be removed. Spaces should be replaced by hyphens and everything into lowercase. So if a user types "Ruddy's Cheese Shop" it should render "ruddys-cheese-shop".
This is what I have so far.
<input id="tb1" />
<div id="tb2"></div>
$('#tb1').keyup(function() {
var Text = $('#tb1').val();
Text = Text.toLowerCase();
Text = Text.replace(/[^a-zA-Z0-9]+/g,'-');
$('#tb2').html($('#tb1').val(Text));
});
It almost works but I am new to js. Thanks
Your code but slightly improved.
$('#tb1').keyup(function() {
var text = $(this).val().toLowerCase();
text = text.replace(/[^a-z0-9]+/g, '-');
$('#tb2').text(text);
});
You don't need to find $('#tb1') element over and over again since you have a refference to it inside the function as $(this).
http://jsfiddle.net/jFjR3/
It looks ok except where you set the #tb2 value. I think you want:
$('#tb2').html(Text);
Of course, remember since you've called toLowerCase, you don't need to replace upper case chars. Rather a simpler regexp:
Text = Text.replace(/[^a-z0-9]+/g,'-');
If you also want to update the edit field as the user types, here's a full example. Note that it will only update #td2 when you start typing.
<html>
<head>
<script src="js/jquery.js" ></script>
<script language="javascript">
$(function() {
$('#tb1').keyup(function() {
var Text = $('#tb1').val();
Text = Text.toLowerCase();
Text = Text.replace(/[^a-z0-9]+/g,'-');
$('#tb2').html(Text);
$('#tb1').val(Text);
});
});
</script>
</head>
<body>
<input type="text" id="tb1" value="Ruddy's Cheese Shop" />
<div id="tb2"></div>
</body>
</html>
Looks like you need to run a couple of replaces i.e.
Text = Text.replace(/[\s]+/g,'-');
Text = Text.replace(/[^a-z_0-9\-]+/g,'');
That converts ruddy's Cheese Shop to ruddys-cheese-shop
Hope that helps

Categories