jQuery validation, NOT the normal plugin - javascript

I've been looking at the jQuery Validation Plugin and it seems like overkill (my site's script requirements are ballooning), and also not quite what I want.
Let me define some terminology: an <input type="text"> field's status is VALID if it matches both RegEx 1 and RegEx 2, PARTIAL if it matches RegEx 1 but not RegEx 2, and INVALID if it doesn't match RegEx 1.
For example, RegEx 1 could be /^[A-Z_]*$/ and RegEx 2 could be /^[A-Z]+(_[A-Z]+)*$/.
The requirements are:
any key press which would lead to an INVALID status is ignored, without interfering with focus or the caret position, and without the value ever being seen to change,
otherwise the status is updated after every key press to be either VALID or PARTIAL, and
whenever an input's status changes, a callback is invoked.
Seems pretty straightforward. This is basically the QStringValidator model.
I have jQuery core but I'm new to it. How can I implement this? Thanks.
P.S. if the best solution lies outside of jQuery, IE support is not required.

if (this.value.match(this.getAttribute('data-regex1')) {
if (this.value.match(this.getAttribute('data-regex2')) {
do_whatever_for_full();
} else {
do_whatever_for_partial();
}
} else {
do_whatever_for_invalid();
}
Put your regexes into the element as custom attributes (data-regex1, data-regex2) then check the data as it changes (not sure how many events you want to check but you probably have to check with onkeydown ignoring enter and tab, or you could create a timer onfocus and just check every half second or so).

Related

Fire HTML input-event only once when more than one character is typed

I'm creating an input field where some data should be fetched (by AJAX) and displayed every time the user enters data into that field. However, if the user types several characters, say he types "test" to get all records who contain the string "test", it would not be necessary to do 4 queries after every character pressed, but one query after he stopped typing. I can think of several solutions with a global variable where I check if the same event has been fired again, but is there a really elegant way to do this? Maybe check if there is something in the keyboard buffer and only proceed if it is empty? Or is there an event that is only fired once the keyboard buffer is empty and all characters are in the input field?
The elegant way is to use a timeout, and to keep clearing the previous timeout with each key press
var tID;
function keyUp (e) {
if (tID) clearTimeout(tID);
tID = setTimeout(function() {
... // make web call
}, 2000);
}
This will ensure that the web call is only called after the last key is pressed (you may want to adjust the timeout value)
There are ways to achieve this that I can think of:
Use timeout, from the last keyup event. This is not always the best and not that precise with users that have low typing speed.
Use space character do regconize if the user has finished typing a word. Based on changes in length and total word count, you can decide if you would want to send AJAX or not.
Depends on the type of input you are working with, you may choose the most suitable method for you. The first one is somewhat quite rigid. The second method requires user to press space every time he finishs typing. A little bit of both could be a sweet spot perhaps. In modern day, I don't think sending request every keyup will cause huge performance effect though.

Using Regex to validate user input as CSS?

I am writing a program that allows the user to create a page using a drag-n-drop GUI. Every element (image, text, etc) will have easy-to-use CSS selectors like background-color and font-size, however my client has asked for the ability, when necessary, to add custom CSS to the element as a final option.
Looking past the dangers of users possibly typing in and saving valid javascript functions, trying to style the body tag etc. (I will make sure to handle that by escaping/PDO-handling user input in PHP), how can I write a regex (or another functionality) that tests, crudely, if what the user types in is valid CSS. My regex at the moment is this:
([A-Za-z\-]+?:\s*?[A-Za-z\-]+?;)+?;
And I run it using
var reg = /([A-Za-z\-]+?:\s*?[A-Za-z\-]+?;)+?/;
if (reg.test(textarea.val())) {
console.log("yay");
//add CSS to element
} else {
console.log("nay");
//let user know their input is wrong
}
This works fine to validate
css-selector: css-value;
However, anything after that it will still validate as true because the first part will be true:
css-selector: css-value;
invalid-css is here!
As for what I mean with crudely, all that I find necessary to check is the presence of a : and a ; with text, and possibly a - in-between, it is not necessary to check if the css-selector itself actually exists as a CSS attribute nor if the CSS-value is a valid value of said selector.
Is there a way to ensure the entire input value MUST be true?
As a final note, if you see a potential danger not directly related to inserting script-tags or styling potential whole-page elements that I should be vary of, please let me know
Edit: due to many saying that I can't validate real CSS, I am going to specify my requirement a bit further; first, valid regex:
css-selector: css-value;
other-css-selector: other-css-value;
invalid regex:
css-selector: css-value;
invalid-css is here!
Secondly, what I want is something that validates if I can pass the string to:
$(element).css(validated-string);
And have chrome handle whether what is applied is actually valid, much like it does if you edit CSS live
Secondly, I mention PHP validation, but what I want is to update the CSS live so the user can see the effect of their edits as they add them
As regex you can use ^([A-Za-z\-]+?:\s*?[0-9A-Za-z\-%]+?;\s*?)*?$, but still i'm not quite sure that it will discard all the invalid css.
If you have test: 100something; is valid for the regex but is not valid CSS.

How can I eliminate lag and fix partial match searches in a dojo FilteringSelect widget?

I'm having trouble making a dijit/form/FilteringSelect widget behave itself. I suspect my combination of options is just off, but I can't seem to hit on the right pattern.
My data source is a list of book names, and I would like the user to be able to use the widget either by either pulling down the menu and selecting an option or typing in part of a name and getting a match. The tricky part is the filter that happens on typing in a value needs to happen with wild card matches on both ends because it is quite likely that the word typed will be the second word in the name.
My problem is with setting an appropriate search delay and with what continuing to type after a search happens. First, the default search delay of 200ms works fine as long as you can keep typing, but with queryExpr set to *${0}* this seems to be broken. When you continue typing you start up with the prefix of the current match instead of only what you had typed so far.
The only way I got this to be usable at all is setting a much larger delay (500ms) and hoping people don't make many typing mistakes. This has the undesired effect of delaying the drop down menu.
var books_widget = new FilteringSelect({
placeHolder: "Kitap",
store: book_list_store,
style: 'width: 12em',
searchAttr: "name",
autocomplete: false,
highlightMatch: 'first',
ignoreCase: true,
queryExpr: '*${0}*',
searchDelay: 500
});
books_widget.placeAt(wrapper_node);
Is there...
...any way to decouple the searchDelay from the dropdown menu triggered with the mouse so that the UI does not have pointless lag?
...a proper way to arrange the settings such that when typing in a partial match, the search function does not destroy the existing entry and you can continue to type characters extending the pattern?
You do not have to use the search delay. The behavior you're getting is because the autoComplete property is set to true.
However, in your configuration you're using autocomplete, and you should use an uppercase "C".
I suppose this fixes both problems, as your dropdown menu will no longer be delayed and when a partial match is found it will no longer override your current text.
The searchDelay property is commonly used to debounce the store access (and perhaps REST access). When you enter "hello world" without a search delay, the store would be queried for each change, so for:
h
he
hel
...
hello world
If you debounce it by using the searchDelay, then it will only access your store, 500 milliseconds after the last change, so if you type fast enough, it will only use it to query "hello world".
One other thing that may reduce lag: provide a limited number of responses that match the input.
Using pageSize: "100" as an input parameter will give only the first 100 matches, along with a link for "more choices".
This really helped performance on a very large set of choices during the typing to narrow the selection.

Change an input when you change another one in javascript

Hard to define the title ^^
I want to have to input fields. For example: one where you type in a color (string) and another for the code of the color (varchar).
Like this: |Green| |#657EC9| (just random color-code)
I do not want to learn how to find the color-code but how to match a value or variable with another. It was just an example.
What i wanna know is how I in the best way auto generate one of the fields when I fill in the second. When I type 'green' in the first field I want the code to automatically appear in the second and vice versa. I just want to do it for a few colors.
I am very new to PHP, HTML and Javascript and could need some good advice about how I should handle the problem.
Thank you
I would tend to just map values to an object literal, so:
var colors = {
Green:'#657EC9',
Red:'#00ffff'
}
Now you could get your value with colors[fieldInputVal] where fieldInputVal might be 'Green' or 'Red' although of course you'd have to test if there actually was a property there. Object literals are the main reason I rarely find a use for switch statements in JS.
As for the event JS, I'm going to be lazy and go with JQuery rather than explain attachEvent vs. addEventListener which would be necessary if you're supporting IE8 or below. If you want to normalize for that yourself and skip JQuery, look up 'addEvent contest' on quirksmode.org
$('.input_one').change( function(){
//note: only fires after the field loses focus - you tab out or focus another field
var inputVal = $(this).val();
if(colors[inputVal] !== undefined){
$('.input_two').val(colors[inputVal]);
}
} );
note: I did not test this code for syntax goofs.
If you want to be more flexible and accept 'green' or 'Green', I would just capitalize the first character before you use it for the lookup. To do the lookup on every character add, you'd have to look up the keyup or keydown events (I prefer keyup to avoid breaking the browsers back when somebody holds a key down).

Capture *all* display-characters in JavaScript?

I was given an unusual request recently that I'm having the most difficult time addressing that involves capturing all display-characters when typed into a text box. The set up is as follows:
I have a text box that has a maxlength of 10 characters. When the user attempts to type more than 10 characters, I need to notify the user that they're typing beyond the character count limit.
The simplest solution would be to specify a maxlength of 11, test the length on every keyup, and truncate back down to 10 characters but this solution seems a bit kludgy. What I'd prefer to do is capture the character before keyup and, depending on whether or not it is a display-character, present the notification to the user and prevent the default action.
A white-list would be challenging since we handle a lot of international data.
I've played around with every combination of keydown, keypress, and keyup, reading event.keyCode, event.charCode, and event.which, but I can't find a single combination that works across all browsers. The best I could manage is the following that works properly in >=IE6, Chrome5, FF3.6, but fails in Opera:
NOTE: The following code utilizes jQuery.
$(function(){
$('#textbox').keypress(function(e){
var $this = $(this);
var key = ('undefined'==typeof e.which?e.keyCode:e.which);
if ($this.val().length==($this.attr('maxlength')||10)) {
switch(key){
case 13: //return
case 9: //tab
case 27: //escape
case 8: //backspace
case 0: //other non-alphanumeric
break;
default:
alert('no - '+e.charCode+' - '+e.which+' - '+e.keyCode);
return false;
};
}
});
});
I'll grant that what I'm doing is likely over-engineering the solution but now that I'm invested in it, I'd like to know of a solution.
The simplest solution would be to specify a maxlength of 11, test the length on every keyup, and truncate back down to 10 characters but this solution seems a bit kludgy.
It is also easily defeated by cut/paste, drag/drop, right-click-undo/redo, etc. There's no reliable way to get every potential bit of input short of polling.
Why not set maxlength to 10, to let the browser enforce the limit properly, and just show a warning if there is another attempted keypress? You don't need to prevent any default action because the browser is already taking care of the length, so the amount of key checking you have to do is lower.
<input id="x" maxlength="10"/>
<div id="x-warning" style="display: none;">can't type any more!</div>
<script type="text/javascript">
function LengthMonitor(element, warning) {
element.onkeypress= function(event) {
if (event===undefined) event= window.event;
var code= 'charCode' in event? event.charCode : 'which' in event? event.which : event.keyCode;
var full= element.value.length===element.maxLength;
var typed= !(code<32 || event.ctrlKey || event.altKey || event.metaKey);
warning.style.display= (full & typed)? 'block' : 'none';
};
element.onblur= function() {
warning.style.display= 'none';
};
}
LengthMonitor(document.getElementById('x'), document.getElementById('x-warning'));
</script>
Since you're using JQuery already, .validate() is terrific for forms. Just set a rule of maxlength for your field, and you're good to go. E.g.
$("form[name='myform']").validate({
rules: {
myfield: {required:true, maxlength:10}
}
});
I had a vaguely similar situation come up in a web-app I am working on where I needed to give feedback to the user, live, as they entered data into an input.
Honestly, the best solution I came up with was just to use a setTimeout to poll the input box periodically. I did a few tests to find a nice balance between responsiveness and efficiency (I think ~400ms).
It works great, and is much better than trying to kludge together event handlers for every scenario (key-down, on-change, etc etc).
It's not as elegant as I would like, but it works.
If you really want to do this, I would watch the input in real time, checking it's length. If it's over the limit, chop it and alert the user.
This would not be a replacement for other validation of course.
I would also consider that this may be unnecessary. I suppose it's nice, but most websites get by with a hard limit and validation-on-submission.
How about presenting a message to the user when they go over the limit, but not truncating their input? You can prevent submission using the onsubmit event and the user will never have the poor experience of a maxlength or a transient input. You can highlight the box in red or display an icon as well to really drive the point home.
However, this is all client-side, so if you really need to validate the input, that must be built into the submission target's server-side logic (in the case of a form).
Alternatively, if this is happening in real-time, link the logic to a variable that is set by the key-up event. If the length limit is exceeded, present an error message, do not truncate, and do not update the private variable.

Categories

Resources