I'm not exactly sure if this is due to my manifest setup, or if there's something going on with the .on event and pages that generate content/modify content on the fly, but I've run into a stumbling block.
Here's the basic idea: I want to be able to catch a click on any link with a URL that matches a pattern regardless of where the user is/what page they're looking at (and do other stuff instead of navigating to the link). The problem I'm running into is that my listener won't work on any page that modifies its content after content loads (jQuery's $(document).ready
) (e.g. gMail). I'm injecting my javascript all over the place and it's still not quite working.
Here's the listener code (in main.js):
$('a[href^="http://www.google.com/calendar/event?action=TEMPLATE"]').on('click', function(event) { event.preventDefault(); SKDMmain(this); });
Here's the code in my background.html: (injects my script when the page loads as well as when the tab/window is changed to, so it should be there. Note: jQuery is included above, along with all of the local .js files I need)
<script type="text/javascript"> $(document).ready( function(){ chrome.tabs.executeScript(null,{file:"main.js"}); }); chrome.tabs.onActiveChanged.addListener( function(tabID,somethingElse){ chrome.tabs.executeScript(tabID,{file:"main.js"}); }); chrome.windows.onFocusChanged.addListener( function(windowID){ if ( windowId != chrome.windows.WINDOW_ID_NONE ) { chrome.tabs.executeScript(null,{file:"main.js"}); } }); </script>
But in pages like gMail or this, the listener doesn't catch the event. I originally had this as a content script, but I recently moved it to using background and programmatically injecting, but neither seem to be working quite right.
Here's my manifest, for reference:
{ "name": "SkedjoolMi", "version": "0.5", "description": "Automated Google Calendar event scheduling", "background_page": "background.html", "permissions": [ "tabs","http://*/","https://*/" ], "content_scripts": [ { "matches": ["<all_urls>"], "js": ["jquery-1-7-1.js"], "run_at": "document_end", "all_frames": true } ] }
In fact, for following jQuery code . on() works for even dynamically added elements. As here, before the event is attached, the dynamic div is already appended to the HTML body: $(document).
If you try to bind the elements that are dynamically added to the DOM using the click() method of jQuery, this will not work, because it only binds the click event to elements that exist at the time of the “binding”. To bind the click event to all existing and future elements, use jQuery's on() method.
The reason to work jquery with static content is they are known to DOM, and can handle the events of known elements. but with dynamic contents you have to bind the event with that element by using .
$('a[href^="http:.......').on('click', function() { ...
Will only work with anchors that are already present when the page is rendered—not dynamically added anchors. The above is exactly identical to
$('a[href^="http:.......').bind('click', function() { ...
Here's how you use on
with dynamically added content:
$(document).on("click", 'a[href^="http://www.google.com/calendar/event?action=TEMPLATE"]', function() ...
This creates a delegated event. All clicks that happen in descendants of your document (which is everything) will be inspected to see if the source of the click matches your selector. If it does, your event will fire. That's why it works with dynamically added content.
Ideally, if you can guarantee that all of these anchors will be inside of some container, say, a div with id foo
, the follow would be more efficient:
$('#foo').on("click", 'a[href^="http://www.google.com/calendar/event?action=TEMPLATE"]', function() ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With