I am trying to detect the following scenarios:
User navigates away from the web page
User closes the tab
User opens a new tab (i.e. visibility is lost on the old tab)
User closes the browser
I am able to detect all four scenarios above in Safari, Firefox and Chrome, except for "User closes the browser" in Chrome (91.0.4472.114). Currently it does not emit an event which I am able to listen for.
This is my code:
window.onbeforeunload = function() {
// do something
}
window.addEventListener('pagehide', function() {
// do something
}, { capture: true, once: true });
window.addEventListener('unload', function() {
// do something
}, { capture: true, once: true });
window.addEventListener('beforeunload', function() {
// do something
}, { capture: true, once: true });
window.addEventListener('visibilitychange', function() {
if (document.visibilityState === 'hidden') {
// do something
}
}, { capture: true} );
As far as I can tell, I'm checking everything, but maybe I'm missing something?
Thanks for your help.
Related
I am creating a new tab and and injecting some code in it straight after.
But the problem is that the code to be injected is not injected properly when using the property active:true(which I need to use) on tabs.create.
Here is the code in popup.js:
chrome.tabs.create({url: "http://localhost:3000/", index: newTabId, active: false}, (newTab) => {
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
// check status so that it sends only one message, and not one for each status change
if(changeInfo.status === "loading") {
if (tab.id === newTab.id) {
chrome.tabs.sendMessage(newTab.id, {message: "watch_video", videoData: selectedVideoData},
function (resp) {
console.log("Resp",resp);
return true;
}
);
}
}
});
})
Here is the problematic line: chrome.tabs.create({url: "http://localhost:3000/", index: newTabId, active: false}. When active is false, the code is injected, but when it is true, nothing seems to happen.
inject.js:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === "watch_video") {
console.log("inject soon")
injectScript(request.videoData);
sendResponse("watch_video script is to be injected in " + window.location.href)
}
});
function injectScript(videoData) {
console.log("injected")
$(document).ready(function() {
document.test = "ABCDE"
const checkState = setInterval(() => {
$(".bkg").css({ "background-color": "#ffffff"})
}, 100)
})
}
Here I tried something with setInterval(), it does not work when active is true.
However it does work with a timeout. But does not not work without any timeout or interval when active is set to true.
I could use just use a timeout, but it is not really clean, I would prefer to understand why it behaves like it does. I am using react btw.
Here is what it is said about the active property:
Whether the tab should become the active tab in the window. Does not affect whether the window is focused (see windows.update). Defaults to true.
Source: https://developer.chrome.com/extensions/tabs#method-create
I have been looking for Electron app events for when the application is shown or hidden. I see in the docs that there is 'browser-window-blur' and 'browser-window-focus' but those do not do what I want.
I would like to know when the user has switched to another application or switched back to my app. The above events get triggered if the user switches between browser windows – including the "developer's tools" window.
The code in main.js
app.on('browser-window-focus', () => {
if (mainWindow) {
console.log('browser-window-focus');
mainWindow.webContents.send('projectMsg', { "event": "focus" });
}
});
app.on('browser-window-blur', () => {
console.log('browser-window-blur');
if (mainWindow) {
mainWindow.webContents.send('projectMsg', { "event": "blur" });
}
});
It seems to me that it works exactly as you described, so maybe the requirements are different.
This code
const {app, BrowserWindow} = require('electron')
app.on('browser-window-focus', (event, win) => {
console.log('browser-window-focus', win.webContents.id)
})
app.on('browser-window-blur', (event, win) => {
if (win.webContents.isDevToolsFocused()) {
console.log('Ignore this case')
} else {
console.log('browser-window-blur', win.webContents.id)
}
})
app.once('ready', () => {
new BrowserWindow()
new BrowserWindow().webContents.openDevTools({detach: true})
})
works the following way (in 3.0.3) given that nothing is focused initially:
Clicking on window 1 prints browser-window-focus 1
Clicking on window 2 prints browser-window-blur 1 browser-window-focus 2
Clicking on devtools window prints browser-window-blur 2 Ignore this case
So as far as I see devtool is not included in these events, windows are getting blurred for any other window focused (including devtool)
There is also show and hide, though you have to explicitly show/hide the app with win.show() and win.hide() to trigger these events.
Check out of these BrowserWindow's events:
Event: 'blur': Emitted when the window loses focus.
Event: 'show': Emitted when the window is shown.
For example:
app.once('ready', () => {
let mainWindow = new BrowserWindow({show: false}) //Create main window
mainWindow.on('show', () => {
//Do something
})
})
Hope this help.
I currently am using a function on a timed loop to check if a user goes offline:
created() {
setInterval(() => {
this.checkOnline();
}, 30000);
}
Method:
checkOnline(){
this.onLine = navigator.onLine ? true : false;
}
Is there a way I can detect this without using the timer?
Secondly...
I am trying to show an 1 second alert to tell the user they are back online. When this.onLine is true, the div should be hidden. When it is false it should also be hidden, but when it goes from false to true I want to show the div for a second or so and then hide it again. I have tried this with a settimeout and using a watcher but neither give the desired effect.
Edit:
So one method that gets me there is:
data() {
return {
onLine: navigator.onLine ? true : false,
}
}
then a watcher to show the back online message
watch: {
onLine: function (val) {
if(this.onLine === true){
this.showBackOnline = true;
setTimeout(()=>{ this.showBackOnline = false; }, 1000);
}
},
},
Is there a better way than a watcher to achieve this, other than using a dedicated notify plugin?
Is there a way I can detect this without using the timer? Yes. By using the online offline event.
Is there a better way than a watcher to achieve this, other than using a dedicated notify plugin? I think the watcher is the most suitable method here.
demo: https://jsfiddle.net/jacobgoh101/xz6e3705/4/
new Vue({
el: "#app",
data: {
onLine: navigator.onLine,
showBackOnline: false
},
methods: {
updateOnlineStatus(e) {
const {
type
} = e;
this.onLine = type === 'online';
}
},
watch: {
onLine(v) {
if (v) {
this.showBackOnline = true;
setTimeout(() => {
this.showBackOnline = false;
}, 1000);
}
}
},
mounted() {
window.addEventListener('online', this.updateOnlineStatus);
window.addEventListener('offline', this.updateOnlineStatus);
},
beforeDestroy() {
window.removeEventListener('online', this.updateOnlineStatus);
window.removeEventListener('offline', this.updateOnlineStatus);
}
})
you can handle this (update onLine status), just by set arrow function in event listener and set that varible true/false by listener.
window object has online/offline events and you don't need to watch for navigator.online value or set interval to check it. you can just set event listener for it and do something on callback method.
in below code i just change value of my 'isOnLine' variable value and in template show message by v-if directive to user about online/offline.
data() {
return {
isOnLine:navigator.onLine
}
},
mounted() {
window.addEventListener('online', ()=>{this.isOnLine=true});
window.addEventListener('offline', ()=>{this.isOnLine=false});
},
I'm trying to do something like this in my webextension inside background script for firefox 52 browser :
Components.utils.import("resource:///modules/NewTabURL.jsm");
NewTabURL.override(value);
But firefox says that Components.utils - undefined .
My extension based on chrome , so i need to use web extension addon type (.
Is it possible to override newtab page in other way before Firefox 54 realize ?
Update : here is my little code which helps me did newtab replace , but it buggy (
var newTabUrl = browser.extension.getURL("../index.html");
function handleActivated(activeInfo) {
console.log("Tab ", activeInfo);
if (activeInfo.url === "about:newtab") {
browser.tabs.update(activeInfo.id, {
url: newTabUrl
});
}
}
var querying = browser.tabs.query({
currentWindow: true,
active: true
});
const newtabdemo = {
getActiveTab: function() {
return browser.tabs.query({
active: true,
currentWindow: true
});
},
openNewTabPage: function() {
newtabdemo.getActiveTab().then((tab) => {
var gettingInfo = browser.tabs.get(tab[0].id);
gettingInfo.then(handleActivated);
});
}
};
browser.tabs.onCreated.addListener(newtabdemo.openNewTabPage);
You can create chrome override page for the newtab page.
https://developer.chrome.com/extensions/override
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/chrome_url_overrides
Example:
"chrome_url_overrides" : {
"newtab": "my-new-tab.html"
}
I have written my first chrome extension today. What I want it to do is open a tab in the background (pinned), and after the page in the tab finishes loading, I want the tab to close.
So far I have:
chrome.tabs.create({url: target, selected: false, pinned: true});
What the above code does is open the tab in the background, and pin it.
How do I close the tab once it has finished loading?
chrome.tabs.create({url: target, selected: false, pinned: true}, myTab => {
function listener(tabId, changeInfo, tab) {
// make sure the status is 'complete' and it's the right tab
if (tabId === myTab.id && changeInfo.status == 'complete') {
chrome.tabs.remove(myTab.id);
chrome.tabs.onUpdated.removeListener(listener);
}
};
chrome.tabs.onUpdated.addListener(listener);
});
You can either bind a chrome.tabs.onUpdated or a chrome.webNavigation.onCompleted event to detect that a page has finished loading, or insert a content script to close the tab.
Using the webNavigation.onCompleted event
var tabsToClose = {};
chrome.webNavigation.onCompleted.addListener(function(details) {
if (details.frameId !== 0) return; // Only process top-frame requests
var tabId = details.tabId;
if (tabsToClose[tabId]) {
delete tabsToClose[tabId];
chrome.tabs.remove(tabId);
}
});
chrome.tabs.create({url: target, selected: false, pinned: true}, function(tab) {
tabsToClose[tab.id] = 1;
});
Note: I assumed that navigation will always succeed. You should also bind a webNavigation.onErrorOccurred event to close the tab on failure.
Using a content script
By using runAt: 'document_idle' (default), window.close(); will be inserted once the page has finished loading.
chrome.tabs.create({url: target, selected: false, pinned: true}, function(tab) {
chrome.tabs.executeScript(tab.id, {
code: 'window.close();',
runAt: 'document_idle'
});
});