jquery autocomplete enter key - javascript

Currently the autocomplete action when pressing the Enter key on a selected element is to put that elements value into the input box.
How can I modify the behavior so that pressing the Enter key on an element triggers that elements embedded url. To simplify I'd like to make the Enter key have the same behavior as a mouse click on a returned element.
Thanks

Easy !
$(".quicksearch-input").autocomplete({
minLength: 4, // minimum length to trigger suggestions
// ... + other configuration options
select: function(e, ui) { // define select handler
var uri = ui.item.link; // where ui.item.link itself is defined in your object which you composing when retrieving JSON from endpoint
window.location = uri; // forwarding to the URL obtained
}, // select //
});
But everything depends on your way of implementation.

This is the function that is called when you select an item and hit enter. The hacky code you see in this function extracts the href from the link and redirects to that url.
$("#searchBox").result(function(event, data, formatted) {
var p = data.toString();
p = p.replace('<a href="', '');
var url = p.substr(0, p.indexOf('"'));
p = p.replace('</a>', '');
p = p.substr(p.indexOf('>') + 1, p.length - p.indexOf('>') - 1);
window.location = "" + url;
return false;
});

Did you try keypress event
have a look on the events
http://api.jquery.com/keypress/
http://api.jquery.com/category/events/keyboard-events/
http://api.jquery.com/category/events/mouse-events/

Related

Mirroring input content with non-printable chars like CTRL, ALT or shift key

When non-printable char is pressed, it's replaced with let's say for CTRL=17 with "[CTRL]".
Here is code an example
$('#textbox1').keyup(function (event) {
if (8 != event.keyCode) {
if(17==event.keyCode){
$('#textbox1').val($('#textbox1').val()+"[CTRL]")
$('#textbox2').val($('#textbox1').val());
}else{
$('#textbox2').val($('#textbox1').val());
}
} else {
$('#textbox2').val($('#textbox1').val());
}
});
the problem is when user presses backspace the second input must reflect the content of the first one, so "[CTRL]" must be deleted at once like any other chars.
You could make use of the keyCode and/or in combination with charCode (if required). Basic idea would be:
Create a map of all required key codes in an array/object
Handle event for say keydown and listen for keycode
Look for the keycode in your map and if found show it
prevent the default (to prevent e.g. say backspace browsing back)
If not found in map, let the character go thru as usual.
A very basic example:
Demo: http://jsfiddle.net/abhitalks/L7nhZ/
Relevant js:
keyMap = {8:"[Backspace]",9:"[Tab]",13:"[Enter]",16:"[Shift]",17:"[Ctrl]",18:"[Alt]",19:"[Break]",20:"[Caps Lock]",27:"[Esc]",32:"[Space]",33:"[Page Up]",34:"[Page Down]",35:"[End]",36:"[Home]",37:"[Left]",38:"[Up]",39:"[Right]",40:"[Down]",45:"[Insert]",46:"[Delete]"};
$("#txt").on("keydown", function(e) {
// check if the keycode is in the map that what you want
if (typeof(keyMap[e.keyCode]) !== 'undefined') {
// if found add the corresponding description to the existing text
this.value += keyMap[e.keyCode];
// prevent the default behavior
e.preventDefault();
}
// if not found, let the entered character go thru as is
});
Edit: (as per the comments)
The concept remains the same, just copying the value to the second input:
Demo 2: http://jsfiddle.net/abhitalks/L7nhZ/3/
$("#txt1").on("keyup", function(e) {
if (typeof(keyMap[e.keyCode]) !== 'undefined') {
this.value += keyMap[e.keyCode];
e.preventDefault();
}
$("#txt2").val(this.value); // copy the value to the second input
});
Regarding deletion of the description, I could not get it done by caching the last inserted descrition from the map. Somehow, I kept struggling with the regex with a variable. Anyway, a simpler solution is to just add another event handler for keyup with hard-coded map.
Thanks to #serakfalcon for (that simple solution), which we are using here:
$('#txt1').keydown(function(event) {
if(8 == event.keyCode) {
var el = $(this);
el.val(el.val().replace(/\[(Tab|Enter|Shift|Ctrl|Alt|Break|Caps Lock|Esc|Space|Page (Up|Down)|End|Home|Left|Up|Right|Down|Insert|Delete)\]$/,' '));
$("#txt2").val(el.val());
}
});
You can check in the keydown for the last character in the input field. If it's a ] you can remove everything from the right to the last found opening bracket [. Unfortunatly this does not work if you're cursor is inside '[ ]'.
$('#textbox1').keydown(function(event) {
if(8 == event.keyCode) {
var element = $(this),
value = element.val(),
lastChar = value.slice(-1);
if(lastChar == ']') {
var lastIndex = value.lastIndexOf('['),
index = value.length - lastIndex;
element.val(value.slice(0, -index) + "]");
}
}
});
Fiddle
you can always use a regex.
$('#textbox1').keydown(function(event) {
if(8 == event.keyCode) {
var el = $(this);
el.val(el.val().replace(/\[(CTRL|ALT|SHIFT)\]$/,' '));
}
});
fiddle
Edit: combined with abhitalks code

Disabling/enabling a button based on multiple other controls using Javascript/jQuery

I have a bunch of controls:
When a user clicks the Generate button, a function uses all of the values from the other controls to generate a string which is then put in the Tag text box.
All of the other controls can have a value of null or empty string. The requirement is that if ANY of the controls have no user entered value then the Generate button is disabled. Once ALL the controls have a valid value, then the Generate button is enabled.
What is the best way to perform this using Javascript/jQuery?
This can be further optimized, but should get you started:
var pass = true;
$('select, input').each(function(){
if ( ! ( $(this).val() || $(this).find(':selected').val() ) ) {
$(this).focus();
pass = false;
return false;
}
});
if (pass) {
// run your generate function
}
http://jsfiddle.net/ZUg4Z/
Note: Don't use this: if ( ! ( $(this).val() || $(this).find(':selected').val() ) ).
It's just for illustration purposes.
This code assumes that all the form fields have a default value of the empty string.
$('selector_for_the_parent_form')
.bind('focus blur click change', function(e){
var
$generate = $('selector_for_the_generate_button');
$generate.removeAttr('disabled');
$(this)
.find('input[type=text], select')
.each(function(index, elem){
if (!$(elem).val()) {
$generate.attr('disabled', 'disabled');
}
});
});
Basically, whenever an event bubbles up to the form that might have affected whether the generate button ought to be displayed, test whether any inputs have empty values. If any do, then disable the button.
Disclaimer: I have not tested the code above, just wrote it in one pass.
If you want the Generate button to be enabled as soon as the user presses a key, then you probably want to capture the keypress event on each input and the change event on each select box. The handlers could all point to one method that enables/disables the Generate button.
function updateGenerateButton() {
if (isAnyInputEmpty()) {
$("#generateButton").attr("disabled", "disabled");
} else {
$("#generateButton").removeAttr("disabled");
}
}
function isAnyInputEmpty() {
var isEmpty = false;
$("#input1, #input2, #select1, #select2").each(function() {
if ($(this).val().length <= 0) {
isEmpty = true;
}
});
return isEmpty;
}
$("#input1, #input2").keypress(updateGenerateButton);
$("#select1, #select2").change(updateGenerateButton);
The above assumes that your input tags have "id" attributes like input1 and select2.

Question on tabbing to next NON-READONLY field

On blur of field1, field2 is set to READONLY but the cursor on my page then defaults to field2 and the cursor is located at the END of the value and when the user clicks the backspace button the value can be erased. I would like the ability to have the cursor move to the next NON-READONLY or ENABLED field on the page. Is that do-able with jQuery?
Any help/direction would be appreciated.
Here is my code:
$(function() {
$("#ARTransferForm\\:fromAccountAmt").blur(function() {
var origAccountAmount = $("#ARTransferForm\\:fromAccountAmt").val();
var fromAccountAmount = $("#ARTransferForm\\:fromAccountAmt").val();
// Call validation "r2" function
var modFromAccountAmount = r2(fromAccountAmount);
//alert("modFromAccountAmount = " + modFromAccountAmount);
fromAccountAmount = $("#ARTransferForm\\:fromAccountAmt").val(modFromAccountAmount).val();
//alert ("modified fromAccountAmount = " + fromAccountAmount);
if (modFromAccountAmount != "N.aN") {
var firstChar = fromAccountAmount.charAt(0);
var fromAcctAmtLen = $("#ARTransferForm\\:fromAccountAmt").val().length;
if (firstChar == "-") {
var revFromAcctAmt = fromAccountAmount.substring(1, fromAcctAmtLen);
$("#ARTransferForm\\:toAccountAmt").val(revFromAcctAmt);
$("#ARTransferForm\\:toAccountAmt").attr("readonly", "readonly");
} else {
$("#ARTransferForm\\:toAccountAmt").val("-"+fromAccountAmount);
$("#ARTransferForm\\:toAccountAmt").attr("readonly", "readonly");
}
} else {
$("#ARTransferForm\\:fromAccountAmt").val(origAccountAmount);
$("#ARTransferForm\\:fromAccountAmt").select();
alert("Invalid From Amount Format. Use ##.## (NO commas or $ sign)");
}
});
});
Have you tried modifying tabindexes onblur, before RETURN TRUE, to control where the cursor goes? It's kind of a hack, but there you go.
Also, you could use a delegated event (perhaps on the form) to intercept and return false on any keypress events that would modify the value of any readonly input. Something like:
$('#ARTransferForm *[readonly]').live("keypress", function(event) {
// compare keycode to blacklist: backspace, perhaps delete too?
if(bKeyIsBlacklisted) {
event.preventDefault();
return false;
}
});
(Note: that is pretty pseudocodeonous. You'll want to double-check the syntax for sizzle's attribute selectors, as well as jquery's event delegation signature. And be real careful about how wide you cast your "no keys" net: try to avoid disallowing Copy and other operations performed with keyboard shortcuts. You will need to check for a modifier key to distinguish between the user trying to type "c" and Ctrl+C.
Which browser(s) are you testing this in?

Determining which submit button was clicked from jQuery/JavaScript [duplicate]

This question already has answers here:
How can I get the button that caused the submit from the form submit event?
(22 answers)
Closed 9 years ago.
I'm ajaxifying some forms from a PHP application I didn't write. To do this, I came up with this clever solution:
jQuery("form").submit(function(event) {
// get some values from elements on the page:
var the_form = jQuery(this);
var data = the_form.serialize();
var url = the_form.attr( 'action' );
var button = event.originalEvent.explicitOriginalTarget;
data = data + "&" + button.name + "=" + button.value;
// Send the data using post and put the results in a div
jQuery.post( url, data, function() {
//Do something crazy
});
// stop form from submitting normally
if (event.preventDefault)
{
event.preventDefault();
}
else
{
event.returnValue = false;
}
});
Which works perfectly. I went away rejoicing. The problem is, I inadvertently used a Mozilla/Gecko only property to determine which button was clicked. (event.originalEvent.explicitOriginalTarget) Which means this only works in Firefox. :-(
All of this is necessary because the web app I'm augmenting relies on the button name/value being in the post data to process the form correctly. So, my question in simple terms would be:
What is the best, cross-browser way to determine which button was clicked in jQuery's submit event?
Edit:
And here is my solution.
jQuery("some selector that targets your form").find(":submit").click(function(event) {
// get some values from elements on the page:
var the_form = jQuery(this).parents("form");
var data = the_form.serialize();
var url = the_form.attr( 'action' );
var button = event.target;
data = data + "&" + button.name + "=" + button.value;
// Send the data using post and put the results in a div
jQuery.post( url, data, function() {
//Do something crazy
});
// stop form from submitting normally
if (event.preventDefault)
{
event.preventDefault();
}
else
{
event.returnValue = false;
}
});
See this question: Crossbrowser equivalent of explicitOriginalTarget event parameter
You're going to have to attach the event listeners to the buttons instead of the form to get a good reliable way of determining which one fired the submit.
http://api.jquery.com/event.target/
jquery.event.target should work because it is normalised for most browsers.
jquery.event.currentTarget can be used to retrieve the current item in the event bubbling chain.
Edit--
After some reflection and #greg's suggestion:
I've posted a code snippet on jsfiddle.
Using click handlers to submit the form is problematic beacuse you cannot use submit event handlers for validation (which is the way pretty much any validator plugin does it). Also, when you are not using AJAX to post, disabling submit buttons can have weird effects in some browsers if done in the click event and not the submit event.
The way jQuery.Form solves this is to set up a click handler which stores the clicked button (and then clears it with a small timeout), and use the submit handler to actually send the form contents via AJAX.
Here is a function I used to "ajaxify" my forms with jQuery.
function ajaxifyForm(form, callback)
{
var clicked
form.find("button").click(function()
{
if (clicked != null) clicked.removeAttr("data-clicked")
clicked = $(this)
$(this).attr("data-clicked", 1)
})
form.submit(function(event)
{
var data = {}
var name = ""
form.find(":input").each(function()
{
var input = $(this)
if (!(name = input.attr("name"))) return
switch (input.attr("type"))
{
case "radio":
case "checkbox":
if (input.attr("checked")) data[name] = input.val()
break
case "submit":
if (input.attr("data-clicked")) data[name] = input.val()
break
default:
data[name] = input.val()
}
})
$.ajax({
url: form.attr("action"),
success: function(data)
{
if (typeof callback == "function") callback("success")
},
error: function()
{
if (typeof callback == "function") callback("error")
},
data: data,
type: form.attr("method")
})
return false
})
return form
}

How to dynamically reconfigure Drupal's jQuery-based autocomplete at runtime?

Drupal has a very well-architected, jQuery-based autocomplete.js. Usually, you don't have to bother with it, since it's configuration and execution is handled by the Drupal form API.
Now, I need a way to reconfigure it at runtime (with JavaScript, that is). I have a standard drop down select box with a text field next to it, and depending what option is selected in the select box, I need to call different URLs for autocompletion, and for one of the options, autocompletion should be disabled entirely. Is it possible to reconfigure the existing autocomplete instance, or will I have to somehow destroy and recreate?
Have a look at misc/autocomplete.js.
/**
* Attaches the autocomplete behavior to all required fields
*/
Drupal.behaviors.autocomplete = function (context) {
var acdb = [];
$('input.autocomplete:not(.autocomplete-processed)', context).each(function () {
var uri = this.value;
if (!acdb[uri]) {
acdb[uri] = new Drupal.ACDB(uri);
}
var input = $('#' + this.id.substr(0, this.id.length - 13))
.attr('autocomplete', 'OFF')[0];
$(input.form).submit(Drupal.autocompleteSubmit);
new Drupal.jsAC(input, acdb[uri]);
$(this).addClass('autocomplete-processed');
});
};
The input's value attribute is used to create ACDB, which is a cache of values for that autocomplete path (uri). That is used in the Drupal.jsAC function to bind the element's keydown, keyup and blur events with triggers the autocomplete ajax operation (which caches its values in the ACDB object for that element), opens popups, etc.
/**
* An AutoComplete object
*/
Drupal.jsAC = function (input, db) {
var ac = this;
this.input = input;
this.db = db;
$(this.input)
.keydown(function (event) { return ac.onkeydown(this, event); })
.keyup(function (event) { ac.onkeyup(this, event); })
.blur(function () { ac.hidePopup(); ac.db.cancel(); });
};
What you'll need to do is change the input's value and also reattach the behavior. You'll reattach the behavior by removing the '.autocomplete-processed' class on the autocomplete text field input element and then call Drupal.attachBehaviors(thatInputElement).
This may not work. Things can go very badly if you attach the same behavior to the same element over and over again. It may be more sensible to create different autocomplete fields and simply hide and show them based on the value of the select. This would still require calling Drupal.attachBehaviors when you hide and display the widget, but the same behavior would remain attached if the switch happened more than once, and you wouldn't risk attaching the same behavior to the element multiple times.
Well, for reference, I've thrown together a hack that works, but if anyone can think of a better solution, I'd be happy to hear it.
Drupal.behaviors.dingCampaignRules = function () {
$('#campaign-rules')
.find('.campaign-rule-wrap')
.each(function (i) {
var type = $(this).find('select').val();
$(this).find('.form-text')
// Remove the current autocomplete bindings.
.unbind()
// And remove the autocomplete class
.removeClass('form-autocomplete')
.end()
.find('select:not(.dingcampaignrules-processed)')
.addClass('dingcampaignrules-processed')
.change(Drupal.behaviors.dingCampaignRules)
.end();
if (type == 'page' || type == 'library' || type == 'taxonomy') {
$(this).find('input.autocomplete')
.removeClass('autocomplete-processed')
.val(Drupal.settings.dingCampaignRules.autocompleteUrl + type)
.end()
.find('.form-text')
.addClass('form-autocomplete');
Drupal.behaviors.autocomplete(this);
}
});
};
This code comes from the ding_campaign module. Feel free to check out the code if you need to do something similar. It's all GPL2.
it should be as simple as dinamically change the "value" of the "hidden" autocomplete
input element that comes aside autocomplete form fields. ie.
$('select#myelement').bind('change', function(e) {
if (/* something */) {
$('input#myelement-autocomplete').attr('value', '/mycustom/path');
}
});
Working solution for Drupal 5
/*
* Błażej Owczarczyk
* blazej.owczarczyk#gmail.com
*
* Name: Autocomplete City Taxonomy
* Description: Hierarchical city selecting (province select and city autocomplete)
*/
var Act = Act || {};
Act.init = function () {
$('select.act-province').change(Act.provinceChange); // select with top taxonomy terms
}
/*
* Change event of select element
*/
Act.provinceChange = function () {
var context = $(this).parent().parent();
var currentTid = $(this).val();
Act.rewriteURI(context, currentTid);
Act.unbind();
Drupal.autocompleteAutoAttach();
};
/*
* Changes the value of hidden autocomplete input
*/
Act.rewriteURI = function (context, newTid) {
var tempArray;
tempArray = $('.autocomplete', context).val().split('/');
tempArray.pop();
tempArray.push(newTid);
$('.autocomplete', context).val(tempArray.join('/'));
};
/*
* Prevents muliple binding of the same events
*/
Act.unbind = function () {
$('.form-autocomplete').unbind().parents('form').unbind('submit');
};
$(document).ready(Act.init);

Categories