prevent word counting of multiple spaces between words in textarea (html / javascript) - textarea

I have a textarea id="task", which has a word counter id="count" connected. The counter is set to count spaces between words, so a word is only accounted for if one puts a space after it. However, if for whatever reason one finds themself in a frenzy of hitting the spacebar, each and every space is then counted as a word which thwarts the final count. Below is the code for you to see for yourselves.
What I am asking is as follows:
1) Is there a way to count only one space after each word and ignore multiple spaces?
2) Can I prevent multiple spaces in the textarea?
Since I am suspecting that the solution dwells within the realm of javascript, I kindly ask for your help as I am still a noob. I will be grateful for any suggestions, be it 1) or 2).
HTML:
<div class="options">
Task:
<textarea type="text" rows="10" cols="97" name="task" id="task" onkeypress="onTestChange01();"
autocorrect="off" spellcheck="false"></textarea>
<p>Word count: <textarea cols="10" name="count" id="count" readonly>0</textarea></p>
</div>
JAVASCRIPT:
// WORD COUNTER FUNCTION
var count = document.getElementById('count');
var input = document.getElementById('task');
input.addEventListener('keyup', function(e){
wordCounter(e.target.value);
});
function wordCounter(text) {
var text = input.value;
var wordCount = 0;
for (var i = 0; i <= text.length; i++) {
if (text.charAt(i) == ' ') {
wordCount++;
}
}
count.innerText = wordCount;
}
I tried fiddling with the JS function and its values.
Also, I found a function to change multiple spaces to one space, which did not work as expected and it disrupted the original function and the counting.
Finally, I tried preventing 'space' altogether in the textarea properties but all in vain.
Looking forward to your ideas. Thanks.
tk

Related

Svelte: How to bind a formatted input field to a property

First of all: Svelte is still new to me. I hope the question is not too trivial.
Within a simple component I want to use the content of a formatted input field for a calculation.
For example:
In the input field a Euro amount should be displayed formatted (1.000).
Next to it a text with the amount plus VAT should be displayed (1.190).
How I do this without formatting is clear to me. The example looks like this:
export let net;
export let vat;
$: gross = net + (net * vat / 100);
$: grossPretty = gross.toLocaleString('de-DE',{ minimumFractionDigits: 0, maximumFractionDigits: 0 });
with a simple markup like this:
<form>
<label>Net amount</label>
<input type="text" step="any" bind:value={net} placeholder="Net amount">
</form>
<div>
Gros = {grossPretty} €
</div>
In vue i used a computed property. Its getter delivers the formatted string and its setter takes the formatted string and saves the raw value.
(In data() I define net, in the computed properties i define netInput. The input field uses netInput as v-model).
It looks like this:
netInput: {
get(){
return this.net.toLocaleString('de-DE',{ minimumFractionDigits: 0, maximumFractionDigits: 0 });
},
set(s){
s = s.replace(/[\D\s._-]+/g, "");
this.net = Number(s);
}
}
How can I handle it in svelte?
You can do something somewhat similar, you create another computed variable that stores the deformatted string from the input field and is used in the calculation instead of the direct input
export let net;
export let vat;
$: net_plain = Number(net.replace(/[\D\s._-]+/g, ""));
$: gross = net_plain + (net_plain * vat / 100);
$: grossPretty = gross.toLocaleString('de-DE',{ minimumFractionDigits: 0, maximumFractionDigits: 0 });
But maybe find a better name for the variable :)
Thanks to Stephane Vanraes I found a solution.
It has not the charm of the vue approach but it's ok. First I inserted 'net_plain'. To have the input field formatted during input, I added an event listener for the keyup event.
<input type="text" step="any" bind:value={net} on:keyup={handleKeyUp} placeholder="Net amount">
The event is handled from the function handleKeyUp as follows:
function handleKeyUp(event){
if ( window.getSelection().toString() !== '' ) {
return;
}
// ignore arrow keys
let arrows = [38,40,37,39];
if ( arrows.includes( event.keyCode)) {
return;
}
let input = event.target.value.replace(/[\D\s._-]+/g, "");
input = input ? parseInt( input, 10 ) : 0;
event.target.value = ( input === 0 ) ? "" : input.toLocaleString( "de-DE" );
}
BUT: If anyone has a solution using getter and setter I would appreciate the anwer!

Implementing preview for markdown text

I am working on Ruby on Rails project and I have implemented markdown syntax for some text descriptions in my project using redcarpet gem.
It works like charm allowing to convert markdown text to HTML as simply as
<%= markdown some_text_variable %>
But now I want to implement preview feature rendering just small part of the full text.
The following naive construction
<%= markdown some_text_variable[0..preview_length] %>
will not work because it can easily break down MD syntax resulting in confusing constructions (imagine, for example, spliting original string on the half of image link).
I came up with
<%= markdown some_text_variable[0..preview_length].split(/\r?\n/)[0..-2].join("\r\n")) %>
but it does not deal, for example, with code blocks.
Is there any way to implement such kind of preview for MD text?
Using markdown.js and / or showdown should work. Here's a StackO with the same question and answer. I personally have used showdown in an Ember app before to render a live preview of the text as it's being typed (via 2-way data binding), and it worked flawlessly.
In the fiddle below, I wrote a little Showdown parser that takes in a string of markdown, splits it on a newline (returns an array of tags), and iterates through the array. On each iteration, it removes the tags, checks the length of the resulting string, and then compares it to the max character count for the preview. Once the next iteration surpasses the max character count, it returns the preview. The do loop ensures that you will always get at least one blob of html as a preview.
Fiddle
$(function() {
var converter = new Showdown.converter();
var previewMax = 200;
$('button').click(function() {
var content = $('#markdown').val(),
charCount = 0,
i = 0,
output = '';
if (!content) {
return $('div.preview').html("Please enter some text.");
}
var mark = converter.makeHtml(content);
var mark_arr = mark.split('\n');
while (charCount < previewMax) {
var html = mark_arr[i];
var text = htmlStrip(html);
if ((charCount + text.length) > previewMax) {
var overflow = (charCount + text.length) - previewMax;
var clipAmount = text.length - overflow;
html = jQuery.truncate(mark_arr[i], { length: clipAmount });
}
output += html;
charCount += text.length;
i++;
};
$('div.preview').html(output);
$('div.full').html(mark);
});
function htmlStrip (html) {
var div = document.createElement('div');
div.innerHTML = html;
var text = div.textContent || div.innerText || "";
return text;
}
});
REVISION
I updated the function using jQuery Truncate to cut the final string into an elipses so that all your previews are the same length as the others. Also, I realized that the original function returned a long string of undefined' over and over when no text was entered, so there is a check to eliminate that. Since this loop will always return at least one html item now, I changed the do loop to a while loop for easier reading. Finally, if you want your truncation to always end at a word boundary, pass the words: true option when you call it. Obviously, this will not give you the same level of truncation for every preview, but it will improve legibility. That's it!
I want to share my preview version it was quite simple with showdown.js and prism.js syntax highlighting.
Prism.js is syntaxing easily with JavaScript and CSS. All you need to pick specific languages and download it to assets folder. Or you can specify it to specific pages.
This is going to happen in realtime preview, in a form.
In Rails form:
<div class="col-md-12">
<div class="form-group">
<%= f.label :body %>
<%= f.text_area :body, class: "form-control", rows: 10 %>
</div>
</div>
<div class="col-md-12">
<h1> Preview Markdown </h1>
<div class="form-group markdownOutput"></div>
</div>
And add this script right below a form page.
<script>
function mkdown(){
var converter = new showdown.Converter(),
$post_body = $("#post_body");
// This line will keep adding new rows for textarea.
function postBodyLengthDetector(post_body){
var lines = post_body.val().split("\n");
post_body.prop('rows', lines.length+5);
}
// Textarea rows in default '10', when focusing on this. It will expand.
$post_body.focus(function(){
postBodyLengthDetector($(this));
$('.markdownOutput').html(converter.makeHtml($post_body.val()));
});
// All simple magic goes here, each time when texting anything into textarea
//it will be generated to markdown. You are able to see preview right below of textarea.
$post_body.keyup(function() {
postBodyLengthDetector($(this));
var value = $( this ).val(),
html = converter.makeHtml(value);
$('.markdownOutput').html(html);
});
}
$(mkdown);
$(document).on("turbolinks:load", mkdown);
</script>

onFullSync action, show updated info - DHTMLX Grid + RoR

I have a Ruby on Rails project where I use a DHTMLX Grid.
Is there a way of showing, using the event handler "onFullSync" provided by the grid API, to show updated data?
Let me explain a little better... I know I can do something like:
dp.attachEvent("onFullSync", function(){
alert("update complete");
})
But what I want is something more complex. I want to, after each completed update, alter a div adding the information like this:
Field 2 was updated to XYZ and field 3 was updated to XER on line X
Field 1 was updated to 123 and field 3 was updated to XSD on line Y
Is this possible?
Thanks
There is a onAfterUpdate event that can be used similar to onFullSync
http://docs.dhtmlx.com/api__dataprocessor_onafterupdate_event.html
It will fire after each data saving operation ( if you are saving 5 rows - it will fire 5 times )
Still, info about updated columns will not be available here.
Also, you can try onEditCell event of grid. It fires after changing data in db, but before real saving in database. Here you can get all necessary info - row, column, old value and new value.
http://docs.dhtmlx.com/api__link__dhtmlxtreegrid_oneditcell_event.html
So, what I end up doing was:
After creating the grid I created an array:
var samples = [];
Then, as per #Aquatic suggestion, I added to "onEditCell" event the following line:
samples[samples.length] = grid.cells(rId, 5).getValue();
This allowed me to add to the array the value present on column 5 of the row changed. Then, on "onFullSync" event I hide or show the div created on the view with the messages (I distinguish if it's on row or more changed on the grid).
//Deals with messages after update
dp.attachEvent("onFullSync", function(){
unique_samples = uniq_fast(samples.sort());
if (unique_samples.length == 1){
$('#updated-samples').text("");
$(".messages").show();
$('#updated-samples').text("A seguinte amostra foi actualizada: " + unique_samples[0]);
//to clear the array
samples = [];
} else if (unique_samples.length > 1){
$('#updated-samples').text("");
$(".messages").show();
$('#updated-samples').text("As seguintes amostras foram actualizadas: " + unique_samples.sort().join(", "));
//to clear the array
samples = [];
} else {
$('#updated-samples').text("");
$(".messages").hide();
//to clear the array
samples = [];
}
})
The problem with using "onEditCell" is that everytime a field is changed on that row I get a repeated value on my "samples" array, I I had to remove duplicate from that array. For that I used one of the suggestions at this answer
// remove duplicates in array
function uniq_fast(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for(var i = 0; i < len; i++) {
var item = a[i];
if(seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
}
Then I have on the beginning of the view, to show the messages:
<div class="alert alert-success messages" id="updated-samples">
And that's it. I could be not the most efficient way but it works for what I wanted. I will leave the question open a few more days to see if any other option appears.

set maxlength in textarea

I want to set maxlength in textarea. I have defined maxlength property in textarea but it seems to be of no use. Pls help. My code:
<html:textarea styleClass="textarea" maxlength="2100" cols="60" rows="3">
Try this javascript function:
$(function(){
$("#id").keypress(function() {
var maxlen = 100; //length as you desire
if ($(this).val().length > maxlen) {
return false;
}
})
});
You have to write code for two events, keyup and copy paste so try this:
onKeyPress = "return ( this.value.length < 2100 );", onPaste = "return onTextAreaPaste(this,2100)"
Here is Js:
function onTextAreaPaste(textArea,size) {
var length = textArea.value.length;
if(window.clipboardData!=undefined)
length = textArea.value.length + window.clipboardData.getData('Text').length;
return length < size;
}
I recently came across a problem with textarea maxlength attribute because the newlines where considered as 1 in Firefox, and 2 in IE and Chrome. So I decide to go for JavaScript for handling this.
Here is how I handle the max length, its a jquery plugin, very easy to set and there's no problem with the different behaviors of browsers, plus give you a feedback of the characters used.

ASP.NET MVC Razor extra whitespace rendered

In Asp.net MVC, Razor inserts extra space between text blocks. I want to render a list this way: "1, 2, 3" but get "1 , 2 , 3".
#for (int i = 1; i < 3; i++)
{
<text>#i</text>
if (i != 2)
{
<text>, </text>
}
}
Is there any ways to remove extra whitespace ?
I want to render a list this way: "1, 2, 3"
Quick and dirty:
#string.Join(", ", Enumerable.Range(1, 3))
Obviously a custom helper seems more appropriate to the job of formatting something in the view:
public static class HtmlExtensions
{
public static IHtmlString FormatList(this HtmlHelper html, IEnumerable<int> list)
{
return MvcHtmlString.Create(string.Join(", ", list));
}
}
and then simply:
#Html.FormatList(Model.MyList)
You are seeing the extra whitespace between the number and the comma because your razor template includes a line break (which displays as whitespace in the browser) between the number and the comma:
#for (int i = 1; i < 3; i++)
{
<text>#i</text> >LINE BREAK HERE<
if (i != 2)
{
<text>, </text>
}
}
I like Darin's answer, and I would suggest removing your loop and replacing it with a more declarative statement, but if you don't want to go that far, try at least removing the line break:
#for (int i = 1; i < 3; i++)
{
<text>#i</text>if (i != 2){<text>, </text>}
}
Instead of writing out bits of text in different places each time round the loop, you could accumulate all the text in a StringBuilder, then outside the loop do #stringBuilderObject.ToString().
The problem is with the source that is generated. When you look at the actual source you get:
1
,
2
,
3
As you can see there is a lot of white space in there which browsers collapse down to a single space (look at the definition for normal).
Using a StringBuilder or string.Join is the way to fix this if all you're doing is outputting these three numbers. But if you're trying to do something else and this is a simplified example then see this blog post for a way of doing it using ol/ul and lis.
I might assume that it is not issue of Razor, but rather element is rendered with some margings.
Open FireBug (or Chrome or whatever) and see that it is really markup issue.
In you css file try to add
text { margin: 0 }

Resources