WKWebView and InnerText with newline - javascript

I am currently working on implementing a web view inside of my iOS application using Xamarin. My webView is a WkWebView. My issue is that any time the text I am passing in has a new line it fails to display. However, testing my function in my browser (chrome) along with Safari I see that it executes just fine. I did some searching and I also tried to replace the \n character with \r\n, but that did not solve my issue. What am I missing?
C#:
private void BuildText(FormEntries entry, FormResponseAnswers formAnswers) {
string function = "buildText('" + entry.Text + "', '" + formAnswers.Answer + "');";
var javaScriptCmd = (NSString)function;
webView.EvaluateJavaScript(javaScriptCmd, null);
}
formAnswers.Answer that is causing the issue is:
"Hello world from the device, I do not know how well this will display our data at all. But we will see how this works. I wonder, if I were to add enter keys will it work?\n\n\nI kinda doubt it. ";
JS:
function buildText(entryText, answer) {
var answerAreaDiv = document.getElementById('answerArea');
var holder = document.createElement('div');
holder.classList.add('holder');
var entryLabel = document.createElement("label");
entryLabel.textContent = entryText + ':';
var answerLabel = document.createElement("label");
answerLabel.innerText = answer;
holder.appendChild(entryLabel);
holder.appendChild(answerLabel);
answerAreaDiv.appendChild(holder);
}
HTML:
<body>
<div id="answerArea">
</div>
</body>

HTML elements don't line break unless you explicitly ask them to; line breaks such as \n are treated as spaces. Try inserting HTML instead, so that you can replace your newline with a <br>:
answerLabel.innerHTML = answer.replace(/\n/g, '<br>');
Example:
document.body.appendChild(document.createElement('label')).innerHTML = `first line
second line`.replace(/\n/g, '<br>');

Related

Add a space between each character, but in a method

Hey :) I know a similiar question was asked before, but i just cant get it through. I want to create a method called something like makeMeSpaces, so my h2 text will have a space between each character.. and i might want to use it elsewhere aswell. I have this until now, from the logic point of view:
var text = "hello";
var betweenChars = ' '; // a space
document.querySelector("h1").innerHTML = (text.split('').join(betweenChars));
it also works pretty fine, but i think i want to do
<h2>Hello.makeMeSpaces()</h2>
or something like this
Thank you guys!
If you really want this in a 'reusable function,' you'd have to write your own:
function addSpaces(text) {
return text.split('').join(' ');
}
Then, elsewhere in code, you could call it like so:
var elem = document.querySelector('h2');
elem.innerHTML = addSpaces(elem.innerHTML);
Maybe this is what you want , not exactly what you showed but some what similar
Element.prototype.Spacefy = function() {
// innerText for IE < 9
// for others it's just textContent
var elem = (this.innerText) ? this.innerText : this.textContent,
// replacing HTML spaces (' ') with simple spaces (' ')
text = elem.replace(/ /g, " ");
// here , space = " " because HTML ASCII spaces are " "
space = " ",
// The output variable
output = "";
for (var i = 0; i < text.length; i++) {
// first take a character form element text
output += text[i];
// then add a space
output += space;
};
// return output
this.innerHTML = output;
};
function myFunction() {
var H1 = document.getElementById("H1");
// calling function
H1.Spacefy();
};
<h1 id="H1">
<!-- The tags inside the h1 will not be taken as text -->
<div>
Hello
</div>
</h1>
<br />
<button onclick="myFunction ()">Space-fy</button>
You can also click the button more than once :)
Note :- this script has a flow, it will not work for a nested DOM structure refer to chat to know more
Here is a link to chat if you need to discuss anything
Here is a good codepen provided by bgran which works better

text string output stops after first space, js/html

I apologize in advance, this is the first Stack Overflow question I've posted. I was tasked with creating a new ADA compliant website for my school district's technology helpdesk. I started with minimal knowledge of HTML and have been teaching myself through w3cschools. So here's my ordeal:
I need to create a page for all of our pdf and html guides. I'm trying to create a somewhat interactable menu that is very simple and will populate a link array from an onclick event, but the title="" text attribute drops everything after the first space and I've unsuccessfully tried using a replace() method since it's coming from an array and not static text.
I know I'm probably supposed to use an example, but my work day is coming to a close soon and I wanted to get this posted so I just copied a bit of my actual code.
So here's what's happening, in example 1 of var gmaildocAlt the tooltip will drop everything after Google, but will show the entire string properly with example 2. I was hoping to create a form input for the other helpdesk personnel to add links without knowing how to code, but was unable to resolve the issue of example 1 with a
var fix = gmaildocAlt.replace(/ /g, "&nb sp;")
//minus the space
//this also happens to break the entire function if I set it below the rest of the other variables
I'm sure there are a vast number of things I'm doing wrong, but I would really appreciate the smallest tip to make my tooltip display properly without requiring a replace method.
// GMAIL----------------------------
function gmailArray() {
var gmaildocLink = ['link1', 'link2'];
var gmaildocTitle = ["title1", "title2"];
var gmaildocAlt = ["Google Cheat Sheet For Gmail", "Google 10-Minute Training For Gmail"];
var gmailvidLink = [];
var gmailvidTitle = [];
var gmailvidAlt = [];
if (document.getElementById("gmailList").innerHTML == "") {
for (i = 0; i < gmaildocTitle.length; i++) {
arrayGmail = "" + gmaildocTitle[i] + "" + "<br>";
document.getElementById("gmailList").innerHTML += arrayGmail;
}
for (i = 0; i < gmailvidTitle.length; i++) {
arrayGmail1 = "";
document.getElementById("").innerHTML += arrayGmail1;
}
} else {
document.getElementById("gmailList").innerHTML = "";
}
}
<div class="fixed1">
<p id="gmail" onclick="gmailArray()" class="gl">Gmail</p>
<ul id="gmailList"></ul>
<p id="calendar" onclick="calendarArray()" class="gl">Calendar</p>
<ul id="calendarList"></ul>
</div>
Building HTML manually with strings can cause issues like this. It's better to build them one step at a time, and let the framework handle quoting and special characters - if you're using jQuery, it could be:
var $link = jQuery("<a></a>")
.attr("href", gmaildocLink[i])
.attr("title", gmaildocAlt[i])
.html(gmaildocTitle[i]);
jQuery("#gmailList").append($link).append("<br>");
Without jQuery, something like:
var link = document.createElement("a");
link.setAttribute("href", gmaildocLink[i]);
link.setAttribute("title", gmaildocAlt[i]);
link.innerHTML = gmaildocTitle[i];
document.getElementById("gmailList").innerHTML += link.outerHTML + "<br>";
If it matters to your audience, setAttribute doesn't work in IE7, and you have to access the attributes as properties of the element: link.href = "something";.
If you add ' to either side of the variable strings then it will ensure that the whole value is read as a single string. Initially, it was assuming that the space was exiting the Title attribute.
Hope the below helps!
UPDATE: If you're worried about using apostrophes in the title strings, you can use " by escaping them using a . This forces JS to read it as a character and not as part of the code structure. See the example below.
Thanks for pointing this one out guys! Sloppy code on my part.
// GMAIL----------------------------
function gmailArray() {
var gmaildocLink = ['link1', 'link2'];
var gmaildocTitle = ["title1", "title2"];
var gmaildocAlt = ["Google's Cheat Sheet For Gmail", "Google 10-Minute Training For Gmail"];
var gmailvidLink = [];
var gmailvidTitle = [];
var gmailvidAlt = [];
if (document.getElementById("gmailList").innerHTML == "") {
for (i = 0; i < gmaildocTitle.length; i++) {
var arrayGmail = "" + gmaildocTitle[i] + "" + "<br>";
document.getElementById("gmailList").innerHTML += arrayGmail;
}
for (var i = 0; i < gmailvidTitle.length; i++) {
var arrayGmail1 = "";
document.getElementById("").innerHTML += arrayGmail1;
}
} else {
document.getElementById("gmailList").innerHTML = "";
}
}
<div class="fixed1">
<p id="gmail" onclick="gmailArray()" class="gl">Gmail</p>
<ul id="gmailList"></ul>
<p id="calendar" onclick="calendarArray()" class="gl">Calendar</p>
<ul id="calendarList"></ul>
</div>

How to add custom image tag to pagedown?

I'm attempting to duplicate the original img tag's functionality in custom img tag that will be added to the pagedown converter.
e.g I'm copy the original behavior:
![image_url][1] [1]: http://lolink.com gives <img src="http://lolink.com">
into a custom one:
?[image_url][1] [1]: http://lolink.com gives <img class="lol" src="http://lolink.com">
Looking at the docs the only way to do this is through using the preblockgamut hook and then adding another "block level structure." I attempted doing this and got an Uncaught Error: Recursive call to converter.makeHtml
here's the code of me messing around with it:
converter.hooks.chain("preBlockGamut", function (text, dosomething) {
return text.replace(/(\?\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, function (whole, inner) {
return "<img src=" + dosomething(inner) + ">";
});
});
I'm not very experienced with hooks and everything so what would I do to fix it? Thanks.
UPDATE: found out that _DoImages runs after prespangamut, will use that instead of preblockgamut
Figured it out! The solution is very clunky and involves editing the source code because I am very bad at regex and the _DoImage() function uses a lot of internal functions only in the source.
solution:
All edits will be made to the markdown.converter file.
do a ctrl+f for the _DoImage function, you will find that it is named in two places, one in the RunSpanGamut and one defining the function. The solution is simple, copy over the DoImage function and related stuff to a new one in order to mimic the original function and edit it to taste.
next to DoImage function add:
function _DoPotatoImages(text) {
text = text.replace(/(\?\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writePotatoImageTag);
text = text.replace(/(\?\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writePotatoImageTag);
return text;
}
function writePotatoImageTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
var whole_match = m1;
var alt_text = m2;
var link_id = m3.toLowerCase();
var url = m4;
var title = m7;
if (!title) title = "";
if (url == "") {
if (link_id == "") {
link_id = alt_text.toLowerCase().replace(/ ?\n/g, " ");
}
url = "#" + link_id;
if (g_urls.get(link_id) != undefined) {
url = g_urls.get(link_id);
if (g_titles.get(link_id) != undefined) {
title = g_titles.get(link_id);
}
}
else {
return whole_match;
}
}
alt_text = escapeCharacters(attributeEncode(alt_text), "*_[]()");
url = escapeCharacters(url, "*_");
var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
title = attributeEncode(title);
title = escapeCharacters(title, "*_");
result += " title=\"" + title + "\"";
result += " class=\"p\" />";
return result;
}
if you look at the difference between the new _DoPotatoImages() function and the original _DoImages(), you will notice I edited the regex to have an escaped question mark \? instead of the normal exclamation mark !
Also notice how the writePotatoImageTag calls g_urls and g_titles which are some of the internal functions that are called.
After that, add your text = _DoPotatoImages(text); to runSpanGamut function (MAKE SURE YOU ADD IT BEFORE THE text = _DoAnchors(text); LINE BECAUSE THAT FUNCTION WILL OVERRIDE IMAGE TAGS) and now you should be able to write ?[image desc](url) along with ![image desc](url)
done.
The full line (not only the regex) in Markdown.Converter.js goes like this:
text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
so check the function writeImageTag. There you can see how the regex matching text is replaced with a full img tag.
You can change the almost-last line before its return from
result += " />";
to
result += ' class="lol" />';
Thanks for the edit to the main post.
I see what you mean now.
It is a bit weird how it uses empty capture groups to specify tags, but if it works, it works.
It looks like you would need to add on an extra () onto the regex string, then specify m8 as a new extra variable to be passed into the function, and then specify it as class = m8; like the other variables at the top of the function.
Then where it says var result =, instead of class =\"p\" you would just put class + title=\"" + .......

js split, at the end of a line

Im making a web page that, will get the html code of it self and then, replace all the harmful html codes like < and > and change them to the ascii counterparts so it doesn't skew it up but it looks write to the user also.
I need it to sperate the lines, by ether using the break line html code <br /> or some other way, I know how many lines I have by using themehtml.split("\n");
So the question is 'I need a way to add a line break at the end of the line'
This Is my most of my js code that kind of helps the question a bit
$(".edit_html_button").click(function()
{
var themehtml = $(".wrapper").html();
var oldhtml = _grubber_blog.html();
themehtml = themehtml.replace(/</g, "<"); //slowly removing html codes
themehtml = themehtml.replace(/>/g, ">"); //slowly removing html codes
themehtml = themehtml.split(' ').join(' ');//slowly removing html codes
themehtml = ("<div class='numberboxleft'></div><div class='edit_theme' contenteditable='true'>"+themehtml+"</div>");
themehtml = themehtml.split("\n");
//alert(themehtml);
_grubber_blog.css("background-color", "#fff");
$("#tiptip_holder").remove();
$("._grubber_blog_customize").html(" ");
$("._grubber_blog_customize").html(themehtml);
//adds the numbers up the left side
var e = 0;
var lenght = themehtml.length;
var numbers = "";
while (e < lenght){
numbers = $(".numberboxleft").html();
$(".numberboxleft").html(numbers + e + "<br />");
e++;
}
});
To replace newlines with html breaks you split on newlines and then join the array with html breaks:
themehtml.split("\n").join('<br>')
So I used the $.each function like so...
$.each(themehtml, function(){
var grad = $("._grubber_blog_customize").html();
$("._grubber_blog_customize").html(grad+this+"<br />");
});
This will gradualy add the striped html code to the div and make it look like its line by line

Inserting a newline into a pre tag (IE, Javascript)

In IE when I insert text into a <pre> tag the newlines are ignored:
<pre id="putItHere"></pre>
<script>
function putText() {
document.getElementById("putItHere").innerHTML = "first line\nsecond line";
}
</script>
Using \r\n instead of a plain \n does not work.
<br/> does work but inserts an extra blank line in FF, which is not acceptable for my purposes.
These quirksmode.org bug report and comments about innerHTML behaviour of Internet Explorer could help:
"IE applies HTML normalization to the data that is assigned to the innerHTML property. This causes incorrect display of whitespace in elements that ought to preserve formatting, such as <pre> and <textarea>."
Does this work in IE?
document.getElementById("putItHere")
.appendChild(document.createTextNode("first line\nsecond line"));
I tested it with Firefox and it works. :-)
The workaround can be found in the page linked to in the accepted answer. For ease of use here it is:
if (elem.tagName == "PRE" && "outerHTML" in elem)
{
elem.outerHTML = "<PRE>" + str + "</PRE>";
}
else
{
elem.innerHTML = str;
}
<br/> shoud only output one line in all browsers. Of course remove the \n as well, code should be:
document.getElementById("putItHere").innerHTML = "first line<br/>second line";
Content inside the <pre> tag should not be considered HTML.
In fact, the point of <pre> tag is so that it does display formatted text.
Using the innerText property is the correct way to modify the content of a <pre> tag.
document.getElementById("putItHere").innerText = "first line\nsecond line";
IE9 does not normalize white spaces, unlike its predecessors.
You should test for support rather than targeting any specific browser. E.g...
var t = document.createElement(elem.tagName);
t.innerHTML = "\n";
if( t.innerHTML === "\n" ){
elem.innerHTML = str;
}
else if("outerHTML" in elem)
{
elem.outerHTML = "<"+elem.tagName+">" + str + "</"+elem.tagName+">";
}
else {
// fallback of your choice, probably do the first one.
}
I reckon this.
What I found was IE is using \r\n and Fx(others) is using \n
var newline;
if ( document.all ) newline = '\r\n';
else newline = '\n';
var data = 'firstline' + newline + 'second line';
document.getElementById("putItHere").appendChild(document.createTextNode(data));
For a TinyMCE(wysiwyg editor) plugin I once made I ended up with using BR i edit mode
and cleaned it up on submit etc.
This code loops through all BR elements inside PRE elements and replaces BR with newlines.
Note that the code relies on the TinyMCE API, but can easily be written using standard Javascript.
Clean up:
var br = ed.dom.select('pre br');
for (var i = 0; i < br.length; i++) {
var nlChar;
if (tinymce.isIE)
nlChar = '\r\n';
else
nlChar = '\n';
var nl = ed.getDoc().createTextNode(nlChar);
ed.dom.insertAfter(nl, br[i]);
ed.dom.remove(br[i]);
}
Good luck!
If you don't want to use outerHTML, you can also do the following for IE, if an additional pre tag is not an issue:
if(isIE)
document.getElementById("putItHere").innerHTML = "<pre>" + content+"</pre>";
else
document.getElementById("putItHere").innerHTML = content;
I've found that innerHTML is processed before it is applied to the element, hence <br> becomes a newline and multiple white spaces are removed.
To preserve the raw text you must use nodeValue, for example;
document.getElementById('pre_id').firstChild.nodeValue=' white space \r\n ad new line';
Here is a very small tweak to Edward Wilde's answer that preserves the attributes on the <pre> tag.
if (elem.tagName == "PRE" && "outerHTML" in elem) {
var outer = elem.outerHTML;
elem.outerHTML = outer.substring(0, outer.indexOf('>') + 1) + str + "</PRE>";
}
else {
elem.innerHTML = str;
}
if (typeof div2.innerText == 'undefined')
div2.innerHTML = value;
else
div2.innerText = value;
that worked for me.

Categories