Chrome Notifications Using AJAX - javascript

On page load I request the user to allow notifications like so:
document.addEventListener('DOMContentLoaded', function () {
if (Notification.permission !== "granted")
Notification.requestPermission();
});
I have then wrote a function to send notifications to the user which works fine:
function push(title, message, location) {
if(!Notification) { return; }
if (Notification.permission !== "granted") { return; }
var notification = new Notification(title, {
icon: 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
body: message,
});
notification.onclick = function () {
window.open(location);
};
}
Used like this:
push('Test', 'Test Message', 'http://example.com');
I then have a PHP script, for the time being it is static and returns the same thing for testing soon to be database driven.
session_start();
header('Content-Type: application/javascript');
if(!isset($_SESSION['notify'])) {
echo json_encode(array(
'Title' => 'Welcome to our Site',
'Message' => 'You are current recieving notifications.',
'Location' => 'http://example.com/',
'State' => true
),true);
$_SESSION['notify'] = true;
} else {
echo json_encode(array(
'State' => false
), true);
}
This works fine too when the page is directly accessed. The issue occurs in my AJAX request:
setInterval(function() {
$(document).ready(function() {
$.post('../notify/get_notify.php').done(function(response) {
if(response.State) {
push(response.Title, response.Message, response.Location);
}
console.log(response);
});
});
}, 5000);
The issue is here! When I check the network, every 5 seconds a request is being made and the response is coming back. However, nothing is logged in the console and the push() method is not executed.
Any help would be greatly appreciated.

I found the issue, due to the scope of the $.post() I was unable to retrieve anything, so instead I returned the value of the response like this:
setInterval(function() {
$(document).ready(function() {
response = $.post('../notify/get_notify.php').done(function(response) {
return response;
});
if(response.State) {
push(response.Title, response.Message, response.Location);
}
});
}, 5000);

Related

With SocketIO & node.js only the message I sent is not visible in chatroom

I developed the chat room app with node.js & expressjs in backend. Use socket.io with chat rooms.
And I found the when I send the message, outgoing messages are not shown. But it works well before so I research the github history but the codes are same as before.
And one thing I cannot understand is, ingoing messages functions are works well, only outgoing messages are not working.
But the DB part works well so When I refresh the page all the chat's are shown well.
The code shown below is part of my app.js's socketIO part.
[app.js]
const io = require('socket.io')(socket);
/* Socket IO Functions */
io.on('connection', function (socket) {
// Join Room Scoket
socket.on('JoinRoom', function (data) {
socket.leave(`${data.leave}`)
// console.log(`Leave ROOM : ${data.leave}`)
socket.join(`${data.joinedRoomName}`);
// console.log(`NEW JOIN IN ${data.joinedRoomName}`)
// console.log(`RECEIVER : ${data.receiver}`)
// When Reads the message SET notice to '1'
// db.query(`UPDATE chatData SET notice='1' WHERE chatReceiver=? AND roomName=?`, [data.receiver, data.joinedRoomName])
// console.log(data);
Chat.aggregate([{
$match: {
'chatReceiver': data.receiver,
'roomName': data.joinedRoomName,
'chatNotice': 1
}
},
{
$set: {
'chatNotice': 0
}
}
], (err, result) => {
if (err) throw err;
// console.log(result);
})
})
// Send Message Socket
socket.on('say', function (data) {
//chat message to the others
socket.to(`${data.joinedRoomName}`).emit('mySaying', data);
console.log(data)
console.log(`Message Send to : ${data.joinedRoomName}`)
console.log(`Message Content : ${data.userId} : ${data.msg}`);
// Chat Message Save to DB SQL
Chat.create({
'roomName': data.joinedRoomName,
'chatSender': data.userId,
'chatReceiver': data.receiver,
'chatMessage': data.msg
})
});
}
[chat.js [Client Side]]
let socket = io();
/* SocketIO Functions */
$(function () {
$('#message').focus(); // Init Focus to Input
let fontColor = 'black';
let nickName = '';
let whoIsTyping = [];
/* Submit Event (Keyboard Enter) */
$('#chat').submit(function () {
if (joinedRoomName === undefined) {
/* Not yet joined Alert */
const Toast = Swal.mixin({
toast: true,
position: 'bottom',
showConfirmButton: false,
timer: 5000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
}
})
Toast.fire({
icon: 'warning',
title: 'Please joined room first!'
})
$('#message').val('Joined ROOM First!!');
} else {
if ($('#message') !== '') {
let msg = $('#message').val();
socket.emit('say', {
msg: msg,
userId: userId,
loginedId: userId,
receiver: others,
joinedRoomName: joinedRoomName
});
}
// Say event means someone transmitted chat
$('#message').val('');
socket.emit('quitTyping')
}
return false;
});
/* Click Event (Click Send Button) */
$('.msg_send_btn').click(function () {
if (joinedRoomName === undefined) {
$('#message').val('Joined ROOM First!!');
} else {
//submit only if it's not empty
if ($('#message').val() != "") {
let msg = $('#message').val();
socket.emit('say', {
msg: msg,
userId: userId,
loginedId: userId,
receiver: others,
joinedRoomName: joinedRoomName
});
}
// Say event means someone transmitted chat
$('#message').val('');
socket.emit('quitTyping')
}
return false;
});
/* Sending Messages Socket */ THIS PART IS CHAT PART!!!!
socket.on('mySaying', function (data) {
d = Date.now();
d = new Date(d);
d = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()} ${d.getHours() > 12 ? d.getHours() - 12 : d.getHours()} : ${d.getMinutes()} ${(d.getHours() >= 12 ? "PM" : "AM")}`;
console.log(data.userId);
console.log(userId);
if (data.userId == userId) {
$('.msg_history').append(`<div class="outgoing_msg"><div class="sent_msg"><p>${data.msg}</p><span class="time_date"> ${d}</span></div></div>`);
} else {
$('.msg_history').append(`<div class="incoming_msg"><div class="incoming_msg_img"><img src="${avatar_url}" alt="sunil"></div><div class="received_msg"><div class="received_withd_msg"><p>${data.msg}</p><span class="time_date">${d}</span></div></div></div>`);
$('#chatData').text(`${data.msg}`)
}
Scroll();
});
/* Typing... Socket */
socket.on('typing', function (whoIsTyping) {
whoIsTyping = others;
$('#message').attr('placeholder', `${whoIsTyping} is typing..`) // Typing... Message
});
/* End Typing Socket */
socket.on('endTyping', function () {
whoIsTyping = [];
$('#message').attr('placeholder', "Type a Message"); // If Notyping Reset to Init placeholder
})
/* Input Typing Socket */
$('#message').keyup(function (event) {
if ($('#message').val() != "" && !whoIsTyping.includes(others)) {
socket.emit('typing', {
others,
joinedRoomName
});
} else if ($('#message').val() == "" && whoIsTyping.includes(others)) {
socket.emit('quitTyping', {
others,
joinedRoomName
});
}
});
});
It looks like this. When I send chat to someone it send to other person works well but in my page, the chat that I sent is not shown.
I don't know where this bug come from.
In your app.js, you are using
socket.to("ROOM").emit('EVENT', data);
Which is, sending to all clients in "ROOM" room except sender
thus the sender will not receive the event (which is happening in your case).
You want to include the sender in a broadcast event use following
io.in("ROOM").emit("EVENT", data);
and for your specific case
io.in(`${data.joinedRoomName}`).emit('mySaying', data);
look at Emit cheatsheet
First, thanks to answer above. And the codes are right.
In my client side socketio version is 2.X but the server side socketio is updated to 3.X so it's not wokring.
If I use version 2.X use my code, but use 3.0
io.in(`${data.joinedRoomName}`).emit('mySaying', data);
is the answer.

How to fix braintree javascript error "t.getVersion is not a function" in latest version

Am getting error TypeError: t.getVersion is not a function, i have searched only the solution i found was about using the upgraded version of braintree-web here. In my case am using 3.60.0, but still get the error when i add braintree.dataCollector.create.
https://js.braintreegateway.com/web/3.60.0/js/client.min.js
https://js.braintreegateway.com/web/3.60.0/js/data-collector.min.js
https://js.braintreegateway.com/web/dropin/1.22.1/js/dropin.min.js
var form = document.querySelector('#payment-form');
var client_token = "<?php echo $clientToken;?>";
braintree.dropin.create({
authorization: client_token,
container: '#dropin-container',
paypal: {
flow: 'vault'
}
}, function (createErr, instance) {
if (createErr) {
console.log('Create Error', createErr);
return;
}
form.addEventListener('submit', function (event) {
event.preventDefault();
braintree.dataCollector.create({
client: instance,
paypal: true
}, function (err, dataCollectorInstance) {
if (err) {
return;
}
document.querySelector('#device').value = dataCollectorInstance.deviceData;
});
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Request Payment Method Error', err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
I was starting out trying to get the simple Drop In example implemented and ran in to the same issue! I know you posted the question a while ago but this may help anyone else coming across this question, as I did 😉.
The clue was #Simon_Weaver's answer to the question Braintree PayPal checkout component throwing “e.client.getVersion is not a function” and these 2 little lines...
Turns out instance is NOT a Client object. It is a Dropin object ;-) It creates its own client stored on _client private property.
I needed instead to do braintree.client.create(...) to get a true Client object.
Unfortunately #Simon_Weaver didn't provide a proper example and "cheated".
In essence, you'll need to create a separate clientInstance and passing that when creating a dataCollector instead of instance
var form = document.querySelector('#payment-form');
var client_token = "<?php echo $clientToken;?>";
braintree.client.create({
authorization: client_token
}, function(err, clientInstance) { // this is the client instance we need when creating a `dataCollector`
braintree.dataCollector.create({
client: clientInstance, // `clientInstance` not dropIn `instance`
paypal: true
}, function (err, dataCollectorInstance) {
if (err) {
return;
}
document.querySelector('#device').value = dataCollectorInstance.deviceData;
});
/* ... rest of the `braintree.dropin.create`
just without the above `braintree.dataCollector.create` stuff in the submit handler...
*/
braintree.dropin.create({
authorization: client_token,
container: '#dropin-container',
paypal: {
flow: 'vault'
}
}, function (createErr, instance) {
if (createErr) {
console.log('Create Error', createErr);
return;
}
form.addEventListener('submit', function (event) {
event.preventDefault();
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Request Payment Method Error', err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
});
I have also moved the initialisation of the dataCollector out of the form submit handler - no need to do it all then.
*** This hasn't been tested but should get you going in the right direction ***
Maybe a bit late for this one... but for the Drop-In UI it should be enough including a dataCollector object in your create call and getting the device data from the payload afterwards:
var form = document.getElementById('my-form-id');
var deviceDataInput = form['device_data'];
var nonceInput = form['payment_method_nonce'];
braintree.dropin.create({
authorization: 'CLIENT_AUTHORIZATION',
container: '#dropin-container',
dataCollector: true
}, function (createErr, instance) {
if (deviceDataInput == null) {
deviceDataInput = document.createElement('input');
deviceDataInput.name = 'device_data';
deviceDataInput.type = 'hidden';
form.appendChild(deviceDataInput);
}
button.addEventListener('click', function () {
instance.requestPaymentMethod(function (requestPaymentMethodErr, payload) {
deviceDataInput.value = payload.deviceData;
nonceInput.value = payload.nonce;
});
});
});

Protractor Javascript not executing in sequence

I have the below function for login, which would console "successful" on success and "Failed" for files ones.
function login() {
return new Promise(function (resolve, reject) {
var username = element(by.name('txtLogin'));
var password = element(by.id('txtPassword'));
var signInButton = element(by.id('btnSignIn'));
for (var i = 0; i < testData.length; i++) {
if (testData[i].env === appConfig) {
username.sendKeys(testData[i].user);
password.sendKeys(testData[i].pass);
signInButton.click();
console.log("Successfully Clicked on the Sign In Button!");
break;
}
}
browser.getTitle().then(function (title) {
if (title == "Page Title") {
resolve("Successfull");
} else {
reject("Failed");
}
});
});
};
And the following test
describe('Login Scenarios', function () {
beforeEach(function () {
login();
});
it('Valid Credentials, Should login successfully from util class', function () {
console.log('Successfully logged in!');
});
});
I am seeing very strange behavior here. This line executes and consoles output even before the page is fully loaded.
console.log("Successfully Clicked on the Sign In Button!");
and the below code never gets executed.
browser.getTitle().then(function (title) {
if (title == "Page Title") {
resolve("Successfull");
} else {
reject("Failed");
}
});
And in the end i see the following error.
failed: error while waiting for protractor to sync with the page: "cannot re ad property '$$testability' of undefined"
I am pretty sure, i have messed up something here. But unable to figure out what's wrong that am doing here.
login returns a promise, but you're not signalling to Jasmine/Protractor that it needs to wait for it to finish. You can do this using the done callback:
beforeEach(function (done) {
login().then(function () {
done();
});
});
See the Jasmine documentation (which seems to have been inexplicibly hidden away in their new website layout...) for more info.

Notification.requestPermission throws an error in Mac versions of Safari

I am trying to display notifications with jQuery locally on page load. The notification is showing correctly in Firefox, Firefox Developer, and Chrome. The notification is not appearing in Safari despite allowed in notification preference settings.
Similar code is working from MDN site https://developer.mozilla.org/en/docs/Web/API/notification.
Snippet is below.
// Display a sample notification
if (window.Notification) {
return $(".au-notifications-page").show(function() {
var notification;
notification = new Notification(
'Success Text', {
//tag: $("[name=tag]").val(),
body: 'Success Message',
iconUrl: 'img/avatar-male.png',
icon: 'img/avatar-male.png'
});
return notification.onclick = function() {
notification.close();
window.open().close();
return window.focus();
};
});
};
Complete code is below.
$(document).ready(function () {
// Request permission on site load
Notification.requestPermission().then(function(result) {
if (result === 'denied') {
//alert('denied');
$(".au-notif-disabled-header").removeClass('hide');
$(".au-notif-disabled-header .btn").addClass('hide');
return;
}
if (result === 'default') {
//alert('ignored');
$(".au-notif-disabled-header").removeClass('hide');
return;
}
//alert('granted');
$(".au-notif-disabled-header").addClass('hide');
});
// Request permission with button
$('.au-notif-disabled-header .btn').click(function () {
Notification.requestPermission().then(function(result) {
if (result === 'denied') {
$(".au-notif-disabled-header").removeClass('hide');
$(".au-notif-disabled-header .btn").addClass('hide');
return;
}
if (result === 'default') {
$(".au-notif-disabled-header").removeClass('hide');
return;
}
$(".au-notif-disabled-header").addClass('hide');
});
});
$( ".au-notification-icon" ).hover(
function() {
$(".au-notifications-menu .au-notif-msg-realtime").slideDown();
$('.au-notification-icon .badge').html("2");
}, function() {
$(".au-notifications-menu .au-notif-msg-realtime").slideUp();
$('.au-notification-icon .badge').html("1");
}
);
//To show notification received while on notifications page
$(".au-notif-msg-realtime").hide();
//$(".au-notifications-page .au-notif-msg-realtime").slideDown();
$(".au-notifications-page .au-notif-msg-realtime").slideDown({
complete: function(){
$('.au-notification-icon .badge').html("2");
$('head title').html("(2) Notifications");
}
});
// Display a sample notification
if (window.Notification) {
return $(".au-notifications-page").show(function() {
var notification;
notification = new Notification(
'Success Heading', {
body: 'Success Text',
iconUrl: 'img/avatar-male.png',
icon: 'img/avatar-male.png'
});
return notification.onclick = function() {
notification.close();
window.open().close();
return window.focus();
};
});
};
});
EDIT 1: Safari throws this exception
undefined is not an object (evaluating 'Notification.requestPermission().then')
You have to use a callback function for Safari, since it doesn't return a Promise.
According to MDN:
This uses the promise-version of the method, as supported in recent
implementations (Firefox 47, for example.) If you want to support
older versions, you might have to use the older callback version,
which looks like this:
Here's the sample code they gave:
Notification.requestPermission(function (permission) {
// If the user accepts, let's create a notification
if (permission === "granted") {
var notification = new Notification("Hi there!");
}
});
To support Safari notifications, this is what I ended up with:
try {
Notification.requestPermission()
.then(() => doSomething())
} catch (error) {
// Safari doesn't return a promise for requestPermissions and it
// throws a TypeError. It takes a callback as the first argument
// instead.
if (error instanceof TypeError) {
Notification.requestPermission(() => {
doSomething();
});
} else {
throw error;
}
}
A better solution is to wrap the results in a Promise and then (no pun intended) run your code. This code works on all browsers (including Safari) and without a complicated if block (concept is discussed in detail in this question)
Promise.resolve(Notification.requestPermission()).then(function(permission) {
// Do something
});
This works because Promise.resolve does nothing to a Promise, but will convert the Safari requestPermission() to a Promise.
Note that iOS Safari still does not support the Notification API so you will need to check if it is available first
To return a promise which doesn't resolve until the user grants or denies permission to show notifications:
if (!permissionPromise && Notification.permission === 'granted' ) {
permissionPromise = Promise.resolve(Notification.permission);
}
if (!permissionPromise) {
permissionPromise = new Promise(function (resolve, reject) {
// Safari uses callback, everything else uses a promise
var maybePromise = $window.Notification.requestPermission(resolve, reject);
if (maybePromise && maybePromise.then) {
resolve(maybePromise);
}
});
}
return permissionPromise;

Meteor: write to database on successful callback from server method

I want to write to database only on successful callback received from server when I invoke it from client.
Meteor.call('job', 'new', name, script, function(err,response) {
if(err) {
console.log(err);
alert('Error while processing your script. Please make sure syntax is correct.')
return;
}else{
taskid = response;
console.log(taskid);
FileSystem.update({ _id: this.params.fileId }, { $set: { content: content, taskid:taskid} }, function (e, t) {
if (e) {
//error
}
});
}
});
write now it says
Exception in delivering result of invoking 'job': TypeError: Cannot read property 'fileId' of undefined
I expected that it will only update the DB when the server call was successful. How can I make this happen?
Assuming this.params exists at all, you're likely losing your data context inside of these callback functions. What you want to do is define a variable before your Meteor.call() and set that variable to this.params.fileId. You can then use that variable inside of the callback function.
I've shown this in code below.
var fileId = this.params.fileId;
Meteor.call('job', 'new', name, script, function(err,response) {
if(err) {
console.log(err);
alert('Error while processing your script. Please make sure syntax is correct.')
return;
}else{
taskid = response;
console.log(taskid);
FileSystem.update({ _id: fileId }, { $set: { content: content, taskid:taskid} }, function (e, t) {
if (e) {
//error
}
});
}
});

Categories

Resources