I'm running into issues with the following code:
var setupSearch = {
searchSuggest: function(field) {
$.getJSON('/get-all-journals', {'url':'on'}, function(data) {
var SHCount = Number($.cookie('SHCount'));
var SHArray = new Array();
for (i=1; i <= SHCount; i++) {
SHArray.push($.cookie('SH'+i));
}
$(field).ddautocomplete(removeDuplicate(SHArray), data.response.docs, {
matchContains: true,
max: 5,
cacheLength: 5000,
selectFirst: false,
scroll: false,
formatResult: function(str) { return str; },
formatItem2: function(item) {
return item.journal_display_name;
},
formatMatch2: function(item) {
return item.journal_display_name;
},
formatResult2: function(item) {
return item.journal_display_name;
}
});
});
},
searchForm: function(form) {
var field = form.find('textarea');
// Setup query field for default text behavior
// setupField(field);
setupSearch.searchSuggest(field);
field.autogrow();
field.keydown(function(e) {
if (e.keyCode == 13) {
form.submit();
return false;
}
});
// Make all forms submitting through Advanced Search Form
form.submit(function(e) {
e.preventDefault();
setupSearch.submitSearch(form, field);
});
},
submitSearch: function(form, field) {
if (advancedSearch.checkMinFields() || (!field.hasClass('defaultText') && field.val() != '')) {
// Sync the refine lists
// syncCheckboxLists($('#refineList input'), $('#advancedRefineList input'));
form.find('button').addClass('active');
$('#advancedSearchForm').submit();
} else {
$('#queryField').focus();
}
},
When I try to use the autocomplete drop-down by hitting enter, it seems to hit a "race condition" where the form will submit what I've typed rather than what autocomplete places into the textfield. Is there some way I can control the order of events so that the form.submit() will use what autocomplete fills into the text field?
The actual autocomplete dropdown menu is most likely represented as a styled list (or some other element) that is floated to be positioned below the textbox. On submit, have your function wait (a second or two max) for the autocomplete menu to be either destroyed or hidden. This will ensure that the plugin has time to fill in the textbox before the data is submitted.
EDIT
Try something like this:
$("#myDropdown").bind("autocompleteclose", function(){
// Continue with submitting your form
});
Use that where you would submit your form, and put the submitting code inside the callback. That way, it will wait for the autocomplete to close before submitting the form. You will want to add some kind of timeout to this to prevent it from submitting after a long delay (not sure when something like this might happen, though).
Related
I have a javascript function that is triggered upon form submission:
var reusecard = true;
var form = document.getElementById('paymentForm');
Worldpay.useOwnForm({
'clientKey': 'xxxxx',
'form': form,
'reusable': reusecard,
'callback': function(status, response) {
document.getElementById('paymentErrors').innerHTML = '';
if (response.error) {
Worldpay.handleError(form, document.getElementById('paymentErrors'), response.error);
$("#paymentErrors").addClass("highlighted_box");
} else {
var token = response.token;
Worldpay.formBuilder(form, 'input', 'hidden', 'token', token);
form.submit();
}
}
});
I want to change the 'reusable' field to false, if the user changes a select box to "NO" on a form, using JQuery.
The ID of the select box is "reuse", which has 2 value choices, "YES" and "NO".
The JQuery I have been trying is:
$(function() {
$( "#reuse" ).change(function() {
if ($("#reuse").val() == "YES") {
reusecard = true;
} else {
reusecard = false;
}
alert (reusecard);
});
});
Whenever the user changes the select box, the Javascript alert works fine, and displays the correct boolean value. However, when the function runs, it always takes the initially set value, and not the changed value.
What am I doing wrong?
Thanks
I am using MVC3 and unobstrusive validation. On certain occasions I want to submit a form even if the form is incomplete providing two fields are selected. The JavaScript I am using is as follows:
$('#form_section11').submit(function () {
//event.preventDefault(); //stops form from submitting immediately
var validatorSection11 = $('#form_section11').validate();
if (!$(this).valid()) {
// or family name and date of birth
var FamilyNameExists = true;
var DateOfBirthExists = true;
if (validatorSection11.errorMap["FamilyName"]) { FamilyNameExists = false; }
if (validatorSection11.errorMap["DateOfBirth"]) { DateOfBirthExists = false; }
// show the partial save rules
$('#ParitalSaveIntructions').show();
// show the partial save checkbox
if (FamilyNameExists && DateOfBirthExists) {
$("#AgreePartialSave").show();
if ($("#PartialSave").is(':checked')) {
// partial save has been requested
return true; //// <- save not happening, INCORRECT action
}
// clear perinatalWomanView_PartialSave
$("#PartialSave").removeAttr('checked');
}
return false; // <- save not happening, correct action
}
return true; // <- save happens, correct action
});
The user is presented with a checkbox to confirm incomplete submission. I've indicated where the JavaScript works and where it fails.
I've also added
var validatorSection11 = $('#form_section11').validate(
{
onsubmit: false
}
);
This has no effect. My questions are:
Why is the original return true not functioning?
Am I using the onsubmit: false correctly?
Is there a better way of doing this?
Thanks in advance.
Try using a variable (save) instead of multiple return statements:
$('#form_section11').submit(function (e) {
'use strict';
var self = $(this),
save = false,
FamilyNameExists = true,
DateOfBirthExists = true,
validatorSection11 = self.validate();
if (!self.valid()) {
// or family name and date of birth
FamilyNameExists = true;
DateOfBirthExists = true;
if (validatorSection11.errorMap["FamilyName"]) {
FamilyNameExists = false;
}
if (validatorSection11.errorMap["DateOfBirth"]) {
DateOfBirthExists = false;
}
// show the partial save rules
$('#ParitalSaveIntructions').show(); // should this be "Parital" or "Partial"
// show the partial save checkbox
if (FamilyNameExists && DateOfBirthExists) {
$("#AgreePartialSave").show();
//if ($("#PartialSave").is(':checked')) { // Comment in answer
// // partial save has been requested
// save = true;
//}
save = $("#PartialSave").is(':checked');
// clear perinatalWomanView_PartialSave
$("#PartialSave").removeAttr('checked');
}
//save = false; //This was overriding the `save = true` above.
}
if (!save) {
e.preventDefault(); // stops form from submitting immediately
}
return save;
});
Also, at the section "Comment in answer", this section will likely only execute after the form has been resubmitted because the following would have to happen:
$("#AgreePartialSave").show(); has to execute and show the section.
The user has to put a check in $("#PartialSave") for $("#PartialSave").is(':checked') to return true.
The $('#form_section11').submit() has to fire again for that section of the handler to evaluate.
If there is a different button that the user has to click to do a partial save, you'll likely want to move that whole section into that button handler.
I know it is not the smartest idea, but I still have to do it.
Our users want to use ENTER like TAB.
So, the best I came up with is this:
Ext.override(Ext.form.field.Base, {
initComponent: function() {
this.callParent(arguments);
this.on('afterrender', function() {
var me=this;
this.getEl().on('keypress',function (e){
if(e.getKey() == 13) {
me.nextNode().focus();
}
});
});
}
});
But it still does not work exactly the same way as TAB.
I mean, it works OK with input fields, but not other controls.
May be there is some low-level solution.
Any ideas?
In the past I've attached the listener to the document, something like this:
Ext.getDoc().on('keypress', function(event, target) {
// get the form field component
var targetEl = Ext.get(target.id),
fieldEl = targetEl.up('[class*=x-field]') || {},
field = Ext.getCmp(fieldEl.id);
if (
// the ENTER key was pressed...
event.ENTER == event.getKey() &&
// from a form field...
field &&
// which has valid data.
field.isValid()
) {
// get the next form field
var next = field.next('[isFormField]');
// focus the next field if it exists
if (next) {
event.stopEvent();
next.focus();
}
}
});
For Ext.form.field.Text and similar xtypes there is a extra config enableKeyEvents that needs to be set before the keypress/keydown/keyup events fire.
The enableKeyEvents config option needs to be set to true as it's default to false.
ExtJS API Doc
Disclaimer: I'm not an expert on ExtJs.
That said, maybe try something like:
if (e.getKey() === 13) {
me.blur();
return false; // cancel key event to prevent the [Enter] behavior
}
You could try this
if (e.getKey() === 13) {
e.keyCode = Ext.EventObject.TAB
this.fireEvent(e, {// any additional options
});
}
Haven't really tried this ever myself.
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.
Is is possible to restrict the user input to only the source values with JQuery autocomplete plugin?
For example, if the source array contains "Bold","Normal","Default","100","200", the user is allowed to only type those values.
I see you already have a solution. Here's a similar way to do this, since I already put some time in on it.
http://jsfiddle.net/pxfunc/j3AN7/
var validOptions = ["Bold", "Normal", "Default", "100", "200"]
previousValue = "";
$('#ac').autocomplete({
autoFocus: true,
source: validOptions
}).keyup(function() {
var isValid = false;
for (i in validOptions) {
if (validOptions[i].toLowerCase().match(this.value.toLowerCase())) {
isValid = true;
}
}
if (!isValid) {
this.value = previousValue
} else {
previousValue = this.value;
}
});
I have a simple alternative. Check this out:
http://jsfiddle.net/uwR3Z/2/
Basically an onChange event on the textbox to clear out the value works the same.
Here is the js:
var validOptions = ["Bold", "Normal", "Default", "100", "200"];
$('#auto-complete-input').autocomplete({
autoFocus: true,
source: validOptions
});
function clearAutoCompleteInput() {
$("#auto-complete-input").val('');
}
And html:
<label for="auto-complete-input">Select one: </label>
<input id="auto-complete-input" type="text" onChange="clearAutoCompleteInput()" />
I agree with the comment made by Rephael, as you want to limit the possible values to the one in autocomplete, a safer choice would be to have a select dropdown.
As a final user can be frustrating to enter data in a textbox and not being able to write what I want. The choice of a select dropdown is "socially" accepted to be limited.
I figured out a way.
Add the following option to the plugin. This works for when the source is an array.
change: function (event, ui) {
if (!ui.item) {
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i"),
valid = false;
$.each(YOUR_SOURCE_ARRAY_NAME, function (index, value) {
if (value.match(matcher)) {
this.selected = valid = true;
return false;
}
});
if (!valid) {
// remove invalid value, as it didn't match anything
$(this).val("");
return false;
}
}
}
This is an old question but I what I do is
set a flag to false when entering the field (onfocus)
Set the flag to true in the autocomplete select event
Test that flag in the field onblur event.
If it is true the input is good, otherwise it is bad.