Problem
When a user drags and drops an element, using jQuery UI, I would like to broadcast the drop to other users so they can see the updated position of the element.
Question
How can I configure the script to be able to send the 'dropping' of the element using socket.broadcast.emit?
Code
Client Side (the drop setup)
$('#dropArea').droppable({
drop: function(event, ui) {
var dropped = ui.draggable;
var droppedOn = $(this);
$(dropped).detach().css({
top: 0,
left: 0
}).appendTo(droppedOn);
socket.emit('status', {
status: 'ToDo',
_id: $(this).find('p').data('id')
});
}
});
Server (some socket setup)
io.sockets.on('status', function(data) {
Item.findOne({_id: data._id}, function(err, item) {
if(err) throw err;
item.status = data.status;
item.save();
});
});
Note
The emit "status" updates the elements status in the database
You can have listener in client side as well for this event,
io.sockets.on('status', function(data) {
//do the update in client here
});
And one other thing is you need to use socket.broadcast.emit here.Because socket.emit will broadcast the message to all the clients with the client who is broadcasting the message.
I worked out a method. I sent the the relevant data required for the item in an object, through a socket.
On the server, I did the status update I needed from the mongoDB and then broadcasted the object back to all clients. And from the client side, removed the item from its current position and re-structured and appended it to its new position using jquery.
Related
I have a scenario where i need to send postMessage of latest version files array from client to service worker on the update event of service worker.
current code
reg.onupdatefound = function() {
// The updatefound event implies that reg.installing is set; see
// https://w3c.github.io/ServiceWorker/#service-worker-registration-updatefound-event
var installingWorker = reg.installing;
console.log('on update found');
// service worker is updated with version name eesh
if(reg.installing)
{
reg.installing.postMessage({
data: cacheUrls()
});
}
installingWorker.onstatechange = function() {
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and the fresh content will
// have been added to the cache.
// It's the perfect time to display a "New content is available; please refresh."
// message in the page's interface.
console.log('New or updated content is available. yo yo');
// navigator.serviceWorker.controller.postMessage({data: location})
} else {
// At this point, everything has been precached.
// It's the perfect time to display a "Content is cached for offline use." message.
console.log('ServiceWorker registration successful with scope: ', reg.scope);
}
break;
case 'redundant':
console.error('The installing service worker became redundant.');
break;
}
};
};
};
But sometimes the installation happens first and then "message" event is listened in service worker. How do i wait for 'message' event inside 'install' event of service worker ?
I believe you can do something like this:
// sw.js
self.addEventListener('install', function(e) {
const installPromise = new Promise(function(resolve, reject) {
// do install stuff, like caching resources, etc.
self.addEventListener('message', function(e) {
// 1. do something with the received data
// 2. remove this event listener
resolve();
});
});
e.waitUntil(installPromise);
});
e.waitUntil() accepts a Promise so we give it one. The install phase gets completed only when the promise passed to e.waitUntil() resolves. We only resolve that Promise once we've already received the message from the client.
I have created chat application using following
Rails
Rabbitmq
nodejs ( with amqplib/callback_api and socket.io )
I have following code in server side
var amqp = require('amqplib/callback_api');
var amqpConn = null;
var app = require('http').createServer()
var io = require('socket.io')(app);
var fs = require('fs');
io.on('connection', function (socket) {
socket.emit('news/1', msg.content.toString());
// socket.disconnect()
});
client side
<%= javascript_include_tag "http://localhost:53597/socket.io/socket.io.js" %>
<script>
var socket = io('http://localhost:53597', {reconnect: true});
socket.on('connect', function () {
console.log('connected');
socket.on('news/1', function (msg) {
console.log('inside coming');
console.log(msg);
});
});
</script>
When I send message, message successfully pushed to queue and messages emitted to socket. The problem is I can get messages when only refresh page and messages are not deleted.
I can't understand what was wrong here ?
Eventually I fixed my issue, the problem is I have placed emit function inside connection event, so that I can get data when only connection established​, connection is established when page load that is the reason I get data when only page load.
I have the following code for emit data
io.sockets.emit('news/1', msg.content.toString());
I am trying to listen for the event which occurs when an "Authorisation Required" dialogue is displayed (see Firefox Addon SDK Hotkeys and contect menu options dont work on Authentication Required Popup).
However I notice that XUL addons can listen for a DOMWillOpenModalDialog event which is apparently triggered when this dialogue box opens. None of the SDK panel events seem to be triggered.
Is there a way to listen for this event from within the addon SDK?
------Edit------
Going on from Noitidart 's sugestion I then tried a couple of other events and they fire. Both the attempts below work.
var events = require("sdk/system/events");
function listener(event) {console.log("An event popup was activated.");}
events.on("xul-window-visible", listener);
CWin.addEventListener("DOMWillOpenModalDialog", function() {CWin.setTimeout(NfyBox, 500);}, true);
function NfyBox() {
console.log("An event popup was activated.");
worker = tabs.activeTab.attach({
contentScriptFile: self.data.url("notifybox.js")
});
worker.port.emit("notify");
}
However that is as far as I get, in the contentScriptFile, a console.log of document produces :-
console.log: infstr: {"location":{"assign":"function assign() {\n [native cod
e]\n}","replace":"function replace() {\n [native code]\n}","reload":"function
reload() {\n [native code]\n}","toString":"function toString() {\n [nativ
e code]\n}","valueOf":"function valueOf() {\n [native code]\n}","href":"http:
//c1s4-1e-syd.hosting-services.net.au:2082/unprotected/redirect.html","origin":"
http://c1s4-1e-syd.hosting-services.net.au:2082","protocol":"http:","username":"
","password":"","host":"c1s4-1e-syd.hosting-services.net.au:2082","hostname":"c1
s4-1e-syd.hosting-services.net.au","port":"2082","pathname":"/unprotected/redire
ct.html","search":"","hash":""}}
But an attempt to get getElementById or anything else I tried comes back undefined. I am obviously making some simple mistake, but can’t see what it is.
Yes listen to popup events. In this case popupshowing: MDN : PopupEvents
This is an example that prevents the main menu at top right (tri stripe menu button) from closing by listening to popuphiding and preventing it:
var PUI = Services.wm.getMostRecentWindow('navigator:browser').document.querySelector('#PanelUI-popup');
try {
PUI.removeEventListener('popuphiding', previt, false);
} catch (ignore) {}
var previt = function(e) {
PUI.style.opacity = 1;
e.stopPropagation();
e.preventDefault();
e.returnValue = false;
return false;
}
PUI.addEventListener('popuphiding', previt, false);
I'm trying to use PrivatePub within my Angular app. I've a chat and messages are managed by AngularJS, my API behind is running with Rails, in my controller I use the helper to Publish to the channel, my problem is on the client side with the Subscribe. Here is what I try to do:
chat.controller("MessageController", ['$scope','Message','Project', function($scope,Message,Project) {
//Fetch messages
Message.query(function(data) {
$scope.messages = data;
});
PrivatePub.subscribe(Project.channel, function(data, channel) {
$scope.messages.push(data.message);
});
}]);
I tried to use $apply and $watch around my PrivatePub subscribe, no way to update my scope. My PrivatePub function should be outside Angular but the data it receives should be added to the $scope.I don't what other solution I could try.
Ok I found the problem, I was not using $apply correctly, I was basically doing:
$timeout(function () {
$scope.$apply(function($scope) {
PrivatePub.subscribe("/mychannel", function(data, channel) {
$scope.addMessage(data.chat_message);
});
});
}, 0);
Instead of:
$timeout(function () {
PrivatePub.subscribe("/mychannel", function(data, channel) {
$scope.$apply(function($scope) {
$scope.addMessage(data.chat_message);
});
});
}, 0);
The changes I want to notify to Angular is not the function itself but what happened inside. Just a bad use.
I'm working in an implementation using SignalR and the Kendo Scheduler. When a new task is created (for exemple), the SchedulerDataSource transport send the connection hub id to the server as an additional parameter:
transport: {
read: { url: global.web_path + 'Home/Tasks' },
update: { url: global.web_path + 'Home/UpdateTask', type: 'PUT', contentType: 'application/json' },
create: { url: global.web_path + 'Home/CreateTask', type: 'POST', contentType: 'application/json' },
destroy: { url: global.web_path + 'Home/DeleteTask', type: 'DELETE', contentType: 'application/json' },
parameterMap: function (options, operation) {
if (operation == "destroy" && options.models) {
return JSON.stringify({ taskId: options.models[0].Id, callerId: $.connection.hub.id });
}
if (operation !== "read" && options.models) {
return JSON.stringify({ tasks: options.models, callerId: $.connection.hub.id });
}
}
},
The server do whatever it has to do, and send a notification to every other user, except de caller:
[HttpPost]
public JsonResult CreateTask(List<ScheduledEvent> tasks, string callerId)
{
...create task and other stuff
//broadcast the newly created object to everyone except caller
var hubContext = GlobalHost.ConnectionManager.GetHubContext<Notebooks.Hubs.SchedulerHub>();
hubContext.Clients.AllExcept(callerId).UpdateSchedule(task);
//return the object to caller
return Json(task);
}
Once the other clients receive a new task from the hub, it is added to the SchedulerDataSource:
hub.client.updateSchedule = function (scheduledEvent) {
schedulerDataSource.add(scheduledEvent);
}
Everything seems to work fine, and it really took me some time to realize this behavior: if a client have the scheduler window open, this window is closed once the schedulerDataSource is updated. This is expected or am I doing something wrong?
Edit: I just realized how old this question is, so you have probably moved on to other things by now, or the pushCreate method may not have existed back then.
I think this may be how it works, but it seems like it should be able to add those events behind the scenes without having to close the edit window. Have you tried the pushCreate method? If that doesn't work, since the add automatically closes the edit dialog, maybe when the events come in, if the dialog is open, you could store the new events, then add them when the user closes the edit dialog.
My answer is now even older ;) but I faced this very same issue today.
First, I'm quite sure this is indeed the expected behavior. You can see in the kendo sources the call of the close editor window method in the transport update and create methods of the scheduler.
Below is what I've done to bypass the issue .
The idea is as simple as to prevent the edit window to close when an appointment modification comes from another hub client.
Server-side : modify the hub methods (example with update method)
public MyAppointmentViewModel Update(MyAppointmentViewModel appointment)
{
if (!appointmentService.Update(appointment))
throw new InvalidOperationException("Something went wrong");
else
{
Clients.Others.PrepareBeforeAddOrUpdateSignal(appointment.Id);
Clients.Others.Update(appointment);
return appointment;
}
}
Here you see we inform every other clients (through PrepareBeforeAddOrUpdate) we're about to update an appintment.
Client-side now (in index.cshtml for instance)
schedulerHub.client.prepareBeforeAddOrUpdateSignal = function(id){ lastModifiedRdvId = id; };
schedulerHub.client.create = function(appointment){ lastModifiedRdvId = 0; }; /* reset the variable for next time */
schedulerHub.client.update = function(appointment){ lastModifiedRdvId = 0; }; /* reset the variable for next time */
function SchedulerEditor()
{
return $(".k-scheduler-edit-form").data("kendoWindow");
}
var eventBeforeChanges = null;
var lastModifiedRdvId = 0;
function onEditorClose(e) {
if (eventBeforeChanges != null) {
if (lastModifiedRdvId > 0 && eventBeforeChanges.Id != lastModifiedRdvId)
e.preventDefault();
else {
var editWin = SchedulerEditor(); /* unbind this callback and use default behavior again */
editWin.unbind('close', onEditorClose);
}
}}
function onEditRdv(e) {
var editWin = SchedulerEditor();
if (editWin != null) /*Bind the close event */
editWin.unbind('close', onEditorClose).bind('close', onEditorClose);
eventBeforeChanges = e.event;
/* continue onEditRdv */
}
you see here the close event is prevented when the appointment id is not the appointment id beeing updated by the current client.
And fortunately, preventing the close event prevents the annoying behavior of having a sort of ghost appointment after one has been changed by another hub client.
I'm sorry if I'm not clear or if the code isn't clear enough. I can provide more information if necessary.
Bye