Apply code highlighter to Textarea - javascript

I have a textarea in my website contains PHP code.
I want to make the users able to Modify the code and then Run it.
So, I have made a textarea called modifyCode:
<textarea id="modifyCode"></textarea>
So far I have managed to run the PHP code which is written in the textarea.
BUT, I really like to apply code highlighter to my text box. With this regard, I have tried a couple of ways:
I have tried "highlight.js" --> https://highlightjs.org/
I have tried "codemirror" --> https://codemirror.net/
Not only I can't get my PHP code to be highlighted, but also it can't be running anymore.
I need to mention that the same method is working fine to highlight XML code, but it won't run too!
As far as I understood, when we apply these code highlighters, the textarea will not act like a textarea anymore. So, is there anyway that I can highlight my PHP code and then run it?

A way to encounter with this issue is to make an middle DIV called modifyCodeDiv:
<div id="modifyCodeDiv" contenteditable="true"></div>
modifyCodeDiv is getting the value of modifyCode textarea:
document.getElementById("modifyCodeDiv").innerHTML =
document.getElementById("modifyCode").value;
So, users can modify the code in the div modifyCodeDiv.
To execute the code, you need to send the value of modifyCodeDiv to modifyCode. As div does not have value attribute, you need to do:
var my_element = document.getElementById('modifyCodeDiv');
var my_str = my_element.innerText || my_element.textContent;
document.getElementById("modifyCode").value = my_str;
Furthermore, you can apply highlight.js to your div modifyCodeDiv.

Related

How to make a live HTML preview textarea safe against HTML/Script Injection

I'm turning here as a last resort. I've scoured google and I'm having troubles coming to a solution. I have a form with a textarea element that allows you to type html in the area and it will render the HTML markup live as you type if you have the preview mode active. Not too different from the way StackOverflow shows the preview below a new post.
However, I have recently discovered that my functionality has a vulnerability. All I got to do is type something like:
</textarea>
<script>alert("Hello World!");</script>
<textarea style="display: none;">
And not only does this run from within the textarea live, if you save the form and reload said data on a different page this code still executes within the textarea on said different page but unbeknownst to the user; to them all the see is a textarea (if there is no alert obviously).
I found this post; Live preview of textarea input with javascript html, and attempted to refactor my JS to the accepted answer there, because I noticed I couldn't write a script tag in the JSFiddle example, though maybe that's some JSFiddle blocking that behaviour, but I couldn't get it working within my JS file.
These few lines is what I use to live render HTML markup:
$(".main").on("keyup", "#actualTextArea", function () {
$('#previewTextArea').html($('#actualTextArea').val());
});
$(".main").on("keydown", "#actualTextArea", function () {
$('#previewTextArea').html($('#actualTextArea').val());
});
Is there a way this can be refactored so it's safe? My only idea at the moment is to wipe the live preview and use a toggle on/off and encode it, but I really think this is a cool feature and would like to keep it live instead of toggle. Is there a way to "live encode" it or escape certain tags or something?
In order to sanitise your text area preview simply replace all the < and > with their html character code equivalents:
function showPreview()
{
var value = $('#writer').val().trim();
value = value.replace("<", "<");
value = value.replace(">", ">");
$('#preview').html(value);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="writer" onInput="showPreview();">
</textarea>
<br/>
<hr/>
<div id="preview">
</div>
Edit: Actually, I think this solution is a little cleaner, and makes the below code unnecessary. In the velocity page all that is needed is to take advantage of the Spring framework. So I replace the textarea with this like so:
#springBindEscaped("myJavaObj.textAreaText" true)
<textarea id="actualTextArea" name="${status.expression}" class="myClass" rows="10" cols="120">$!status.value</textarea>
This paired with some backend Java validation and it ends up being a much cleaner solution.
But if you want a non-spring/ velocity solution, then this below works just fine
I cobbled together a quick fix as my main purpose is to eliminate the ability for others to execute scripts easily. It's not ideal, and I"m not claiming it to be the best answer, so if someone finds a better solution, please do share. I created a "sanitize" function like so:
function sanitize(text){
var sanitized = text.replace("<script>", "");
sanitized = sanitized.replace("</script>", "");
return sanitized;
}
Then the previous two event handlers now look like:
$(".main").on("keyup", "#actualTextArea", function () {
var textAreaMarkup = $('#actualTextArea').val();
var sanitizedMarkup = sanitize(textAreaMarkup );
$('#actualTextArea').val(sanitizedMarkup);
$('#previewTextArea').html(sanitizedMarkup);
});
// This one can remain unchanged and infact needs to be
// If it's the same as above it will wipe the text area
// on a highlight-backspace
$(".main").on("keydown", "#actualTextArea", function () {
$('#previewTextArea').html($('#actualTextArea').val());
});
Along with Java side sanitation to prevent anything harmful being stored in the DB, this serves my purpose, but I'm very open to a better solution if it exists.

Replace parts of string (attributes) in textarea using input boxes

Main Target :
To create a website that will have a live preview of an HTML/CSS code.
More specifically :
The HTML/CSS code will be editable form the user in some specific parts. So, the code in the live preview will not derive from text areas but from divs.
Image of what I am trying to do :
So, in my Previous Question I tried to find a way to make the live preview box work after getting the code from the black boxes. It did not work because the code was given in a div tag and not a textarea. I would like to add that the code in the div tags use xmp tags because some parts are editable from the user.
Now, I have replaced the divs with textarea tags but the EDIT function does not work.
Main Question :
How do I edit parts of a textarea text? Below, I made it work for a div tag but not a textarea. How can I make the following work for a textarea?
$('input#thebox1').keypress(function(e) {
console.log($(this).val());
if(e.which == 13 && $(this).val().length > 0) {
var c = $(this).val();
$('.popup1').removeClass().addClass(c).text(c);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Replace Title Background Color: </div><input type="text" id='thebox1'>
<div id="copyTarget1" class="innerbox css">
<blockquote>
<pre>
<code>
.title
{
background: #<b class="popup1" style="color:#FF0000;">value </b>;
vertical-align: middle;
}
</code>
</pre>
</blockquote>
</div>
<br><br><br><br><br><br>
I thought about taking another approach to make your life easier using Ace (Cloud9 Editor). It is an awesome solution to get code editors for different languages. All built in JavaScript. It is quite easy to integrate. I just downloaded it to create the case you are trying to build.
You can find the example I have just made here: https://dubaloop.io/dev/html_css_js_editor/
Basically, you load the library for ace:
<script src="src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
Then you create a "pre" container for your HTML, CSS, JavaScript editor:
<pre class="editor" id="editor_js">
function foo(items) {
alert('works');
}</pre>
You will be able to convert them into code editor by using the function:
var editor_js = ace.edit("editor_js");
editor_js.setTheme("ace/theme/monokai");
editor_js.session.setMode("ace/mode/javascript");
It will generate a nice code editor that can through error, warnings, etc. You also have different themes. It is very user friendly as you could see. In my example I just get the content of each code container and send it to an blank iframe that. In order to retrieve the content you can use:
editor_js.getValue();
Check the source code for example I sent you above. I also created .zip with the example here: https://dubaloop.io/dev/html_css_js_editor/example.zip
Have a look to see if this would work for you.
GitHub repo for ACE: https://github.com/ajaxorg/ace-builds
I hope it helps.
UPDATE:
I decided to update the response to replay to your last comment. A few things about it:
First, I updated the code in the link I sent you previously: https://dubaloop.io/dev/html_css_js_editor/
The idea was to check the guide to see how you can manipulate the input and adjust it to what you need. They have great manipulation options. This is the guide: https://ace.c9.io/#nav=howto&api=editor
I just made a short version of what you are trying to do: I am replacing the content for the <h1> in HTML editor, by entering it in a textfield input; similar to what you are trying to achieve. I set the html code editor as a readonly so you cant edit on it. Have a look and let me know.
Second, I created another example using your code. You can check it here: https://dubaloop.io/dev/html_css_js_editor/example.html
I noticed that the first problem you were having was related to how you were triggering the preview update ($('.innerbox').on("keyup"...)). There was not keyup event there. For now I set it on any input when you hit enter. The other big problem, and probably the main one you had was how you were accessing the iframes through jQuery. You need to use $('selector').contents().find('selector2'). Finally another problem was the you were retrieving the data getting the attribute value from your code wrapper. What you need to get is the actual content as flat text in order to avoid other html content. In order to do that you need to use .text() (Please check the updated GetHtml() and GetCss() functions).
I hope you can make it work from here. Still, I like option 1 :P
I hope it helps.

Cannot get value of textarea with Shopify Product Options by Bold

I'm trying to get the value of a textarea with Shopify Product Options by Bold and it is currently not working. I am able to get the value of a textarea locally, but I can not get the value when I move the code over to Shopify. I have looked here and here to no avail.
Here's the relevant code:
document.getElementById("248832").onkeyup=function(){getVal()};
var textbox = document.getElementsByName("properties[Message Body]")[0].value;
and here's the textarea I'm trying to get the value of
<textarea data-option-key="ta_248832" id="248832" class="bold_option_child shapp_full_width " name="properties[Message Body]"></textarea>
When I try to run this on Shopify, I get an error saying "Uncaught TypeError: Cannot set property 'onkeyup' of null", although I did notice that at one point shopify runs the following jQuery code, which might be what's causing my problem:
<script>
jQuery('#248832').change(function (){conditional_rules(7437760391);})
</script>
I am trying to get the value of the textarea so I can run get the amount of words in said textarea.
Any help would be greatly appreciated!
Look to see if the element that is returned as null has loaded yet. Others in similar situations fixed this by loading the script last. Hope this is helpful :)
https://stackoverflow.com/a/25018299/1305878
https://stackoverflow.com/a/31333349/1305878
https://stackoverflow.com/a/23544789/1305878
Solution
You are trying to use something similar to jQuery methods without jQuery:
document.getElementById("248832").onkeyup=function(){getVal()};
while DOM elements don't have the onkeyup method. It should be
jQuery("#248832").on("keyup",function(){getVal()});
Extra notes
even without using the recommended '.on' method, you have to write it as
jQuery("#248832").keyup(function(){getVal()});
(docs), not as
jQuery("#248832").onkeyup(function(){getVal()});
If you'd like to use DOM methods, that would be
document.getElementById("248832").addEventListener("keyup",function(){getVal()});
Also, may be you have wrote this as a minimal example, but the fact that you only call getVal() and don't pass the value somewhere sounds strange, although I don't know if what getVal() does exactly.

Script insert line breaks in div contentEditable

I have a webpage div with contentEditable=true. After the user modifies the content of the div, the system uses document.getElementById(id).innerHTML to get the content and send it to server. This is all working:
<div id='editBox'; contentEditable='true'></div>
<script>
document.getElementById('editBox').onkeydown=function(e){
clearTimeout ( backupTimeoutID );
backupTimeoutID = setTimeout(function(){sendDivContentToServer()},3000);
}
<script>
the reason I'm using the a div with contentEditable=true instead of text area is that I need to allow displaying and formatting of background-colored text in the div. If I'm unaware of any better way, please, let me know.
My problem is with the inconsistence with which line breaks are displayed. If the user presses return inside the div, it creates another div for the line break. So, when the function gets the innerHtml, it looks like this
first line of text<div>second line of text</div>
Sometimes, when pasting text from other sources in the edit box (from internet, word, etc), line breaks appear as <p>.
I want all line breaks to look like this:
first line of text<br>second line of text
I have tried changing the behavior of the <div> whenever the user presses return; I know the code is working, for if I try to insert a word instead of return it works. But, when I set the code to substitute return for <br> it acts erradically. This is the code I'm using for this:
<script>
document.getElementById('editBox').onkeydown=function(e){
clearTimeout ( backupTimeoutID );
backupTimeoutID = setTimeout(function(){sendDivContentToServer()},3000);
}
} else if ( pressedKeyCode==13 ) {
e.preventDefault();
document.execCommand("InsertHTML",false,"a"); // this works
document.execCommand("InsertHTML",false,"<br>"); // I don't see the effects I want with this
}
<script>
Converting the multiple line breaks – <div>, <p> and <br> – seem to be a hard task. Using <br> for line breaks seems less error prone.
I'm developing for a web viewer in FileMaker for use in Mac OSX. So, so far, I care more about Safari than any other browser.
Thanks, in advance, for the help.
Reining in contentEditable is not an easy task. Unfortunately it's not really standardized and every browser has its quirks.
I would suggest you have a look at the many well written HTML rich text editors that are around.
For example, CKEditor only creates sensible, valid HTML, it allows you to configure what happens, when the user presses return, it can remove or replace any unwanted HTML and you can disable any features that the user shouldn't use.

Javascript innerHTML with Popup

I can't understand why this inner html script isn't working. I posted the javascript on jsFiddle. You can see it here: http://jsfiddle.net/JyV73/1/
I have two versions of the link. In the first the rewrite link is within a popup that needs to be closed and another opened with the proper text within the textarea.
In the second, there is just a link on the page that when it is clicked should hopefully open the popup with the proper text within wht textarea.
The only problem is that it doesn't work for the second version because of I must close the popup. If I comment out that first document.getElementById(id).style.display = 'none' then the plain link works, so my first thought is to create two function. But since this javascript is part of a php template file that is included I think it would be simpler on the php code to just solve this using pure javascript.
I'm still learning javascript, and any help would be appreciated. I hope I was clear. Thank you so much.
HTML
open
<div id="popup" class="popup"> Rewrite
</div>
<div id="new" class="popup">
<textarea id="new-text"></textarea>
</div>
<!-- This is the stuff that doesnt work for some reason Rewrite
<div id="new" class="popup">
<textarea id="new-text"></textarea>
</div>
-->
The Javascript
function rewrite(id, text) {
document.getElementById(id).style.display = 'none';
document.getElementById('new-text').innerHTML = text;
}
I am not entirely clear on what you are trying to do here, but from the way I read your code you want to set the value of the text area to a specific value.
here is how you do that: http://jsfiddle.net/JyV73/9/
function rewrite(id, text) {
$('#new-text').val(text);
}
You're not using pop-ups, you're using modals, which means its' a div inside the page that toggles visibility. You can access information from those components whether they are visible or not, fyi.
Still, Im not entirely sure on what you're trying to do here.
I changed document.getElementById('new-text').innerHTML = text; to document.getElementById('new-text').value = text; because it's the value attribute of the text box which you want to set.
Also each element on the page with an ID needs to have a unique ID (it seems like you might have been trying to reuse IDs at one point but maybe I'm wrong!)
I still haven't worked out exactly what you're trying to achieve but those changes needed to be made no matter what.
This code is sufficient to achieve your second goal though: http://jsfiddle.net/JyV73/19/
I added an onClick attribute (onClick="rewrite('popup', 'blah')") to your "open" link to do the writing to the textbox. :)

Categories

Resources