|
// This function is from https://github.com/adam-p/markdown-here/blob/3fca89d704d431dc55e78c68b1afae762794c7e7/src/firefox/chrome/content/ff-overlay.js#L382 |
|
/* |
|
* doFunction will be passed a [browser](https://developer.mozilla.org/en-US/docs/XUL/browser) |
|
* (which is approximately analogous to a tab) |
|
* and a [tabbrowser](https://developer.mozilla.org/en-US/docs/XUL/tabbrowser) |
|
* (which is approximately analogous to the window containing the tab) |
|
* for each open tab. browser.contentDocument can be used to access the page's |
|
* document object. |
|
*/ |
|
function forAllTabsDo(doFunction) { |
|
// Tab enumerating code from: https://developer.mozilla.org/en-US/docs/Code_snippets/Tabbed_browser#Reusing_tabs |
|
var windowMediator = Components.classes['@mozilla.org/appshell/window-mediator;1'] |
|
.getService(Components.interfaces.nsIWindowMediator); |
|
|
|
var isNormalTab = function(browser) { |
|
// Someday we might want to make this smarter or optional (maybe the caller |
|
// wants to enumerate `about:` and `resource:` tabs?), but for now we'll |
|
// restrict it to normal web page tabs by looking for http:// and https:// |
|
if (!browser.currentURI.spec.match(/^https?:\/\//i)) { |
|
return false; |
|
} |
|
|
|
// Tabs that haven't loaded properly seem to have a null body. |
|
if (!browser.contentDocument || !browser.contentDocument.body) { |
|
return false; |
|
} |
|
|
|
return true; |
|
}; |
|
|
|
// Iterate through all browser windows... |
|
var browserEnumerator = windowMediator.getEnumerator("navigator:browser"); |
|
while (browserEnumerator.hasMoreElements()) { |
|
var browserWin = browserEnumerator.getNext(); |
|
var tabbrowser = browserWin.gBrowser; |
|
|
|
// ...and through all tabs in the windows |
|
var numTabs = tabbrowser.browsers.length; |
|
for (var index = 0; index < numTabs; index++) { |
|
var browser = tabbrowser.getBrowserAtIndex(index); |
|
|
|
if (isNormalTab(browser)) { |
|
// Do the per-tab work |
|
doFunction(browser, tabbrowser); |
|
} |
|
} |
|
} |
|
} |
|
|
|
// Documentation: |
|
// appendNotification: https://developer.mozilla.org/en-US/docs/XUL/Method/appendNotification |
|
// removeNotification: https://developer.mozilla.org/en-US/docs/XUL/Method/removeNotification |
|
// getNotificiationBox: http://mdn.beonex.com/en/XUL/Method/getNotificationBox.html |
|
// getNotificationWithValue: https://developer.mozilla.org/en-US/docs/XUL/Method/getNotificationWithValue |
|
|
|
var NOTIFICATION_VALUE = 'markdown-here-updated-notification'; |
|
var globalNotificationClearNeeded = false; |
|
|
|
function showNotificationOnTab(browser, tabbrowser) { |
|
var nb = tabbrowser.getNotificationBox(browser); |
|
var notification = nb.getNotificationWithValue(NOTIFICATION_VALUE); |
|
if (notification) { |
|
// This tab already has our notification. |
|
return; |
|
} |
|
|
|
var buttons = [ |
|
{ |
|
accessKey: 'v', |
|
label: 'View changes', |
|
popup: null, // "the id of a popup for the button" (presumably defined in you XUL); null means no popup |
|
callback: function(notification, button) { |
|
// Fires when the button is clicked. |
|
console.log(notification); console.log(button); |
|
|
|
if (globalNotificationClearNeeded) { |
|
globalNotificationClearNeeded = false; |
|
forAllTabsDo(clearNotificationFromTab); |
|
} |
|
|
|
// Do something useful, like show the options+changelist page. |
|
} |
|
}]; |
|
|
|
notification = nb.appendNotification( |
|
'Markdown Here has been updated', |
|
NOTIFICATION_VALUE, |
|
'resource://markdown_here_common/images/icon16.png', |
|
nb.PRIORITY_INFO_LOW, |
|
buttons, |
|
function(eventName) { |
|
// Per the documentation, the only possible value for `eventName` is "removed". |
|
// The callback fires when the user dismisses the notification. |
|
if (globalNotificationClearNeeded) { |
|
globalNotificationClearNeeded = false; |
|
forAllTabsDo(clearNotificationFromTab); |
|
} |
|
}); |
|
} |
|
|
|
function clearNotificationFromTab(browser, tabbrowser) { |
|
var nb = tabbrowser.getNotificationBox(browser); |
|
var notification = nb.getNotificationWithValue(NOTIFICATION_VALUE); |
|
if (notification) { |
|
nb.removeNotification(notification); |
|
} |
|
} |
|
|
|
forAllTabsDo(showNotificationOnTab); |
|
globalNotificationClearNeeded = true; |