I am trying to write a custom magento module and i've got it all complete and working perfectly except one problem.
The module is a form with 4 radio buttons. They are all blank on the checkout page and I have them set up so that when you click one it submits the form and reloads the cart page with the "additional fees" in the subtotal.
My problem is that I need the first option to "auto submit" on page load. But I've tried ALOT of different things and can't come up with a way to use the jquery .submit() function to ONLY submit the form once. as it is now it works how I want it, except it loads the page in an endless loop.
Any way to say submit() only once?
I'd set the default radio button server-side rather than having an extra submit/refresh cycle, but if you insist on doing it client-side...
I assume on subsequent refreshes the previous selection will be retained (because your server-side code echoes back the previously selected values?), so can you perhaps test whether any radios are checked and if not assume that that is the first and only time to auto-submit?
$(document).ready(function() {
var $radios = $('#yourFormId input[name="yourRadioButtonGroupName"]');
if (!$radios.is(":checked")) {
// No radios currently checked, so check the first and submit
$radios.eq(0).prop("checked",true);
$("#yourFormId").submit();
}
});
The .is() method will "Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments."
Related
I'm building a Chrome extension that auto-fills a form. The first field on the form triggers additional fields to appear after it is filled out. I'm able to successfully field out the first field, but am struggling to fill out the sub fields.
To fill out the first field I use this code:
document.getElementById('theElementID').focus()
document.execCommand('insertText', false, 'theTextToAutoFill)
Here are a few things I've tried:
Use that same code (updated with the correct IDs) for additional form fields, but document.getElementById returns null because those fields don't exist when the page initially loads
Refresh the page after filling out the first form using reload(), but it's refreshing the entire page (not just the section after the first field). Is there a way to just reload a section of the page?
Add an event listener to the class the first field is in (which also contains the sub fields). Wait until that class has been clicked to attempt to fill the subfields. See code below.
document.getElementsByClassName('theClassContainingSubFormFields')[0].addEventListener("click", function() {
document.execCommand('insertText', false, 'theTextToAutoFill)
});
Ideally, I'm looking for a solution that uses JavaScript.
I have a form with a 'Reset' button. When i select my radio button the data from my DataTable is passed and pre-pops my fields. This working fine and does in fact pre-populate the relevant radio button
JQuery
if (modifyRecordData.startTime == 'Anytime') {
$('#anyTimeRadioButton').attr('checked', true);
$('#specificTimeRadioButton').removeAttr('checked');
$('#startEndTimeFields').hide();
} else {
$('#anyTimeRadioButton').removeAttr('checked');
$('#specificTimeRadioButton').attr('checked', true);
$('#startEndTimeFields').show();
$('#startTimeHr').val(modifyRecordData.startTimeHr);
$('#startTimeMin').val(modifyRecordData.startTimeMin);
$('#endTimeHr').val(modifyRecordData.endTimeHr);
$('#endTimeMin').val(modifyRecordData.endTimeMin);
}
Data returned
Page loaded
Now the issue, if the user, after data load goes to update the details and selects the other radio button the hidden fields are displayed (again correct)
Then user clicks the 'Reset' button and it fails in the correct function
$('#resetButton').mousedown(function (event) {
buttonclicked = "Reset";
event.stopImmediatePropagation();
modifyRadioButtonSelection(modifyRecordData);
})
and then goes back to the initial loaded data and it does drop in the IF code above
Debuging
Then it re-hides the hidden section (which is correct) but it does not re-tick the radio button as expected.
If i dont have the following code in the IF it leaves the previously selected one checked although the data falls in the IF
$('#specificTimeRadioButton').removeAttr('checked');
No idea whats going wrong at all. I even tried adding the following the 'Reset' button function but it just will not re-check the correct `radio button
$('#anyTimeRadioButton').removeAttr('checked');
$('#specificTimeRadioButton').removeAttr('checked');
Historically, there's been a lot of ambiguity and confusion between three related but different concepts:
The value of the HTML attribute in the source code.
The value of the HTML attribute in DOM tree.
The value of the JavaScript property.
To address that, jQuery/1.6.1 introduced the prop() method, which I suggest you adopt.
Scenario: I have a form with several accordions (that are expandable divs), each one has some required fields, the user is free to collapse or expand them, so, in some cases, there are non filled mandatory hidden fields (because collapse) when form is submitted.
Problem: In Chrome, no errors appears to user, only in the console you can read:
An invalid form control with name='' is not focusable.
I've found plenty of answers to this issue. I exactly know why is this happening, but I've not found any solution to my problem.
What i've tried: Before submitting the form, expand all accordions to make visible all required fields so I can allow browser to focus element and show Required field message (see update)
Desired solution: identify id of mandatory field that requires a content, to expand it's accordion container and focus the field
UPDATE:
Solution found expanding all collapsable divs by javascript is not working in all cases, so IS NOT a solution.
QUESTION: there is some way can I show the field before validation?? If no... Can I focus or identify a hidden mandatory field when submitting form.
I personally would go with Niet the Dark Absol's suggestion about checking fields when changing section and displaying warning flags (I think it would give a better user experience).
But if you want to continue with the check on form submission, there's a way of tricking the browser into doing what you want by using JavaScript. The browser identifies and highlights the first invalid field that is visible when the page validates (for IE and FF it will highlight all the invalid fields that are visible); so, before the form validation happens, you'd need to run a quick check and open the accordion section that contains the first invalid field.
The key is to run that check before the HTML5 validation happens. That means that onsubmit is not good enough, as the browser will validate before the submit event. You need to run the code when the submit button/image is clicked, as that click event happens before the browser validates the fields.
You didn't specify if it was for jQuery UI or Bootstrap, so here are examples for both (the code is similar, just changing the way to handle opening/closing the accordion):
JQUERY UI ACCORDION
You can see a working demo for jQuery UI on this JSFiddle: http://jsfiddle.net/ma8v32ug/1/. The JavaScript check would be like this:
// save the accordion in a variable as you'll need it later
$accordion = $("#accordion").accordion();
// when the submit is clicked
$("#myForm input[type='submit']").on("click", function(event) {
// traverse all the required elements looking for an empty one
$("#myForm input[required='required']").each(function() {
// if the value is empty, that means that is invalid
if ($(this).val() == "") {
// find the index of the closest h3 (divide by 2 because jQuery UI accordion goes in pairs h3-div. A bit hacky, sorry)
var item = $(this).closest(".ui-accordion-content").prev().index() / 2;
// open that accordion section that contains the required field
$accordion.accordion("option","active", item);
// stop scrolling through the required elements
return false;
}
});
});
BOOTSTRAP ACCORDION
Note: this is valid for version 3.3.4 of Bootstrap. I haven't checked in older or newer versions.
One important thing to take into account for Bootstrap is that you cannot use the .collapse({toggle: true}) functionality because the animation takes more time than what the browser needs to validate the form, and the result will be unexpected (normally, the browser will stop the animation to point at the error, and it will not be the field that you want).
A solution to that is to do the toggle without animation, just by changing the .in class in the panels, and adjusting the target panel height. In the end, the function would look really close to the one for jQuery UI, just changing slightly:
// when the submit is clicked
$("#myForm input[type='submit']").on("click", function(event) {
// traverse all the required elements looking for an empty one
$("#myForm input[required='required']").each(function() {
// if the value is empty, that means that is invalid
if ($(this).val() == "") {
// hide the currently open accordion and open the one with the invalid field
$(".panel-collapse.in").removeClass("in");
$(this).closest(".panel-collapse").addClass("in").css("height","auto");
// stop scrolling through the required elements
return false;
}
});
});
You can see it working on this JSFiddle: http://jsfiddle.net/ma8v32ug/2/
This is probably all kinds of bad user-experience, but I don't know much about that so I won't go into it XD Basically, as you can tell just from the practicality issues you're facing as the programmer, hiding required fields is bad.
I would suggest implementing validation yourself, such as in change events. Check for the validity of all input elements within that accordion section, and if any of them fail you can put a warning flag on the accordion's header bar and disable the submit button.
Only when all fields pass validation do you then enable the submit button and allow the user to continue.
Of course, this does defeat the purpose of the native validation that HTML5 provides, but you're already using non-native accordions so you kind of have to go non-native for your validation to work.
I'm using the JQuery Cycle plugin (with attributes defined in a separate site wide custom js file) to cycle between two pages (separated by tables) of a form. Each page has its own validation group for the controls on that page. The first page has a "Next" button that when clicked manually fires page validation for the first validation group. If it fails the tool tips are displayed for the user to correct the information. If validation succeeds, the cycle next command is called.
$('#request-information').cycle('next');
On the second page, the controls are grouped in a second validation group with the submit button. When the submit button is clicked, server side validation is triggered and if it fails the page reloads on postback. All of this works, except if the second page fails I want the form to stay on the second page. So if the web page is reloaded because the second page of the form failed to validate I need to either set the starting slide to the second page of the form or if that's not possible at least trigger the cycle next command.
It doesn't seem like I can just set the startingslide to the second page of the form because that will overwrite the other defined attributes of the cycle function that are set in the separate js file.
So does anyone know how to advance to the second slide on postback page load based on whether the second validation group failed when the submit button was clicked? Or should I be doing something different using viewstate or something?
Sorry this is a long winded question. Hope its clear and not confusing.
Thank you
If you know that you need to go to the second slide when your page loads then you could do something like this:
var init = { startingSlide: 1 }; // i.e. second slide, the indices are zero-based
$('whatever').cycle($.extend(init, the_name_of_your_global_default_options));
You'd just have to arrange for init to be an empty object literal except when you needed to set startingSlide. If .cycle() is being somewhere outside your page, then you could reserve a variable for page-specific options and $.extend() that where .cycle() is called. For example, in your page, you could do something like this:
app_name_space.page_cycle_opts = { startingSlide: 1 };
and then way off in the JavaScript file that is binding the cycle stuff:
app_name_space.page_cycle_opts = app_name_space.page_cycle_opts || { };
$('whatever').cycle($.extend(app_name_space.page_cycle_opts, default_options));
I'm using app_name_space as a placeholder for whatever global namespace your application is already using to avoid name conflicts. If you had to deal with multiple cycle instances on a single page then you'd want to index page_cycle_opts by element ID, for example:
app_name_space.page_cycle_opts['X'] = { startingSlide: 1 };
and then way off elsewhere:
$('whatever').each(function() {
$(this).cycle($.extend(
app_name_space.page_cycle_opts[this.id] || { },
default_options
));
});
The basic idea is to consider the global configuration options as a set of defaults and then allow page-specific overrides through a well defined and documented mechanism.
A long winded answer to a long winded question. Hope its clear and not confusing.
I'm working on the Web GUI of an appliance-like product.
I have an HTML form that works fine: it shows a list of things with checkboxes, the user checks some of them and clicks the "remove" button which submits the form. The server gets the POST, removes the items, and refreshes the page. All fine.
There's a requirement to add an "are you sure?" confirmation to the form. If I add a call to
confirm("are you sure?");
as the onsubmit method in the FORM tag, or the onclick in the submit button tag, it works fine but uses the ugly browser-native confirm dialog.
Elsewhere in the product we have a nice custom CSS-styled confirm dialog I'd like to use, but it works like this: At the appropriate place, you put a call to
myConfirm("Confirm", "Are you sure", "Yes", "No", confirmCallback);
This puts up a clickmask, customizes a dialog, centers and displays it, and then returns FALSE and the form doesn't submit.
Later when the user decides, if they press "Yes", it calls the confirmCallback function. In the other, Ajax based pages of the product this gathers info, creates a postBody and uses Prototype's Ajax object to post it, and all is fine. (If "No", then the dialog and clickmask are removed and things continue.)
On this simpler page, with the pure HTML form, I have a confirmCallback function that looks like this:
var confirmCallback = function() {
document.myForm.submit();
}
and it fires OK, but when the form is submitted, the remove button has ALREADY been clicked, and the false returned by the custom confirm suppressed submission. Instead, this is considered a new submission, and the remove button was not actually clicked, so it is not considered "successful" in terms of W3.org's HTML 4 standard section 17.13.3. The server gets the data, no remove button, says "I got it but I dunno what you want me to do with it" and just does nothing but serve the next page.
If you're read this far, THANK YOU, and here is my actual question. How can I, in my confirmCallback javascript function, in a crossbrowser manner, cause the remove button to fire, become "successful" and submit along with the rest of the data?
Sounds like you're gonna need a hidden field to pretend to be the pressed button, and each button will require no name, but instead an onclick event to manipulate the value of the hidden field.
If the name of the buttons are all different, you might need to use DOM methods to add the hidden field because I don't think you can change the name of a field once it has been added to the DOM in all browsers.
If you require this solution to still work without JS, then you may need play around with the JS logic a little more (to do more modifications to your initial DOM tree) or modify the server code. You could even put the "Are you sure" behaviour into the response then...
Assuming that the remove button is the submit button for that form then probably the easiest solution is to give the form an id
<form id="submitForm"...
Then in your confirm call the form submit
document.getElementById("submitForm").submit()
I think that will do what you're asking but it seems like you were pretty much at that solution already so if you're asking something else let me know.
In your callback, remove the onclick handler for the button (causing the confirmation), then trigger a click on the button. This will cause the button click to submit the form and result in the button causing the submit to be posted back along with the form data.
var confirmCallback = function() {
$('submitButton').stopObserving('click');
$('submitButton').click();
}