• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[GELÖST] HTML5 Webnoti - mehrere Notis auf einmal im Firefox

mikdoe

Moderator
Frage: Warum zeigt nur der Firefox (Chrome funktioniert) die drei Notis der Schaltfläche "Test 3 Notis auf einmal" nicht an?
Ist dem Firefox die Schleife zu schnell? Wie kann man in JS Verzögerungen in einer Schleife machen?
Können andere bestätigen, dass FF sie nicht anzeigt oder ist das nur bei mir so?
Weiß jemand eine Lösung?

Online: Test HTML 5 Notification

Zum kopieren:
HTML:
<!DOCTYPE html>

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Language" content="de">
<meta name="google" content="notranslate">
<title>Test HTML 5 Notification</title>
<style type="text/css">
body {
	font-family:	Arial;
	font-size:		12px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
function webnotification(act,title,options,click,btn) {
	"use strict";
	if (act == 'check') {
		if (window.webkitNotifications || "Notification" in window) { return true; }
		else { return false; }
	}
	else if (act == 'send') {
		var status = localStorage.getItem('kal_termstat'+options['id']);
		if (!status) {
			var sendNotification;
			var defaultaction = function(title,options,click) {
				var listener = function() {	// Zwangsweise über Variable, weil sonst removeEventListener() nicht klappt
					var status = localStorage.getItem('kal_termstat'+options['id']);
					localStorage.removeItem('kal_termstat'+options['id']);
					window.onbeforeunload = null;
					if (status == '1') {	// Firefox feuert beim onclick auch immer onclose
						webnotification('send',title,options,click,btn);
					}
				};
				var schliessen = function() {
					window.clearTimeout(timer);
					noti.removeEventListener('close',listener,false);
					noti.close();
					localStorage.removeItem('kal_termstat'+options['id']);
				};
				var noti = new Notification(title,options);
				noti.addEventListener(
					'click'
					,function() {
						schliessen();
						window.onbeforeunload = null;
						if (click) { click(); }
					}
					,false
				);
				noti.addEventListener('close',listener,false);
				var timer = window.setTimeout(function() {	// damit sich der Chrome genauso verhält wie der Firefox, alle paar Sekunden neu anzeigen
					noti.close();
				},4500);
				window.addEventListener('beforeunload',function() { schliessen(); },false);	// damit sich der Chrome genauso verhält wie der Firefox, Noti nach Seitenwechsel schließen
			};
			if (window.webkitNotifications) {	// Chrome, muss zu oberst abgefragt werden, weil er auch die Methode Notification kennt
				if (window.webkitNotifications.checkPermission() == 0) {	// 0=PERMISSION_ALLOWED; 1=PERMISSION_NOT_ALLOWED; 2=PERMISSION_DENIED
					sendNotification = defaultaction;
				}
				else {
					// ACHTUNG: Chrome lässt requestPermission nur zu, wenn es durch einen Eventhandler aufgerufen wird, der durch eine Benutzeraktion angestossen wurde!
					if (btn) {
						btn.onclick = function() {
							window.webkitNotifications.requestPermission(function() { webnotification(act,title,options,click,btn); });	// direkt nach Rechteerteilung Noti anzeigen
							btn.style.display = 'none';
						}
						if (btn.style.display = 'none') { btn.style.display = ''; }
						return 4;
					}
					else { return 0; }
				}
			}
			else if ("Notification" in window) {	// Firefox
				if (Notification.permission === "granted") {
					sendNotification = defaultaction;
				}
				else if (Notification.permission !== 'denied') {
					Notification.requestPermission(function(permission) {
						if (!('permission' in Notification)) {
							Notification.permission = permission;
						}
						webnotification(act,title,options,click,btn);	// direkt nach Rechteerteilung Noti anzeigen
					});
					return 4;
				}
			}
			if (sendNotification) {
				sendNotification(title,options,click);
				localStorage.setItem('kal_termstat'+options['id'],'1');	// Status 1=wird noch angezeigt
				return 1;
			}
			else { return 0; }
		}
		else { return 2; }
	}
}
</script>
</head>

<body>

<script>
function sende() {
	window.setTimeout(function() {
		var button_zulassen = document.createElement('input');
		button_zulassen.value = 'Notificationberechtigung anstossen';
		button_zulassen.type = 'button';
		button_zulassen.style.display = 'none';
		document.getElementById('schalter').appendChild(button_zulassen);

		var title = 'Testnoti '+document.getElementById('notiid').value;
		var options = {
			body:	'Testnoti Body',
			icon:	'http://www.slipway.de/images/ico_bell.png',
			id:		document.getElementById('notiid').value,
			tag:	document.getElementById('notiid').value,
			lang:	'de'
		};
		var klick = function() {
			alert('angeklickt ID '+options['id']);
		};

		var ret = parseInt(webnotification('send',title,options,klick,button_zulassen),10);
		document.getElementById('testergebnis').innerHTML = 'Senden war '+(ret
			? (ret == 2
				? 'unnötig, weil die Anzeige noch läuft'
				: (ret == 4
					? 'erfolgreich, Anzeige erfolgt unmittelbar nach Rechteerteilung'
					: 'erfolgreich'
				)
			)
			: 'nicht erfolgreich'
		);
	},50);	// falls man die Noti verzögert anzeigen möchte, um zu zeigen, dass sie auch zu sehen ist, wenn der Browser im Hintergrund liegt
}
function sendedrei(data) {
	var dat = '20140327';
	var zeit = '0755';

	var button_zulassen = document.createElement('input');
	button_zulassen.value = 'Notificationberechtigung anstossen';
	button_zulassen.type = 'button';
	button_zulassen.style.display = 'none';
	document.getElementById('schalter').appendChild(button_zulassen);

	jQuery.each(data['stapel'],function(g) {
		if (dat <= data['stapel'][g]['bis_dat'] && zeit <= data['stapel'][g]['bis_zeit']) {
console.log(data['stapel'][g]['id']);
			var title = data['stapel'][g]['title'];
			var options = {
				body:	data['stapel'][g]['body'],
				icon:	data['icon'],
				id:		data['stapel'][g]['id'],
				tag:	data['stapel'][g]['id'],
				lang:	'de'
			};
			var klick = '';
			var ret = webnotification('send',title,options,klick,button_zulassen);
console.log(ret);
		}
	});
}
function startsendedrei() {
	sendedrei({"icon":"http://www.slipway.de/images/ico_bell.png","stapel":[{"body":"test1","bis_zeit":"0800","von_zeit":"0715","aktion":"0","title":"Benachrichtigung für Heute um 08:00","id":"ERI2014032707151","bis_dat":"20140327"},{"body":"test3","bis_zeit":"0810","von_zeit":"0740","aktion":"0","title":"Benachrichtigung für Heute um 08:10","id":"ERI2014032707403","bis_dat":"20140327"},{"body":"test2","bis_zeit":"0800","von_zeit":"0715","aktion":"0","title":"Benachrichtigung für Heute um 08:00","id":"ERI2014032707152","bis_dat":"20140327"}]});
}
</script>

<h1>Test HTML 5 Webnotification</h1>

<div>
	ID: <input type="text" id="notiid"> (unterschiedliche Nummer verwenden stapelt die Notis, das sieht im Chrome sehr nett aus)<br>
	<input onclick="sende();" type="button" value="Test">
</div>
<div id="testergebnis"></div>

<div id="schalter"></div>

<br> <br> <br> <br>
<form method="get" action="http://www.google.de" name="test"></form>
<input type="button" value="Verschwindet die Noti, wenn man hier klickt?" onclick="document.test.submit();">

<br> <br>
<form method="get" action="html5_noti.html" name="test2"></form>
<input type="button" value="Verschwindet sie auch, wenn man hier klickt?" onclick="document.test2.submit();">

<br> <br> <br> <br>
<input type="button" value="localStorage leeren" onclick="localStorage.clear();">

<br> <br> <br> <br>
<input onclick="startsendedrei();" type="button" value="Test 3 Notis auf einmal">

<div>
 <br> <br> <br>
Links:<br>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/notification#Browser_compatibility" target="_new">Browser Kompatibilität</a><br>
<a href="http://www.html5rocks.com/en/tutorials/notifications/quick/?redirect_from_locale=de" target="_new">Using the Notifications API Ernest Delgado</a><br>
</div>

</body>
</html>
 
Zuletzt bearbeitet:
Hab die Schleife mal mit einem "sleep" versehen, klappt trotzdem nicht. Da bin ich gerade ziemlich ratlos.
Oder ist mein künstliches "sleep" fehlerhaft? Mich wundert, dass die Consolen Ausgaben nicht in Sekundenschritten kommen sondern nach 3 Sekunden alle zusammen. Oder ist das eine Eigenart der Console?
Weiß niemand was dazu?

HTML:
function sleep_until(seconds) {
	// Quelle: http://stackoverflow.com/a/4548079
   var max_sec = new Date().getTime();
   while (new Date() < max_sec + seconds * 1000) {}
    return true;
}

	jQuery.each(data['stapel'],function(g) {
console.log('Durchlauf '+g);
		if (dat <= data['stapel'][g]['bis_dat'] && zeit <= data['stapel'][g]['bis_zeit']) {
console.log(data['stapel'][g]['id']);
			var title = data['stapel'][g]['title'];
			var options = {
				body:	data['stapel'][g]['body'],
				icon:	data['icon'],
				id:		data['stapel'][g]['id'],
				tag:	data['stapel'][g]['id'],
				lang:	'de'
			};
			var klick = '';
			var ret = webnotification('send',title,options,klick,button_zulassen);
			sleep_until(1);
console.log(ret);
		}
	});
 
So eine sleep-Funktion ist in JS komplett sinnfrei und eher hinderlich. Wenn du etwas zeitlich versetzt machen willst, musst du window.setTimeout() verwenden - hier scheint ein Abstand von 100ms zwischen den Erstellzeitpunkten nötig zu sein.
Aber ich würde da sowieso immer nur eine Benachrichtigung raushauen und wenn es mehrere Termine sind, kannst du ja die alle untereinander in die eine Benachrichtigung schreiben. Mehr als ca. sieben Benachrichtigungen würde z.B. gar nicht auf meinen Bildschrim passen.
 
Wenn du etwas zeitlich versetzt machen willst, musst du window.setTimeout() verwenden - hier scheint ein Abstand von 100ms zwischen den Erstellzeitpunkten nötig zu sein.
Das hatte ich in verschiedensten Varianten ausprobiert. Sogar mit 1000 und 2000 ms. Hat nichts geändert. Hast du eine funktionierende Variante für mich?

Aber ich würde da sowieso immer nur eine Benachrichtigung raushauen und wenn es mehrere Termine sind, kannst du ja die alle untereinander in die eine Benachrichtigung schreiben.
Unschön, möchte ich nicht, weil ich an den Klick auf die Noti eine Aktion für diesen einen Termin binde, die der Benutzer auswählen kann (z.B. "nicht mehr benachrichtigen", "Termin anzeigen" usw.)

Mehr als ca. sieben Benachrichtigungen würde z.B. gar nicht auf meinen Bildschrim passen.
Was nicht passt legt der Browser in eine neue Reihe. Das hab ich mal auf einer Testseite gesehen. Also darum kümmert sich der Browser ganz allein.
 
Hast du eine funktionierende Variante für mich?
Klar:
Code:
jQuery.each(data['stapel'],function(g, s) {
		window.setTimeout(
			function(){
				if (dat <= s.bis_dat && zeit <= s.bis_zeit) {
					console.log(s.id);
					var title = s.title;
					var options = {
						body:	s.body,
						icon:	data['icon'],
						id:		s.id,
						tag:	s.id,
						lang:	'de'
					};
					var klick = '';
					var ret = webnotification('send',title,options,klick,button_zulassen);
					console.log(ret);
				}
			}, g*100
		);
	});

Unschön, möchte ich nicht, weil ich an den Klick auf die Noti eine Aktion für diesen einen Termin binde, die der Benutzer auswählen kann (z.B. "nicht mehr benachrichtigen", "Termin anzeigen" usw.)
Hm... dachte da irgendwas im Kopf zu haben, dass man da auch HTML in den Body reinschreiben kann. Ist aber nicht so... schade.

Was nicht passt legt der Browser in eine neue Reihe. Das hab ich mal auf einer Testseite gesehen. Also darum kümmert sich der Browser ganz allein.
OK - hatte ich noch nicht ausprobiert.
 
Hammer! Die Variante g*100 hatte ich nicht probiert, hatte da einen festen Wert stehen, dann klappt es nämlich nicht. Jetzt muss ich mal nachdenken, warum da g*100 stehen muss. Das ist bestimmt wieder so ein Closure JS Zeugs :)
Auf jeden Fall vielen vielen Dank, Korbinian!!
 
Noch eine Frage: Könnte man diese Verzögerung auch in der function webnotification(){} unterbringen? Sodass die aufrufende Funktion davon garnichts mitbekommen braucht?
 
Das g* brauchst du da, damit die nicht nicht alle gleichzeitig feuern, sondern das erste nach 0ms, das zweite nach 100ms usw.

In die Funktion webnotification() könnte man das schon einbauen. Man müsste sich dann hald sowas wie eine Queue einbauen, die dann im 100ms Abstand abgearbeitet wird.

PS: das ist definitiv ein Bug im FF und du solltest da auf jeden Fall einen Bugreport einreichen.
 
Das g* brauchst du da, damit die nicht nicht alle gleichzeitig feuern, sondern das erste nach 0ms, das zweite nach 100ms usw.
Ja, aber daran zu denken, dass man jeden Durchlauf von dem gleichen Zeitpunkt aus verzögern muss ist mir noch nicht geläufig. Wieso wird in JS nicht jeder Durchlauf vom vorhergehenden ab gemessen?

In die Funktion webnotification() könnte man das schon einbauen. Man müsste sich dann hald sowas wie eine Queue einbauen, die dann im 100ms Abstand abgearbeitet wird.
Ist das sehr aufwendig? Wie müsste sowas aussehen?

PS: das ist definitiv ein Bug im FF und du solltest da auf jeden Fall einen Bugreport einreichen.
Wo stellt man am besten Bugs für FF ein?

Mehr als ca. sieben Benachrichtigungen würde z.B. gar nicht auf meinen Bildschrim passen.
Das hab ich mir übrigens gerade nochmal angeschaut, der Firefox tapeziert nicht sondern macht die Reihe voll bis oben hin und dann ein Laufband. Und der Chrome macht es genau so, zeigt aber maximal drei untereinander an. Was ich da im Kopf hatte was den Bildschirm tapeziert war ein jQuery Plugin. Also die Anzahl muss einem tatsächlich keine Sorgen machen, das funktioniert in beiden meistens. Manchmal ist es im Firefox so, dass wenn nur noch eine Noti übrig ist, dass diese immer höher rutscht, statt unten zu bleiben. Das sieht witzig aus :)
Ich muss sagen, so üble Implementationen einer neuen Funktion habe ich bisher noch nie gesehen. Kann verstehen, dass sich MS und Opera da zurückhalten :)
 
Zuletzt bearbeitet:
Ja, aber daran zu denken, dass man jeden Durchlauf von dem gleichen Zeitpunkt aus verzögern muss ist mir noch nicht geläufig. Wieso wird in JS nicht jeder Durchlauf vom vorhergehenden ab gemessen?
Äh... window.setTimeout() ist asynchron - würde ja sonst den Browser einfrieren lassen. Die Schleifen läuft einfach durch ohne dass auf irgendein Timeout gewartet wird. Genau das ist ja der Sinn von Timeouts.

Ist das sehr aufwendig? Wie müsste sowas aussehen?
Geht so. Ich würde da hald einen Array machen, in den die Benachrichtigungen reingespeichert werden und über ein window.setInterval() wird dann alle 100ms der erste Eintrag aus dem Array angezeigt und aus dem Array gelöscht. Wobei man beachten muss, dass die neu geöffneten Benachrichtigungen auch in der Queue landen müssen.

Wo stellt man am besten Bugs für FF ein?
https://bugzilla.mozilla.org/
 
https://bugzilla.mozilla.org/show_bug.cgi?id=989702

Denkst du, ich sollte das auch melden, dass der Firefox die Noti nur 4 Sekunden lang anzeigt anstatt die Anzeige zu belassen wie im Chrome?
Auf https://developer.mozilla.org/en-US/docs/WebAPI/Using_Web_Notifications haben die unter "Creating a notification" in einem Kasten das stehen:
Note: Firefox and Safari do not follow the specification regarding the close event. The specification stated that a notification must be closed by the user only. However, Firefox and Safari close the notifications automatically after a few moments; therefore, there is no guarantee that it's the user who closed the notification.

The specification clearly stated that notification auto close should be done at the application level using the Notification.close() method, for example with the following code
Was heißt das denn jetzt? Das heißt, man weiß, dass Firefox und Safari nicht nach Spec arbeiten, aber muss dafür ein Bug gemeldet werden? Oder beheben die das von selbst irgendwann?
 
Zuletzt bearbeitet:
Ich darf den Bugreport irgendwie (noch) nicht ansehen...

Das heißt, man weiß, dass Firefox und Safari nicht nach Spec arbeiten, aber muss dafür ein Bug gemeldet werden? Oder beheben die das von selbst irgendwann?
Wenn das schon bekannt ist, musst du da eigentlich nichts melden. Wenn das absichtlich so gemacht wurde, werden sie es deswegen nicht ändern.
 
Ich darf den Bugreport irgendwie (noch) nicht ansehen...
Ist auch besser so angesichts meiner Englischkenntnisse :)

Wenn das schon bekannt ist, musst du da eigentlich nichts melden. Wenn das absichtlich so gemacht wurde, werden sie es deswegen nicht ändern.
Hab ich das denn richtig interpretiert? Man findet den Text ja auf der Mozilla Developer Seite, also kommt das doch aus der Riege, oder? Oder kann das aus einer ganz anderen Ecke kommen?
 
Das sind schon unterschiedliche Leute, aber die sollten (hoffentlich) miteinander reden. Ich denke nur, dass die Webnotifications einfach keine hohe Priorität haben.
 
dieser ff bug scheint irgendwann behoben worden zu sein. aktuell kann ich den fehler nicht provozieren. ist also erledigt.
 
Zurück
Oben