Getting textarea to count line breaks properly - javascript

I've been banging my head against a wall trying to work out what the best way to get a character countdown from a textarea. I've create this jsfiddle but if I paste in 4000 characters from lipsum.com then it says it's 12 characters over. I know this is because of the line breaks, but I'm unsure on how to get it to work correctly, and consistently across browsers.
$('textarea').on('keyup', function() {
characterCount(this);
});
$('textarea:not(:empty)').each(function() {
characterCount(this);
});
function characterCount(that) {
var $this = $(that),
$maxLength = $this.attr('data-val-length-max'),
$lengthOfText = $this.val().length,
$charCountEl = $this.closest('.form-group').find('.maxchar-count');
if($maxLength) {
$($charCountEl).text($maxLength - $lengthOfText);
}
if($lengthOfText > $maxLength) {
$charCountEl.addClass('has-error');
} else {
$charCountEl.removeClass('has-error');
}
}
And the markup
<div class="form-group">
<textarea rows="5" data-val-length-max="4000"></textarea>
<div>
<span class="maxchar-count">4000</span>
</div>
</div>
I've seen some similar questions but yet to find an answer that works for me.
Thanks
Henry

Try
$lengthOfText = $this.val().replace(/\n/g, '').length
Instead of
$lengthOfText = $this.val().length
This way you'll get rid of new line characters in textarea.
If you want all kind of spacing avoided from total count, you can use
$lengthOfText = $this.val().replace(/\s/g, '').length
Hope this helps.

Related

How to detect text language with jQuery and XRegExp to display mixed RTL and LTR text correctly

I'm trying to display a Twitter feed in a WordPress site. My client tweets in English and in Arabic and sometimes in a combination of the two languages. I need to detect the language and add the class 'rtl' to Arabic tweets and also those tweets where the content is predominately in Arabic. I'm using a plugin which strips the Twitter iso_language_code metadata.
When attempting this on a previous development site a few years ago, I remember successfully using a variation of Tristan's solution found here:
How to detect that text typed in text-area is RTL
Unfortunately it no longer seems to work.
Tristan's jsfiddle no longer works either.
I'm using this resource:
http://cdnjs.cloudflare.com/ajax/libs/xregexp/2.0.0/xregexp-min.js
and this script:
jQuery(document).ready(function($) {
$('p').each(function() {
if(isRTL($(this).text()))
$(this).addClass('rtl');
});
function isRTL(str) {
var isArabic = XRegExp('[\\p{Arabic}]');
var isLatin = XRegExp('[\\p{Latin}]');
var partLatin = 0;
var partArabic = 0;
var rtlIndex = 0;
var isRTL = false;
for(i=0;i<str.length;i++){
if(isLatin.test(str[i]))
partLatin++;
if(isArabic.test(str[i]))
partArabic++;
}
rtlIndex = partArabic/(partLatin + partArabic);
if(rtlIndex > .5) {
isRTL = true;
}
return isRTL;
}
});
Can anyone help me with where I'm going wrong?
Many thanks,
Phil
Update
I've managed to get a partial solution working:
jQuery(document).ready(function($) {
var arabic = /[\u0600-\u06FF]/;
$('p').each(function() {
if (arabic.test($(this).text())) {
$(this).addClass( "rtl" ).attr('style','text-align:right;direction:rtl');
}
else {
$(this).addClass( "ltr" ).attr('style','text-align:left;direction:ltr');
}
});
});
My apologies in advance - I'm very much a beginner at this.
I've done a jsfiddle here:
http://jsfiddle.net/philnicholl/4xn6jftw
This works if the text is all Arabic or all English but a single word of Arabic in an English tweet will mess things up.
Bizarely, when I added this script to a real world WordPress test, it produced exactly the opposite result from what I wanted, as in Arablic paragraphs and tweets were given the LTR class and styling and English text given RTL.
Reversing the if else gives the right result.
Any help would be greatly appreciated.
Thank you again.
Phil
You can use regular expression to determine if contain only Arabic letters
$('p').each(function() {
if(isRTL($(this).text()))
$(this).addClass('rtl');
});
function isRTL(str) {
return /^[\u0600-\u06FF]/.test(str);
}
p.rtl {
direction: rtl;
}
p.ltr {
direction: ltr;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Hello World</p>
<p>مرحبا بالعالم</p>
<p>Hello World مرحبا بالعالم</p>
I suggest another solution if you are using wordpress you can assign variable in the head of header.php or at the end of your footer.php file
you can assign new variable by check wordpress function is_rtl()
example:
Js code in header.php or footer.php between < script > tag
<?php if ( is_rtl() ) :?>
var is_rtl = true
<php else:?>
var is_rtl = false;
<?php endif;?>
Then in your js file use it to check
jQuery(document).ready(function($) {
$('p').each(function() {
if(is_rtl)
$(this).addClass('rtl');
});

Insert character at Cursor position in VUE JS

I have been trying to insert emoji in textarea exactly where the cursor is at. I looked around how tos in the web could not find anything specific in VUE JS. Most of them are in plain JS.
I have this Code
<div class="picker" v-show="showPicker">
<click-outside :handler="handleClickOutside">
<picker
set ="messenger"
title="Pick your emoji…"
emoji="point_up"
#click="addEmoji"
:emoji-size="16"
>
</picker>
</click-outside>
</div>
<textarea id="greeting_text_input" class="form-control"
type="text"
v-model="greeting_text"
rows="8"
required
placeholder="Hi {first-name}! Welcome to our bot. Click on the ‘Get
Started’ button to begin
">
</textarea>
My Method
addEmoji(emoji){
this.greeting_text += emoji.native;
this.showPicker = !this.showPicker;
}
Obviously, this code will add the character (emoji, in my case) to the last of the string. I need a pure vuejs solution for this.
What would be the best practise for this kind of problem in Vue? as there are few solutions in the web that based either in vanilla JS or Jquery.
Two steps:
1 get textarea element using a vue-way:
1.1 Add ref attrbute to textarea tag in your template code:
<textarea ref="ta"></textarea>
1.2 get this element after mounted hook of this component:
let textarea = this.$refs.ta
2 get cursor position of textarea element.
let cursorPosition = textarea.selectionStart
Here is reference: ref
<!-- tag -->
<textarea ref="yourTextarea" v-model.trim="txtContent" ......></textarea>
// methods:
insertSomething: function(insert) {
const self = this;
var tArea = this.$refs.yourTextarea;
// filter:
if (0 == insert) {
return;
}
if (0 == cursorPos) {
return;
}
// get cursor's position:
var startPos = tArea.selectionStart,
endPos = tArea.selectionEnd,
cursorPos = startPos,
tmpStr = tArea.value;
// insert:
self.txtContent = tmpStr.substring(0, startPos) + insert + tmpStr.substring(endPos, tmpStr.length);
// move cursor:
setTimeout(() => {
cursorPos += insert.length;
tArea.selectionStart = tArea.selectionEnd = cursorPos;
}, 10);
}
I learned about setSelectionRange from a different question, and I used it to handle credit card number input. I will show my solution here so a person can perhaps become inspired by it.
template:
<input
ref="input"
v-model="value"
#input="handleChange"
>
instance methods:
data() {
return {
lastValue: '',
}
},
methods: {
setCursorPosition(el, pos) {
el.focus();
el.setSelectionRange(pos, pos);
},
handleChange() {
// handle backspace event
if (this.value.length < this.lastValue.length) {
this.lastValue = this.value;
this.$emit('input-changed', this.value);
return;
}
// handle value-edit event
if (this.$refs.input.selectionStart < this.value.length) {
const startPos = this.$refs.input.selectionStart;
this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
this.$nextTick(() => this.setCursorPosition(this.$refs.input, startPos));
this.lastValue = this.value;
this.$emit('input-changed', this.value);
return;
}
// handle everything else
this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
this.lastValue = this.value;
this.$emit('input-changed', this.value);
},
},
The goal with the above code is to add spaces into a credit card input, so 1234123412341234 is automatically reformatted to 1234 1234 1234 1234. A person venturing into this territory will notice that problems arise when editing the input value.
You can see there are three conditions in my sample above. The last one is the default which simply reformats the current value with a 2-step combo: remove all spaces then adds a space every 4th character.
If you comment out the two if blocks, you can watch the problems emerge.
The first if block handles the backspace event. As you can see, every time the input changes, the value is captured as this.lastValue. When you press backspace, the goal of the first condition is to NOT run the regex. In my opinion, this is better UX. If you comment out that condition, you can see.
The second if block handles the editing events. A good way to test it, is to enter a valid CC but omit the 3rd character, so that everything is off by one. Then add the character in. Everything should be good. Likewise if you backspace multiple characters out. The goal of the second condition is to properly manage the cursor position (or caret position if you prefer that nomenclature).
You can safely delete the first condition and all references to lastValue and the code will still work. This is arguably simpler but worse UX.

show div base on specific input text in multiple strings

Jquery question...So this is simple find the value if match from keyup show the button. But I want to ask for 2 questions to improve this:
Fiddle
$("#test").keyup(function () {
$("#yeah").css("display", this.value == "test" ? "block" : "none");
});
Where im stuck is:
Type test = good
type test here = nothing
I want to keep the display no matter how the string is place as long as its placed it will not go away
So Ex: I want to do some tests - will show
And the other question is how do you do multiple strings? like if i want to show it on test and something like test2?
Use a regular expression:
$("#test").keyup(function() {
$("#yeah").toggle(/test|something/.test(this.value));
});
#yeah {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="test">
<div id="yeah">
Yeah!
</div>
This regexp matches anything with test or something in it.
Here is another answer for your both questions.
$('input[name=amount]').keyup(function() {
var testStr = $(this).val();
var testStr2 = 'test';
var testStr3 = 'texts';
if (testStr.indexOf(testStr2) != -1 || testStr.indexOf(testStr3) != -1 )
$('#yeah').show();
else
$('#yeah').hide();
});

Jquery changing css and form data

I'm making a form where the users fill in a title which they can size up or down. I have a preview window that changes when they click on the "size up button". But I want to store this in a hidden form to get the value when posting.
HTML - FORM
<input id="title" name="title" />
<input id="titlesize" name="titlesize" value="50" />
<div id="sizeUp">Size up!</div>
HTML - PREVIEW WINDOW
<h2 id="titlepreview" style="font-size: 50px;">Title</h2>
Javascript
$(document).ready(function() {
$("#sizeUp").click(function() {
$("#titlepreview").css("font-size","+=5"),
$("#titlesize").val("+=5"); // <-- Here's the problem
});
Any ideas?
Try this using the .val( function(index, value) ):
$(document).ready(function () {
$("#sizeUp").click(function () {
$("#titlepreview").css("font-size", "+=5"),
$("#titlesize").val(function (index, value) {
return parseInt(value, 10) + 5;
});
});
});
FIDDLE DEMO
You need parseInt to handle strings as numbers.
$("#sizeUp").click(function () {
var obj = $("#titlesize");
var value = parseInt(obj.val());
obj.val(value + 5);
});
OK, I'm not entirely sure where the problem is here, but here's a way of going about it anyway:
If you want a range of sizes so you can't get a title too big or small, you could (while this is long-winded) make a css class for each size.
Then, you could use JqueryUI's .addClass() and .removeClass. With these you could do something like:
$("#sizeupbutton").click(function(e){
$(#title).removeClass("size45");
$(#title).addClass("size50");
});
Sorry if I've completely got your question wrong, but good luck!
Edit: OK, now i think i understand what you want, I would advise you check out Vucko's answer below.
you can get variable like this:
$(document).ready(function () {
$("#sizeUp").click(function () {
$("#titlepreview").css("font-size", "+=5");
var up=parseInt(($("#titlepreview").css("font-size")),10);
$("#titlesize").val(up);
});
});
example:fiddle

update charcount of multiple divs with single function

I am trying to use a code snippet I found online to implement charcount. It works for one single text area. I have multiple text areas with different count limits. Here is the code that works for one single form.
Javascript:
function countChar(val,count,focus){
var len = val.value.length;
var lim=count;
var focussed=focus;
if (len >= lim) {
$('#charNum').text(lim - len);
$('#charNum').addClass('exceeded');
/* val.value = val.value.substring(0, lim);*/
}else {
if(focussed===0){
$('#charNum').html('<a> </a>');
}
else {
$('#charNum').text(lim - len);
$('#charNum').removeClass('exceeded');
}
}
};
HTML:
<div id='charNum' class='counter'> </div>
<textarea id='description' name='description' onkeyup=\"countChar(this,200,1)\" onblur=\"countChar(this,200,0)\" rows='10' cols='20'></textarea>
If I have two text areas, how can I modify this code to work ? I know how to get the id of the div in the script, But I dont know how to correctly update the counter div, say #charNum1, and #charNum2. Appreciate some hints. Thanks
EDIT:
I was thinking, I can name the counter div as "Charnum+divName" if that helps
If you attach your event handler(s) with jQuery you can use this within the handler to refer to whichever element the event was triggered on, thus avoiding having to hardcode element ids inside your function.
I'd suggest adding an attribute with the max chars allowed and removing the inline event handlers:
<div id='charNum' class='counter'> </div>
<textarea id='description' name='description' data-maxChars="200" rows='10' cols='20'></textarea>
<div id='charNum2' class='counter'> </div>
<textarea id='otherfield' name='otherfield' data-maxChars="400" rows='10' cols='20'></textarea>
Then:
$(document).ready(function() {
$("textarea[data-maxChars]").on("keyup blur", function(e) {
var $this = $(this),
$counter = $this.prev(),
len = $this.val().length,
maxChars = +$this.attr("data-maxChars");
$counter.text(maxChars - len).toggleClass("exceeded", len > maxChars);
});
});
Demo: http://jsfiddle.net/nnnnnn/GTyW3/
If each textarea is going to have it's own div, you can just add an extra parameter to the countChar function which would be the name of the div. So you'd have something like:
function countChar(val,count,focus, charCountDiv)
then, instead of hardcoding it in the function, the jQuery would be:
$(charCountDiv)
That should do what I think you are looking to do.

Categories