My goal is to create a notification with a Chrome extension when a value in firebase changes.
With the code below I receive a notification the first time I'm changing the value, but not the following times.
f.on('child_changed', function (snapshot) {
ignoreInitialData = false;
var options = {
type: 'basic',
iconUrl: '../../icons/green.png',
title: "Availability notifier",
message: snapshot.val(),
contextMessage: "",
eventTime: Date.now(),
isClickable: false,
};
chrome.notifications.create("child_changed", options, function (notificationID) {
console.error(chrome.runtime.lastError);
});
});
Any solutions?
Since you're using a fixed notification ID, it's updated instead of creating a new one.
If the notification is not closed but hidden in the Chrome notification center, it will not be shown again.
Your options include:
Not using a fixed ID (pass "" as ID)
This will cause both the old and the new notifications to remain until dismissed. Probably not what you want.
Closing the old notification just before showing a new one.
This works well, but is visually jarring if your old notification did not yet disappear. However, you may actually want this effect if you want to emphasize "this is new information"
Using a priority change trick to re-show the notification.
This works best, but is "hacky". We can only hope Chrome API will improve to do this natively.
You can also add a timestamp suffix so every notification is different:
var timestamp = new Date().getTime();
var id = 'myid' + timestamp;
Related
I have a WebExtension for Mozilla, which notifies me with the desktop notification function.
It works exactly how I want, but Firefox will close the notification automatically after X seconds. Is it possible to display the notification until the user clicks on it?
The thing I did is to close and reopen the notification every 5 seconds, so the user has to click on it to close it permanently.
This looks like this:
// This is the notification function
function notifyMeFunction() {
var notification = new Notification('Alert', {
icon: chrome.extension.getURL('icons.png'),
body: "New Notification",
tag: "DesktopNotification",
});
notification.onclick = function(event) {
notificationClicked = true;
}
notification.onclose = function(event) {
notificationClicked = true;
}
}
// Function which will self-open every 5 seconds
function notifyMe() {
if (notificationClicked == false) {
notifyMeFunction();
setTimeout(notifyMe, 5000);
} else {
notificationClicked = false;
}
}
Any ideas how to set the display time to something like "must interact"?
There is, currently (Firefox version <= 51.0a1), no method of indicating to the API that the user must interact with these notifications. Nor is there any way to specify for how long the notification is displayed to the user.
Note: You are using the Web Notifications API, not the WebExtensions chrome.notifications API. Neither has a way to require user interacting in Firefox.
From Chrome 50, Google Chrome does have an option to require that the user must interact with the notification: requireInteraction. Thus, at some point in time, Firefox will probably support such an option.
However, at least as of this point in time, the string requireInteraction does not exist in the Firefox source code.
I am working on a web based application, in which I have to open popup window. I am using window.open() method to open the popup, like this:
window.open(url, "popupWin");
where url contains the URL I would like my popup window to navigate to. Now, the problem is, if I execute window.open() from multiple tabs (with same or different URLs), at least on Chrome, it might / might not give you the same window which was opened earlier. This behaviour is inconsistent, I mean, either it should get me fresh window every time, or it should get me previously opened window every time.
I need to persist the same popup window for entire domain. How can I do that?
Well looks like there is a direction to go or at least to give it a try.
It fully remains on localStorage which gives you ability to share the knowledge across your tabs within a single domain.
The code I give below does not work yet (it is only a direction), so don't expect too much from running it as it is.
What it does: it saves the popups by the url in a localStorage and when you try to open a new one with the same url it won't do that. If you don't want to distinguish them by URL it is even simpler: store boolean in a localStorage instead of an object.
What it does not do but should:
it should listen to the popup onunload (close) event and reset the localStorage information accordingly. Best for you here is just to set your localStorage boolean value to false
it should listen to the current tab onunload (reload, close) event and also reset something according to Your logic. As I understand the best for you would be just check whether this tab is the last one from your domain (you can also do this using localStorage, e.g. on every new tab adding its identifier, e.g. creation timestamp and destroying it on tab close) and if it is set your localStorage boolean value to false.
This, I think, would be enough to solve the problem. And finally a small piece of code:
// get the localstorage url map
function getOpenPopups() {
var obj = localStorage.getItem('mypopups');
return obj ? JSON.parse(obj) : {};
}
// set the localstorage url map
function setOpenPopups(object) {
localStorage.setItem('mypopups', JSON.stringify(object))
}
// open the popup
function popup(url, title) {
var popups = getOpenPopups();
// check whether popup with this url is already open
// if not then set it and open the popup
if (!popups[url]) {
popups[url] = true;
setOpenPopups(popups);
return window.open('abc', 'cde');
}
else {
return false;
}
}
jsFiddle
From w3c documentation we can see that window.open() returns a reference to the newly created window, or null if the call failed. That means we can keep it in memory and check for closed flag of that window.
var newWindow = window.open('/some/path', 'TestWindow');
// ...
if (!newWindow.closed) {
}
Keep in mind that if window with following name exists, page will be loaded in the same window without opening new one.
Other variants of name parameter like _blank, _self, _top, _parent you can find in official docs too.
I was asked to take a look at what should be a simple problem with one of our web pages for a small dashboard web app. This app just shows some basic state info for underlying backend apps which I work heavily on. The issues is as follows:
On a page where a user can input parameters and request to view a report with the given user input, a button invokes a JS function which opens a new page in the browser to show the rendered report. The code looks like this:
$('#btnShowReport').click(function () {
document.getElementById("Error").innerHTML = "";
var exists = CheckSession();
if (exists) {
window.open('<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>');
}
});
The page that is then opened has the following code which is called from Page_Load:
rptViewer.ProcessingMode = ProcessingMode.Remote
rptViewer.AsyncRendering = True
rptViewer.ServerReport.Timeout = CInt(WebConfigurationManager.AppSettings("ReportTimeout")) * 60000
rptViewer.ServerReport.ReportServerUrl = New Uri(My.Settings.ReportURL)
rptViewer.ServerReport.ReportPath = "/" & My.Settings.ReportPath & "/" & Request("Report")
'Set the report to use the credentials from web.config
rptViewer.ServerReport.ReportServerCredentials = New SQLReportCredentials(My.Settings.ReportServerUser, My.Settings.ReportServerPassword, My.Settings.ReportServerDomain)
Dim myCredentials As New Microsoft.Reporting.WebForms.DataSourceCredentials
myCredentials.Name = My.Settings.ReportDataSource
myCredentials.UserId = My.Settings.DatabaseUser
myCredentials.Password = My.Settings.DatabasePassword
rptViewer.ServerReport.SetDataSourceCredentials(New Microsoft.Reporting.WebForms.DataSourceCredentials(0) {myCredentials})
rptViewer.ServerReport.SetParameters(parameters)
rptViewer.ServerReport.Refresh()
I have omitted some code which builds up the parameters for the report, but I doubt any of that is relevant.
The problem is that, when the user clicks the show report button, and this new page opens up, depending on the types of parameters they use the report could take quite some time to render, and in the mean time, the original page becomes completely unresponsive. The moment the report page actually renders, the main page begins functioning again. Where should I start (google keywords, ReportViewer properties, etc) if I want to fix this behavior such that the other page can load asynchronously without affecting the main page?
Edit -
I tried doing the follow, which was in a linked answer in a comment here:
$.ajax({
context: document.body,
async: true, //NOTE THIS
success: function () {
window.open(Address);
}
});
this replaced the window.open call. This seems to work, but when I check out the documentation, trying to understand what this is doing I found this:
The .context property was deprecated in jQuery 1.10 and is only maintained to the extent needed for supporting .live() in the jQuery Migrate plugin. It may be removed without notice in a future version.
I removed the context property entirely and it didnt seem to affect the code at all... Is it ok to use this ajax call in this way to open up the other window, or is there a better approach?
Using a timeout should open the window without blocking your main page
$('#btnShowReport').click(function () {
document.getElementById("Error").innerHTML = "";
var exists = CheckSession();
if (exists) {
setTimeout(function() {
window.open('<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>');
}, 0);
}
});
This is a long shot, but have you tried opening the window with a blank URL first, and subsequently changing the location?
$("#btnShowReport").click(function(){
If (CheckSession()) {
var pop = window.open ('', 'showReport');
pop = window.open ('<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>', 'showReport');
}
})
use
`$('#btnShowReport').click(function () {
document.getElementById("Error").innerHTML = "";
var exists = CheckSession();
if (exists) {
window.location.href='<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>';
}
});`
it will work.
My app uses the gcm module to listen for notifications and displays android notifications for every new notification that comes in. Additionally, the current window gets updated with the new count of unread messages.
This window is created using Ti.UI.createWindow({exitOnClose:true})
The problem is, that when the user presses the back button, the application stops. This means, I don't receive any more notifications and thus cannot display them in the notifications bar.
Is there a way to make titanium hide the app when pressing the back button, but not stop it, so that my code stil is running in the background?
I know of the possibility to start a service, but the downside of this is that i cannot update my window, when it's currently visible to the user, since there seems to be no way to communicate between the service and the app. Or is there a way?
app.js
//this is the most important line in this code.
//if I do exitOnClose:true, I stop receiving notifications every 5 seconds when pressing the back button (not good!, I want to keep getting notifications)
//if I do exitOnClose:false, I go back to a blank, "powered by titanium" window, when pressing the back button (not good!, I want the app to go to the background)
var win = Ti.UI.createWindow({exitOnClose:true});
//not part of the question
var label = Ti.UI.createLabel({text:"0"});
win.add(label);
win.open();
var notifications = [];
//listen for notifications (not part of the question)
listenForNotifications(function(notification){
//handle the notification
notifications.push(notification);
//update window
label.text = "Notification Count: "+notifications.length;
//display notification in title bar
displayNotificationInTitleBar(notification);
})
//this function is just dummy code to simulate listening for notifications in background using the gcm module
//it simulates a new notification every 5 seconds with an always increasing id
//it actually does not matter what module I use for notifications, Just take it as given that there runs code in the background,
//that I don't want to stop, after the user taps the backbutton
function listenForNotifications(cb){
var i = 0;
setInterval(function(){
cb({id:i++});
},5000);
}
//This function is actually not part of the question, it's just a sample
function displayNotificationInTitleBar(notification){
var intent = Ti.Android.createIntent({
action: Ti.Android.ACTION_MAIN,
packageName:"com.company.backgroundnotificationstest",
className:"com.company.backgroundnotificationstest.BackgroundnotificationstestActivity",
flags:Ti.Android.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Ti.Android.FLAG_ACTIVITY_SINGLE_TOP
});
intent.addCategory(Ti.Android.CATEGORY_LAUNCHER);
intent.putExtra("notificationid",notification.id);
Titanium.Android.NotificationManager.notify(notification.id, Titanium.Android.createNotification({
contentTitle: "New Notification",
contentText : "ID: "+notification.id,
contentIntent: Ti.Android.createPendingIntent({
intent:intent,
type : Ti.Android.PENDING_INTENT_FOR_ACTIVITY
}),
flags : Titanium.Android.ACTION_DEFAULT | Titanium.Android.FLAG_AUTO_CANCEL | Titanium.Android.FLAG_SHOW_LIGHTS
}));
}
The sample app is available at: https://github.com/VanCoding/TitaniumBackgroundNotificationsTest
Feel free to compile it and see it yourself :)
Since you set exitOnClose your app will exit on closing the window you have created. To prevent exiting from the app you need to reset the key as follows while creating the window.
Ti.UI.createWindow({exitOnClose: false});
If you would like to show the notifications in the notifications tray, make sure that you have set the following keys
showTrayNotification
showTrayNotificationsWhenFocused : This will display the notification in the tray even when the app is focused.
To show/hide a badge, you can try the following tip.
You need to keep track how many notifications you received and you need to update it upon receiving the notification. Just update the badge using the value stored. I tried this solution and is working great in one of my app
After a bit of thinking, I came to the following (a bit hacky) solution:
win.addEventListener("android:back",function(){ //listen for the back-button-tap event
e.cancelBubble = true; //prevent the back-button default action
//display the home screen
var intent = Ti.Android.createIntent({
action: Ti.Android.ACTION_MAIN,
flags:Ti.Android.FLAG_ACTIVITY_NEW_TASK
});
intent.addCategory(Ti.Android.CATEGORY_HOME);
Ti.Android.currentActivity.startActivity(intent);
});
I have a web-application for iPhone, and I need to trigger a Javascript function when the web page is in focus, in other words, when Safari is open.
What I want to accomplish is to start a timer in some way when the user clicks on a tel-link and starts the call. When the call ends, Safari pops up again, and the timer ends.
Is there any way to do this?
Best Regards
Linus
try this:
if you trigger the link for the call set the actual time in a localStorage-item.
$("#yourButton").click(function() {
var actualTime = new Date().getTime();
window.localStorage.setItem('callStart', actualTime);
})
after that you need to read the Storage after user ends up the call.
You can set this in the document.ready on the opening page.
in $(document).ready(function() {})
// check for the localStorageItem
if (window.localStorage.getItem('callStart')) {
// get it
var timeStart = window.localStorage.getItem('callStart');
var now = new Date().getTime();
/*
Now calculate here the difference now - timeStart
and you will get seconds, minutes or whatever you want
*/
// !!! Dont forget to clear the localStorageItem
window.localStorage.removeItem('callStart');
}
This is what I would try. The Usage of the HTML5-localStorage gives you the possibility to store key/values and data isnt lost if user stops the app or device is automatically locked.
Hope this helps a bit.
ADDED: You even can store JSON as the value in the localStorageItem. So you can set an callID and implement a calling-history for your users.