I show a 'sticky' notification like this:
function show(text) {
let alreadyOn = false; // ??? how to get this ???
if (!alreadyOn) {
new Notification(text, {
requireInteraction : true
});
}
}
Notification.requestPermission();
show("first");
setTimeout(() => show("second"), 1000);
(note this just a sample and you need to permit notification the first time it runs and try again)
Is there a way for my code to later determine if this notification is still on or the user already dismissed it ? That is how to determine alreadyOn above ?
You can add an event handler with Notification.onclose method to do something when the Notification is closed by the user.
Notification.onclose = function () {
// do something...
}
Related
I have two functions that do the same thing, but are used differently.
I currently have a popup that is triggered on actions based on device. On desktop, if the mouse leaves the page, it triggers the popup (function called exitUserMessage). On mobile, if the mouse is inactive for 10 seconds+ it triggers the popup (function called inactiveUserMessage). See below:
//display popup for inactive users
const inactiveUserMessage = () => {
//other code was here but deleted bc not relevant
return dismissModal();
};
//display popup for users leaving the page
function exitUserMessage() {
//other code was here but deleted bc not relevant
return dismissModal();
}
Here is where the functions are used, both separately for desktop and mobile:
if (width <= 480) {
// Start the timer on page load
window.addEventListener("load", () => {
timer = setTimeout(inactiveUserMessage, 10000);
});
document.addEventListener("mousemove", debounce(inactiveUserMessage, 10000), timer);
} else {
// Trigger popup for desktop
document.addEventListener("mouseleave", (e) => {
if (Evergage.cashDom("#abandon-cart-message").length === 0) {
return exitUserMessage();
}
});
}
inactiveUserMessage is used in the debounce function that delays it by 10 seconds, then triggers the popup to show.
exitUserMessage is returned when the mouse leaves the page for desktop. My question is both of these functions are doing the same thing above ^.
Any ways to simplify? I am fairly new to JavaScript so looking to learn best practice!
Something worth noting: these are tracked as separate actions in our dataLayer.
Thank you!
You can call the inactiveUserMessage variable like functions. If there are different parts in those functions, add a parameter like isDesktop to inactiveUserMessage and debounce functions . If true, run the relevant desktop code in if statement.
const inactiveUserMessage = (isDesktop) => {
if (isDestop) {
//Desktop
} else {
//Mobile
}
return dismissModal();
};
if (width <= 480) {
// Start the timer on page load
window.addEventListener("load", () => {
timer = setTimeout(inactiveUserMessage, 10000);
});
document.addEventListener("mousemove", debounce(inactiveUserMessage, false, 10000), timer);
} else {
// Trigger popup for desktop
document.addEventListener("mouseleave", (e) => {
if (Evergage.cashDom("#abandon-cart-message").length === 0) {
return inactiveUserMessage(true);
}
});
}
I am detecting the end of a webrtc stream in JavaScript like this...
stream.getVideoTracks()[0].onended = () => {
alert('Feed Has Ended');
};
This is working correctly, but if the user refreshes or reloads the page then the alert is also shown.
I understand that this is technically correct, but how can I get it to not display the alert under those conditions?
Why don't you use a global boolean to check if video is playing or not? When you will reload or refresh the page, isVideoRunning will become false and alert won't show.
Like
this.isVideoRunning = false;
On addtrack,
this.rtcPeerCon_.ontrack = function (event) {
if (!this.rtcPeerCon_) {
return;
}
if( !this.remoteVideo_ ) {
return;
}
this.remoteVideo_.srcObject = event.streams[0];
this.isVideoRunning = true;
}
then in your onStream ended callback you can check
if (this.isVideoRunning) {
alert('whatever');
this.isVideoRunning = false;
}
(I wanted this to be comment but I am not allowed to comment yet)
i have troubles detecting a closing window after the build is done.
const newWindow = window.open(url, '_blank', options);
newWindow.onbeforeunload = () => null;
newWindow.addEventListener('beforeunload', (evt: BeforeUnloadEvent) =>
{
console.log(evt)
}
);
it works great until i do the build, there the beforeunload event does not get triggered. i also tried placing a host listener in the new window's component:
#HostListener('window:beforeunload', [ '$event' ])
beforeUnloadHander(event: BeforeUnloadEvent): void {
debugger;
}
but the same problem here. after the build is done, we don't arrive at the debugger anymore
anybody any idea what i am doing wrong? thanks for your help!
Edit Workaround
const heartBeatNewWindow = setInterval(() => {
if (newWindow.closed) {
this.canvasSettings.displayInNewWindow = false;
clearTimeout(heartBeatNewWindow);
}
}, 1500);
I had to do something similar and my approach was the following:
I created a generic catch from close event windows in the constructor of my service, them call method what handle this event. Inside this method I validate the origin of this event is the correct to execute the logic I needed. Look this example:
Inside the constructor:
if(window.addEventListener){
window.addEventListener("message", this.authService.handleMessage.bind(this), false);
}else{
(<any>window).attachEvent('onmessage', this.authService.handleMessage.bind(this));
}
And my method to handle that event:
handleMessage(event: Event) {
event.preventDefault();
const message = event as MessageEvent;
// Only trust messages from the below origin.
//
if ((message.origin !== environment.BASE_URL)) return;
const result = JSON.parse(message.data);
//Add your logic here
I Hope be helpfull.
I am stuck on getting a timeout working. I already have a working code but it seems to me the wrong way to do it.
Working code but probably not the best:
/* Autosave */
// On load we hide all autosave messages.
$('.jform_params_autosave-cg').hide();
// Below is the function that handles the autosave.
$.fn.autoSave = function(){
// We remove the autosave message from it's place defined by the xml and add it to the system message container.
var autosavemessage = $('.jform_params_autosave-cg');
autosavemessage.detach();
autosavemessage.appendTo('#system-message-container');
// Now we show the message.
$('.jform_params_autosave-cg').show();
// Here we save the extension.
Joomla.submitbutton('module.apply');
}
// On change of the below elements we run the autosave.
//------------------------------------------//
// DUPLICATE AUTOSAVE FUNCTION BELOW
//------------------------------------------//
// Autosave: Theme Selection
$("#jform_params_theme_selection").change(function() {
$.fn.autoSave();
});
// Autosave: Add Content
$("a.group-add.btn.btn-mini.button.btn-success").click(function() {
setTimeout(
function()
{
$.fn.autoSave();
}, 5000);
});
The Function:
$.fn.autoSave = function(){
// We remove the autosave message from it's place defined by the xml and add it to the system message container.
var autosavemessage = $('.jform_params_autosave-cg');
autosavemessage.detach();
autosavemessage.appendTo('#system-message-container');
// Now we show the message.
$('.jform_params_autosave-cg').show();
// Here we save the extension.
Joomla.submitbutton('module.apply');
}
The Function Call
$("#jform_params_theme_selection").change(function() {
$.fn.autoSave();
});
The Function Call with Timeout
$("a.group-add.btn.btn-mini.button.btn-success").click(function() {
setTimeout(
function()
{
$.fn.autoSave();
}, 5000);
});
What do I want to achieve
Make the Timeout inside the function.
Define the timeout when calling the function.
With defining I mean calling it something like $.fn.autoSave(5000); or $.fn.autoSave().timeout(500);
I have been trying to get a working code but so far no luck. Will keep updating this post whenever I get more success or details to add.
Thanks everyone for helping.
Any link to existing SO questions will also be appreciated as I might be googling for the wrong key words.
Here it is the modified version of your function. Now it has optional timeout parameter. You can use it like
$('selector').autoSave(5000) or $('selector').autoSave()
$.fn.autoSave = function(timeout) {
function doIt() {
// We remove the autosave message from it's place defined by the xml and add it to the system message container.
var autosavemessage = $('.jform_params_autosave-cg');
autosavemessage.detach();
autosavemessage.appendTo('#system-message-container');
// Now we show the message.
$('.jform_params_autosave-cg').show();
// Here we save the extension.
Joomla.submitbutton('module.apply');
return this;
}
timeout = Number(timeout) || 0;
var f = doIt.bind(this);
if(timeout < 0) return f();
setTimeout(f, timeout);
return this;
}
When using Google Chrome extension alarms, the alarm will go off if it was set and Chrome is closed and reopened after the time expires for the alarm.
How can I stop this?
Here is a small code sample to explain what I mean.
/*
If we perform Browser Action to create alarm, then
close the browser, wait about 2 minutes for the alarm to expire
and then reopen the browser, the alarm will go off and the DoSomething
function will get called twice, once by the onStartup event and once
by the onAlarm event.
*/
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.alarms.create('myAlarm', {
delayInMinutes : 2.0
});
});
chrome.alarms.onAlarm.addListener(function (alarm) {
console.log('Fired alarm!');
if (alarm.name == 'myAlarm') {
createListener();
}
});
chrome.runtime.onStartup.addListener(function () {
console.log('Extension started up...');
DoSomething();
});
function DoSomething() {
alert('Function executed!');
}
So if you will read the comment at the top of my code sample you will see what happens.
What I want though, is for the alarm to get cleared if the browser is closed as I want the DoSomething function to get executed only by the onStartup event if the browser is just started, and let the alarm execute the DoSomething function only after the browser is started and my code creates a new alarm.
I never want an alarm to stay around after the browser is closed and then execute onAlarm when the browser is reopened.
How can achieve this?
It's not possible for a Chrome extension to reliably run some code when the browser closes.
Instead of cleaning up on shutdown, just make sure that old alarms are not run on startup. This can be achieved by generating an unique (to the session) identifier.
If you're using event pages, store the identifier in chrome.storage.local (don't forget to set the storage permission in the manifest file). Otherwise, store it in the global scope.
// ID generation:
chrome.runtime.onStartup.addListener(function () {
console.log('Extension started up...');
chrome.storage.local.set({
alarm_suffix: Date.now()
}, function() {
// Initialize your extension, e.g. create browser action handler
// and bind alarm listener
doSomething();
});
});
// Alarm setter:
chrome.storage.local.get('alarm_suffix', function(items) {
chrome.alarms.create('myAlarm' + items.alarm_suffix, {
delayInMinutes : 2.0
});
});
// Bind alarm listener. Note: this must happen *after* the unique ID has been set
chrome.alarms.onAlarm.addListener(function(alarm) {
var parsedName = alarm.name.match(/^([\S\s]*?)(\d+)$/);
if (parsedName) {
alarm.name = parsedName[0];
alarm.suffix = +parsedName[1];
}
if (alarm.name == 'myAlarm') {
chrome.storage.local.get('alarm_suffix', function(data) {
if (data.alarm_suffix === alarm.suffix) {
doSomething();
}
});
}
});
If you're not using event pages, but normal background pages, just store the variable globally (advantage: id reading/writing becomes synchronous, which requires less code):
chrome.runtime.onStartup.addListener(function () {
window.alarm_suffix = Date.now();
});
chrome.alarms.create('myAlarm' + window.alarm_suffix, {
delayInMinutes : 2.0
});
chrome.alarms.onAlarm.addListener(function(alarm) {
var parsedName = alarm.name.match(/^([\S\s]*?)(\d+)$/);
if (parsedName) {
alarm.name = parsedName[0];
alarm.suffix = +parsedName[1];
}
if (alarm.name == 'myAlarm') {
if (alarm.suffix === window.alarm_suffix) {
doSomething();
}
}
});
Or just use the good old setTimeout to achieve the same goal without side effects.
setTimeout(function() {
doSomething();
}, 2*60*1000); // 2 minutes