<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form>
<textarea id="source" cols="100" rows="20"></textarea>
</form>
<script type="text/javascript">
var txarea = document.getElementById('source');
txarea.addEventListener('paste', function(){
let text = txarea.value;
console.log(text);
let replace_text = text.replace(/\n/g, ' ')
console.log(replace_text);
txarea.value = replace_text;
});
</script>
</body>
</html>
Copy some text with line break \n, for example
abc
ef
Then repeat: Control + A + Control + V. Then you can see there are more and more texts coming up each time.
I tried to add a debugger and check what's going on. But after I step over the last statement, it just becomes a mess.
What's wrong?
Lets break down the test case and how it interacts with your code.
User selects all text in the text area.
User initiates a "paste".
Before the paste takes place, your callback fires.
Your callback replaces the contents of the textarea with new, modified contents. (Replacing newlines with spaces.)
Because you have entirely replaced the textarea's contents with new contents, the user's initial text selection is no longer valid. So the effective cursor position is now at the end of the new, replaced contents.
The paste happens, adding new text to the end of the textarea's contents.
In step #5, if the text wasn't modified (i.e. it didn't have newlines to begin with) then the selection remains valid and the paste happens as a replace instead of an append.
I think that what you are trying to do is this:
Detect that the user is attempting to paste some text.
Modify the text before it gets pasted in. (By replacing newlines with spaces.)
You can find out what text is being pasted in using the paste event, i.e.:
let paste = (event.clipboardData || window.clipboardData).getData('text');
But you don't want to just replace the contents of the textarea with this pasted info, nor do you want to append it at the end. What if the user places the caret in the middle of the text and then hits ctrl+v?
Enter document.execCommand.
var txarea = document.getElementById('source');
txarea.addEventListener('paste', function(e) {
e.preventDefault();
let text = '';
if (e.clipboardData || e.originalEvent.clipboardData) {
text = (e.originalEvent || e).clipboardData.getData('text/plain');
} else if (window.clipboardData) {
text = window.clipboardData.getData('Text');
}
console.log(text);
let replace_text = text.replace(/\n/g, ' ');
console.log(replace_text);
if (document.queryCommandSupported('insertText')) {
document.execCommand('insertText', false, replace_text);
} else {
document.execCommand('paste', false, replace_text);
}
});
<form>
<textarea id="source" cols="100" rows="20"></textarea>
</form>
Note: Firefox does not (at the time of writing) support 'insertText' or 'paste' commands on a textarea or input (bug report 1220696), but it does support these commands on a contenteditable div.
Related
I was just playing with the medium editor I found something special. while writing if you try to hit space more than once it does not work means the editor does not accept more than one space. How cool it is.
it will be cool if we implement this in textareas or contenteditable to restrict the user from entering lots of spaces.
if somebody knows how to do it please share it with me.
Update
<h2 contenteditable="true">Write here</h2>
how do i restrict user from hiting more than one space.
I tried it with a textarea. You won't be able to type in more than one space when typing in characters into this textarea. Is this what you were looking for?:
function trimSpaces(event){
var content = $('#sampleText').val();
//If you need to trim all white spaces and replace with single space
//content = content.replace(/\s\s+/g, ' ');
$('#sampleText').val("");
content = content.replace(/ +/g, ' ');
$('#sampleText').val(content);
}
function validate(event){
// Donot add the character keyed into textbox before validation
event.preventDefault();
var content = $('#sampleText').val();
//which is supported by FF and keyCode by other browsers.
var x = event.which || event.keyCode;
if(x==32){
if( content[content.length -1] ==" "){
// Do nothing if previous character was a space
}else{
// Add the character into the text area if its not a space
content+=String.fromCharCode(x);
$('#sampleText').val(content);
}
}else{
// add any characters keyed in to the text area if its not a space.
content+=String.fromCharCode(x);
$('#sampleText').val(content);
}
}
<!DOCTYPE html>
<html>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<body>
<textarea name="sampleText" id="sampleText" maxlength="200" onkeypress="validate(event)" onkeyup="trimSpaces(event)"></textarea>
</body>
</html>
I have a pre tag that displays text taken from a database (notes for a shopping order). I use the pre tag because it displays new lines.
I use contenteditable="true" on it so that users can edit the field, and click a save button to save it.
However upon saving, when I take the field's value using field.text(), the new lines are not preserved.
Reproduce:
HTML:
<pre id="notes" contenteditable="true">Some
test
Txt
</pre>
JS:
// Works fine here
console.log($('#notes').text());
// add some text with new lines, then "blur" the text and you can see the issue happening in the log -- new lines not preserved
$('#notes').on('blur', function (e) {
console.log($('#notes').text());
});
What I am trying but so far haven't succeeded
// When user presses enter on an editable field.
$('#notes').on('keydown', function (e) {
if (e.keyCode === 13) {
// trap the return key being pressed and insert new line at THIS place --- how??? (Possibly not the most elegant solution either)
}
});
https://jsfiddle.net/6496pke5/
Use html() instead of text() in order to create a break line on hit Enter.
Using html() will wrap a <br> tag into a <div> element though, to prevent that behaviour use document.execCommand() method:
$('#notes').on('keydown', function (e) {
if (e.keyCode === 13) {
document.execCommand('insertHTML', false, '<br>');
return false;
}
});
Here is fiddle https://jsfiddle.net/6496pke5/1/
It won't because you are doing
console.log($('#notes').text());
since when you press enter to create a new line <br> is added to the markup which will not come in the textContent attribute of the element of which .text() is a short form of.
try instead
console.log($('#notes').html());
you will see the new lines <br> added.
Consider the following problem:
Have a textarea like so:
<textarea id="body" name="body"></textarea>
Also have some simple JavaScript (jQuery) that inserts some new text into the textarea so a user can embed an image:
$('textarea').val($('textarea').val() + '[img]path to image file[/img]');
The trick is to automatically highlight the text in between the [img][/img] tags after that text is inserted so the user can just copy and paste their image URL in quickly, instead of manually selecting, then copy and pasting.
I've racked my brain and gone all over the internet trying to figure this out, and the best I could do was this popular StackOverflow question Selecting text in an element (akin to highlighting with your mouse) which only addresses the problem of selecting the text inside an ENTIRE element, which is not what is desired here. The problem is to select text that matches a certain string, in this case path to image file, so the user can just copy/paste. (not sure if this is the best way to do it, but that's what I thought of...).
Is this possible? I'm guessing we're going to need getSelection() and createRange() but other than that I have no idea where to go... any JavaScript wizards figured this one out already? I feel like this could be a popular question. Using jQuery is fine, as I'm already using it on the rest of the document.
You could use my jQuery plug-in. It works around browser differences in textarea selection manipulation and has some convenience methods:
https://code.google.com/p/rangyinputs/
For your example, the code would be
var $textarea = $("#body");
var text = "path to image file"
$textarea.replaceSelectedText(text, "select");
$textarea.surroundSelectedText("[img]", "[/img]");
Demo: http://jsfiddle.net/P8Jrh/1/
I actually figured this one out myself... I used the Rangy library https://code.google.com/p/rangy/ and code like this:
// Add text to the reply area at the very end, and move the cursor to the very end.
function insertText(textarea, text) {
textarea = $(textarea);
textarea.focus();
textarea.val(textarea.val() + text);
textarea.focus();
// Trigger the textarea's keyup to emulate typing.
textarea.trigger("keyup");
}
// Add text to the reply area, with the options of wrapping it around a selection and selecting a part of it when it's inserted.
function wrapText(textarea, tagStart, tagEnd, selectArgument, defaultArgumentValue) {
textarea = $(textarea);
// Save the scroll position of the textarea.
var scrollTop = textarea.scrollTop();
// Work out what text is currently selected.
var selectionInfo = textarea.getSelection();
if (textarea.val().substring(selectionInfo.start, selectionInfo.start + 1).match(/ /)) selectionInfo.start++;
if (textarea.val().substring(selectionInfo.end - 1, selectionInfo.end).match(/ /)) selectionInfo.end--;
var selection = textarea.val().substring(selectionInfo.start, selectionInfo.end);
// Work out the text to insert over the selection.
selection = selection ? selection : (defaultArgumentValue ? defaultArgumentValue : "");
var text = tagStart + selection + (typeof tagEnd != "undefined" ? tagEnd : tagStart);
// Replace the textarea's value.
textarea.val(textarea.val().substr(0, selectionInfo.start) + text + textarea.val().substr(selectionInfo.end));
// Scroll back down and refocus on the textarea.
textarea.focus();
// If a selectArgument was passed, work out where it is and select it. Otherwise, select the text that was selected
// before this function was called.
if (selectArgument) {
var newStart = selectionInfo.start + tagStart.indexOf(selectArgument);
var newEnd = newStart + selectArgument.length;
} else {
var newStart = selectionInfo.start + tagStart.length;
var newEnd = newStart + selection.length;
}
textarea.selectRange(newStart, newEnd);
// Trigger the textarea's keyup to emulate typing.
textarea.trigger("keyup");
}
var bbcode = {
bold: function(id) {wrapText($("textarea"), "[b]", "[/b]", "", "bolded text");},
};
Example usage:
bbcode.bold();
Full code (in a larger project I did): https://github.com/wnajar/textarea
I had a text box in my browser. Whatever you typed in the text box and clicked on okay button, the text submitted server through a AJAX request and then spread that message to remaining people, including to me also.
The message is appeared on a <div>.
What's my problem is if I typed html or script tags in that message they are not appearing in the message <div> and they are executing .
If I typed like tags opened and end with script in that middle code is executing on client side, how can I prevent executing and I am able to spread <script> tags also in the messages spreading to all.
If you want the text to always be text, treat is as text and don't use it to set innerHTML property for example.
Update text nodes instead.
Update
For example, if you had user input in userInput, and you wanted to display it, you would treat it as text, not HTML.
var element = document.body,
// For example
userInput = "Alex <script>alert('xss')</script>";
// Don't do this! Your input is text, not HTML.
// element.innerHTML = userInput;
// Use this instead
if ('textContent' in element) {
element.textContent = userInput;
} else {
element.innerText = userInput;
}
jsFiddle.
Have you tried replacing with html character entities? For example replacing all < with <.
I want to copy the content of an asp:label using javascript.
I can do it using this method:
strContent = document.getElementById('MainContent_lblHtml').innerText;
window.clipboardData.setData("Text", strContent);
but it strips the formatting and just copies text. (I assume because the dataformat is set to "text".)
The label contains some formatted html. I want to preserve the format, getting the same effect as if I were to highlight it on screen with my mouse, and then copy into (for example) a word document.
Updated
The following will highlight the desired div and then copy the HTML to the clipboard. Go to Word and press CTRL+V to paste the formatted html into a document.
<script type="text/javascript">
function CopyHTMLToClipboard() {
if (document.body.createControlRange) {
var htmlContent = document.getElementById('MainContent_lblHtml');
var controlRange;
var range = document.body.createTextRange();
range.moveToElementText(htmlContent);
//Uncomment the next line if you don't want the text in the div to be selected
range.select();
controlRange = document.body.createControlRange();
controlRange.addElement(htmlContent);
//This line will copy the formatted text to the clipboard
controlRange.execCommand('Copy');
alert('Your HTML has been copied\n\r\n\rGo to Word and press Ctrl+V');
}
}
</script>