Problem/Motivation
Search block form does not comply with W3C HTML validation:
"Bad value for attribute name on element input: Must not be empty."
…selector="edit-submit" type="submit" id="edit-submit" name="" value="Search" />
The name attribute is mandatory but can't be empty :
http://www.w3schools.com/tags/att_input_name.asp
The Views module exposed forms have the same problem.
The reason this happens is that both Search and Views are using a hack to the Form API to make it so that the internal form keys do not show up in GET URLs when the forms are used, something like this:
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Search'),
// Prevent op from showing up in the query string.
'#name' => '',
);
Proposed resolution
Fix the form.inc code so that empty name attributes on buttons are not printed in the HTML.
Remaining tasks
Review and manually test the back port patch for Drupal 7.
User interface changes
Valid HTML for submit buttons used on GET forms that try to have clean URLs.
API changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #76 | w3c_search_block_validation-D7-2637680-76.patch | 2.34 KB | chris burge |
Comments
Comment #2
dom. commentedBefore patch:
<input class="search-form__submit button js-form-submit form-submit" data-drupal-selector="edit-submit" type="submit" id="edit-submit" name value="Search">W3C validation:
"Bad value for attribute name on element input: Must not be empty."
…selector="edit-submit" type="submit" id="edit-submit" name="" value="Search" />After patch:
<input class="search-form__submit button js-form-submit form-submit" data-drupal-selector="edit-submit" type="submit" id="edit-submit" name="search-block-submit" value="Search">=>W3C is now OK
NOTE: Please rebuild cache after applying patch when testing.
Comment #5
dom. commentedAccording to code comments, this empty "name" attributes has been introduce to remove the action name from URL, but in the meanwhile, it is not valid. What is the correct approach, any other opinion ?
Should I just correct the URL in the test to have the "name" parameter in URL ?
Comment #6
nils.destoop commentedImo, the url should stay as it's now.
Isn't it just an option to let the empty name stay, and make sure the name attribute isn't rendered when it's empty (for all elements, so not only this search submit)? This will prevent that other modules also introduce w3c invalid html.
Comment #7
mikeocana commentedill work on this
Comment #8
mikeocana commentedadded the name attribute based on the standard name in drupal 8 to avoid empty #name.
'#name' => 'search_block_form_submit',
Comment #10
dom. commented@mikeocana for #7: good idea.
@mikeocana for #8: indeed, better name.
We should push on the direction of #7 instead of #8 I think.
Comment #11
mikeocana commented@dom, thank you.
more checking :)
Comment #12
cilefen commentedI marked this issue as related to #1366020: Overhaul SearchQuery; make search redirects use GET query params for keywords. Those following this issue should read that.
Comment #13
jhodgdonUm, wrong component. ;)
So. The reason that we put #name='' is shown in the comment just before the patched line from #8 and reflected in the test failure. That is, we do NOT want the submit button showing up in the GET parameters.
This patch breaks that, and in fact having any name in there breaks that.
I do not think there is a way to have a non-empty name and avoid having an ugly search URL. So I think this is a Won't Fix. But if someone can figure out how to have the Search block pass w3c validation and still pass the test that checks that the search URL is clean, sure...
Maybe #6 will work? Try it...
Comment #14
laranajim commentedUnassigning @mikeocana as it has been a month without any activity. This will be my first patch for Drupal core.
Comment #15
laranajim commentedHey @jhodgdon
I took a look at the code that generates the markup for the input fields. I was able to add some logic that will check for empty name attributes and if empty would remove them. I have run my code through the W3C validator to ensure the resulting HTML for the submit button is now valid.
This is my first patch to Drupal core.
Comment #16
dom. commentedHi laranajim !
Congratulation for your patch !! I have tried it and it's okay to me, here is the reason why:
BEFORE:
Input button code:
<input class="search-form__submit button js-form-submit form-submit" data-drupal-selector="edit-submit" type="submit" id="edit-submit" name="" value="Search">Attached is the W3C error corresponding.
The request for searching "foobar" in the search box is :
Request URL: http://.../search/node?keys=foobar
AFTER PATCH #8:
The request for searching "foobar" in the search box is :
Request URL: http://.../search/node?keys=foobar&search_block_form_submit=Search
which is not correct as per @jhodgon #13
AFTER PATCH #15:
Input button code:
<input class="search-form__submit button js-form-submit form-submit" data-drupal-selector="edit-submit" type="submit" id="edit-submit" value="Search">No more error regarding this button in W3C validation.
The request for searching "foobar" in the search box is :
Request URL: http://.../search/node?keys=foobar
Thus #15 is RTBC for me.
NOTE: I still wait for unit tests to get green to actually flag the issue as RTBC.
However, arguably, I would change the following in your patch. For this reason, I'm attaching another patch here just in case others agrees with me. But if your patch is OK for others, let's go with it !
Small typo here:
"Remove name attribute if empty, for W3C compliance."
For me, the cast in (string) is not necessary here since it has to be one. Anyway, 'empty' method allows other objects then string in case [name] could an array such as [class] is for instance.
Comment #17
wiifmHey @Dom,
I was helping @laranajim with this patch, and totally agree with your point #1, I will ensure a re-roll takes place tomorrow for this. As for point #2,
$variables['attributes']['name']is an object of typeAttribute, the type cast seems to make it work reliably, but open to suggestions for ways to improve this (this is my first time working with this class).Thanks for your time with the review! Very comprehensive.
Comment #18
dom. commented@wiifm : Your are right, ['attributes']['name'] is generally a string as in D7, but in this case debugger says it is a "Drupal\Core\Template\AttributeString" (and I think it will/should always be this). Actually, my patch even don't work because of that: I did fucked up the review of my own patch ^^
So here is a patch with just first point included !
Comment #19
jhodgdonThis patch looks like a good solution to me. It has rather far-reaching consequences though (way beyond the Search module), so I'm moving this into the Form component.
Comment #20
dom. commentedTests are passing, so I guess the number of impacted empty name is quite low.
Actually a search for the various combinaison of 'name' => '', "#name" => '' and everything that can happen between the two using:
['"]#?name['"]\s?=>?\s?['"]{2}gives me 12 occurences in core, most of it being in Tests, with the notable:
It's the only two I could found about name attributs set to empty.
Patch for this issue will thus also make views with expose filters to be W3C valid.
Comment #21
jhodgdonThanks for the research! Updating title and issue summary, and I think this is RTBC.
Comment #22
BarisW commentedThis is an issue in D7 too.
Comment #23
wiifmHey @BarisW, cool, let's backport to D7 after being committed to D8.
Comment #24
jhodgdonSo we should probably tag this issue as "needs backport to D7" and mark the other one as a duplicate then???
Comment #25
cilefen commentedComment #26
cilefen commentedMaybe not - is the other issue fixed in Views?
Comment #27
jhodgdonThe idea would be to fix the underlying problem, which also exists in D7, and needs to be fixed in Core because it is a Core form API problem.
Comment #28
catchPatch looks fine, but this could use automated testing.
Comment #29
jhodgdonWhat do you suggest for additional automated testing? There is already quite a bit of testing of the Search form, which earlier patches failed (there are tests for instance that verify that the form ID stuff doesn't get into the URL when you submit the form with GET).
I don't believe we can test for W3C validity easily in an automated test...
Comment #30
dom. commented@jhodgdon : I made the W3CValidator module. It could somehow be activated as part of Jenkins post-process tests for instance. Or we just taking the W3C processor part of this module and add it to the testing profile ?
Comment #31
jhodgdonMaybe we could just make a short test for this particular issue that would verify that there is not an empty 'name' attribute in the form?
Comment #32
dom. commentedOK, trying here with a test checking that the input button does not have an empty name attribut.
The patch #32 is the same as the #18 + the #32--test-only
Comment #34
dom. commentedtest-only as failed for obvious reasons ! ^^
The 32.patch includes the test and validates. Thus, the test at least seems credible and submitted for humain reviewing.
Comment #35
jhodgdonLooks good to me, thanks! Verified the tests failed/passed as expected.
Comment #36
BarisW commentedMinor typo (attributE).
Comment #37
dom. commentedTypo corrected.
Thanks @jhodgdon and @BarisW for review !
Comment #38
jhodgdonOK! Thanks BarisW for being more detail-spotting than the rest of us.
Comment #41
catchCommitted/pushed to 8.1.x and cherry-picked to 8.0.x. Thanks!
Comment #42
maximpodorov commentedThis patch is a direct backport for Drupal 7.
Comment #44
maximpodorov commentedThe next attempt.
Comment #45
maximpodorov commentedTest only patch. Single failure is expected.
Oops. Something went wrong.
Comment #46
jhodgdonHm. Does Drupal 7 even have the same problem? Maybe not since the test didn't fail...
Comment #47
maximpodorov commentedThe problem exists for Views exposed forms, see #2514028: Empty 'name' value for the exposed filter submit button.
Comment #48
maximpodorov commentedIn D7, default value for 'name' attribute of a button is 'op', see system_element_info().
So, unless you specify it explicitly as empty string, the resulting HTML code is valid.
Views exposed forms do exactly this in views_exposed_form() function in order to "prevent from showing up in $_GET".
This means the test must contain creating a special form with a button having #name set to empty string.
Comment #49
jhodgdonAh, so in D7 this problem doesn't affect the Search form I guess. Anyway, sounds like you know how to modify the test. Setting to Needs Work because the test needs work.
Comment #50
Collins405 commentedCan confirm patch in #44 works nicely in 7. Thanks.
Comment #51
uzmaabdulrasheed1@gmail.com commentedComment #52
jhodgdonThe test needs work. See earlier comments.
Comment #55
ollie222 commentedJust a little more info on this as I've just come across the issue.
I have a views exposed filter with the name="" as expected. As discussed it doesn't pass W3C validation and I've also noticed that there is different behaviour between browsers.
On a windows machine Chrome doesn't include the button value in the search string but in IE it's included but without a name. For example with me it was appending &=Search in IE for the search button.
This means that as far as caching is concerned the pages are not the same and therefore need caching again.
For some reason it also means that return has to be pressed twice in IE when entering a search term.
The patch in #44 appears to fix all of the issues for me so it's a thumbs up from me.
Comment #56
tameeshb commentedI'd like to take this up! :)
Comment #57
ollie222 commentedI'd commented in #55 that
After more testing I don't think it's related to this issue and more to do with a browser quirk if you enter a term that has already been entered previously but I can't replicate it every time.
Either way it's not to do with the original issue.
Comment #60
tameeshb commentedAre there any tasks left on this issue?
Comment #61
tameeshb commentedComment #62
danielvezaWhats the latest on this ticket. Looks like there has been commits but never marked as fixed.
We are seeing this on our distribution, just interested to know if this could be the issue or if this is considered fixed.
Comment #63
maximpodorov commentedD7 should be fixed also.
Comment #64
Diane Bryan commentedDoesn't look fixed based on my WC3 site validation check, and yet supposedly catch has committed a fix. (#59)
Comment #65
volkswagenchickTagging for upcoming contribution days.
Comment #66
altback commentedThis issue still remains with drupal 8.6.8 and needs to fixed.
Here is the error I receive in w3c validator:
Comment #67
altback commentedThis issue remain with 8.6.8 and needs to be fixed.
Comment #68
altback commentedw3c validation returns error :
Bad value for attribute name on element button: Must not be empty
Comment #69
altback commentedComment #70
altback commentedI tried a work-around for this issue. I am not sure if it is the right approach or not.
As the 'name' attribute is NULL for the html tag , it is causing the W3C validator to issue the following error:
Error: Bad value for attribute name on element button: Must not be empty.In order to deal with it, I created a 'block--theme-search.html.twig' file in the templates folder of the sub-theme.
This overrides the core code.
I particularly removed the attribute 'name' and error is gone.
Here is code for the 'block--theme.search.html.twig' file:
As I mentioned earlier, I am not sure if its the right approach or not.
Needs to be tested and reviewed by the community.
Comment #71
tim.plunkettFixing tags
Comment #72
andrewmacpherson commentedComment #73
vacho commentedThis issue does not apply for 8.6.x or 8.7.x. Definitely D8 does not present this issue.
Comment #74
chris burge commentedI can confirm this issue does not exist in 8.5.x or higher. Setting back to 7.x-dev for back porting of patch. Patch #44 corrects the issue. Attached is a re-rolled copy against HEAD.
The test is no longer valid, however. Below is what the Search form markup looks like in 7.65:
<div class="form-actions form-wrapper" id="edit-actions"><input type="submit" id="edit-submit" name="op" value="Search" class="form-submit"></div><input type="hidden" name="form_build_id" value="form-fqsEapcJJVZpN9nno_Rkobvl6jJGPaxvHkJIS7TzY1Q">Because of the change in the Search module, I tested with an exposed filter in views.
Leaving at Needs Work due to test coverage.
Comment #75
chris burge commentedD7 branch tests are failing. Test failures are unrelated to patch #74.
Comment #76
chris burge commentedUpdated patch with updated tests.
Comment #77
mradcliffeI removed the Needs issue summary update after a few tweaks. I also removed the Needs Accessibility Review tag because the approach is already in 8.1.x. Ideally the back port should now be a follow-up issue these days, which may be why there was some confusion.
Comment #78
joseph.olstadas per @alexpott #3061891: Validate Attributes (W3C validation)
This should be fixed in bootstrap, not core.
here is a bootstrap type of a fix that others have been using.
for more details, see @alexpott bootstrap patch and discussion in #3061891: Validate Attributes (W3C validation)
Comment #79
chris burge commentedThe issue can be reproduced without Bootstrap. There are two parts to patch #76 - the bug fix and updated tests. We can verify this is a core issue by running tests on a test-only version of the patch. This patch should fail. I'm uploading a test-only version of #76 and setting the project back to D7 core to allow tests to run.
Comment #81
chris burge commentedTests failed, as expected:
Form API.FormsElementsLabelsTestCase.testFormLabels
This result confirms this issue is a Drupal core issue. Without this patch
theme_button()will render anameattribute with no value. Setting back to Needs Review. Patch #76 remains the latest patch for review/commit.Comment #82
sjerdoPatch in #76 LGTM +1
Comment #83
mcdruid commentedAs mentioned in earlier comments, this doesn't seem to affect D7 core directly because it doesn't use an empty name attribute to avoid unwanted GET params, and core's search forms use POST.
So perhaps the "empty name hack" only applies to views in D7? (and possibly unknown other contrib modules, custom code etc..?)
https://git.drupalcode.org/project/views/-/blob/7.x-3.24/views.module#L2163
I'm not entirely sure we should be "fixing" this in core?
I've manually tested with a views exposed filter and confirmed that the empty name attribute is removed with the patch, and that the GET params when the search form is used are unaffected.
However, why was this hack put there in the first place then? Looks like without views setting an empty name, core provides a default
name="op"which does then pollute the GET params.(Sorry for probably going over old ground but restating this makes it easier to review a 80+ comment issue that dealt with D8 and then became a D7 backport).
So this change is probably okay for D7 core to make as it's effectively removing an artefact of a hack that contrib code does to avoid core's default behaviour.
Comment #84
fabianx commentedRTBC + 1, while not technically a core bug, core has always been friendly to contrib shenanigans :D.
There is no harm that I can see in removing an empty attribute and if themes are broken worst case can override theme_button() again.
Comment #86
mcdruid commentedThank you!