Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Chrome/Safari (Webkit) query string missing buttons

Status
Not open for further replies.

djhill

Programmer
Apr 20, 2004
9
0
0
US
I have a classic ASP site I maintain for a friend, part of which consists of a framework providing a "wizard" interface with navigation buttons (i.e., "Next" and "Previous"). The buttons have the same name and id of 'navButton', and have an onClick() event that invoke a function to perform some client-side validation prior to actually allowing the form.submit() to proceed. The server-side code manages navigation by detecting which button the user has clicked. This code has been working for years.

Now we're getting feedback from some users that navigation doesn't work. On inspection, I've found that if the users are running a WebKit-based browser (Chrome, Safari, etc.), the navigation button object ('navButton') is missing from the query string returned by the Request object. In both IE and FireFox, the button is present in the query string.

I've found this to be the case for both type='submit' and type='button'. The only workaround is to use a hidden field to pass the identity of the clicked button, which should not be necessary.

Has anyone else seen this behavior? This would seem to be a bug in WebKit, though I don't know whether the spec requires browsers to pass inputs of type submit or button.

Thanks!
 
Hi

[ul]
[li][tt]id[/tt]s must be unique per document[/li]
[li][tt]button[/tt] [tt]input[/tt] information is not submitted[/li]
[li][tt]submit[/tt] and [tt]image[/tt] [tt]input[/tt] information is submitted only for the one which started the submit[/li]
[li]if [tt]form[/tt] submit was started programmatically, no [tt]submit[/tt] or [tt]image[/tt] [tt]input[/tt] information is submitted[/li]
[/ul]
Sorry, I know about no specification, the above is certainly true for Gecko browsers, but I am quite sure the others work the same way.

I would say, is impossible the site ever worked the way you described. If it worked, I suspect that ASP added some JavaScript code.

However, this is how I would do it :
Code:
[b]<form[/b] [maroon]action[/maroon][teal]=[/teal][green][i]""[/i][/green] [maroon]onsubmit[/maroon][teal]=[/teal][green][i]"return validate(this)"[/i][/green][b]>[/b]
[gray]<!-- whatever else needed -->[/gray]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"submit"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"navButton"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"Previous"[/i][/green][b]>[/b]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"submit"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"navButton"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"Next"[/i][/green][b]>[/b]
[b]</form>[/b]
The important piece : use [tt]submit[/tt] [tt]input[/tt]s and validate [tt]onsubmit[/tt].


Feherke.
 
The pages using this framework use event handlers to manage validation and submittal; some pages use a hidden form for the actual submittal, in which case the form the user completes has no action attribute, so a form-level onSubmit() handler is inappropriate. The user form's buttons have an onClick() event handler that performs validation and displays errors if necessary. If the data are valid it populates the hidden form (if used) and issues form.submit().

You are correct that the (HTML DOM) "id" must be unique. I hoped that was the answer, but the behavior I've seen also occurs on forms with only a single submit button where no duplicate id exists (for example, the entry to a wizard, where there are only Reset and Continue buttons). In any case, IE and FF seem to ignore duplicate id's (though it's a good thing I wasn't doing any DOM stuff here!). The WebKit-based browsers may be less forgiving.

I'm unsure what you mean in your last three points...

On point two, are you asserting that form elements of type='submit' are not submitted to the server? This is exactly the behavior I'm seeing with the WebKit-based browsers (the whole point of my original question), but it is most certainly not the behavior of IE and FF. Please run the testForm.asp and TestFormHandler.asp (see below) under each browser, and you'll see that IE and FF do in fact include the submit button in the result (at least with method='POST'), so the button is accessible in the resulting form handler, meaning it can distinguish between the the buttons the user might have available, whether they be "Previous", "Next", "Finish" or "Cancel".

On point three, I have no idea what you mean by "submit and image input information is submitted only for the one which started the submit". In that context, what is "the one"? The form itself, or the button the user clicked? Form submittal can be initiated via a button of type=submit, but It can also be initiated by programatically invoking the submit() method on a form object (not necessarily the form the user sees, as described above), in which case the the button's event handler returns false to suppress submission of the visible form.

On point four, are you asserting that a "programmitic" submittal, i.e., form.submit(), does not transfer the form data to the server? This is certainly not the case as the code below demonstrates.

By "specification", I mean the W3C's HTML 4.01 specification. Please see successful controls, which clearly specifies that the active submit button (regardless of how many submit buttons may be present) is a "successful control" and will be included in the data transferred to the server. IE and FF honor this requirement; WebKit-based browsers apparently do not.

Here are the test pages (I hope it doesn't mess with the quotes this time...):

testForm.asp
Code:
<%@ language="JavaScript" %>
<% Response.Buffer = true %>
<html xmlns="[URL unfurl="true"]http://www.w3.org/1999/xhtml">[/URL]
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
	<title>Test Form</title>
	<script language="JavaScript">
	<!--
	function handleSubmit(navForm, navButton) {
	
		var theForm		= new Object(navForm);
	    var theButton	= new Object(navButton);
		var obj			= null;
		var hidden		= null;
	    var val			= 0;
	    var selection	= 0;
		var i, j;
	
	    // get the selection and hidden field reference
		for (i=0, j=theForm.length; i<j; i++) {
			obj = new Object(theForm.elements[i]);
	
			if (obj.type == "radio") { 
		        val = parseInt(obj.value);
	            if (obj.checked == true) { selection = val; }
			}

			if (obj.type == "hidden") { 
		        hidden = obj;
			}
		}

		// in real form, validation would be done here. just set hidden field
		hidden.value = "The button clicked was '" + navButton.name + "', the selection was '" + selection + "'";
        
        alert("set hidden.value = '" + hidden.value + "' - about to submit form.");
          	
	    theForm.submit();
	    return true; 
	}
	-->
	</script>
</head>
<body>
	<h1>Test Form</h1>
	<form name='testForm' id='testForm' method='POST' action='testFormHandler.asp' >
		<table>
        	<tr><td colspan='2'>Please make a selection:</td></tr>
			<tr><td><input type='radio' name='navChoice'  id='navChoice1' value='1' checked='checked' /></td><td>Choice 1</td></tr>
			<tr><td><input type='radio' name='navChoice'  id='navChoice2' value='2' />                  </td><td>Choice 2</td></tr>
			<tr><td colspan='2'>
				<input type='reset'  name='navReset'  id='navReset'  value='Reset' />
                &nbsp;&nbsp;&nbsp;
				<input type='submit' name='navButton' id='navButton' value='Continue' onClick='return (handleSubmit(testForm,this)); ' />
			</td></tr>
		</table>
		<input type='hidden' name='navHidden'  id='navHidden' value='not set' />
	</form>
</body>
</html>

testFormHandler.asp
Code:
<%@ language="JavaScript" %>
<% Response.Buffer = true %>
<html xmlns="[URL unfurl="true"]http://www.w3.org/1999/xhtml">[/URL]
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
	<title>Test Form Handler</title>
</head>
<body>
	<h1>Test Form Handler</h1>
<% 
	// display the contents of the user agent header and the query string
    
    var	userAgent = new String(Request.ServerVariables ("HTTP_USER_AGENT"));

	var msg = "", f = null, q = null, v = null;     
	for (f = new Enumerator(Request.Form()); !f.atEnd(); f.moveNext()) { 
	    q = f.item(); 
        v = Request.Form(q);
        if (msg != null) {  msg += ", "; }
	    msg += (q + " = '" + v + "'");
	} 
	
	Response.write("HTTP_USER_AGENT : "	+ userAgent	+ "<br />");
	Response.write("Query string: "		+ msg		+ "<br />");
    
%>
</body>
</html>
 
Hi

Glad to see you found the specification.

Sorry, can not run you ASP test pages.

Anyway, here is my test to support what I wrote earlier :
Code:
[b]<html>[/b]
[b]<head>[/b]
[b]<title></title>[/b]
[b]</head>[/b]
[b]<body>[/b]
[b]<form[/b] [maroon]action[/maroon][teal]=[/teal][green][i]""[/i][/green][b]>[/b]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"text"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"text1"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"text one"[/i][/green][b]>[/b]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"text"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"text2"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"text two"[/i][/green][b]>[/b]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"button"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"button1"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"button one"[/i][/green] [maroon]onclick[/maroon][teal]=[/teal][green][i]"this.form.submit()"[/i][/green][b]>[/b]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"button"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"button2"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"button two"[/i][/green] [maroon]onclick[/maroon][teal]=[/teal][green][i]"this.form.submit()"[/i][/green][b]>[/b]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"submit"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"submit1"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"submit one"[/i][/green][b]>[/b]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"submit"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"submit2"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"submit two"[/i][/green][b]>[/b]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"image"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"image1"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"image one"[/i][/green] [maroon]src[/maroon][teal]=[/teal][green][i]""[/i][/green] [maroon]alt[/maroon][teal]=[/teal][green][i]"image one"[/i][/green][b]>[/b]
[b]<input[/b] [maroon]type[/maroon][teal]=[/teal][green][i]"image"[/i][/green] [maroon]name[/maroon][teal]=[/teal][green][i]"image2"[/i][/green] [maroon]value[/maroon][teal]=[/teal][green][i]"image two"[/i][/green] [maroon]src[/maroon][teal]=[/teal][green][i]""[/i][/green] [maroon]alt[/maroon][teal]=[/teal][green][i]"image two"[/i][/green][b]>[/b]
[b]</form>[/b]
[b]</body>[/b]
[b]</html>[/b]
And the results :
[tt]
submitted [gray]|[/gray] submitted controls
by [gray]|[/gray] ( X = submitted, empty = not )
clicking [gray]|[/gray] text [gray]|[/gray] button[gray]|[/gray] submit[gray]|[/gray] image [gray]|[/gray]
on [gray]|[/gray] 1 [gray]|[/gray] 2 [gray]|[/gray] 1 [gray]|[/gray] 2 [gray]|[/gray] 1 [gray]|[/gray] 2 [gray]|[/gray] 1 [gray]|[/gray] 2 [gray]|[/gray]
[gray]----------+--------------------------------[/gray]
button 1 [gray]|[/gray] X [gray]|[/gray] X [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray]
2 [gray]|[/gray] X [gray]|[/gray] X [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray]
submit 1 [gray]|[/gray] X [gray]|[/gray] X [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] X [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray]
2 [gray]|[/gray] X [gray]|[/gray] X [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] X [gray]|[/gray] [gray]|[/gray] [gray]|[/gray]
image 1 [gray]|[/gray] X [gray]|[/gray] X [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] X [gray]|[/gray] [gray]|[/gray]
image 2 [gray]|[/gray] X [gray]|[/gray] X [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] [gray]|[/gray] X [gray]|[/gray]
[/tt]
I got the same results on Gecko ( FireFox, SeaMonkey ), Presto ( Opera ), WebKit ( Chromium, Midori, Arora, rekonq, Epiphany ) and KHTML ( Konqueror ).

Regarding your JavaScript code, to me is hard to follow and impossible to predict its result. I never seen anyone using [tt]new Object[teal]()[/teal][/tt] like that.

Anyway, your code let me see what you hit. Gecko browsers do not submit [tt]form[/tt]s pertaining to no [tt]document[/tt]. You have to add [tt]document[teal].[/teal]body[teal].[/teal]appendChild[teal]([/teal]theForm[teal])[/teal][/tt] before calling [tt]submit()[/tt].


Feherke.
 
Hi again... finally got back to this. Here are a few clarifications:

1) the use of "var xyz = new Object(someOtherObject)" was a workaround, probably dating to IE6 or earlier. I'd found that in some cases, objects passed as method arguments and then assigned to a variable would yield "object does not support this property or method" errors when attempting to access the object via the new variable.

2) I wasn't aware of the need to invoke addChild() as you described. Does this apply only to form objects created on the fly via script? That would make sense, but in this case the page has two forms: the one the user sees and interacts with, and a second form containing only hidden fields. Both should be part of the DOM, so I would think addChild() would be inapplicable. Is it possble Gecko-based browsers make assumptions about the order in which the forms are defined?

3) in any case, such hidden forms are only used in a few places. I was also seeing problems on other forms where INPUT TYPE='button' was tried, but where I'de reverted to type='submit', in both cases performing validation in an onclick() event script. Here's the difference I found: in WebKit-based browsers (Chrome and Safari), if the submit button has no event ecript, the button will be included in the query string. However if it has onclick() event script which subsequently issues a form.submit(), the browser does NOT include the button in the query string even though it was in fact clicked! Both IE and FireFox (mine says "Gecko20101203")) include the button in the query string in all cases. So, it woud appear the difference is between WebKit-based browsers and both IE and FireFox (and possibly other Gecko implementations, at least since Gecko20101203). As such, it still appears to me to be a bug. Do you know what Gecko branch the WebKit-based browsers are based on? Finally, is there a preferred feature-based technique for detecting WebKit-based browsers?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top