The code below is working fine except that if I paste a string with more than 10 characters in it, it should only paste in the first 10 characters. Currently it does not do this, how do I prevent more than 10 characters being pasted?
http://jsfiddle.net/qfzkw/2/
As stated, <textarea maxlength="10"> will work for a small amount of cases - but not all.
It is hard to determine how to prevent the user (in firefox for example) from entering the text area, selecting the browser menu Edit and then clicking on Paste. I am really at a loss for how to prevent that. You can check the keydown event to prevent ctrl + v. You can disable the context menu to disallow the right clicking of the text area (although a malicious user can edit the front end javascript and then re-enable this feature).
In short, there is no universal way to prevent user paste in a proper fashion.
However, you could hack a solution (always my favorite when it seems there is no way to continue on something you really want). This approach I am about to suggest is dependent on how many timers you have running. If you have multiple timers for animation, google suggests you try to fold them all into one timing unit which the others derive from. If this is the case, please refactor your timers.
Implement a global timer. Implement a function which runs ever 25ms based on that timer. Cache the contents of the textarea. See if those contents have changed.
textarea
<textarea id="maintextarea"></textarea>
script
/*init*/
var globalTimer = new Date();
var cachedText = document.getElementById("maintextarea").value;
var iterationCount = 0;
function cacheText() {
cachedText = document.getElementById("maintextarea").value;
}
function upDateTimer() {
globalTimer = new Date();
var timerTimeout = setTimeout('upDateTimer()', 5);
timeBasedOperations();
}
upDateTimer();
function timeBasedOperations() {
iterationCount++;//this will allow timing to occur
//TODO: Add in other timers calls based on global timer
if (iterationCount % 5) {//every fifth iteration (hence 25ms)
checkTextArea();
}
}
function checkTextArea() {
var currentText = document.getElementById("maintextarea").value;
var textArea = document.getElementById("maintextarea");
if (currentText.length > cachedText.length) {
//TODO: Add additional logic for catching a paste or text change
textArea.value = currentText.substr(0, 10);
}
cacheText();
}
I think although this implements a timer, this is a very practical solution. It also happens to work (tested).
:)
simply use
<textarea maxlength="10"></textarea>
No javascript needed for this. It automatically takes care of copy paste also.
Here is the updated jsFiddle.
You can't peek into the clipboard buffer from browsers, so your only option is to limit it to 10 chars like you currently do. Use the maxlength="10" attribute instead of the javascript character counting thing you got going on.
<textarea maxlength="10"></textarea>
Related
I have a functionality which forbids users to input specific symbols into <input> tags and also convert all alphabet characters to uppercase.
Everything worked fine when I found out this bug with fast tabbing between elements.
Problem:
Whenever a user inputs a character and presses the tab key really fast, the last character won't get converted to upper case.
Note:
I still want to let users tab between inputs so just e.preventDefault() is not an option here. I need to slightly slow down the tab action with 20-30 milliseconds or so.
Code:
var $inputs = $('input[type="text"]');
$inputs.on('keyup keydown keyhold paste', function(e) {
//validate_input will return true if character is allowed and transformed into upper case
if (!validate_input(e, $(this))) {
return false;
}
if (e.which == 9) {
// i need to do something here to slightly slow down the tab process
// just to make sure the above function will execute before the default tab action.
}
});
I suggest that you use input-event instead. That is fired when the value has changed. You can do you filtering of allowed values there, and convert it to upper case. That is a much easier, foolproof, less buggy, browser independent, keyboard independent, assistive technology independent, approach to solve your problem.
This may be a quite naive question but I really need some help.
Prior to writing this post, I was programming on JSBin. Turns out without me realizing, I ran a setInterval loop prompting for userInput and it kept on looping, making me unable to click anywhere to change the code to fix the loop. It kept on repeating and repeating. It got to the point where I had to refresh and lose all my hard-written-code (I was not logged in, so my code was not saved)! I want to avoid that next time.
So, my question is how do I stop any such kind of setInterval Loops, so that I am able to access my code and change it and re-run it. Below is a code that demonstrates my issue, if you try running it on JSBin.com (obviously, it is not the code I wrote before). As you can see, I can not click on my code to change it (or save it) in any way, which means I lose all my code!
This may seem like a useless question, but I really want to know ways to fix it and perhaps fixing it from the developer tools will help me be familiar with the overwhelming set of tools it has :P. So please help me if you know a solution.
Thank you for taking your time to help me! I appreciate it.
setInterval(demo,1);
function demo()
{
var name = prompt("Enter your name: ");
}
Another option is to search the developer tools "Elements" panel for the iframe (this should be doable even if the main document is unresponsive due to prompt's blocking) - then, just right click the iframe element and remove it, no need to type any Javascript. (or, if you want you can select the iframe with querySelector and remove it, eg document.querySelector('iframe').remove())
That's kind of a hack and should only be used in cases like the one exposed in OP but,
About all implementations use integers as timerid that just get incremented at every call.
So what you can do, is to clear all timeouts that were created on the page.
To do so you need to first get to which timerid we are, then call cleatTimeout or clearInterval (they do the same) in a loop until you reach the last call:
function stopAllTimers() {
const timerid = setTimeout(_=>{}); // first grab the current id
let i=0;
while(i < timerid) {
clearTimeout(i); // clear all
i++;
}
};
btn.onclick = stopAllTimers;
// some stoopid orphan intervals
setInterval(()=>console.log('5000'), 5000);
setInterval(()=>console.log('1000'), 1000);
setInterval(()=>console.log('3000'), 3000);
const recursive = () => {
console.log('recursive timeout');
setTimeout(recursive, 5000);
};
recursive();
<button id="btn">stop all timeouts</button>
Assuming the dev tools are closed, hit esc and f12 nearly simultaneously. This should open the dev tools. If it doesn't keep trying until it does.
Once they are open, hit esc and f8. Again, retry til it halts javascript execution at some arbitrary point in the code.
In the "sources" tab locate the generated script for what you wrote (offhand I don't know how it would look like from within JSBin) and literally delete the var name = prompt("Enter your name: "); line. Hitting f8 again will continue execution as if the "new" code is running. This should free you up to copy/paste your code from the site itself before you refresh the page
I'm currently having an issue with a code. In my code, I've got a textarea where the user can enter the title of an article and I would like this article to be only in one row. That's why I wrote a script to prevent users to press the return key. But they could bypass this security, indeed if they copy/past the line break they could enter a line break. So, is there a way to detect line break ? I suppose we can do this with regular expressions and with \n or \n. However I tried this:
var enteredText = $('textarea[name="titleIdea"]').val();
var match = /\r|\n/.exec(enteredText);
if (match) {
alert('working');
}
and it doesn't work for an unknown reason. I think the var enteredText = $('textarea[name="titleIdea"]').val(); doesn't work because when I try to alert() it, it shows nothing. But something strange is that when I do an alert on $('textarea[name="titleIdea"]').val(); and not on the enteredText variable it shows the content.
Have a great day. (sorry for mistakes, I'm french)
if they copy/past the line break they could enter a line break
That's why you shouldn't even worry about preventing them from entering it - just don't save it. Remove it on the blur and input events if you really want to, but the only time it actually matters is before you save it to the database (or whatever you are using).
$('textarea[name="titleIdea"]').on('blur input', function() {
$(this).val($(this).val().replace(/(\r\n|\n|\r)/gm,""));
});
And, as other people have already mentioned, if they can't do line breaks, you shouldn't be using a textarea.
I assume your problem is with the paste event.
If i guessed this is my snippet:
$(function () {
$('textarea[name="titleIdea"]').on('paste', function(e) {
var data;
if (window.clipboardData) { // for IE
data = window.clipboardData.getData('Text');
} else {
data = e.originalEvent.clipboardData.getData('Text');
}
var match = /\r|\n/.exec(data);
if (match) {
alert('working');
console.log(data);
}
})
});
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<textarea name="titleIdea">
</textarea>
This needs to be handled in the backend. Even if you use the recommended appropriate HTML input type of text (instead of textarea), you still do not remove the possibility of return chars getting saved.
The two other answers use Javascript - which technically is the domain of this question. However, this can not be solved with Javascript! This assumes that the input will always come from the form you created with the JS function working perfectly.
The only way to avoid specific characters being inserted into your database is to parse and clean the data in the backend language prior to inserting into your database.
For example, if you are using PHP, you could run a similar regex that stripped out the \n\r chars before it went into processing.
Javascript only helps the UX in this case (the user sees what they will be saving). But the only way to ensure you have data integrity is to validate it on the server side.
Let me start by saying that my task is complete. But I'm trying to get an understanding of how it's working, and one thing is confusing to me. In other words, I stumbled on the answer by accident.
My task was simple: in an input box, mask the input as the user types, by changing each character to * after a delay. This is how android phones handle masked input, slightly different than iPhone.
I used a combination of jQuery/javascript and regex. My working code:
$('.room_input').focus(function () {
currentFocus = $(this);
});
$('.key').click(function () {
setTimeout(function () {
currentFocus.val(currentFocus.val().replace(/[^\*]/, '*'));
}, 2000);
});
It's pretty simple, and it works great. When each key is pressed, it changes to * after 2 seconds. Each key is on its own timer. But there is one major thing I don't understand. When the callback from setTimeout triggers, the code above seems like it would set the entire contents of the textbox to *'s. Because the "replace" above replaces the entire content of the value with any characters not *.
But it doesn't. Each key changes after 2 seconds from when it was clicked (as it should).
Why is that? I'm thinking it might be the regex - does it only change the first match it finds? Did I just answer my own question?
UPDATE: I did.
It's the regex. It only replaces the first matched character in the string. I was thinking it maybe had something to do with single-threading issues... as usual, I'm making a problem much more difficult than it is. :)
Yep you are correct.
Every key click adds a character, and then starts a timer that later turns the first non-asterisk into an asterisk. It's far simpler than you might expect.
I am trying to edit some existing JavaScript validation code.
Using the onkeydown event, the code checks that the value in a textbox does not go past a maximum length. I cannot use <input maxlength="value" /> as there may be some formatting characters in the string that I can safely exclude from the maximum length.
The code works fine apart from when the user has pressed the insert key to turn overtype on and they have reached the maximum length. When this occurs if they place the cursor before a character and try to overwrite it the validation thinks that this will go over the limit and doesn't realise that a character will actually be replaced.
This answer states that I cannot detect if overtype is on, but doesn't provide any references. So assuming that I cannot detect overtype, is there anyway in the onkeydown event to detect if a character is going to be replaced.
I am happy with an IE only solution.
Update: onblur is not appropriate as this will let them go many characters over the limit before warning them of the maximum length. I would like to prevent them from going over the limit.
Your handler should look at the entire value and check the length. If the length is legal, return. If not, you can update the value with a substring. You may have to use caret position to determine exactly how to manipulate the string which can be tricky as it's slightly different in IE and other browsers.
This is different from what you have now which is probably preventing keypress when max length is reached. Don't prevent keypress, just trim the resulting string.
I don't think your problem is with the onblur validation, but an event you calling on key press by the sounds of it (eg preventing the user to key any more once they reach the limit) or I have misunderstood.
IF your validation is indeed onblur, you shouldn't have to worry about things like insert/overwrite being enabled, you are only interested in what the value of the input element is once the user has completed their input.
IF you are trying to stop the user if they reach this limit as they type, I would write a function to compute the actual length you are testing. For eg,
function validateMyInput() {
var myInputField = document.getElementById('myInput');
var removeAllExcludedCharsResult = myInputField.value.replace('&','');//exclude &
var totalLength = removeAllExcludedCharsResult.length;
if(totalLength < 500) { //limit of this test is 500
return true;
}
else {
return false;
}
}
Obviously change this function to what you need and maybe make it more generic by passing in the element of the input, max length and array of excluded chars to make it reusable.
UPDATE
I have tested this problem is Chrome and the insert key seems to be ignored. IE on the other hand does overkey. However, it seems page specific, for eg, if i have enabled insert on Page A, it doesn't seem to affect Page B. I found this page which seems to be able to grab the keycode event even when insert has been pressed. It might be due to the following code?
if(window.event) {
event = window.event; //where event is the javascript key event.
}
Either way, the link above seems to have accounted for the problem, hopefully it will have the answer if the above is not correct.
Hope I haven't misunderstood what the problem was and this helped.