{"action":"created","issue":{"url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer/issues/226","repository_url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer","labels_url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer/issues/226/labels{/name}","comments_url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer/issues/226/comments","events_url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer/issues/226/events","html_url":"https://github.com/squizlabs/HTML_CodeSniffer/issues/226","id":352897580,"node_id":"MDU6SXNzdWUzNTI4OTc1ODA=","number":226,"title":"Check for submit buttons outside of form element, associated using form attribute","user":{"login":"fuzzbomb","id":1243005,"node_id":"MDQ6VXNlcjEyNDMwMDU=","avatar_url":"https://avatars1.githubusercontent.com/u/1243005?v=4","gravatar_id":"","url":"https://api.github.com/users/fuzzbomb","html_url":"https://github.com/fuzzbomb","followers_url":"https://api.github.com/users/fuzzbomb/followers","following_url":"https://api.github.com/users/fuzzbomb/following{/other_user}","gists_url":"https://api.github.com/users/fuzzbomb/gists{/gist_id}","starred_url":"https://api.github.com/users/fuzzbomb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fuzzbomb/subscriptions","organizations_url":"https://api.github.com/users/fuzzbomb/orgs","repos_url":"https://api.github.com/users/fuzzbomb/repos","events_url":"https://api.github.com/users/fuzzbomb/events{/privacy}","received_events_url":"https://api.github.com/users/fuzzbomb/received_events","type":"User","site_admin":false},"labels":[{"id":142200199,"node_id":"MDU6TGFiZWwxNDIyMDAxOTk=","url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer/labels/Enhancement","name":"Enhancement","color":"6c6998","default":false},{"id":365349355,"node_id":"MDU6TGFiZWwzNjUzNDkzNTU=","url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer/labels/HTML5","name":"HTML5","color":"fef2c0","default":false},{"id":7307300,"node_id":"MDU6TGFiZWw3MzA3MzAw","url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer/labels/Standards","name":"Standards","color":"ffcb31","default":false}],"state":"open","locked":false,"assignee":{"login":"ironikart","id":1054708,"node_id":"MDQ6VXNlcjEwNTQ3MDg=","avatar_url":"https://avatars1.githubusercontent.com/u/1054708?v=4","gravatar_id":"","url":"https://api.github.com/users/ironikart","html_url":"https://github.com/ironikart","followers_url":"https://api.github.com/users/ironikart/followers","following_url":"https://api.github.com/users/ironikart/following{/other_user}","gists_url":"https://api.github.com/users/ironikart/gists{/gist_id}","starred_url":"https://api.github.com/users/ironikart/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ironikart/subscriptions","organizations_url":"https://api.github.com/users/ironikart/orgs","repos_url":"https://api.github.com/users/ironikart/repos","events_url":"https://api.github.com/users/ironikart/events{/privacy}","received_events_url":"https://api.github.com/users/ironikart/received_events","type":"User","site_admin":false},"assignees":[{"login":"ironikart","id":1054708,"node_id":"MDQ6VXNlcjEwNTQ3MDg=","avatar_url":"https://avatars1.githubusercontent.com/u/1054708?v=4","gravatar_id":"","url":"https://api.github.com/users/ironikart","html_url":"https://github.com/ironikart","followers_url":"https://api.github.com/users/ironikart/followers","following_url":"https://api.github.com/users/ironikart/following{/other_user}","gists_url":"https://api.github.com/users/ironikart/gists{/gist_id}","starred_url":"https://api.github.com/users/ironikart/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ironikart/subscriptions","organizations_url":"https://api.github.com/users/ironikart/orgs","repos_url":"https://api.github.com/users/ironikart/repos","events_url":"https://api.github.com/users/ironikart/events{/privacy}","received_events_url":"https://api.github.com/users/ironikart/received_events","type":"User","site_admin":false}],"milestone":null,"comments":2,"created_at":"2018-08-22T10:41:35Z","updated_at":"2018-08-26T06:08:33Z","closed_at":null,"author_association":"NONE","body":"(Expanding on of an issue originally filed to pa11y: pa11y/pa11y#419)\r\n\r\nHTML5 introduced the `form` attribute to buttons (and other form controls) so they could be associated with a `<form>`, and trigger form submission, without actually having to be nested inside the `<form>` element itself.  See [Association of controls and forms](https://www.w3.org/TR/html52/sec-forms.html#form-owner) in the HTML5 recommendation.\r\n\r\nWhen a `<button>` has a `form` attribute, but is outside the `<form>` element itself, you get the error about a missing submit button:\r\n\r\n> This form does not contain a submit button, which creates issues for those who cannot submit the form using the keyboard. Submit\r\nbuttons are INPUT elements with type attribute \"submit\" or \"image\", or BUTTON elements with type \"submit\" or omitted/invalid.\r\n\r\nThe following code only checks for submit buttons that are _inside_ the form element.  Note that querySelectorAll() is called on the form element, so it only looks for descendants.  (In `Standards/WCAG2AAA/Sniffs/Principle3/Guideline3_2/3_2_2.js`).\r\n\r\n\r\n```\r\n/**\r\n     * Test for forms that don't have a submit button of some sort (technique H32).\r\n     *\r\n     * @param {DOMNode} form The form to test.\r\n     */\r\n    checkFormSubmitButton: function(form)\r\n    {\r\n        var ok = false;\r\n\r\n        // Test for INPUT-based submit buttons. The type must be specified, as\r\n        // the default for INPUT is text.\r\n        var inputButtons = form.querySelectorAll('input[type=submit], input[type=image]');\r\n        if (inputButtons.length > 0) {\r\n            ok = true;\r\n        } else {\r\n            // Check for BUTTONs that aren't reset buttons, or normal buttons.\r\n            // If they're blank or invalid, they are submit buttons.\r\n            var buttonButtons    = form.querySelectorAll('button');\r\n            var nonSubmitButtons = form.querySelectorAll('button[type=reset], button[type=button]');\r\n            if (buttonButtons.length > nonSubmitButtons.length) {\r\n                ok = true;\r\n            }\r\n        }//end if\r\n```\r\n\r\nI propose this test can be extended to look for submit buttons outside the form element, which are associated correctly using a `form` attribute."},"comment":{"url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer/issues/comments/416016462","html_url":"https://github.com/squizlabs/HTML_CodeSniffer/issues/226#issuecomment-416016462","issue_url":"https://api.github.com/repos/squizlabs/HTML_CodeSniffer/issues/226","id":416016462,"node_id":"MDEyOklzc3VlQ29tbWVudDQxNjAxNjQ2Mg==","user":{"login":"fuzzbomb","id":1243005,"node_id":"MDQ6VXNlcjEyNDMwMDU=","avatar_url":"https://avatars1.githubusercontent.com/u/1243005?v=4","gravatar_id":"","url":"https://api.github.com/users/fuzzbomb","html_url":"https://github.com/fuzzbomb","followers_url":"https://api.github.com/users/fuzzbomb/followers","following_url":"https://api.github.com/users/fuzzbomb/following{/other_user}","gists_url":"https://api.github.com/users/fuzzbomb/gists{/gist_id}","starred_url":"https://api.github.com/users/fuzzbomb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fuzzbomb/subscriptions","organizations_url":"https://api.github.com/users/fuzzbomb/orgs","repos_url":"https://api.github.com/users/fuzzbomb/repos","events_url":"https://api.github.com/users/fuzzbomb/events{/privacy}","received_events_url":"https://api.github.com/users/fuzzbomb/received_events","type":"User","site_admin":false},"created_at":"2018-08-26T06:08:33Z","updated_at":"2018-08-26T06:08:33Z","author_association":"NONE","body":"I got this working.  First it looks for buttons which have form attributes, then does a couple more checks on each one to confirm it's a submit button for the form in question."}}
{"actor":{"display_login":"fuzzbomb"}}