Connection dropped but endPoints did not change or remained same - jsplumb

How will I come to know easily that an attempt was made by dragging one connection, left in between having no change in endpoints?

You need to get notified when a endpoint is dragged to make connection but dropped such that no connection was made. To attain this we need to handle 2 events:
1.event triggered when connection was made. (jsPlumbConnection)
2.event triggered when endpoint stopped dragging. (dragOptions: {stop})
NOTE: jsPlumbConnection event is triggered before stop event.
Maintain a global variable(FLAG) which is initially false and set to true when connection is made. While endpoint is stopped dragging we check FLAG for our result.
FLAG=false; //global variable
jsPlumb.bind("jsPlumbConnection", function(ci) { //Register event when connection is made
flag=true; // set to true when connection is made
});
var e = jsPlumb.addEndpoint("DOM_ELEMENT", {
endpoint:"Dot",
hoverPaintStyle:{ fillStyle:"red" },
anchor:"Right",
dragOptions: {
stop:function() { //Register event when endpoint stopped dragging
if(FLAG===false)
alert("No connection was made");
else
FLAG=false; // Reset variable for next use
}
}
});

Related

How to tell if a streamDestroyed event was triggered by session.disconnect() or closing of browser

I have a user interface with a "Hang Up" button used to end a call.
The "Hang Up" button calls session.disconnect()
On calling session.disconnect() the other participant in the call listens for the streamDestroyed event which returns a reason of "clientDisconnected"
According to the docs:
"clientDisconnected" — A client disconnected from the session by calling the disconnect() method of the Session object or by closing the browser.
Thing is, I need to differentiate across these two scenarios so that I can provide different messaging to the call participant.
How do I tell if the call ended by 1) explicit hang up (calling session.disconnect()) or 2) closing of the browser?
The only other options for a reason are "networkDisconnected" which means that the other participant lost their internet connection, and "forceDisconnected" which means the participant was force disconnected using session.forceDisconnect(). Neither of these are what you want.
You could keep track of hangups yourself though if you send a signal to everyone in the session before you hangup. Then on the receiving side keep track of whether someone has sent the hangup signal. ie.
// On the hangup side
function hangup() {
session.signal({type: 'hangup'}, function() {
session.disconnect();
});
}
// On the receiving side...
var hangups = {};
session.on('signal:hangup', function(event) {
hangups[event.from.connectionId] = true;
});
session.on('streamDestroyed', function(event) {
if (hangups[event.stream.connection.connectionId] === true) {
// They pressed the hangup button!
}
});

Xamarin.Forms - BLE any device connection lost

In the last project I use BLE plugin.
adapter.DeviceDiscovered += (s, a) =>
{
myDeviceList.Add(a.Device);
}
await adapter.StartScanningForDevicesAsync();
But right now I'm just looking for devices and adding what you find directly to this list.
I want this scan to work continuously and if any device gets lost, it can automatically delete it here.
BLE has StartScanningForDevicesAsync class but I don't know if this is useful for me.
event EventHandler<DeviceErrorEventArgs> DeviceConnectionLost;
//
// Summary:
// Occurs when a device has been disconnected. This occurs on intendet disconnects
// after Plugin.BLE.Abstractions.Contracts.IAdapter.DisconnectDeviceAsync(Plugin.BLE.Abstractions.Contracts.IDevice).
Is this possible?
I think, you can use something like this (pseudocode + C#):
StartTimer(TimeSpan.FromSeconds(30),
() =>
{
if (!isScanning)
{
new Handler().PostDelayed(StopScan, 10000); // stop
scanning after 10 sec
isScanning = true;
StartScan();
}
return true; // this result will tell to fire onTimer event again
});
Here StartScan and StopScan - functions you use for communicating with BLE

RxJS: Auto (dis)connect on (un)subscribe with Websockets and Stomp

I'm building a litte RxJS Wrapper for Stomp over Websockets, which already works.
But now I had the idea of a really cool feature, that may (hopefully - correct me if I'm wrong) be easily done using RxJS.
Current behavior:
myStompWrapper.configure("/stomp_endpoint");
myStompWrapper.connect(); // onSuccess: set state to CONNECTED
// state (Observable) can be DISCONNECTED or CONNECTED
var subscription = myStompWrapper.getState()
.filter(state => state == "CONNECTED")
.flatMap(myStompWrapper.subscribeDestination("/foo"))
.subscribe(msg => console.log(msg));
// ... and some time later:
subscription.unsubscribe(); // calls 'unsubscribe' for this stomp destination
myStompWrapper.disconnect(); // disconnects the stomp websocket connection
As you can see, I must wait for state == "CONNECTED" in order to subscribe to subscribeDestination(..). Else I'd get an Error from the Stomp Library.
The new behavior:
The next implementation should make things easier for the user. Here's what I imagine:
myStompWrapper.configure("/stomp_endpoint");
var subscription = myStompWrapper.subscribeDestination("/foo")
.subscribe(msg => console.log(msg));
// ... and some time later:
subscription.unsubscribe();
How it should work internally:
configure can only be called while DISCONNECTED
when subscribeDestination is called, there are 2 possibilities:
if CONNECTED: just subscribe to the destination
if DISCONNECTED: first call connect(), then subscribe to the destination
when unsubscribe is called, there are 2 possibilities:
if this was the last subscription: call disconnect()
if this wasn't the last subscription: do nothing
I'm not yet sure how to get there, but that's why I ask this question here ;-)
Thanks in advance!
EDIT: more code, examples and explanations
When configure() is called while not disconnected it should throw an Error. But that's not a big deal.
stompClient.connect(..) is non-blocking. It has an onSuccess callback:
public connect() {
stompClient.connect({}, this.onSuccess, this.errorHandler);
}
public onSuccess = () => {
this.state.next(State.CONNECTED);
}
observeDestination(..) subscribes to a Stomp Message Channel (= destination) and returns an Rx.Observable which then can be used to unsubscribe from this Stomp Message Channel:
public observeDestination(destination: string) {
return this.state
.filter(state => state == State.CONNECTED)
.flatMap(_ => Rx.Observable.create(observer => {
let stompSubscription = this.client.subscribe(
destination,
message => observer.next(message),
{}
);
return () => {
stompSubscription.unsubscribe();
}
}));
}
It can be used like this:
myStompWrapper.configure("/stomp_endpoint");
myStompWrapper.connect();
myStompWrapper.observeDestination("/foo")
.subscribe(..);
myStompWrapper.observeDestination("/bar")
.subscribe(..);
Now I'd like to get rid of myStompWrapper.connect(). The code should automatically call this.connect() when the first one subscribes by calling observeDestination(..).subscribe(..) and it should call this.disconnect() when the last one called unsubscribe().
Example:
myStompWrapper.configure("/stomp_endpoint");
let subscription1 = myStompWrapper.observeDestination("/foo")
.subscribe(..); // execute connect(), because this
// is the first subscription
let subscription2 = myStompWrapper.observeDestination("/bar")
.subscribe(..);
subscription2.unsubscribe();
subscription1.unsubscribe(); // execute disconnect(), because this
// was the last subscription
RxJS: Auto (dis)connect on (un)subscribe with Websockets and Stomp
I agree the code you are suggesting to tuck away into myStompWrapper will be happier in its new home.
I would still suggest to use a name like observeDestination rather than subscribeDestination("/foo") as you are not actually subscribing from that method but rather just completing your observable chain.
configure() can only be called while DISCONNECTED
You do not specify here what should happen if it is called while not DISCONNECTED. As you do not seem to be returning any value here that you would use, I will assume that you intend to throw an exception if it has an inconvenient status. To keep track of such statuses, I would use a BehaviourSubject that starts with the initial value of DISCONNECTED. You likely will want to keep state within observeDestination to decide whether to throw an exception though
if CONNECTED: just subscribe to the destination
if DISCONNECTED: first call connect(), then subscribe to the destination
As I mentioned before, I think you will be happier if the subscription does not happen within subscribeDestination("/foo") but rather that you just build your observable chain. As you simply want to call connect() in some cases, I would simply use a .do() call within your observable chain that contains a condition on the state.
To make use of the rx-y logic, you likely want to call disconnect() as part of your observable unsubscribe and simply return a shared refcounted observable to start with. This way, each new subscriber does not recreate a new subscription, instead .refCount() will make a single subscription to the observable chain and unsubscribe() once there is no more subscribers downstream.
Assuming the messages are coming in as this.observedData$ in myStompWrapper My suggested code as part of myStompWrapper would look something like this:
observeDestination() {
return Rx.Observable.create(function (observer) {
var subscription = this.getState()
.filter(state => state == "CONNECTED")
.do(state => state ? this.connect() : Observable.of(true))
.switchMap(this.observedData$)
.refCount();
.subscribe(value => {
try {
subscriber.next(someCallback(value));
} catch(err) {
subscriber.error(err);
}
},
err => subscriber.error(err),
() => subscriber.complete());
return { unsubscribe() { this.disconnect(); subscription.unsubscribe(); } };
}
Because I am missing some of your code, I am allowing myself to not test my code. But hopefully it illustrates and presents the concepts I mentioned in my answer.

How to send message or establish 2 way communication between two XUL Overlay Firefox extensions/add-ons

I have an XUL Overlay Firefox extension, I need to develop a dummy XUL extension that establishes connection with the original extension and sends a set of parameters (message) to the original extension. In short, I have to trigger my original extension with my dummy extension.
Probably the easiest way to do this is to have the original extension listening for a custom event on the base browser window. The dummy extension can then create and dispatch the event with whatever custom data is desired.
Creating and dispatching the event from the dummy:
function sendDataToMainExtension(data) {
if (typeof window === "undefined") {
//If there is no window defined, get the most recent.
var window=Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator)
.getMostRecentWindow("navigator:browser");
}
//This assumes that this event is being both sent from
// and received by privileged (main add-on) code.
var event = new CustomEvent('MyExtensionName-From-Dummy', { 'detail': data });
window.dispatchEvent(event);
}
You may need to take the same steps for making sure the data is visible on the receiving end as would be necessary when firing from privileged code to non-privileged code.
Listening for the event in main:
Components.utils.import("resource://gre/modules/Services.jsm");
const Ci = Components.interfaces;
//Listen for the event on all windows as it is unknown on which one
// the event will be sent.
function loadIntoWindow(myWindow) {
myWindow.addEventListener("MyExtensionName-From-Dummy",
receiveMessageFromDummy, false);
}
function unloadFromWindow(myWindow) {
myWindow.removeEventListener("MyExtensionName-From-Dummy",
receiveMessageFromDummy, false);
}
function forEachOpenWindow(fn) {
// Apply a function to all open browser windows
var windows = Services.wm.getEnumerator("navigator:browser");
let windowCount =0;
while (windows.hasMoreElements()) {
windowCount++;
fn(windows.getNext().QueryInterface(Ci.nsIDOMWindow));
}
}
function receiveMessageFromDummy(event) {
var dataFromDummy = event.detail;
//Do whatever was desired with the data.
}
var WindowListener = {
onOpenWindow: function(aWindow)
{
let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
function onWindowLoad()
{
domWindow.removeEventListener("load",onWindowLoad);
if (domWindow.document.documentElement.getAttribute("windowtype")
== "navigator:browser") {
loadIntoWindow(domWindow);
}
}
domWindow.addEventListener("load",onWindowLoad);
},
onCloseWindow: function(xulWindow) { }, // Each window has an unload event handler.
onWindowTitleChange: function(xulWindow, newTitle) { }
};
//Listen for the custom event on all current browser windows.
forEachOpenWindow(loadIntoWindow);
//Listen for the custom event on any new browser window.
Services.wm.addListener(WindowListener);
The data sent should be available as event.detail within the receiveMessageFromDummy() function.
The code above provides one way communication. Two way communication is obtained just duplicating the code to communicate in the other direction with a different custom event. In other words, by having the main extension dispatching a different custom event called something like MyExtensionName-From-Main and having the dummy extension listening for that event. The code is exactly the same as above, but with the event name changed and the function called being receiveMessageFromMain().
Alternately, you could use Window.postMessage(). Doing so sends a "message" event for which you can listen. However, doing so leads to complications which are easier to avoid by using a custom event (e.g. you have to account for the fact that any code (i.e. some other random extension) could be using this event for their own purpose).
Note: The code to loop through windows was originally taken from Converting an old overlay-based Firefox extension into a restartless addon which that author re-wrote as the initial part of How to convert an overlay extension to restartless on MDN. It has been modified multiple times from that code. It may have even earlier versions from other sources.

JsPlumb flowchart no self-connections

I have a problem where I'm more-or less using the jsPlumb flow-chart demo example but where there is only ever one drop target per window and there may be one or many drag targets. However I want to forbid self-connections so that a connection can be dragged from any window to any other window EXCEPT itself.
I was thinking that maybe you would use scopes but this would mean a different scope for each window which seems over the top. Does anyone have a tidy solution?
Thanks for the answers they pointed me in the right direction. In the end used "beforeDrop"
when binding the "connection" it was detaching the source endpoint of the window as well as the connection.
The final solution was:
instance.bind("beforeDrop", function (info) {
// console.log("before drop: " + info.sourceId + ", " + info.targetId);
if (info.sourceId === info.targetId) { //source and target ID's are same
console.log("source and target ID's are the same - self connections not allowed.")
return false;
} else {
return true;
}
});
from http://www.jsplumb.org/doc/connections.html#draganddrop
Preventing Loopback Connections
In vanilla jsPlumb only, you can instruct jsPlumb to prevent loopback connections without having to resort to a beforeDrop interceptor. You do this by setting allowLoopback:false on the parameters passed to the makeTarget method:
jsPlumb.makeTarget("foo", {
allowLoopback:false
});
Bind an event to get notified whenever new connection is created. After connection creation check whether source and target of connection are same, if so detach that connection to avoid self loop. Code:
jsPlumb.bind("jsPlumbConnection", function(ci) {
var s=ci.sourceId,c=ci.targetId;
if( s===c ){ //source and target ID's are same
jsPlumb.detach(ci.connection);
}
else{ // Keep connection if ID's are different (Do nothing)
// console.log(s+"->"+c);
}
});

Resources