I have a search form that has different elements in it, checkboxes, selects, text fields etc. Each change is accompanied by an ajax call that gets the number of results as a sort of counter. I would like to reset only the previous element that caused the counter to return a value of 0.
I was thinking about keeping track of each change in a variable, and each time the counter evaluates to 0, I would then reset the element that caused the change. I however fear that this could force me to handle all the different elements differently with a lot of code and jumping around.
Is there a possible more elegant solution to the problem that anybody can think of? I would appreciate the help.
I cannot comment your question, but : if I understand correcty, there is a big form, and each change on any element, triggers an ajax call, that returns a resultset.
If this resultset size is zero, then, you want the form to reset to previous value.
That would mean, that only the last-changed value has to be tracked down, and reset ?
In this case, your onchange event callback should use this value to get current form element value, and ID. Then, as the resultset comes back, set back the stored value to that element if there are no rows.
Otherwise, if the form is managed globally, you could always store it with a .clone() call, then .remove() it and .insert() the clone back if the resultset is empty.
PS : i know this solution not really elegant :)
Your AJAX module could return a JSON-Encoded string with the data causing this event to occur (PHP-Function: JSON_encode) and from there on, you can cycle through the erroneous values resetting them and displaying further informations. i.e. "Your E-Mail seems to be invalid".
PHP: See JSON_encode
JavaScript: See getElementsByTagName('input') (or textarea or select)
Note: In case of a select item, you may rather want to change the Attribute "selectedIndex" than "value".
I solved the problem by recording each change to the form with
$("#form_id").on("change", function(event) {
//Event bubbling
type = $(event.target).get(0).type;
selector = $(event.target);
}
Then using the Strategy design pattern (Javascript Strategy Design Pattern), I reset each possible field type accordingly. Example for text field,
var Fields = {
"text": {
resetAction: function(fieldSelector) {
fieldSelector.val('');
}
}
};
//To call the reset action for the type of field,
Fields[type].resetAction(selector);
I had to trigger a change event for hidden fields to have their changes also bubble.
Related
I was using the following script to disable multiple field objects when one field was selected, I have changed the fields so that they no longer have a default value of zero but can have varying values:
JS
function disablefield(fieldObj)
{
var fields = new Array('Seat_1200', 'Seat_1230', 'Seat_100','Seat_130','Seat_500','Seat_530','Seat_600','Seat_630','Seat_700','Seat_730','Seat_800','Seat_830');
for(var i=0; i<fields.length; i++)
{
fieldObj.form[fields[i]].disabled = (fieldObj.value!=0 && fieldObj.name!=fields[i]);
}
return;
}
Can anyone suggest a way to detect the current value of the fields seat_xxxx (which are loaded dynamically) integrate it into the above script then disable the all fields when the value one changes. Or alternatively if the field is de-selected i.e. the user changes his mind and selects another option, then the field is set to zero automatically to satisfy the above script re-enabling all the selection options.
In response to the problem from the author I have a new code set.
I would use a Jquery button set to represent all the tables you have. Then selectively disable them based on the result. Below is a fiddle
http://jsfiddle.net/05cpss80/
Buttonsets are really just classed checkboxes but they give you what you need.
<input type="checkbox" id="check1"><label for="check1">Table1</label>
As such you can add additional classes to them to stop them from "checking"
$('#check2').attr("disabled", "disabled");
I would recommend you add some css to make it more obvious, but try the fiddle. Click 2, then the button and it will no longer work. (Thus when they make a selection you call disable on whatever tables you need)
I have quite a few input elements on a page that a user can change. I don't want to submit a form. I just want the database value to be changed after the user changes the value inside one of the elements.
I'm currently experimenting with binding focusout to each of the inputs. Is this the way it's usually done (facebook, etc..)?
$('input').focusout(function() {
var current_val = $(this).val();
var preset_val = $(this).attr('rel');//attribute set with original value
if (current_val !== preset_val) {
alert ('Value changed.');//where I would post to php page to update database
}
});"
The way it is "usually done" is to wait until the user clicks a button to save or commit the changes. If you're going to update each change, you should make sure to be very clear about that to the user.
The appropriate event to use will be dictated by how aggressive you want to be in capturing changes. For per-keystroke updates, keyup would be appropriate for inputs, click for selects and radios/checkboxes. Less aggressive would be blur or change.
One way to be extremely proactive about capturing any possible change is to attach a click and a keyup to the form element itself. This will also save the overhead of adding a listener to every element. Each time an event is fired on the form, you can either a) check the original target, or b) ajax the entire form, or c) loop all the elements and detect changes, only ajax changed fields.
onbeforeupload can be used to do a final check of the form in case the window is closed, as well, but that's probably being a little too hyper.
Documentation
https://developer.mozilla.org/en-US/docs/DOM/HTMLFormElement
https://developer.mozilla.org/en-US/docs/DOM/element.onkeyup
https://developer.mozilla.org/en-US/docs/DOM/element.onchange
https://developer.mozilla.org/en-US/docs/DOM/element.onblur
https://developer.mozilla.org/en-US/docs/DOM/element.onclick
Given the following code:
sPosSelect="#fpJpos input[name=posnum" + iiPos + "]";
if (fIn>fPosMaxWtUse[iiPos]) {
alert(sprintf('%.0f is %.0f more than the position max of %.0f.',fIn,fIn-fPosMaxWtUse[iiPos],fPosMaxWtUse[iiPos]));
$(sPosSelect).val('');
$(sPosSelect).focus();
return;
}
It works in that I get the alert, and the field is blanked. However, the focus then moves on to the next field when what I want is for it to stay on the field just blanked so the user can try again.
All suggestions are welcome, including anything I'm doing that could be done in a better way.
Terry
I assume your code is within an event attached to the field in question, presumably on blur?
If this is the case, you should simply use return false at the end of the function. This will tell the browser to ignore it's default behaviour, which in this case would be moving to the next field.
What your code is doing at the moment is setting focus in the field, and then returning control to the browser, which assumes everything went okay, and happily moves on to the next field.
Also, if this code is within an event attached to the field, you should really be using $(this) in place of repeating the selector $(sPosSelect).
Our webapp has a form with fields and values that change depending on values entered. Each time there is a change event on one of the form elements, we use an expensive AJAX call to update other elements on the page.
This works great for selects, radio buttons and checkboxes. The issue comes in when a user adds content to a text field, and then clicks a link without taking the focus from the text field. The browser moves to a new page, and the contents of the text field are never saved. Is there an easy way to code around this? The AJAX call is too expensive to call with each key press.
Here's an example of my Prototype code at the moment:
$$('.productOption input.text').invoke('observe', 'change', saveChangeEvent);
Have you considered hooking into the window unload() event? Here is a c/p jQuery example using .unload().
$(window).unload(function() {
var input = $("#MyInput"); // Text field to check for
if(input.length > 0)
{
//Ajax call to save data, make sure async:false is set on ajax call.
}
});
This lets you work around making a call on each key press, by making one if they leave the page.
using prototype, you can have a PeriodicExecuter listen while you're typing and sending off an ajax query when nothing has happened for e.g. 2 seconds and value has changed since the last AJAX request. Start the executor using a focus event and shut it down using a blur event, that way you only need one executor at a time
I'm creating a data entry app for some in-house stuff.
My team needs to enter info about "items" which can have many "categories" and vice versa.
I need a quick way to let them enter an arbitrary amount of categories.
Here's my idea:
On the item entry page, I'll have it so that initially there's one text input for "categories" and if it's tabbed out of while it's empty, the input field is deleted (unless it's the only one) and focus skips to the next field. If it's not empty when it's tabbed out of and if it's the last input field in the array, then an additional "category" text input will be added and focused.
This way people can enter an arbitrary amount of categories really quickly, without taking their hands off the keyboard, just by typing and hitting tab. Then hitting tab twice to denote the end of the list.
First of all, what do you think of this interface? Is there a better way to do it?
Second of all, is there a jQuery (or something) plugin to do this? I've searched but can't find one. I searched scriptaculous/prototype and mootools too, with no luck.
I would obviously rather use something tried and tested than roll my own.
Any and all advice appreciated
First I'll try to address the problems commented on nickf solution.
To set the focus on the newly created input $copy.find(":text").focus(); will not work. The jQuery focus method only triggers the event, but does not call the underlying focus method.
You can set the focus with setTimeout(function(){$copy.find(":text").get(0).focus()}, 10); but:
setTimeout is needed in firefox or strange things will happen with the blinking cursor.
IE7 needs another input to focus when tabbing. I haven't found the way to set the focus on an input if the focus goes to the address bar. I suppose this will not be a problem because you will need at least a submit button.
To control shift-tab I've been trying to track the focused element, in order to skip the blurHandler when the focused element is a previous input, but the resulting code is really ugly so I'll post this and look for a better solution.
And last, you're asking what we think of this UI, and I think that a comma separated list of categories is easier to code an to fill in. :-)
it's actually not too difficult to implement that, even with vanilla JS (ie: no jQuery, prototype, etc), but everything is easier with jQuery, so I'll have a go at it using that:
Assuming a structure like this:
<form id="myForm">
<div class="inputRow">
<input type="text" name="myInput[]" />
</div>
<div class="inputRow">
<input type="text" name="myInput[]" />
</div>
...
</form>
Here's the JS
$('#myForm :text').blur(onBlurHandler);
function onBlurHandler() {
$row = $(this).parent();
if ($row
.nextAll(":has(:text)") // all following divs with a text element
.length == 0 // but there aren't any, we're on the last one
) {
if ($.trim($row.find(":text").val())) { // the text box isn't empty
$copy = $row.clone(true);
$copy
.find(":text") // get the new text box,
.val('') // remove any text in it
.blur(onBlurHandler) // and add the event handler (is this necessary?)
;
$copy.insertAfter($row);
} else if ($row.prev(':has(:text)').length) { // the text box is empty, and this one isn't the first row
$row.remove(); // get rid of the row.
}
}
}
Response to comments:
thanks for the answer! i've tried it but it doesn't seem to work as intended. i'm on mac firefox. if i tab off the last field, it adds the new one but focuses the address bar. i tried adding: $copy.find(":text").focus(); after the insertAfter line, but it doesn't change anything. any ideas?
also if i shift-tab the blurhandler doesn't know i'm going in the opposite direction. is there any way around that?
Hmm, I hadn't thought about that. What you could try doing is to put an element after all your text fields which can take focus (like a textbox which is rendered off-screen, eg: margin-left: -10000px). Add an onfocus handler onto that to see if the last row is empty, and if it is, then it would have been added just then by the onBlurHandler function, so pass the focus back to the last row. If the last row isn't empty, then pass the focus onto the next element (your submit button, probably). If there are issues with the last row not existing in the DOM yet, then put the above into a timeout.
(If this actually works) this should let your users tab backwards and forwards without hassle.