How to input cents with mottie keyboard and keep them there? - javascript

I am going crazy over here... I've invested over 16 hours trying to get this thing to work, if anyone has any clue of the reason of this evil behavior please advice..
I have multiple inputs of type number inside a form where I attached the keyboard to each input like this:
$('.amount').keyboard({
layout: 'custom',
customLayout : {
'normal' : ['1 2 3', '4 5 6', '7 8 9','{clear} 0 {bksp}','{accept}']
},
display : {
'accept' : 'Confirm:Confirm (Shift-Enter)',
'bksp' : 'Delete:Delete',
'clear': 'Clear:Clear'
},
beforeVisible: function(e, keyboard, el) {
$("#"+keyboard.$keyboard[0].id).addClass("hide-me");
},
restrictInput: true,
preventPaste: true,
autoAccept: true,
usePreview: false,
useWheel: false,
repeatRate: 0,
// this function is so I can display cents in the input
// there is no decimal in the keyboard as part of the requirements
change: function(e, keyboard, el) {
if (el.value === null || el.value === "") {
el.value = "0.00";
}
el.value = parseInt(el.value);
el.value = el.value * 0.01;
},
// this function is so I can display cents in the inputs
// there is no decimal in the keyboard as part of the requirements
accepted: function(e, keyboard, el) {
if (el.value === null || el.value === "") {
el.value = "0.00";
}
el.value = parseInt(el.value);
el.value = el.value * 0.01;
},
caretToEnd: 'true',
maxLength : '20',
css: {
container: 'center-block dropdown-menu custom-keypad',
buttonDefault: 'btn-kb',
buttonHover: 'btn-primary',
buttonAction: 'active',
buttonDisabled: 'disabled'
}
});
Keyboard pops up as it should, I can see the decimals in my input correctly as I type and as I confirm my input. My goal is to sum all the input.val() and validate them as soon any change happens on the form. That functionality to do that is like this:
$('form').on('change', '.amount', function () {
var balance = NUMBER;
var sum = 0;
$(".amount").each(function (){
var valTotal = Number($(this).val());
if (!isNaN(valTotal)) {
sum += valTotal;
}
});
if (sum > balance) {
//stuff happens
}
});//.end of form
Here is where the problem starts, when I go to sum the inputs, my decimals disappear! what was 22.22 is now 2222 so my sum is wrong, causing my sum to be always larger that my balance. I tried to create a fiddle but it won't pop the keyboard on the result box so I can't show you a live example..
This are the CDN's I'm using:
https://cdnjs.cloudflare.com/ajax/libs/virtual-keyboard/1.26.17/js/jquery.keyboard.extension-all.min.js
https://cdnjs.cloudflare.com/ajax/libs/virtual-keyboard/1.26.17/js/jquery.keyboard.min.js
PLEASE ADVICE!!

So I got in touch with the creator of the plugin and he was kind enough to answer my question via email. His solution worked perfectly!
You can see the fiddle right here..
http://jsfiddle.net/Mottie/egb3a1sk/2506/
/* VIRTUAL KEYBOARD DEMO - https://github.com/Mottie/Keyboard */
$(function() {
// this function is so I can display cents in the input
// there is no decimal in the keyboard as part of the requirements
function convert(el) {
var value = el.value;
if (el.value === null || el.value === "") {
value = "0.00";
}
value = parseInt(value, 10);
value = value * 0.01;
el.value = value.toFixed(2);
}
NUMBER = 100;
function sum() {
var balance = NUMBER;
var sum = 0;
$(".amount:not(:disabled)").each(function() {
var valTotal = Number($(this).val());
if (!isNaN(valTotal)) {
sum += valTotal;
}
});
if (sum > balance) {
//stuff happens
}
$('.sum').text(sum);
}
$('.amount').keyboard({
layout: 'custom',
customLayout: {
'normal': ['1 2 3', '4 5 6', '7 8 9', '{clear} 0 {bksp}', '{accept}']
},
display: {
'accept': 'Confirm:Confirm (Shift-Enter)',
'bksp': 'Delete:Delete',
'clear': 'Clear:Clear'
},
beforeVisible: function(e, keyboard, el) {
$("#" + keyboard.$keyboard[0].id).addClass("hide-me");
},
restrictInput: true,
preventPaste: true,
autoAccept: true,
usePreview: false,
useWheel: false,
repeatRate: 0,
change: function(e, keyboard, el) {
convert(el);
},
accepted: function(e, keyboard, el) {
convert(el);
sum();
},
caretToEnd: 'true',
maxLength: '20',
css: {
container: 'center-block dropdown-menu custom-keypad',
buttonDefault: 'btn-kb',
buttonHover: 'btn-primary',
buttonAction: 'active',
buttonDisabled: 'disabled'
}
});
});
The main issue was that the $('.amount') selector was including a hidden duplicate input so he changed it to $(".amount:not(:disabled)")
And he also performed the sum() operation right after the formatting happened on 'accepted'
Worked perfectly =)

Related

How to add units to roundslider's values?

I have a roundslider widget and I am trying to add units to its values, when value = 0-999 then Hz unit should show up next to the value, and when value = 1000-999999 then it is KHz ... so on so forth.
This is my original slider:
$("#slider").roundSlider({
sliderType: "min-range",
radius: 150,
handleSize: "+12",
mouseScrollAction: true,
min: 0,
max: 100000000,
value: 0, // default value at start
change: function(event) {
$.getJSON('/set_Frequency/' + event.value);
}
});
And here is my non working attempt:
$("#slider").roundSlider({
sliderType: "min-range",
radius: 150,
handleSize: "+12",
mouseScrollAction: true,
min: 0,
max: 100000000,
value: 0, // default value at start
//change: function(event) { $.getJSON('/valueofslider', {slide1_val: event.value}); }
change: function(event) {
var value = event.value, content;
if (value <= 999) content = "Hz";
else if (value <= 999999) content = "KHz";
else if (value >= 1000000) content = "MHz";
else content = "GHz";
$.getJSON('/set_Frequency/' + event.value + content);
}
});
Can you help please?
For any formatting you can use the tooltipFormat event. I hope for your scenario you want to select any value from Hz - GHz.
I have updated the demo based on your required logic. Here you can select the value from 1 kHz to 100 MHz.
DEMO
And, if you can show your actual use-case scenario then I can do a better suggestion for your requirement.

How to restrict number of characters per line in textarea?

I have one Ext JS TextArea. There I want to restrict my characters to 15 characters in each line and total number of lines should be not more than 10.
What I am tring to do here is
function(){
var myValue = this.getValue();
var myValueData = myValue.split(/\r*\n/);
myValueData.length = 10;
}
Ideally it should ommit all the lines after line number 10, but is not happening. Also how to restrict only upto 15 characters per line?
You can give that one a try, not perfect, but should work.
Maybe its be better instead using the change listeners, overwriting setValue or setRawValue functions on the component.
https://fiddle.sencha.com/#view/editor&fiddle/2js1
{
xtype: 'textareafield',
grow: true,
name: 'message',
fieldLabel: 'Message',
anchor: '100%',
listeners: {
change: function (cmp, newVal, oldVal) {
var arrayForEachLine = newVal.split(/\r\n|\r|\n/g);
var newVal = [];
Ext.Array.each(arrayForEachLine, function (line, index) {
if (line.length >= 10) {
offset = line;
while (offset.length > 0) {
newVal.push(offset.substring(0, 10));
offset = offset.substring(10);
}
} else {
newVal.push(line);
}
if (index === 10) return false;
if (newVal.length >= 10) {
newVal = newVal.slice(0, 10);
return false;
}
});
cmp.suspendEvent('change');
cmp.setValue(newVal.join('\n'));
cmp.resumeEvent('change');
}
}
}
This can be achieved by using the change listener. I have created a demo (fiddle). Please look at the fiddle as the code there is neat and has comments too. Please look at my change listener code below:
listeners: {
change: function () {
var myValue = Ext.getCmp('myField').getValue();
var lines = myValue.split("\n");
if (lines.length > 10) {
alert("You've exceeded the 10 line limit!");
Ext.getCmp('myField').setValue(textAreaValue);
} else { //if num of lines <= 10
for (var i = 0; i < lines.length; i++) { /
if (lines[i].length > 15) { /
alert("Length exceeded in line " + (i+1));
Ext.getCmp('myField').setValue(textAreaValue);
} else if (lines[i].length <= 15 && i == lines.length - 1) {
textAreaValue = myValue;
}
}
}
}
}
Please mark this as an answer if this answer solved your problem as this will also help other people in future. If there is anything wrong with this answer please let me know in the comments. I am sorry if something's wrong as I am not an extjs expert. But I still tried.
This problem is prefect for regex...
My solution focuses on the "max char width" and "max line number" requirements which I don't consider to be the same as "max char count" due to wrapping on words. Because this solution uses plain regex it works best with plain-text with newline chars \n for line breaks rather than html.
This function is idempotent which means it's output can be piped into it's input without issue. It's also very efficient because it's pure regex. Both of these attributes make it perfect for dropping into an onchange handler to update text on every key-press without incurring large performance penalties.
const fit = (str, w = 80, h = 24) => {
w = new RegExp(`(?![^\\n]{1,${w}}$)([^\\n]{1,${w}})\\s`, 'g');
str = str.replace(w, '$1\n');
h = new RegExp(`(((^|\\n)[^\\n]*){${h}})((($|\\n)[^\\n]*)+)`);
str = str.replace(h, '$1');
return str;
};
This function will format the string into the given width / height, but it does so in a very agreeable way: The wrapping regex is considerate of existing new lines which is why it's idempotent, and breaks lines between words not through them. For an in depth explanation of how the word wrap regex works and why it's robust, see my answer for word wrapping strings in JavaScript with regex:
Wrap Text In JavaScript
To restrict textarea character length you can use the following attribute maxlength .
<textarea maxlength="50">
To truncate a string or number.
text_truncate = function(str, length, ending) {
if (length == null) {
length = 100;
}
if (ending == null) {
ending = '...';
}
if (str.length > length) {
return str.substring(0, length - ending.length) + ending;
} else {
return str;
}
};
you can call it by
text_truncate(yourContentToTruncate,15);
This solution is using pure JavaScript.
The basic idea is creating an array of chunks made of 15 characters with .match(/.{1,10}/g) and then, joining the array with a line break join("\n") to create an string again. The number of lines are restricted just removing the remaining chunks using splice(10, chunks.length - 1).
We are using .onkeyup event, but could be another event, that's because the code is not fired until we release a key. But this code also works if we paste text inside the textarea because the event is fired as well.
document.getElementById("textArea").onkeyup = function() {
var text = this.value.replace("\n", "");
if (text.length > 15) {
var chunks = text.match(/.{1,15}/g);
if (chunks.length > 10) {
chunks.splice(10, chunks.length - 1);
alert("if text have more than 10 lines is removed");
}
this.value = chunks.join("\n");
}
};
<textarea rows="18" cols="50" id="textArea">
</textarea>
In the place where you are specifying the textarea field, you need to set 'enforceMaxLength' attribute to true and then set 'maxLength' attribute to number of characters as your limit. Please find the following sample code for extjs. In the example i have set the restriction of no more than 10 characters. Hope this helps.
Ext.create('Ext.form.Panel', {
title: 'Contact Info',
width: 300,
bodyPadding: 10,
renderTo: Ext.getBody(),
items: [{
xtype: 'textarea',
name: 'name',
fieldLabel: 'Name',
enforceMaxLength:true,
maxLength:10,
allowBlank: false // requires a non-empty value
}]
});
for 10 line accept condition
$(document).ready(function(){
var lines = 10;
var linesUsed = $('#linesUsed');
$('#countMe').keydown(function(e) {
newLines = $(this).val().split("\n").length;
linesUsed.text(newLines);
if(e.keyCode == 13 && newLines >= lines) {
linesUsed.css('color', 'red');
return false;
}
else {
linesUsed.css('color', '');
}
});
});
I have written the solution which puts cuted characters to the start of the next line. Only 10 lines are allowed, in each line 15 characters.
Solution with Ext JS
Unfortunately, snippets on SO do not work with Ext JS.
And because of this you can see it on this codepen.io link.
Ext.application(
{
name: 'ExtApp',
launch: function ()
{
Ext.create('Ext.form.Panel',
{
title: 'Sample TextArea',
bodyPadding: 10,
renderTo: Ext.getBody(),
title: 'Restricted number of characters per line in textarea',
height: 500,
width: 700,
items:
[{
xtype: 'textareafield',
grow: true,
fieldLabel: 'Please write your text:',
height: 320,
width: 480,
listeners:
{
change: function(self, newVal)
{
var chunks = newVal.split(/\r*\n/g),
lastLineCutedTxt = '';
for(var i = 0; i < chunks.length; i++)
{
chunks[i] = lastLineCutedTxt + chunks[i];
if(chunks[i].length > 15)
{
lastLineCutedTxt = chunks[i].slice(15);
chunks[i] = chunks[i].slice(0, 15);
}
else lastLineCutedTxt = '';
}
if(lastLineCutedTxt != '')
chunks.push(lastLineCutedTxt);
self.suspendEvent('change');
self.setValue(chunks.slice(0, 10).join('\n'));
self.resumeEvent('change');
}
}
}]
});
}
});
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/extjs/6.0.0/ext-all.js"></script>
<link rel="stylesheet" type="text/css" href="http://cdnjs.cloudflare.com/ajax/libs/extjs/6.0.0/classic/theme-triton/resources/theme-triton-all.css">
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/extjs/6.0.0/classic/theme-triton/theme-triton.js"></script>
Solution with pure JavaScript
var txtArea = document.getElementById('txt-area')
txtArea.onkeyup = function(e)
{
var chunks = this.value.split(/\r*\n/g),
lastLineCutedTxt = '';
for(var i = 0; i < chunks.length; i++)
{
chunks[i] = lastLineCutedTxt + chunks[i];
if(chunks[i].length > 15)
{
lastLineCutedTxt = chunks[i].slice(15);
chunks[i] = chunks[i].slice(0, 15);
}
else lastLineCutedTxt = '';
}
if(lastLineCutedTxt != '')
chunks.push(lastLineCutedTxt);
this.value = chunks.slice(0, 10).join('\n');
};
<textarea id="txt-area" rows="16" cols="35"></textarea>

jQuery Is not a number

I have a table that sum values. How can I do for when I type something that is not a number, keep the result at 0?
Some code:
$(document).on('keyup','input',newSum);
function newSum() {
var sum = 0;
var thisRow = $(this).closest('tr');
var total = 0;
$(thisRow).find("td:not(.total) input").each(function () {
sum += parseInt(this.value);
});
// Insertamos el color de la suma de cada fila.
if((sum % 2 == 0)) {$(thisRow).find('.total').animate( { backgroundColor: 'green' }, 1000);}
else{$(thisRow).find('.total').animate( { backgroundColor: 'red' }, 1000);}
$(thisRow).find(".total").html(sum);
$('.total').each(function () {
total += parseInt($(this).html());
});
}
FULL CODE
Thank you in advance.
Try short circuit boolean evaluation: sum += +this.value || 0;
The + tries to box the value to a Number, if that fails use value 0
sum+= isNaN(Number(this.value))?0:Number(this.value);
Code to stop the keypress for non numeric numbers
Code Here
Js Code :
function checkAlphbet(event) {
var code = event.keyCode ? event.keyCode : event.which;
var currentKey = alphabetKeyRestriction(code, true);
if (!currentKey) {
event.stopPropagation();
} else {
event.preventDefault();
}
}

Limit the number of character in tinyMCE

Im using tinyMCe for my project.Everything is working fine but now i want to restrict the number of character that will be insert into tinyMce textarea
tinyMCE.init({
// General options
mode : "textareas",
theme : "simple",
plugins : "autolink,lists,pagebreak,style,table,save,advhr,advimage,advlink,emotions,media,noneditable,nonbreaking",
// Theme options
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,fontselect,fontsizeselect",
theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,code,|,forecolor,backcolor",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_statusbar_location : "bottom",
max_chars : "10",
max_chars_indicator : "lengthBox",
theme_advanced_resizing : true
});
I used :-
max_chars : "10",
max_chars_indicator : "lengthBox",
but still not working.Thanks in advance.
This works in tinyMCE 4.3.12 and also captures pasting:
EDIT: Fixed bugs and extended code to display a character counter under the editor. Possibly not the best way as it relies a bit on the current HTML structure of tinyMCE having the editor div before the hidden textarea.
This version only counts the text length and ignores HTML tag length. To count full HTML length, replace all "innerText" with "innerHTML".
tinymce.init({
max_chars: 1000, // max. allowed chars
setup: function (ed) {
var allowedKeys = [8, 37, 38, 39, 40, 46]; // backspace, delete and cursor keys
ed.on('keydown', function (e) {
if (allowedKeys.indexOf(e.keyCode) != -1) return true;
if (tinymce_getContentLength() + 1 > this.settings.max_chars) {
e.preventDefault();
e.stopPropagation();
return false;
}
return true;
});
ed.on('keyup', function (e) {
tinymce_updateCharCounter(this, tinymce_getContentLength());
});
},
init_instance_callback: function () { // initialize counter div
$('#' + this.id).prev().append('<div class="char_count" style="text-align:right"></div>');
tinymce_updateCharCounter(this, tinymce_getContentLength());
},
paste_preprocess: function (plugin, args) {
var editor = tinymce.get(tinymce.activeEditor.id);
var len = editor.contentDocument.body.innerText.length;
var text = $(args.content).text();
if (len + text.length > editor.settings.max_chars) {
alert('Pasting this exceeds the maximum allowed number of ' + editor.settings.max_chars + ' characters.');
args.content = '';
} else {
tinymce_updateCharCounter(editor, len + text.length);
}
}
});
function tinymce_updateCharCounter(el, len) {
$('#' + el.id).prev().find('.char_count').text(len + '/' + el.settings.max_chars);
}
function tinymce_getContentLength() {
return tinymce.get(tinymce.activeEditor.id).contentDocument.body.innerText.length;
}
Reference: How can I prevent tinyMCE's paste event?
TinyMCE 4+
+
jQuery
<textarea id="description_edit" name="description_edit"><?=htmlspecialchars($this->company->description);?></textarea>
<div><span>Characters left:</span> <span id="chars_left"></span></div>
<script type="text/javascript" src="/js/tinymce/tinymce.min.js"></script>
<script>
var max_chars = 200; //max characters
var max_for_html = 300; //max characters for html tags
var allowed_keys = [8, 13, 16, 17, 18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 46];
var chars_without_html = 0;
function alarmChars() {
if (chars_without_html > (max_chars - 25)) {
$('#chars_left').css('color', 'red');
} else {
$('#chars_left').css('color', 'gray');
}
}
$(function () {
tinymce.init({
selector: "#description_edit",
theme: "modern",
width: 320,
height: 130,
plugins: [
"advlist autolink lists charmap print preview hr anchor pagebreak",
"searchreplace visualblocks visualchars code insertdatetime media nonbreaking",
"save table contextmenu directionality paste textcolor"
],
image_advtab: true,
language: 'en',
menubar: false,
statusbar: false,
setup: function (ed) {
ed.on("KeyDown", function (ed, evt) {
chars_without_html = $.trim(tinyMCE.activeEditor.getContent().replace(/(<([^>]+)>)/ig, "")).length;
chars_with_html = tinyMCE.activeEditor.getContent().length;
var key = ed.keyCode;
$('#chars_left').html(max_chars - chars_without_html);
if (allowed_keys.indexOf(key) != -1) {
alarmChars();
return;
}
if (chars_with_html > (max_chars + max_for_html)) {
ed.stopPropagation();
ed.preventDefault();
} else if (chars_without_html > max_chars - 1 && key != 8 && key != 46) {
alert('Characters limit!');
ed.stopPropagation();
ed.preventDefault();
}
alarmChars();
});
},
toolbar: "bold italic underline | alignleft aligncenter alignright alignjustify | forecolor backcolor | bullist numlist | charmap",
style_formats: [
{title: 'Bold text', inline: 'b'},
{title: 'Red text', inline: 'span', styles: {color: '#ff0000'}},
{title: 'Red header', block: 'h1', styles: {color: '#ff0000'}},
{title: 'Example 1', inline: 'span', classes: 'example1'},
{title: 'Example 2', inline: 'span', classes: 'example2'},
{title: 'Table styles'},
{title: 'Table row 1', selector: 'tr', classes: 'tablerow1'}
]
});
chars_without_html = $.trim($("#description_edit").text().replace(/(<([^>]+)>)/ig, "")).length;
$('#chars_left').html(max_chars - chars_without_html);
alarmChars();
});
</script>
Answers above were great! I've made a small amendment so that we can set max_chars by adding it as an attribute to textarea element itself
setup : function(ed) {
ed.onKeyDown.add(function(ed, evt) {
//if ( $(ed.getBody()).text().length+1 > ed.getParam('max_chars')){
if ( $(ed.getBody()).text().length+1 > $(tinyMCE.get(tinyMCE.activeEditor.id).getElement()).attr('max_chars')){
evt.preventDefault();
evt.stopPropagation();
return false;
}
});
}
Providing support to backspace and delete keys. My version:
max_chars : 2000,
max_chars_indicator : ".maxCharsSpan",
setup : function(ed) {
wordcount = 0;
wordCounter = function (ed, e) {
text = ed.getContent().replace(/<[^>]*>/g, '').replace(/\s+/g, ' ');
text = text.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
this.wordcount = ed.getParam('max_chars') - text.length;
$(ed.getParam('max_chars_indicator')).text( this.wordcount + " (out of " +ed.getParam('max_chars')+ ") char(s) left." );
};
ed.onKeyUp.add( wordCounter );
ed.onKeyDown.add(function(ed, e) {
if (this.wordcount <= 0 && e.keyCode != 8 && e.keyCode != 46) {
tinymce.dom.Event.cancel(e);
}
});
This is the solution that worked for me.
I basically took the code provided by #needfulthing and fixed the errors and improved it.
function initTinymce(){
tinymce.init({
selector: '.richtext-editable',
plugins: ['paste'],
max_chars: 50000, // max. allowed chars
setup: function (ed) {
var allowedKeys = [8, 13, 16, 17, 18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 46];
ed.on('keydown', function (e) {
if (allowedKeys.indexOf(e.keyCode) != -1) return true;
if (tinymce_getContentLength() + 1 > this.settings.max_chars) {
e.preventDefault();
e.stopPropagation();
return false;
}
return true;
});
ed.on('keyup', function (e) {
tinymce_updateCharCounter(this, tinymce_getContentLength());
});
},
init_instance_callback: function () { // initialize counter div
$('#' + this.id).prev().append('<div class="char_count" style="text-align:right"></div>');
tinymce_updateCharCounter(this, tinymce_getContentLength());
},
paste_preprocess: function (plugin, args) {
var editor = tinymce.get(tinymce.activeEditor.id);
var len = editor.contentDocument.body.innerText.length;
if (len + args.content.length > editor.settings.max_chars) {
alert('Pasting this exceeds the maximum allowed number of ' + editor.settings.max_chars + ' characters for the input.');
args.content = '';
}
tinymce_updateCharCounter(editor, len + args.content.length);
}
});
function tinymce_updateCharCounter(el, len) {
$('#' + el.id).prev().find('.char_count').text(len + '/' + el.settings.max_chars);
}
function tinymce_getContentLength() {
return tinymce.get(tinymce.activeEditor.id).contentDocument.body.innerText.length;
}
}
Just to improve a little bit the good example given by Vladimir Miroshnichenko, to get a more accurate count, mainly for languages with accented characters.
I also inlcude the Javascript SpellChecker as the tinyMCE's one (4.1) cannot be used anymore.
So the ed.addButton() will include a button in the toolbar to call $Spelling.SpellCheckInWindow('editors'). That perfectly works with tinyMCE 4.1.7.
I also added a count of words, if you prefer to trig the alarm on word instead of characters.
<textarea id="paragraph1" name="description_edit"><?=htmlspecialchars($this->company->description);?></textarea>
<div><span>Characters left:</span> <span id="chars_left"></span></div>
<script type="text/javascript" src="tinymce/tinymce.min.js"></script>
<script type="text/javascript" src="JavaScriptSpellCheck/include.js"></script>
<script>
var max_chars = 300; //max characters
var max_for_html = 1000; //max characters for html tags
var allowed_keys = [8, 13, 16, 17, 18, 20, 33, 34, 35,36, 37, 38, 39, 40, 46];
var chars_without_html = 0;
function alarmChars(){
if(chars_without_html > (max_chars - 25)){
$('#chars_left').css('color','red');
}else{
$('#chars_left').css('color','gray');
}
}
$(function() {
tinymce.init({
selector: "textarea#paragraph1",
theme: "modern",
plugins: [
"advlist autolink lists charmap preview hr anchor pagebreak",
"visualblocks visualchars insertdatetime nonbreaking",
"directionality paste textcolor"
],
menubar:false,
statusbar:false,
toolbar: "bold italic underline | alignleft aligncenter alignright alignjustify | forecolor backcolor | bullist numlist | charmap | preview | Spellcheck",
setup : function(ed) {
ed.addButton('Spellcheck', {
title : 'Spellcheck',
image : '/img/dict.png',
onclick : function() {
// Add you own code to execute something on click
$Spelling.SpellCheckInWindow('editors');
}
});
ed.on("KeyDown", function(ed,evt) {
whtml = tinyMCE.activeEditor.getContent();
without_html = whtml.replace(/(<([^>]+)>)/ig,"");
without_html = without_html.replace(/&([A-za- z])(?:acute|cedil|caron|circ|grave|orn|ring|slash|th|tilde|uml);/ig,'$1');
without_html = without_html.replace(/…/ig,'...');
without_html = without_html.replace(/’/ig,'\'');
without_html = $.trim(without_html.replace(/&([A-za-z]{2})(?:lig);/ig,'$1'));
chars_without_html = without_html.length;
chars_with_html = whtml.length;
wordscount = without_html.split(/[ ]+/).length; // Just to get the wordcount, in case...
var key = ed.keyCode;
$('#chars_left').html(max_chars - chars_without_html);
if(allowed_keys.indexOf(key) != -1){
alarmChars();
return;
}
if (chars_with_html > (max_chars + max_for_html)){
ed.stopPropagation();
ed.preventDefault();
}else if (chars_without_html > max_chars-1 && key != 8 && key != 46){
alert('Characters limit!');
ed.stopPropagation();
ed.preventDefault();
}
alarmChars();
}
);
},
});
whtml = $("#paragraph1").text();
without_html = whtml.replace(/(<([^>]+)>)/ig,"");
without_html = without_html.replace(/&([A-za-z])(?:acute|cedil|caron|circ|grave|orn|ring|slash|th|tilde|uml);/ig,'$1');
without_html = without_html.replace(/…/ig,'...');
without_html = without_html.replace(/’/ig,'\'');
without_html = $.trim(without_html.replace(/&([A-za-z]{2})(?:lig);/ig,'$1'));
chars_without_html = without_html.length;
$('#chars_left').html(max_chars - chars_without_html);
alarmChars();
});
I hope it will help as tinyMCE team seems to be a bit stubborn on this subject...
// Returns text statistics for the specified editor by id
function getStats(id) {
var body = tinymce.get(id).getBody(), text = tinymce.trim(body.innerText || body.textContent);
return {
chars: text.length,
words: text.split(/[\w\u2019\'-]+/).length
};
}
function submitForm() {
// Check if the user has entered less than 10 characters
if (getStats('content').chars < 10) {
alert("You need to enter 1000 characters or more.");
return;
}
// Check if the user has entered less than 1 words
if (getStats('content').words < 1) {
alert("You need to enter 1 words or more.");
return;
}
// Submit the form
document.forms[0].submit();
}
http://www.tinymce.com/wiki.php/How_to_limit_number_of_characters/words
Hope it helps
There is no tinymce configuration setting max_chars, except you implement it yourself:
tinyMCE.init({
...
max_chars : "10",
setup : function(ed) {
ed.onKeyDown.add(function(ed, evt) {
if ( $(ed.getBody()).text().length > ed.getParam('max_char')){
e.preventDefault();
e.stopPropagation();
return false;
}
});
}
});
the solution worked for me but with a small bug. If you see the character count is not right, thats because you use
ed.on("KeyDown")
change it to
ed.on("KeyUp")
,then it will work fine. I havent tested it with ('Change'). it may works too!
tinyMCE not provide any way to limit the character and restrict user to enter more character, the only way is use any explicit plugin or your logic for it. Below code show issue raised with me, it is working properly.
This is used on textarea having id summary and one another paragrap id character_count that used to show character count. User is not able to enter more character than max limit, Inthis case only backspace key is working. You can free to use any key by giving ascii value if the key in condition.
tinymce.init({
selector: '#summary', // change this value according to your HTML
auto_focus: 'element1',
statusbar: false,
toolbar: 'undo redo | styleselect | bold italic underline | formatselect | aligncenter | fontselect',
setup: function (ed) {
ed.on('KeyDown', function (e) {
var max = 150;
var count = CountCharacters();
if (count >= max) {
if(e.keyCode != 8 && e.keyCode != 46)
tinymce.dom.Event.cancel(e);
document.getElementById("character_count").innerHTML = "Maximun allowed character is: 150";
} else {
document.getElementById("character_count").innerHTML = "Characters: " + count;
}
});
}
});
function CountCharacters() {
var body = tinymce.get("summary").getBody();
var content = tinymce.trim(body.innerText || body.textContent);
return content.length;
};
The solution below works good for me:
1 - in the html code of the textarea it is necessary to include the value of maxlength and id of textarea.
2 - in script part, code below. If you want, uncomment the alert() line, and put your message.
<script type="text/javascript">
tinymce.init ({
...
...
setup: function(ed) {
var maxlength = parseInt($("#" + (ed.id)).attr("maxlength"));
var count = 0;
ed.on("keydown", function(e) {
count++;
if (count > maxlength) {
// alert("You have reached the character limit");
e.stopPropagation();
return false;
}
});
},
<textarea type="text" id="test" name="test" maxlength="10"></textarea>
Ok with the new tinyMCE4X thing's change a little bit.
tinymce.init({
charLimit : 10, // this is a default value which can get modified later
setup: function(editor) {
editor.on('change', function(e) {
//define local variables
var tinymax, tinylen, htmlcount;
//setting our max character limit
tinymax = this.settings.charLimit;
//grabbing the length of the curent editors content
tinylen = this.getContent().length;
if (tinylen > tinymax) {
alert('to big');
}
});
}
});
If you are here maybe you are looking for simple solution.
Here is my solution. It is not perfect, but it is very simple
var max_length = 3;
tinymce.init({
selector: '#description',
// some my settings for tiny mce
toolbar: ' undo redo | bold italic | formatselect',
setup : function(ed) {
// important part
ed.on("keypress", function(event){
// get content of the tinymce and remove tags
// tinymce will be adding tags while you type in it.
// when tags are removed, you will heave real input length (the one that customer sees)
var content = tinymce.activeEditor.getContent().replace(/(<([^>]+)>)/ig,"");
// now just compare that length to your prefered length.
// if it is larger or same, return false, and that will disregard last input.
if(content.length >= max_length){
return false;
}
});
}
});
TinyMCE + AngularJS
Here's how you can limit max number of characters on frontend using ng-maxlength directive from AngularJS.
Param : ngMaxlength
Type : number
Details : Sets maxlength validation error key if the value is longer than maxlength.
Please note that this directive doesn't just count the displayed text characters, it counts all the text inside <textarea> in HTML like tags and scripts.
First of all, include AngularJS, TinyMCE 4 distributive, and AngularUI wrapper for TinyMCE.
HTML:
<form name="form" action="#">
<textarea ng-model="myMCEContent" ui-tinymce ng-maxlength="200" name="body"></textarea>
<span ng-show="form.body.$error.maxlength" class="error">Reached limit!/span>
</form>
JavaScript:
angular.module('myApp', ['ui.tinymce'])
.config(['$sceProvider', function($sceProvider) {
// Disable Strict Contextual Escaping
$sceProvider.enabled(false);
}])
.constant('uiTinymceConfig', {/*...*/})
.controller('myCtrl', ['$scope', function($scope) {
// ...
}]);
jsFiddle
! Attention !
Read the manual before using this solution to fully understand consequences of disabling SCE in AngularJS: $sce service.
easiest way:
contentContentLenght = tinyMCE.activeEditor.getContent({format : 'text'}).length; //takes lenght of current editor
if (contentContentLenght > 1499) {
e.preventDefault();
e.stopPropagation();
return false;
} // 1500 is my limit in mine project.
to prevent paste:
editor.on('paste', function(e){
contentContentLenght = tinyMCE.activeEditor.getContent({format : 'text'}).length;
var data = e.clipboardData.getData('Text');
if (data.length > (1500 - contentContentLenght)) {
return false;
} else {
return true;
}
});
Thariama's answers was awesome just implemented it and it was just what I was looking for, just made a few modifications:
max_chars : "10",
setup : function(ed) {
ed.onKeyDown.add(function(ed, evt) {
if ( $(ed.getBody()).text().length+1 > ed.getParam('max_chars')){
evt.preventDefault();
evt.stopPropagation();
return false;
}
});
}
Thanks Thariama.

How do I let a computed observable be set via entering or from being calculated from other inputs?

I have the following code:
function ViewModel() {
var self = this;
self.deckareax = ko.observable(0);
self.deckareay = ko.observable(0);
self.calculatedarea = ko.observable(20);
self.deckareax.subscribe(function () {
if (self.deckareax() == 0 || deckareay == 0) {
self.calculatedarea(0);
} else {
self.calculatedarea(self.deckareax() * self.deckareay());
}
}
);
self.deckareay.subscribe(function () {
console.log("deckareay " + self.deckareay())
if (self.deckareax() == 0 || self.deckareay() == 0) {
self.calculatedarea(0);
} else {
self.calculatedarea(self.deckareax() * self.deckareay());
}
}
);
self.deckareamxm = ko.computed({
read: function () {
return self.calculatedarea();
},
write: function (value) {
self.calculatedarea(value);
if ((self.deckareax() * self.deckareay(0)) != value) {
self.deckareax(0);
self.deckareay(0);
}
},
owner:self
});
}
;
ko.applyBindings(new ViewModel());
I want to be able to set the total area (deckareamxm) by either manually inputting or calcualting from entering deckareax * deckareay. If I enter a result and (deckareax * deckareay) doesn't equal total deck area x and y should be cleared.
This pretty much works however if I enter total area it clears both but also clears itself. If I then enter again total area it stays. I think it may have got to complex. Any ideas?
This jsfiddle seems to do what you want. There were a couple other bugs but I primary fixed the problem by moving the self.calculatedarea(value); to the bottom of the write function.

Categories