I am writing a Chrome Userscript (Greasemonkey) extension to display a confirmation dialog when the user clicks on Gmail's Send button (in the compose window etc.).
I have manged to attach to the click even of the button and show a dialog when the button is clicked, by using:
addEventListener("click", function(e) { ......... }, true);
But I cannot stop the email from being sent. I have tried using:
e.stopPropagation();
e.preventDefault();
return false;
How can I stop Gmail from sending the email?
I think that those mentioned by you can prevent default action that is built-in in browser, and stop propagation of event to parent elements in DOM hierarchy. You probably need to get the Gmail's event listener and do something with it - wrap it with your function (so, remove original event listener and bind your function, which displays a dialog and then invoke Gmail's one). Currently, when you only add an event listener, there are two independent event handlers.
Those posts might be useful:
How to find event listeners on a DOM node?
How to check if any JavaScript event listeners/handlers attached to an element/document?
Related
With this code I want to create an event listener for whenever chrome storage updates.
I want 2 things to happen when the event listener is triggered:
The code will console log the updated values. This part works.
I want the HTML for the extension (the document that opens in the corner when you click the icon) to update and render the data value that is in chrome storage. This is that part I need help with.
chrome.storage.onChanged.addListener(function(changes, namespace) {
//part 1
console.log('New data type is %s. New value is %s',
changes['type'].newValue, changes['data'].newValue)
//part 2
document.getElementById('output').innerHTML =
changes['data'].newValue
});
I realize that calling "document" inside the function doesn't make sense, but I'm unsure how to move forward to get it to render in the extension's HTML.
I tried creating an event listener for when the context menu is accessed (users can update the chrome storage but clicking a button in the context menu) but I couldn't get it to work. Also the event should trigger when chrome storage is updated, not when the context menu is simply accessed.
Right now I get this error:
Error in event handler: TypeError: Cannot set property 'innerHTML' of null
(There is an element with id 'output', so that isn't the problem)
Thanks for your help!
The background script runs in a separate hidden background page. It's not related to the browserAction or pageAction popup page, it doesn't have any of the popup page elements, its DOM is empty except for the auto-generated script tags of the background scripts.
The popup is also a separate page and just like any normal page its environment/DOM exists only when the page is shown. You can't modify it when it's not shown. You can't show it from your code in general case either.
Solution 1
Put that onChanged listener in popup.js script that's loaded in your popup.html (declared as "browser_action": {"default_popup":"popup.html"} in your manifest.json) using the standard <script src="popup.js"></script> tag. It will update the popup page if it's shown, and to display the current values when the popup opens read them with chrome.storage.local.get or chrome.storage.sync.get depending on which storage you're using in your extension.
Solution 2
Use chrome.notifications API to show a small notification at the bottom of the screen, see also the official demo extensions.
Solution 3
Use chrome.browserAction.setBadgeText to display short text like a temperature right under the extension icon. Don't forget to declare at least "browser_action": {} in your manifest.json.
I have a basic chrome extension that fires when the user switches to a new active tab. In the background page the URL is examined and the extension icon changes based on the URL.
chrome.tabs.onActivated.addListener(function(tabInfo) {
chrome.tabs.get(tabInfo.tabId, function(tab) {
update_tab(...)
});
});
This works fine, but the problem I am facing is that by the time the function fires and the decision is made to update the icon, the user can switch tabs again, but the icon is changed based on the previous tab.
How can I handle this more reliability?
You can have per-tab browser action icons, so you don't need to track tab switching.
If you use chrome.browserAction.setIcon to update your icon, it takes an optional tabId parameter. Same applies to setTitle.
If you do this, you need not worry about tab activations; onUpdated will inform you of URL changes.
You could try adding the onUpdated listener too:
chrome.tabs.onUpdated.addListener(function(tabInfo) {
chrome.tabs.get(tabInfo.tabId, function(tab) {
update_tab(...)
});
});
Fires when the active tab in a window changes. Note that the tab's URL
may not be set at the time this event fired, but you can listen to
onUpdated events to be notified when a URL is set. https://developer.chrome.com/extensions/tabs
I'm looking for an event that can be fired just right before changing a tab?
I have already seen this post, and I have also looked into the tabSelect event in the firefox extension, but I couldn't find any event that can be fired just before the tab change.
Unfortunately there is no such event.
However you can watch, with a MutationObserver, the type attribute of selected tab's browser element (gBrowser.mCurrentBrowser). When it changes from content-primary to content-targetable it's a signal that a tab switch is in progress.
As paa already noted, there is no event that happens before a tab is selected. What you can use are tricks, e.g. the Object.watch() method (yes, using it isn't exactly recommended). It allows you to listen to changes of the gBrowser.tabContainer.selectedIndex property (the setter of this property is where the select event is being fired):
gBrowser.tabContainer.watch("selectedIndex", function(prop, oldval, newval)
{
// New tab being selected, do something here!
return newval;
});
The advantage of this approach: by returning oldval from the handler you can prevent the selection from taking place.
I have a group of links on a page. when the user clicks a link it triggers an asynchronous request and a content area on the page is updated with the response html.
This works fine, except for if the user clicks the link with the 'middle-button' (or mouse wheel, whatever it's called!). Then a new tab opens and the response gets returned and rendered to that tab.
Is there any way for me to prevent this from happening?
catch the link with javascript and override the default link behaviour.
like this:
$('a.ajax').click(function(e){
e.preventDefault();
// do ajax stuff, and add an onfinish function that does
// something like document.location.href = this.attr('href');
});
You don't have to do the document.location.href, as I just noticed that a content area is updated. Just catch the default behaviour with the e.preventDefault();
// edit
The preventDefault won't stop the middle mouse button... Have you considered not using tags? I know it should be accessible so maybe a span containing the link, so you can add the onclick event on the span and hide the link with css?
Unfortunately no, Javascript wont have access to that sort of control for security reasons as it would be wide open for abuse.
I use the <a> tag to build buttons. I use JavaScript (jQuery) to implement the behavior.
How can I prevent the browser from following a link, while continuing to execute all click() events?
This:
$("a.button").live("click", function(event) { return false; });
doesn't work, because, depending on the position of that handler it might prevent other .click() handlers from executing. For some buttons it works as I want it, but for some it prevents my other handlers from executing.
I know I could use a single click handler per button, but I would rather do it the AOP-way.
jQuery provides a method called preventDefault which will stop the default action of the event from occurring. With this the following code will stop the link from being follow but should not stop the propagation of the even to other handlers.
$("a.button").click(function(event){ event.preventDefault(); });