Javascript - Get a formated preview of files read with FileReader()? - javascript

I tryed to implement a drag file functionality. I need a preview with the text of the file, in this case an HTML file. But when I insert the result of FileReader into the DOM, the preview loses all the line breaks and text-indent.
I tryed using jQuery .split() and inserting a <br/>, but still the text loses all the indentation.
for(var i = 0; i <files.length; i++){
reader = new FileReader();
reader.onload = function(evt){
var r = evt.target.result;
r = r.replace(/>/g,'> >');
r = r.replace(/</g,'<');
r = r.split('>')
var text="";
for(var i =0; i<r.length; i++){
r[i] = $.trim(r[i]);
text += r[i]+'<br/>';
}
$('.drop-area').html(text);
}
reader.readAsText(files[i]);
}
Try dragging an HTML file here http://jsfiddle.net/gVZRU/2/
Is possible to solve that? Is there any other approach I can take to have this functionality?

You simply need to add white-space: pre-wrap; to the style of the display box.
Multiple successive whitespace in an HTML source is always collapsed into a single output whitespace in the rendered content. The white-space CSS properties allows you to change this behavior, and the pre value says to treat whitespace as the <pre> tag does (i.e., show all whitespace in the rendered result). pre-wrap is just like pre, but allows wrapping of the text.

Use the .text method to insert text. No need for escaping manually. To fix the display issue, don't try to insert <br> tags after every closing tag but just use appropriate CSS: white-space: pre-wrap;.

Related

Adding Line Numbers To Pre-formatted Text

I have a body of text that I show in a web page within some <pre> tags. I would like to add a column to the left of this text body to show the line number of the text.
The body of text is retrieved by using [PHP] file_get_contents() so I am just echo-ing a string within the <pre> tags.
I imagine this can be accomplished with JavaScript but I have yet to find a solution.
Solutions I have seen on here usually use a library or CSS. The CSS method would be great but this method seems to require that each line of the body text have its own corresponding tag (eg <p> or <span>).
// Example of CSS Solution
p:not(:first-child):before {
counter-increment: custom-counter+1;
content: counter(custom-counter)". ";
display: table-cell;
}
p:first-child:before {
display: table-cell;
content: '1. '
}
I would like to avoid having to create a DOM element (before load) line by line. That said, if that is the best solution I simply want to know the "preferred" way to go about this.
How could I accomplish this using JavaScript / jQuery?
One simple solution would be to split the string on "\n" with javascript to get each line append the line numbers then re-join them together. This will only work if you are using <pre> tags where newlines are literal newlines.
JsFiddle
let text = document.getElementById("test").innerHTML;
let lines = text.split("\n");
for (let i=0;i<lines.length;i++) {
lines[i] = (i+1)+" "+lines[i];
}
text = lines.join("\n");
document.getElementById("test").innerHTML = text;

jquery & doc.createElement throws error for <

Both the $("<test") & document.createElement(",test") throws error due to < character associated to the text. I do not want to replace the character & wanted to see if there is option to create dom or jquery object using such text. I know replace will work but since the code is pre-existing & also since code is written such that it assume it can either have the simple text (textnode) or html tag (like span) hence this error is occuring as it fails to check if it is proper self closing html tag.
I am thinking of creating it to xml node & then check if the childnode is textNode or not before trying to create jquery object,however I am looking for suggestion & best approach to tackle such issue. I know replace of < will work & also there is no need to check for attributes of plain text but since the code is dynamic it sometimes retrieves plain text & some time it gives valid html tag that why this issue appears
I am not sure what your exact end goal is, but basically you need to do something like this:
function makeElemHack( str ) {
var div = $("<div>").html(str); //create a div and add the html
var html = div.html(); //read the html
if (!html.length) { //if the html has no length the str was invalid
div.html(str.replace(/</g,"<")); //escape the < like text should be
//div.text(str); //or you can just add it as plain text
}
return div; //with the div wraper
//return div.contents(); //without the div wrapper
}
var bd = $("body");
bd.append( makeElemHack("<p>Hello</p>") );
bd.append( makeElemHack("1<0") );
bd.append( makeElemHack("<booo") );

How can I Strip all regular html tags except <a></a>, <img>(attributes inside) and <br> with javascript?

When a user create a message there is a multibox and this multibox is connected to a design panel which lets users change fonts, color, size etc.. When the message is submited the message will be displayed with html tags if the user have changed color, size etc on the font.
Note: I need the design panel, I know its possible to remove it but this is not the case :)
It's a Sharepoint standard, The only solution I have is to use javascript to strip these tags when it displayed. The user should only be able to insert links, images and add linebreaks.
Which means that all html tags should be stripped except <a></a>, <img> and <br> tags.
Its also important that the attributes inside the the <img> tag that wont be removed. It could be isplayed like this:
<img src="/image/Penguins.jpg" alt="Penguins.jpg" style="margin:5px;width:331px;">
How can I accomplish this with javascript?
I used to use this following codebehind C# code which worked perfectly but it would strip all html tags except <br> tag only.
public string Strip(string text)
{
return Regex.Replace(text, #"<(?!br[\x20/>])[^<>]+>", string.Empty);
}
Any kind of help is appreciated alot
Does this do what you want? http://jsfiddle.net/smerny/r7vhd/
$("body").find("*").not("a,img,br").each(function() {
$(this).replaceWith(this.innerHTML);
});
Basically select everything except a, img, br and replace them with their content.
Smerny's answer is working well except that the HTML structure is like:
var s = '<div><div>Link<span> Span</span><li></li></div></div>';
var $s = $(s);
$s.find("*").not("a,img,br").each(function() {
$(this).replaceWith(this.innerHTML);
});
console.log($s.html());
The live code is here: http://jsfiddle.net/btvuut55/1/
This happens when there are more than two wrapper outside (two divs in the example above).
Because jQuery reaches the most outside div first, and its innerHTML, which contains span has been retained.
This answer $('#container').find('*:not(br,a,img)').contents().unwrap() fails to deal with tags with empty content.
A working solution is simple: loop from the most inner element towards outside:
var $elements = $s.find("*").not("a,img,br");
for (var i = $elements.length - 1; i >= 0; i--) {
var e = $elements[i];
$(e).replaceWith(e.innerHTML);
}
The working copy is: http://jsfiddle.net/btvuut55/3/
with jQuery you can find all the elements you don't want - then use unwrap to strip the tags
$('#container').find('*:not(br,a,img)').contents().unwrap()
FIDDLE
I think it would be better to extract to good tags. It is easy to match a few tags than to remove the rest of the element and all html possibilities. Try something like this, I tested it and it works fine:
// the following regex matches the good tags with attrinutes an inner content
var ptt = new RegExp("<(?:img|a|br){1}.*/?>(?:(?:.|\n)*</(?:img|a|br){1}>)?", "g");
var input = "<this string would contain the html input to clean>";
var result = "";
var match = ptt.exec(input);
while (match) {
result += match;
match = ptt.exec(input);
}
// result will contain the clean HTML with only the good tags
console.log(result);

turn <br> into line breaks using javascript (not php)

I need to extract the text from a div with paragraphs and spans and other things and put it into a textarea. I need to load just the text, not the HTML.
For that, I can use:
loadtext = $('#mydiv').text();
However, I DO need to retain the line breaks.
For that, I'm doing:
loadtext = $('#mydiv').text().replace(/<br>/gm, '\r\n');
But it doesn't seem to be working, because when I load that text into a textarea, it's all flat with no line breaks. Am I doing something wrong?
$('#mydiv').text() has already been stripped of all HTML, including<br> elements, so this will not work. You need to modify the HTML of the #mydiv element and replace all <br/> elements, then retrieve the text.
$('#mydiv').find('br').each(function(){
$(this).after("\n")
.remove();
});
var loadtext = $("#mydiv").text();
An alternate solution is to use an intermediate element that's never added to the document.
var html = $('#mydiv').html(); // e.g. '<p>line 1</p><br><br><p>line 2</p>'
var text = $('<div>').html(html.replace(/<br\/?>/g, '\n')).text();
/* text =
"line 1
line 2"
*/
$('#mytextarea').text(text);
This supports <br> (HTML) and <br/>(XHTML).

CKEDITOR.replace() is hiding the textarea that I want converted

I'm using Javascript to create a textarea that I want to be a ckeditor. My code is something like
var html = '<textarea name="text"></textarea>';
$('#mydiv').append(html);
var textareas = document.getElementsByTagName('textarea');
// Could be more than one textarea
for (i = 0; i<textareas.lenght; i++) {
var textarea = textareas[i];
CKEDITOR.replace(textarea.name);
}
When I run this code and check the output the textarea is hidden. Inspecting it in firebug I'm getting a style="visibilty:hidden". However removing this just gives me a textarea and not a ckeditor. Does anyone have any suggestions on how to solve it.
Putting it as a div worked but the examples all seemed to be in textareas.
The hiding is correct. Because the <textarea/> has no wysiwyg support. The .replace() method replaces the <textarea/> with it's wysiwyg Editor. That's why it's hidden.
CKEDITOR.replace(elementOrIdOrName, config)
Replaces a or a DOM element (DIV) with a CKEditor instance. Source
As you can see in the documentation you don't need to append the <textarea/>, instead you could use your div directly:
CKEDITOR.replace('mydiv')

Categories