Been knocking up a simple suggestion box on an input field.. all working as it should so far except for two issues I can't seem to resolve:
1) when onkeypress event fires, the value of the input box is not correct - it misses off the last character! So for e.g. if you enter 3 chars only first two get carried through. so sometimes suggestions aren't totally accurate!
2) I need to watch out for users pressing the arrow down key, and then set focus to the first list item in the suggestion box! Can't seem to get this working though!
Have included code for you to look at! Any suggestions welcomed.. However I don't really want to use a plugin seeing as I have this 95% done already..
Here is the jsfiddle link!
http://jsfiddle.net/beardedSi/kr4Cq/
Note - I just noticed that in the fiddle verison as I have put dummy array in the code it is no longer matching suggestions - but this doesn't matter, it works fine in my working code!
work = true;
function finish() {
work = true;
}
var autoComp = $('.autoComp');
var skillInput = $('.new-skills input');
$('.new-skills input').keypress(function (e) {
var param = $(skillInput).val();
if (param.length > 0) {
$.getJSON('/recruiter/home/GetAutocompleteSkills?term=' + param, function (data) {
$(autoComp).slideDown().empty();
var items = [];
$.each(data, function (key, val) {
items.push('<li>' + val + '</li>');
});
$(autoComp).append(items.join(''));
$('.base-wrapper a').not('.button').click(function (e) {
work = false;
e.preventDefault();
$(skillInput).val($(this).text());
$(autoComp).empty().slideUp(500, finish);
});
});
}
});
$(skillInput).keydown(function (e) {
if (e.keyCode == 40) {
console.log("down");
$('.autoComp li:first:child').focus();
}
});
$('.new-skills input').blur(function () {
if (work == true)
$(autoComp).slideUp();
});
Related
I have this little piece of code that filters through a list of results and hides the divs that don't match. I am writing this for a PhoneGap iOS application. It works fine on Android, but on iOS for some reason it hides the entire search field as well after typing a few characters, not just the results.
Any idea why? I've stripped it down to almost only the HTML code and jQuery and it's still happening. I tried commenting out the $(this).hide(); part and it stops hiding the search field, so I assume somehow that's the culprit, but I can't figure out why or how to fix this. Been at it for 10 hours straight. Any ideas? Maybe I can target the results some other way?
$('#box_search').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis == "") {
$('#listing-results > .listing_container').show();
} else {
$('#listing-results > .listing_container').each(function() {
var text = ($(this).find('.listing_results_text_name').text() + $(this).find('.listing_results_text_name').data("alt")).toLowerCase();
if (text.indexOf(valThis) >= 0) {
$(this).show();
} else {
$(this).hide();
}
});
};
});
obviously I cant see the html but sometimes it helps to clean the code and just change the logic slightly
var box_search = function(e){
var myIndex = $(this).val();
val = (!myIndex || myIndex==='')?false:myIndex;
if(!myIndex){
$('#listing-results > .listing_container').show();
return;
}
//
$('#listing-results > .listing_container').each(function() {
var text = $(this).find('.listing_results_text_name').text() +
$(this).find('.listing_results_text_name').data("alt")
text = (!text || text==='')?false:text;
text = text.toLowerCase();
if(text.indexOf(myIndex.toLowerCase()) >= 0){
$(this).show();
return;
}
$(this).hide();
});
} //end of function
$('.box_search').keyup(box_search);
This is my jquery code that I am using to truncate the pasted text, so that it doesn't exceed the maxlength of an element. The default behaviour on Chrome is to check this automatically but in IE 8 and 9 it pastes the whole text and doesn't check the maxLength of an element. Please help me to do this. This is my first time asking a question here, so please let me know if I need to provide some more details. Thanks.
<script type="text/javascript">
//var lenGlobal;
var maxLength;
function doKeypress(control) {
maxLength = control.attributes["maxLength"].value;
value = control.value;
if (maxLength && value.length > maxLength - 1) {
event.returnValue = false;
maxLength = parseInt(maxLength);
}
}
//function doBeforePaste(control) {
//maxLength = control.attributes["maxLength"].value;
//if (maxLength) {
// event.returnValue = false;
//var v = control.value;
//lenGlobal = v.length;
// }
// }
$(document).on("focus","input[type=text],textarea",function(e){
var t = e.target;
maxLength = parseInt($(this).attr('maxLength'));
if(!$(t).data("EventListenerSet")){
//get length of field before paste
var keyup = function(){
$(this).data("lastLength",$(this).val().length);
};
$(t).data("lastLength", $(t).val().length);
//catch paste event
var paste = function(){
$(this).data("paste",1);//Opera 11.11+
};
//process modified data, if paste occured
var func = function(){
if($(this).data("paste")){
var dat = this.value.substr($(this).data("lastLength"));
//alert(this.value.substr($(this).data("lastLength")));
// alert(dat.substr(0,4));
$(this).data("paste",0);
//this.value = this.value.substr(0,$(this).data("lastLength"));
$(t).data("lastLength", $(t).val().length);
if (dat == ""){
this.value = $(t).val();
}
else
{
this.value = dat.substr(0,maxLength);
}
}
};
if(window.addEventListener) {
t.addEventListener('keyup', keyup, false);
t.addEventListener('paste', paste, false);
t.addEventListener('input', func, false);
} else{//IE
t.attachEvent('onkeyup', function() {keyup.call(t);});
t.attachEvent('onpaste', function() {paste.call(t);});
t.attachEvent('onpropertychange', function() {func.call(t);});
}
$(t).data("EventListenerSet",1);
}
});
</script>
You could do something like this, mind you this was done in YUI but something simlar can be done for jquery. All you need to do is get the length of the comment that was entered and then truncate the text down the the desired length which in the case of this example is 2000 characters.
comment_text_box.on('valuechange', function(e) {
//Get the comment the user input
var comment_text = e.currentTarget.get('value');
//Get the comment length
var comment_length = comment_text.length;
if(comment_length > 2000){
alert('The comment entered is ' + comment_length + ' characters long and will be truncated to 2000 characters.');
//Truncate the comment
var new_comment = comment_text.substring(0, 2000);
//Set the value of the textarea to truncated comment
e.currentTarget.set('value', new_comment);
}
});
You're putting too much effort into something that is apparently a browser quirk and is mostly beyond your control and could change in the future. In fact, I can't recreate this in IE10 - it behaves just like Chrome for me.
Make sure you are validating the length on the server-side, since it's still possible to get around a field's maxlength when submitting the form input to the server (see this somewhat similar question). That's not to say you shouldn't have some client-side logic to validate the length of the input to enforce the maxlength constraint - I just think you don't need to go to the length you are attempting here to essentially intercept a paste command. Keep it simple - having a basic length validation check in your JavaScript is going to be a lot less messy than what you have here.
Perhaps consider a bit of jQuery like this:
$("#myTextControl").change(function() {
if ($(this).val().length > $(this).attr('maxlength')) {
DisplayLengthError();
}
});
(where DisplayLengthError() is an arbitrary function that triggers some kind of feedback to the user that they have exceeded the maxlength constraint of the field, be it an error label, and alert box, etc.)
I know we can use bind paste event as below:
$('#id').bind('paste', function(e) {
alert('pasting!')
});
But the problem is, that it will call before the pasted text paste. I want a function to be triggered after the right click -> paste text pasted on the input field, so that I can access the pasted value inside the event handler function.
.change() event also doesn't help. Currently I use .keyup() event, because I need to show the remaining characters count while typing in that input field.
Kind of a hack, but:
$("#id").bind('paste', function(e) {
var ctl = $(this);
setTimeout(function() {
//Do whatever you want to $(ctl) here....
}, 100);
});
Why not use the "input" event?
$("#id").bind('input', function(e) {
var $this = $(this);
console.log($this.val());
});
This will stop user from any pasting, coping or cutting with the keyboard:
$("#myField").keydown(function(event) {
var forbiddenKeys = new Array('c', 'x', 'v');
var keyCode = (event.keyCode) ? event.keyCode : event.which;
var isCtrl;
isCtrl = event.ctrlKey
if (isCtrl) {
for (i = 0; i < forbiddenKeys.length; i++) {
if (forbiddenKeys[i] == String.fromCharCode(keyCode).toLowerCase()) {
return false;
}
}
}
return true;
});
This one will do the same for the mouse events:
$("#myField").bind("cut copy paste",function(event) {
event.preventDefault();
});
Even though the above one will not prevent right clicks, the user will not be able to paste, cut or copy from that field.
To use it after the event, like you wondered on your question, you must use JavaScript Timing Event
setTimeout(function() {
// your code goes here
}, 10);
I had the same issue, I opted to replicate the paste action through javascript and use that output instead:
var getPostPasteText = function (element, pastedData) {
// get the highlighted text (if any) from the element
var selection = getSelection(element);
var selectionStart = selection.start;
var selectionEnd = selection.end;
// figure out what text is to the left and right of the highlighted text (if any)
var oldText = $(element).val();
var leftPiece = oldText.substr(0, selectionStart);
var rightPiece = oldText.substr(selectionEnd, oldText.length);
// compute what the new value of the element will be after the paste
// note behavior of paste is to REPLACE any highlighted text
return leftPiece + pastedData + rightPiece;
};
See IE's document.selection.createRange doesn't include leading or trailing blank lines for source of the getSelection function.
No need to bind :
$(document).on('keyup input', '#myID', function () {
//Do something
});
In a table, I have a row with two inputs - one select and one text. What I want to achieve is that if one has a value, then the other (on the same row) should disable. This works correctly onload when there is a value in the textbox, but doesn't seem to work when there is a value in only the select box.
As you can see in the example here: http://jsfiddle.net/anAgent/UBUhn/1/ the "change" event works correctly, but it doesn't work onload.
Any help would greatly be appreciated!
I'm working with jQuery 1.5.2 and with both Google Chrome and IE9
Update With Final Code
Thanks #scoopseven and #eicto for your input. Based on these two answers, here's the final code. I hope it helps someone else.
$(document).ready(function() {
$(".validation-compare").change(runRowValidation);
$(".validation-compare").each(runRowValidation);
});
function runRowValidation() {
var $me = $(this),
$other = $('.validation-compare',$me.closest("tr")).not($me),
mVal = $me.val(),
oVal =$other.val();
if(mVal != "" && oVal == "") {
$me.removeAttr('disabled');
$other.attr('disabled',1);
} else if(mVal == "" && oVal != "") {
$other.removeAttr('disabled');
$me.attr('disabled',1);
} else {
$other.removeAttr('disabled');
$me.removeAttr('disabled');
}
}
You can see it in action at: http://jsfiddle.net/anAgent/UBUhn/24/
i don't think that you you need to set the class valid, all you have to do is replacing
var $otherInput = $('.validation-compare', $parent).not('.valid');
by
var $otherInput = $('.validation-compare', $parent).not($me);
And this will resolve your problem on onload. Here is an example
var validme=function() {
var me=$(this);
me.removeClass('validation-compare');
if (me.val()) {
console.log(me);
me.addClass('valid');
me.parent().parent().find('.validation-compare').attr('disabled',1);
me.addClass('validation-compare');
return;
}
me.removeClass('valid');
if (me.parent().parent().find('.validation-compare.valid').length<1) {
me.parent().parent().find('.validation-compare').removeAttr('disabled'); }
me.addClass('validation-compare');
}
$('.validation-compare').each(validme);
$('.validation-compare').change(validme)
http://jsfiddle.net/UBUhn/22/
You need to separate out the function and call it on the click event and on page load. Something like this:
jQuery(function($){
function myFunction() {
// do somestuff
}
// myFunction needs to be called when select is clicked and when page is loaded
$('#someelement').click(myFunction);
$(document).ready(myFunction);
});
I have listview with two checkboxes in itemtemplate.
I want to validate that user can only select only one checkbox in each row.
The behaviour you're describing is accomplished using standard HTML radiobuttons. If you change your design to use these you'll get the benefit that
The user can only select a single item, no extra javascript needed
Users expect to be able to choose multiple checkboxes but only a single radiobutton IE you're working with their expectations
If you're still sure you want to use jQuery then something like this should do it.
$(':checkbox').change(function(){
if($(this).attr('checked')) {
$(this).siblings(':checkbox').attr('checked',false);
}
});
#vinit,
just a little change, you forgot the else part,
$('input:checkbox[id*=EmailCheckBox]').click(uncheckOthercheckbox);
$('input:checkbox[id*=SMSCheckBox]').click(uncheckOthercheckbox);
function uncheckOthercheckbox() {
if (this.id.indexOf("EmailCheckBox") != -1) {
var otherCheckBoxId = this.id.substring(0, this.id.indexOf("EmailCheckBox")) + "SMSCheckBox";
}
else {
var otherCheckBoxId = this.id.substring(0, this.id.indexOf("SMSCheckBox")) + "EmailCheckBox";
}
var i = "#" + otherCheckBoxId;
if (this.checked) {
$(i).removeAttr('checked');
}
else {
if ($(i).attr('checked') === false) {
$(i).attr('checked', 'checked');
}
}
}
Thanks for the reply. had also asked one of my friend and he gave me the following solution which is working fine. Posting it, if anybody needs it.-
say ur checkboxes in the 2 clumns are named EmailCheckBox and SMSCheckBox
then use this code to toggle the checkboxes in each single row:
$('input:checkbox[id*=EmailCheckBox]').click(uncheckOthercheckbox);
$('input:checkbox[id*=SMSCheckBox]').click(uncheckOthercheckbox);
function uncheckOthercheckbox() {
if (this.id.indexOf("EmailCheckBox") != -1) {
var otherCheckBoxId = this.id.substring(0, this.id.indexOf("EmailCheckBox")) + "SMSCheckBox";
}
else {
var otherCheckBoxId = this.id.substring(0, this.id.indexOf("SMSCheckBox")) + "EmailCheckBox";
}
var i = "#" + otherCheckBoxId;
if (this.checked) {
$(i).removeAttr('checked');
}
}