简体   繁体   中英

How to hook jquery form submit in Chrome extension

I have simple content script in chrome extension to catch all forms submits. It works when submit triggered by button (see code) but not when called by jquery. It should work can't understand whats wrong.

content.js
---------
jQuery("form").submit(function() {
    alert('submit hooked!: ' + $(this).serialize());
});

page:

page.html
--------
<html>
  <head>
    <script type="text/javascript" src="jquery-1.8.2.min.js"></script>
    <script language="JavaScript">
      function foo() {
        jQuery("#some_form").submit();
      }

      function foo_native() {
        document.getElementById('some_form').submit();
      }
    </script>
  </head>
<body>
    <form action="http://example.com/handler" id="some_form">
      Your name:<input type="text" name="name"><br>
      Your email:<input type="text" name="email"><br>
      <!-- This hooked -->
      <input type="submit" value="Send simple submit"><br>
      <!-- Hook not working for such calls -->
      <input type="button" value="Send jquery submit" onclick="foo()"><br>
      <input type="button" value="Send native submit" onclick="foo_native()">
    </form>
    <br>
</body>
</html>

Background

This is related to the way that the submit event works. You can test out the onsubmit event on a fiddle here: http://jsfiddle.net/sirhc/VueEJ/

This behavior is by design due to historical reasons as described here in the W3C mailing list .

To workaround this, you may have to overwrite the native submit method. And to do so, you have to inject javascript onto the page as content scripts are unable to access the local variables in the content window.

Solution

My solution involves listening to the submit event on the document for normal form submits while also injecting a submit handler for to manually trigger submit events on the page.

Note that the JavaScript methods here make use of the fact that the browser is a modern DOM compatible browser. Some methods here are not available in IE versions 8 and below, but that is fine because this code is meant for use in a Chrome Extension. May I also suggest not using jQuery and writing your own serialize method.

Although not requested, I also made submit handler respect event.preventDefault() .

content.js

document.addEventListener("submit", function (e) {
  alert('submit hooked!: ' + $(e.target).serialize());
}, false);

// Remember to change this to the relative path to inject.js
injectScript( chrome.extension.getURL( "/" ), "inject.js" );

function injectScript ( aBasePath, aScriptURL ) {
  var scriptEl = document.createElement( "script" );
  scriptEl.src = aBasePath + aScriptURL;
  scriptEl.async = false;

  (document.body || document.head || document.documentElement)
  .appendChild( scriptEl );
}

inject.js

HTMLFormElement.prototype._nativeSubmit = HTMLFormElement.prototype.submit;
HTMLFormElement.prototype.submit = function () {
  var submitEvent = document.createEvent("HTMLEvents");
  submitEvent.initEvent("submit", true, true);
  if (this.dispatchEvent(submitEvent)) {
    this._nativeSubmit.apply(this, arguments);
  }
};

manifest.json (to be added, this is not the entire file)

"web_accessible_resources": [ "inject.js" ]

The addition to the manifest allows the inject.js JavaScript file to be injected to the page.

References

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM