Cursor jumps forward in contenteditable div element - javascript

I have this code:
<div id="ce" contenteditable>I love me some foo bar and shit.</div>
<p>
clear
</p>
<script>
var changed, lastValue = '', div = $('#ce'), words = [ 'oele', 'geel',
'politie', 'foo bar' ];
function markWords() {
var html = div.html().replace(/<\/?strong>/gi, ''), text = html
.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' '), exp;
$.each(words, function(i, word) {
exp = new RegExp('\\b(' + word + ')\\b', 'gi');
html = html.replace(exp, function(m) {
console.log('WORD MATCH:', m);
return '<strong>' + m + '</strong>';
});
});
//html = html.replace(' ', ' ').replace(/\s+/g, ' ');
console.log('HTML:', html);
console.log('----');
div.html(html);
}
setInterval(function() {
var html = div.html();
if (lastValue != html && html) {
//console.log(lastValue);
//console.log(html);
//console.log('----');
lastValue = html;
markWords();
setEndOfContenteditable(div[0]);
}
}, 500);
function setEndOfContenteditable(contentEditableElement) {
var range, selection;
if (document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+
{
range = document.createRange();//Create a range (a range is a like the selection but invisible)
range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
selection = window.getSelection();//get the selection object (allows you to change selection)
selection.removeAllRanges();//remove any selections already made
selection.addRange(range);//make the range you have just created the visible selection
} else if (document.selection)//IE 8 and lower
{
range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible)
range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range
}
}
</script>
<style>
[contenteditable] {
padding: 10px;
border: dotted 1px #aaa;
}
[contenteditable]>div {
margin: 10px 0;
}
[contenteditable] strong {
font-weight: normal;
background: red;
color: white;
}
</style>
http://jsfiddle.net/nebgcpzz/
What it does is that it gets specific words and puts red background on them. But when you put cursor in middle or anywhere (but the end) and type 1 character, cursors jumps forward. Any taughts?

Related

Autostyle input text in contenteditable div while typing

I am making a text editor, and I want to have a feature, such that while typing, if the user enters some keyword (e.g. happy, sad), the word is automaticly styled (e.g. color changed). How might I go about doing this?
document.getElementById('texteditor').addEventListener('keyup', function(e) {
styleCode(); //Style the text input
});
//Change the result of pressing Enter and Tab keys
document.getElementById('texteditor').addEventListener('keydown', function(e) {
switch (e.key) {
case 'Tab':
e.preventDefault();
document.execCommand('insertHTML', false, ' '); //Insert a 4-space tab
break;
case 'Enter':
e.preventDefault();
document.execCommand("insertLineBreak"); //Insert a new line
break;
}
});
function styleCode(){
//Style the code in the input box
}
#texteditor {
border: 3px solid black;
width:100%;
height: 500px;;
overflow:auto;
flex:1;
word-wrap: break-word;
word-break: break-all;
white-space:pre-wrap;
padding:5px;
font-family: Consolas,"courier new";
font-size:14px;
}
.styleA {
color:red;
}
.styleB {
color:blue;
}
<div id='texteditor' contenteditable></div>
Basically, when the user fully types "happy" (upon releasing the 'y' key) the word "happy" should turn red (using the styleA CSS class) in the editor. A similar thing should happen when the user finishes typing "sad"; the word "sad" should turn blue using the styleB CSS class.
Thanks in advance for any help.
const SpecialWords = [
"happy",
"sad"//style word
];
const WordColors = [
"styleA",
"styleB"//style class name
];
document.getElementById('texteditor').addEventListener('keyup', function(e) {
styleCode(); //Style the text input
});
//Change the result of pressing Enter and Tab keys
document.getElementById('texteditor').addEventListener('keydown', function(e) {
switch (e.key) {
case 'Tab':
e.preventDefault();
document.execCommand('insertHTML', false, ' '); //Insert a 4-space tab
break;
case 'Enter':
e.preventDefault();
document.execCommand("insertLineBreak"); //Insert a new line
break;
}
});
var oldWord = "";//initialise
function styleCode() {
//Style the code in the input box
var wordList = document.getElementById('texteditor').innerText.split(" ");
/*if old word is same as now then it means we have presed arrow key or caps or so,it do not wan't to style now as no change*/
if(!(oldWord == document.getElementById('texteditor').innerText)){
var oldPos = getCaretPosition(document.getElementById('texteditor'));//backup old position of cursor
for (let n = 0; n < SpecialWords.length; n++) {
var res = replaceAll(wordList,SpecialWords[n],`<span class="${WordColors[n]}">${SpecialWords[n]}</span>`).join(" ");//style adding
}
document.getElementById('texteditorS').innerHTML=res;
setCursor(oldPos,document.getElementById('texteditor'));//set back cursor position
}
oldWord = document.getElementById('texteditor').innerText;//old word for next time's reference
}
function replaceAll(array, find, replace) {
var arr = array;
for (let i = 0; i < arr.length; i++) {
if (arr[i] == find)
arr[i] = replace;
}
return (arr);
}
function getCaretPosition(editableDiv) {
var caretPos = 0,
sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
range = sel.getRangeAt(0);
if (range.commonAncestorContainer.parentNode == editableDiv) {
caretPos = range.endOffset;
}
}
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
if (range.parentElement() == editableDiv) {
var tempEl = document.createElement("span");
editableDiv.insertBefore(tempEl, editableDiv.firstChild);
var tempRange = range.duplicate();
tempRange.moveToElementText(tempEl);
tempRange.setEndPoint("EndToEnd", range);
caretPos = tempRange.text.length;
}
}
return caretPos;
}
function setCursor(pos,editableDiv) {
if(!(pos == 0)){//if 0 it gives unwanted error
var tag = editableDiv;
// Creates range object
var setpos = document.createRange();
// Creates object for selection
var set = window.getSelection();
// Set start position of range
setpos.setStart(tag.childNodes[0], pos);
// Collapse range within its boundary points
// Returns boolean
setpos.collapse(true);
// Remove all ranges set
set.removeAllRanges();
// Add range with respect to range object.
set.addRange(setpos);
// Set cursor on focus
tag.focus();
}
}
.edit {
border: 3px solid black;
width: 100%;
height: 500px;
;
overflow: auto;
flex: 1;
word-wrap: break-word;
word-break: break-all;
white-space: pre-wrap;
padding: 5px;
font-family: Consolas, "courier new";
font-size: 14px;
}
.styleA {
color: red;
}
.styleB {
color: blue;
}
#texteditorS{
pointer-events:none; /*click through*/
position:relative;
bottom: calc(500px + 2 * (5px + 3px));/*overlay on top of editable div,500px is height,5px is padding,3px is border*/
}
<div id='texteditor' class="edit" contenteditable></div>
<div id='texteditorS' class="edit"></div>
Features
support selection( ctrl-a ), arrow keys ...
many word,style support - just define variable
scrollable higlight
highly commented code
Idea
use another editor named texteditorS for style ,it overlaps the main editor,have click-through support for mouse to click the below/underlying editor
check whether any change in words has occured as it might be press of ctrl-a or arrow keys
sync-scroll of texteditor to texteditorS for scrolling styles
save the cursor position and after setting innerHTML set back cursor position.

Incorrect positioning of getBoundingClientRect after newline character

I'm trying to make a dropdown menu follow the cursor in a Rich Text Editor for the web. Using the following I'm able to get the cursor's coordinates no problem:
const sel = window.getSelection();
if (!sel || sel.rangeCount === 0) return;
const position = sel.getRangeAt(0).getBoundingClientRect());
However, if I try to use this after a \n character it returns the position of the cursor after the newline char rather than the beginning of the new line (where the cursor actually appears in the window):
Is there a way to avoid this?
Edit: Based on the comments below here's a more in depth version of what I'm trying to achieve.
I'm currently building a text editor with React and Slate.js (https://github.com/ianstormtaylor/slate). It's a more robust version of a contentEditable component at its heart but allows you to drop in an editable text field into a page. Because of the node structure I'm using, I want there to be soft breaks between paragraphs rather than new <div /> elements. Because this is non-standard behavior for contentEditable, it is very difficult to make a small example without recreating the whole app.
Edit (further responses to comments):
The raw HTML of the text element looks like this:
<span data-slate-string="true">working until newline
see?
</span>
you can see that slate literally translates the break to a \n character which is what I think is causing the problem.
Even when using the default contenteditable of the browser there is indeed a weird behavior when the cursor is set to a new line: the Range's getClientRects() will be empty and thus getBoundingClientRect() will return a full 0 DOMRect.
Here is a simple demo demonstrating the issue:
const target = document.getElementById('target');
document.onselectionchange = (e) => {
const sel = window.getSelection();
if (!sel || sel.rangeCount === 0) {
return;
}
const range = sel.getRangeAt(0);
const position = range.getBoundingClientRect();
floater.style.top = position.bottom + 'px';
floater.style.left = position.right + 'px';
}
#floater {
position: absolute;
width: 20px;
height: 30px;
background: #DDAADDCC;
pointer-events: none;
bottom: 0;
}
<div id="target" contenteditable>Type here and enter new lines</div>
<div id="floater"></div>
For this, there is a simple workaround which consists in selecting the contents of the current Range's container:
// check if we have client rects
const rects = range.getClientRects();
if(!rects.length) {
// probably new line buggy behavior
if(range.startContainer && range.collapsed) {
// explicitely select the contents
range.selectNodeContents(range.startContainer);
}
}
const target = document.getElementById('target');
document.onselectionchange = (e) => {
const sel = window.getSelection();
if (!sel || sel.rangeCount === 0) {
return;
}
const range = sel.getRangeAt(0);
// check if we have client rects
const rects = range.getClientRects();
if(!rects.length) {
// probably new line buggy behavior
if(range.startContainer && range.collapsed) {
// explicitely select the contents
range.selectNodeContents(range.startContainer);
}
}
const position = range.getBoundingClientRect();
floater.style.top = position.bottom + 'px';
floater.style.left = position.right + 'px';
}
#floater {
position: absolute;
width: 20px;
height: 30px;
background: #DDAADDCC;
pointer-events: none;
bottom: 0;
}
<div id="target" contenteditable>Type here and enter new lines</div>
<div id="floater"></div>
Now OP seems to be in a different issue, since they do deal with soft-breaks \n and a white-space: pre.
However I was able to reproduce it only from my Firefox., Chrome behaving "as expected" in this case...
So in my Firefox, the DOMRect will not be all 0, but it will be the one before the line break.
To demonstrate this case, click on the empty line:
const target = document.getElementById('target');
document.onselectionchange = (e) => {
const sel = window.getSelection();
if (!sel || sel.rangeCount === 0) {
return;
}
const range = sel.getRangeAt(0);
const position = range.getBoundingClientRect();
floater.style.top = position.bottom + 'px';
floater.style.left = position.right + 'px';
}
#target {
white-space: pre;
}
#floater {
position: absolute;
width: 20px;
height: 30px;
background: #DDAADDCC;
pointer-events: none;
bottom: 0;
}
<div id="target" contenteditable>Click on the below empty line
Click on the above empty line</div>
<div id="floater"></div>
And to workaround this case, it's a bit more complex...
We need to check what is the character before our Range, if it's a new line, then we need to update our range by selecting the next character. But doing so, we'd also move the cursor, so we actually need to do it from a cloned Range. But since Chrome doesn't behave like this, we need to also check if the previous character was on a different line, which becomes a problem when there is no such previous character...
const target = document.getElementById('target');
document.onselectionchange = (e) => {
const sel = window.getSelection();
if (!sel || sel.rangeCount === 0) {
return;
}
const range = sel.getRangeAt(0);
// we can still workaround the default behavior too
const rects = range.getClientRects();
if(!rects.length) {
if(range.startContainer && range.collapsed) {
range.selectNodeContents(range.startContainer);
}
}
let position = range.getBoundingClientRect();
const char_before = range.startContainer.textContent[range.startOffset - 1];
// if we are on a \n
if(range.collapsed && char_before === "\n") {
// create a clone of our Range so we don't mess with the visible one
const clone = range.cloneRange();
// check if we are experiencing a bug
clone.setStart(range.startContainer, range.startOffset-1);
if(clone.getBoundingClientRect().top === position.top) {
// make it select the next character
clone.setStart(range.startContainer, range.startOffset + 1 );
position = clone.getBoundingClientRect();
}
}
floater.style.top = position.bottom + 'px';
floater.style.left = position.right + 'px';
}
#target {
white-space: pre;
}
#floater {
position: absolute;
width: 20px;
height: 30px;
background: #DDAADDCC;
pointer-events: none;
bottom: 0;
}
<div id="target" contenteditable>Click on the below empty line
Click on the above empty line</div>
<div id="floater"></div>
This works:
Insert a "zero width space" in the range and again call getBoundingClientRect.
Then remove the the space.
function rangeRect(r){
let rect = r.getBoundingClientRect();
if (r.collapsed && rect.top===0 && rect.left===0) {
let tmpNode = document.createTextNode('\ufeff');
r.insertNode(tmpNode);
rect = r.getBoundingClientRect();
tmpNode.remove();
}
return rect;
}

how to show a div below selected text in textarea?

I have a scenario,where I need to show a div(like popup) on-select of text in text-area.But, I used mouse-down for it,the position of div is not exactly below the text sometimes.
JavaScript:
function getSel() {
// obtain the object reference for the textarea>
var txtarea = document.getElementById("mytextarea");
// obtain the index of the first selected character
var start = txtarea.selectionStart;
// obtain the index of the last selected character
var finish = txtarea.selectionEnd;
//obtain all Text
var allText = txtarea.value;
// obtain the selected text
var sel = allText.substring(start, finish);
sel = sel.replace(/[\S]/g, "*");
//append te text;
var newText = allText.substring(0, start) + sel + allText.substring(finish, allText.length);
txtarea.value = newText;
$('#newpost').offset({ top: 0, left: 0 }).hide();
}
$(document).ready(function () {
var position;
$('#newpost').hide();
$('#mytextarea').on('select', function (e) {
var str = $('#mytextarea').val();
$('#newpost').offset(position).show();
var txtarea = document.getElementById("mytextarea");
var start = txtarea.selectionStart;
var finish = txtarea.selectionEnd;
$('#newpost div').text('Replace with stars');
}).on('select', function (e) {
position = { top: e.pageY+10, left: e.pageX };
});
$('#newpost').hide();
});
function closePopUp() {
$('#newpost').hide();
}
Here is my plunker link
Here my requirement is to show a div on-select of text.But when I am using on-select instead of mouse-down,the div is showing below text-area.
Thanks in Advance.
A few days ago in this answer I suggested an approach of finding the cursor position and displaying a div over the textarea when the user selects some text.
This approach works, however, as #anub has mentioned, div is sometimes displayed not right under the selected text, but a couple of pixels up or down - because it's position is determined based on the first user's click.
After a short search I found this post that describes how to find the position of the selected text in the textarea by creating a temporary div clone of the given textarea.
I've adopted the getCursorXY method from there and used it to position the popup.
Give it a try!
function getSel() {
// obtain the object reference for the textarea>
var txtarea = document.getElementById("mytextarea");
// obtain the index of the first selected character
var start = txtarea.selectionStart;
// obtain the index of the last selected character
var finish = txtarea.selectionEnd;
//obtain all Text
var allText = txtarea.value;
// obtain the selected text
var sel = Array(finish - start + 1).join("*");
//append te text;
var newText = allText.substring(0, start) + sel + allText.substring(finish, allText.length);
txtarea.value = newText;
$('#newpost').offset({top: 0, left: 0}).hide();
}
function closePopUp() {
$('#newpost').offset({top: 0, left: 0}).hide();
}
$(document).ready(function () {
closePopUp();
var newpost = $('#newpost');
$('#mytextarea').on('select', function (e) {
var txtarea = document.getElementById("mytextarea");
var start = txtarea.selectionStart;
var finish = txtarea.selectionEnd;
newpost.offset(getCursorXY(txtarea, start, 20)).show();
newpost.find('div').text(Array(finish - start + 1).join("*"));
});
});
const getCursorXY = (input, selectionPoint, offset) => {
const {
offsetLeft: inputX,
offsetTop: inputY,
} = input
// create a dummy element that will be a clone of our input
const div = document.createElement('div')
// get the computed style of the input and clone it onto the dummy element
const copyStyle = getComputedStyle(input)
for (const prop of copyStyle) {
div.style[prop] = copyStyle[prop]
}
// we need a character that will replace whitespace when filling our dummy element
// if it's a single line <input/>
const swap = '.'
const inputValue = input.tagName === 'INPUT' ? input.value.replace(/ /g, swap) : input.value
// set the div content to that of the textarea up until selection
const textContent = inputValue.substr(0, selectionPoint)
// set the text content of the dummy element div
div.textContent = textContent
if (input.tagName === 'TEXTAREA') div.style.height = 'auto'
// if a single line input then the div needs to be single line and not break out like a text area
if (input.tagName === 'INPUT') div.style.width = 'auto'
// create a marker element to obtain caret position
const span = document.createElement('span')
// give the span the textContent of remaining content so that the recreated dummy element
// is as close as possible
span.textContent = inputValue.substr(selectionPoint) || '.'
// append the span marker to the div
div.appendChild(span)
// append the dummy element to the body
document.body.appendChild(div)
// get the marker position, this is the caret position top and left relative to the input
const { offsetLeft: spanX, offsetTop: spanY } = span
// lastly, remove that dummy element
// NOTE:: can comment this out for debugging purposes if you want to see where that span is rendered
document.body.removeChild(div)
// return an object with the x and y of the caret. account for input positioning
// so that you don't need to wrap the input
return {
left: inputX + spanX,
top: inputY + spanY + offset,
}
}
#mytextarea {width: 600px; height: 200px; overflow:hidden; position:fixed}
#newpost {
position:absolute;
background-color:#ffffdc;
border:1px solid #DCDCDC;
border-radius:10px;
padding-right:5px;
width: auto;
height: 30px;
}
#newpost span {
cursor:pointer;
position: absolute;
top: 0;
right: 5px;
font-size: 22px;
}
#newpost div {
color:#0000ff;
padding:10px;
margin-right:10px;
width: auto;
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<body>
<textArea id="mytextarea"></textArea>
<div id="newpost">
<span onclick="closePopUp();">˟</span>
<div onclick="getSel()"></div>
</div>
</body>
</html>
I have encountered that problem while close the popup and reselecting another region, I resolved that by
function closePopUp() {
$('#newpost').offset({ top: 0, left: 0 }).hide();
}
check this out

Style first letter of each word in paragraph

I am trying to style the first letter of a paragraph using CSS and wanted to add some animation using greensock, But actually the requirement is to style the each word's first letter not just the first letter paragraph.
Whats the suggestion/ideas on this?
p{
font-size:150%;
color:#000000;
}
p::first-letter {
font-size: 200%;
color: #ff0000;
}
<p>Hello This Is The Title</p>
UPDATE I tried handling the following way (adding span tag and targeting first element of each span) but it doesn't work:
p span:nth-child(1)::first-letter {
font-size: 200%;
color: #ff0000;
}
use with split(" ") for create the array form string and forEach() is iterate the each word. Then slice(0,1) the cut first letter of the word then append with span .And add the css effect with span
var str = $('p').text().split(" ");
$('p').empty();
str.forEach(function(a) {
$('p').append(' <span>' + a.slice(0, 1) + '</span>' + a.slice(1))
})
p {
font-size: 150%;
color: #000000;
}
span {
font-size: 200%;
color: #ff0000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Hello This Is The Title</p>
const p = document.getElementById('text')
const styleMe = l => '<span class="styled">' + l + '</span>'
const newS = p.innerText.split(' ').map(w => w.split('').map((l,i) => (i === 0) ? styleMe(l) : l).join('')).join(' ')
p.innerHTML = newS
.styled {
color:red
}
<p id="text">Hello This Is The Title</p>
There is no css first-word css selector. So you can use jquery to achieve this.
Solution 1: To style only 1st word of a paragraph .
$(function() {
$('p').each(function() {
var text = this.innerHTML;
var firstSpaceIndex = text.indexOf(" ");
if (firstSpaceIndex > 0) {
var substrBefore = text.substring(0,firstSpaceIndex);
var substrAfter = text.substring(firstSpaceIndex, text.length)
var newText = '<span class="firstWord">' + substrBefore + '</span>' + substrAfter;
this.innerHTML = newText;
} else {
this.innerHTML = '<span class="firstWord">' + text + '</span>';
}
});
});
.firstWord{ color:red; font-size:20px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Styling the first word of pragraph.</p>
Solution 2 : Too style each first letter of paragraph line
$(document).ready(function() {
var words = $('p').text().split(' ');
var html = '';
$.each(words, function() {
html += '<span class="firstLetter">'+this.substring(0,1)+'</span>'+this.substring(1) + ' ';
});
$('p').html(html);
});
.firstLetter{ color:red; font-size:20px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Styling each first letter of the word in pragraph.</p>
What you are looking for is a pseudo-element that doesn't exist. There is :first-letter and :first-line, but no :first-letter-every-word.
The easiest option would be to wrap the first letter of each word in a <span>. Another option would be to try a javascript solution.

word count textarea jquery script initial text count onload issue

I'm using a word count textarea jquery script and I'm trying to work out how to update the word count onload to e.g. 2 from the preset text area "this example" to start with.
(it currently shows 0)
I can set the focus on it and move the cursor but I don't know how to update it initially, any ideas?
HTML
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript" src="js/jQuery.textareaCounter.c.js"></script>
<textarea id="txtarea" name="text" rows="7" cols="120">this example</textarea>
<script type="text/javascript">
$("textarea").textareaCounter();
document.getElementById('txtarea').focus();
var val = document.getElementById('txtarea').value; //store the value of the element
document.getElementById('txtarea').value = ''; //clear the value of the element
document.getElementById('txtarea').value = val; //set that value back. so cursor is at end.
</script>
jquery.min.js contains:-
(function(a){a.fn.textareaCounter=function(b){var c={limit:10};var b=a.extend(c,b);return this.each(function(){var c,d,e,f;c=a(this);c.after('<span style="font-size: 11px; clear: both; margin-top: 3px; display: block;" id="counter-text">Max. '+b.limit+" words</span>");c.keyup(function(){d=c.val();if(d===""){e=0}else{e=a.trim(d).split(" ").length}if(e>b.limit){a("#counter-text").html('<span style="color: #DD0000;">0 words left</span>');f=a.trim(d).split(" ",b.limit);f=f.join(" ");a(this).val(f)}else{a("#counter-text").html(b.limit-e+" words left")}})})}})(jQuery)
jQuery.textareaCounter.c.js contains:-
(function(a) {
a.fn.textareaCounter = function(b) {
var c = {
limit: 10
};
var b = a.extend(c, b);
return this.each(function() {
var c, d, e, f;
c = a(this);
c.after('<span style="font-size: 11px; clear: both; margin-top: 3px; display: block;" id="counter-text">' + "0 words</span>");
c.keyup(function() {
d = c.val();
if (d === "") {
e = 0
} else {
e = d.replace(/^[\s,.;]+/, "").replace(/[\s,.;]+$/, "").split(/[\s,.;]+/).length;
}
if (e > b.limit) {
// a("#counter-text").html('<span style="color: #DD0000;">0 words left</span>');
// f=a.trim(d).split(" ",b.limit);
// f=f.join(" ");
// a(this).val(f)
a("#counter-text").html(e + " words ")
document.myform.numwords.value = e;
} else {
a("#counter-text").html(e + " words ")
document.myform.numwords.value = e;
}
});
});
}
})
(jQuery)
This is what I changed in jQuery.textareaCounter.c.js:
var initCount = c.text().split(" ").length;
if(initCount < 2){initCount=0;}
c.after('<span style="font-size: 11px; clear: both; margin-top: 3px; display: block;" id="counter-text">' + initCount +" words</span>");
Here is the JSFiddle demo
You can fire a keyup event during initialization to trigger the update:
<script type="text/javascript">
$("textarea").textareaCounter();
document.getElementById('txtarea').focus();
var val = document.getElementById('txtarea').value; //store the value of the element
document.getElementById('txtarea').value = ''; //clear the value of the element
document.getElementById('txtarea').value = val; //set that value back. so cursor is at end.
// init word count
$("textarea")[0].dispatchEvent(new Event('keyup'));
</script>
//Function to show maxlength of Textarea
document.getElementById("textArea").addEventListener("keyup",function(){
var textAreaValue = document.getElementById("textArea").value;
var show = (250 - (textAreaValue.length));
document.getElementById('count').innerHTML = show + " characters remaining";
});

Categories

Resources