I'm practicing my Javascript by making a browser plugin to display external comment from Reddit on other webpages. The comments come in this format:
<div class="md"><p>I have them all over my yard. I didn't realize they spread so bad when I planted them.
They look cool with early morning dew on them though.</p>
</div>
I need to re-introduce the HTML characters (i.e. <div> => <div>), in order to put the formatted HTML onto the page.
Is there some native functionality Javascript provides to do this?
From what I can tell: x = document.createElement("div"); x.innerHTML = rawComment does not work, as the HTML is escaped, and the innerHTML returns a <div> with a string in it instead of a series of DOM nodes.
What you might try to do is the following:
// some dummy deocded text
let encoded = '<div class="md"><p>I have them all over my yard.</p></div>';
// create a new textarea and insert your encoded text
let dummyElement = document.createElement('textarea');
dummyElement.innerHTML = encoded;
// retrieve the textarea's value, which will be your decoded text
let decoded = dummyElement.value;
// decoded will be: <div class="md"><p>I have them all over my yard.</p></div>
Working Fiddle
This will work without jQuery, as you're only using the pure Javascript function's of your browser.
Related
I am new to this technology, and this is my first project.
I am calling an API and receiving a big parsed JSON file. From that entire big JSON.text (which is HTML code inside JSON.TEXT), how can I tap a particular class from that text?
Here is a sample:
After parsing the JSON.text - the outcome is -
some big html code then <table class ="info"> some big html code with TD and TR tag then </table> then again big HTML code.
I have to tap this table with class="info" from the entire parsed JSON.text which is HTML code.
screenshot -
Use DOMParser:
let response = {
parse: {
text: {
"*": `<div><\/div>
<p><\/p>
<table class="infobox vcard"><\/table>`
}
}
};
let parser = new DOMParser();
// extract the text part and pass it to the parser
let doc = parser.parseFromString(response.parse.text["*"], "text/html");
// get the first table element from the DOM, and display its `class` attribute
let tab = doc.querySelector("table");
console.log(tab.className); // infobox vcard
Once you've got the HTML out of your JSON file into a string you have two options. Option 1 is a regular expression:
// You have some string html
let match = html.match(/<table class="([^"])*"/)[1]
// match is the string "class1 class2" or whatever
match = match.split(" ")
// match is now an array ["class1", "class2"]
Option 2 is to find an HMTL parsing library (look one up), use it to parse the whole string, find the table using the output of that library, and extract its class that way.
simplifying the existing post.
say I have a string
let someText = "<h1>test</h1><p>desc of test</p>"
I'd like to use React or javascript to change that to
someText = "<h1 id="test">test</h1><p>desc of test</p>"
for a table of contents type of functionality for any headers can be anchored from elsewhere on the page
I'm using react on the frontend and can also use jquery/jsdom on the backend with express
Ok, here is my solution:
let str = `<h1>topic 1</h1>
<p>desc of topic 1</p>
<h1>topic 2</h1>
<p>desc of topic 2</p>`;
const innerHTMLarr = str.match(/<h1>.*(?=<\/h1>)/g).map(x => x.substring(4));
const result = str.replace(/<h1>/g, function() {
return `<h1 id="${innerHTMLarr.shift()}">`;
});
console.log(result)
First I match every <h1> in a regex. I have added a look-ahead to match the closing </h1> but without actually including it in the result. The same cannot be done for the opening <h1> since JavaScript doesn't support look-behinds (as far as I know), so we have to remove it manually with substring().
Once we have the innerHTML for each <h1> tag, we can do a replace() on the whole string by finding with regex "<h1>" and replacing it with "<h1 id=[x]>", where x the first result of the array we populated above. We do shift() here to remove used values.
NOTE: The above will generate an invalid id attribute since you can't have spaces in the attribute value. You may want to expand my answer for your specific use-case.
I don't really understand what you're trying to do here, but based on your example, a simple replace should work fine.
let someText = "<h1>test</h1><p>desc of test</p>"
let idInfo = "id='test'"
let replaced = someText.replace("<h1>", `<h1 ${idInfo}>`)
console.log(replaced);
If I want to add an ascii symbol form js to a node somewhere?
Tried as a TextNode, but it didn't parse it as a code:
var dropdownTriggerText = document.createTextNode('blabla ∧');
You can't create nodes with HTML entities. Your alternatives would be to use unicode values
var dropdownTriggerText = document.createTextNode('blabla \u0026');
or set innerHTML of the element. You can of course directly input &...
createTextNode is supposed to take any text input and insert it into the DOM exactly like it is. This makes it impossible to insert for example HTML elements, and HTML entities. It’s actually a feature, so you don’t need to escape these first. Instead you just operate on the DOM to insert text nodes.
So, you can actually just use the & symbol directly:
var dropdownTriggerText = document.createTextNode('blabla &');
I couldn't find an automated way to do this. So I made a function.
// render HTML as text for inserting into text nodes
function renderHTML(txt) {
var tmpDiv = document.createElement("div"); tmpDiv.innerHTML = txt;
return tmpDiv.innerText || tmpDiv.textContent || txt;
}
Let's say we have a paragraph:
<p>txt0</p>
... and we want to append some text:
$("p").append("_txt1");
$("p").append("_txt2");
$("p").append("_txt3");
The result will be, as expected:
txt0_txt1_txt2_txt3
However if we inspect the result in browser, what it really is:
<p>
"txt0"
"_txt1"
"_txt2"
"_txt3"
</p>
There are 4 different strings that are only rendered as one. The problem is I'm creating a flash object dynamically and appending strings this way will not work because of the quotes. I really need it to be one continuous string like this:
<p>
txt0_txt1_txt2_txt3
</p>
Is there a way to append in such a way? Or to remove all the quotes afterwards?
PS. before you say to make one big string before appending, that won't work because the string is too big and for ex. it works in Chrome but not in Firefox or IExplorer (but that's a different issue).
Use text, otherwise you're appending a new TextNode everytime:
var $p = $('p');
$p.text('txt0');
$p.text($p.text() + '_txt1');
Or with textContent it's less confusing:
var p = $('p')[0];
p.textContent += 'txt0';
p.textContent += '_txt1';
...
You can manipulate the html inside the p-tag this way:
$('p').html($('p').html() + '_text');
My solution is similar to #DonnyDee's
$("p").append("_txt1");
$("p").append("_txt2");
$("p").append("_txt3");
$("p").html($("p").html());
Somehow .html knows how to remove the quotation marks where there are two strings together i.e. "txt0"
"_txt1" etc
afaik .text() is destructive, i.e. will replace html with text which is perhaps not what we want, although I agree for this example it would suffice.
$('p').html(function(index, oldHTML) { return oldHTML + '_text';});
looks like a good solution though. e.g.
$("p").append("_txt1");
$("p").append("_txt2");
$("p").append("_txt3");
$("p").html(function(index, oldHTML) { return oldHTML);
I am currently trying to code an input form where you can type and format a text for later use as XML entries. In order to make the HTML code XML-readable, I have to replace the code brackets with the corresponding symbol codes, i.e. < with < and > with >.
The formatted text gets transferred as HTML code with the variable inputtext, so we have for example the text
The <b>Genji</b> and the <b>Heike</b> waged a long and bloody war.
which needs to get converted into
The <b>Genji</b> and the <b>Heike</b> waged a long and bloody war.
I tried it with the .replace() function:
inputxml = inputxml.replace("<", "<");
inputxml = inputxml.replace(">", ">");
But this would just replace the first occurrence of the brackets. I'm pretty sure I need some sort of loop for this; I also tried using the each() function from jQuery (a friend recommended I looked at the jQuery package), but I'm still new to coding in general and I have troubles getting this to work.
How would you code a loop which would replace the code brackets within a variable as described above?
Additional information
You are, of course, right in the assumption that this is part of something larger. I am a graduate student in Japanese studies and currently, I am trying to visualize information about Japenese history in a more accessible way. For this, I am using the Simile Timeline API developed by MIT grad students. You can see a working test of a timeline on my homepage.
The Simile Timeline uses an API based on AJAX and Javascript. If you don't want to install the AJAX engine on your own server, you can implement the timeline API from the MIT. The data for the timeline is usually provided either by one or several XML files or JSON files. In my case, I use XML files; you can have a look at the XML structure in this example.
Within the timeline, there are so-called "events" on which you can click in order to reveal additional information within an info bubble popup. The text within those info bubbles originates from the XML source file. Now, if you want to do some HTML formatting within the info bubbles, you cannot use code bracket because those will just be displayed as plain text. It works if you use the symbol codes instead of the plain brackets, however.
The content for the timeline will be written by people absolutely and totally not accustomed to codified markup, i.e. historians, art historians, sociologists, among them several persons of age 50 and older. I have tried to explain to them how they have to format the XML file if they want to create a timeline, but they occasionally slip up and get frustrated when the timeline doesn't load because they forgot to close a bracket or to include an apostrophe.
In order to make it easier, I have tried making an easy-to-use input form where you can enter all the information and format the text WYSIWYG style and then have it converted into XML code which you just have to copy and paste into the XML source file. Most of it works, though I am still struggling with the conversion of the text markup in the main text field.
The conversion of the code brackets into symbol code is the last thing I needed to get working in order to have a working input form.
look here:
http://www.bradino.com/javascript/string-replace/
just use this regex to replace all:
str = str.replace(/\</g,"<") //for <
str = str.replace(/\>/g,">") //for >
To store an arbitrary string in XML, use the native XML capabilities of the browser. It will be a hell of a lot simpler that way, plus you will never have to think about the edge cases again (for example attribute values that contain quotes or pointy brackets).
A tip to think of when working with XML: Do never ever ever build XML from strings by concatenation if there is any way to avoid it. You will get yourself into trouble that way. There are APIs to handle XML, use them.
Going from your code, I would suggest the following:
$(function() {
$("#addbutton").click(function() {
var eventXml = XmlCreate("<event/>");
var $event = $(eventXml);
$event.attr("title", $("#titlefield").val());
$event.attr("start", [$("#bmonth").val(), $("#bday").val(), $("#byear").val()].join(" "));
if (parseInt($("#eyear").val()) > 0) {
$event.attr("end", [$("#emonth").val(), $("#eday").val(), $("#eyear").val()].join(" "));
$event.attr("isDuration", "true");
} else {
$event.attr("isDuration", "false");
}
$event.text( tinyMCE.activeEditor.getContent() );
$("#outputtext").val( XmlSerialize(eventXml) );
});
});
// helper function to create an XML DOM Document
function XmlCreate(xmlString) {
var x;
if (typeof DOMParser === "function") {
var p = new DOMParser();
x = p.parseFromString(xmlString,"text/xml");
} else {
x = new ActiveXObject("Microsoft.XMLDOM");
x.async = false;
x.loadXML(xmlString);
}
return x.documentElement;
}
// helper function to turn an XML DOM Document into a string
function XmlSerialize(xml) {
var s;
if (typeof XMLSerializer === "function") {
var x = new XMLSerializer();
s = x.serializeToString(xml);
} else {
s = xml.xml;
}
return s
}
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace
You might use a regular expression with the "g" (global match) flag.
var entities = {'<': '<', '>': '>'};
'<inputtext><anotherinputext>'.replace(
/[<>]/g, function (s) {
return entities[s];
}
);
You could also surround your XML entries with the following:
<![CDATA[...]]>
See example:
<xml>
<tag><![CDATA[The <b>Genji</b> and the <b>Heike</b> waged a long and bloody war.]]></tag>
</xml>
Wikipedia Article:
http://en.wikipedia.org/wiki/CDATA
What you really need, as mentioned in comments, is to XML-encode the string. If you absolutely want to do this is Javascript, have a look at the PHP.js function htmlentities.
I created a simple JS function to replace Greater Than and Less Than characters
Here is an example dirty string: < noreply#email.com >
Here is an example cleaned string: [ noreply#email.com ]
function RemoveGLthanChar(notes) {
var regex = /<[^>](.*?)>/g;
var strBlocks = notes.match(regex);
strBlocks.forEach(function (dirtyBlock) {
let cleanBlock = dirtyBlock.replace("<", "[").replace(">", "]");
notes = notes.replace(dirtyBlock, cleanBlock);
});
return notes;
}
Call it using
$('#form1').submit(function (e) {
e.preventDefault();
var dirtyBlock = $("#comments").val();
var cleanedBlock = RemoveGLthanChar(dirtyBlock);
$("#comments").val(cleanedBlock);
this.submit();
});