see the list of event listeners currently attached - cytoscape.js

I want to check the list of event listeners that are added. For example, I used the code cy.on('pan zoom resize', update); and added function called update in for loop. I do this many times. I also call cy.off('pan zoom resize', update); to remove the event listeners but I want to be sure about it.
The only think I can think of is using console.log but this method might not be helpful.
I also think that in some places people forgot to remove the event listeners and just always added. With too many repetitions this might cause problems.

There is a data field in the private cytoscape object called listeners. You can see that if you:
console.log() the cy object,
navigate to _private,
then open the emitter object
and lastly go to listeners
This is the array listing all the default and user defined event listeners with some metadata like the event, type and scope of the listener.
You can access this in your code by simply calling
cy.emitter().listeners
The question now is, why do you need this information in the first place? Normally, you should be just fine if you call cy.off('eventXY', ...) before using any cy.on('eventXY', ...). Are you sure you need this for your application to work? Maybe elaborate more on the core problem (why you want these information in the first place).
Thanks and have a great day!

Related

Whenever a property or function of `Vue instance` changes , some of the methods gets executed. Please explain this behavior

https://jsfiddle.net/Arpan_Banerjee7/bfnL50vs/1/
I have shared a link of JSFiddle, you can see the demo there.
Whenever you mousemove over the last paragraph, the coordinates changes and it gets logged as expected.
But I have noticed a rather strange behavior.
I noticed that whenever the function changeCoordinates() is executed the other two functions within the method also gets executed--randomNumber() and testFunction().
Please open the dev tools>console to see the logs of testFunction().
Does all the methods execute whenever any of the methods executes?
Can you please explain this?
See https://v2.vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods
In comparison, a method invocation will always run the function whenever a re-render happens.
So whenever your X or y values change a re-render is invoked on the page and the methods are run, since they are called from the template.
In your case it seems that "all method" are run, but that is simply because all methods are present in the template. Methods only run when explicitly activated, either by code in another method or by invocation from the template.

custom, emitted events (handling) - vueJS

Im new to VueJS.
I'm trying to understand the syntax behind emitting events.
There is the following video tutorial where I'm having problems understanding what happens:
https://www.youtube.com/watch?v=5pvG6fzkdFM
Here is the code:
Inside parent:
https://imgur.com/bxcyjZq
https://imgur.com/Rynifqq
And Child (emitting component):
https://imgur.com/iHh3zc3
Now, the first thing I very much DONT understand is how the "v-on:CustomEvent" actually works.
v-on, as I understand it, attaches an event handler. But it doesnt specify it, does it? I usually have to type "v-on:click". So why does anything happen at all in this tutorial when this code is executed? Nowhere is there a definition what kind of event shall trigger the function.
And the second thing is how the data is handled.
In the header, inside the parameter of the function, $event is handed over.
But how is this supposed to give any useful data? The event usually is an object where I have to get the payload extracted manually, like event.target.value?
So why does this work?
You code looks fine, there is no fix needed
Alternate way is, no need to mention $event, it automatically pass with the arguments by just mentioning the method name
<app-header v-bind:title="title" v-on:changeTitle="updateTitle"></app-header>

Where can we add our event data to cytoscape triggered events?

Looking to find where we can insert our own data for triggered events.
I have an extension that use to call onImpl(events, selector, data, callback), but that was back in 2.3.7. What is the updated way to add my event data if I want to pass data that can be used with the event?
As far as I know, it is not possible to pass data to core events anymore. But you can do it when you emit the events programmatically.
I'm assuming this is the extension that you mentioned. If you just want the paz/zoom functionality, you can use the pan-zoom extension.
I'm not sure if a toolbar extension would be any useful. The customization of the toolbar with an extension would be very limited. You can create a fancy toolbar, style and position it as you like and connect the buttons with Cytoscape events with jQuery or other similar libraries.
P.S: instead of passing the data to the event, you may keep the data in a global variable and access it from callback function.

Load options on the first open of the Async drop down menu

When I provide loadOptions to an Async control it loads options on mount.
If I pass autoload={false} then it doesn't load options neither on mount nor on open. But it loads options on the first close (or type, or blur).
If I pass onCloseResetsInput={false} then it doesn't load options until I type something. (showing "Type to search" in the menu)
Async provides onOpen handler, but I didn't find the way to use it in this situation. (and react-select#2.0.0-alpha.2 doesn't have it)
So the user needs to type a character, then delete it, to see the full list of options.
How can this be avoided?
Example sandbox: https://codesandbox.io/s/mjkmowr91j
Solution demo: https://codesandbox.io/s/o51yw14l59
I used the Async options loaded externally section from the react-select repo.
We start by loading the options on the Select's onFocus and also set the state to isLoading: true. When we receive the options we save them in the state and render them in the options.
I also keep track of optionsLoaded so that only on the first focus do we trigger the call to get options.
In our use case, we have several of these select inputs on a single page, all async, so the requests to the server will pile up, and are completely unnecessary in a lot of cases (users won't even bother clicking).
I found a workaround for this issue that'll work for my use case on 2.0.0-beta.6:
Include defaultOptions
Add 2 members to your class that will store the resolve/reject methods for the promise.
In your loadOptions function, check if the input is '', if so, create a new promise, and store the values of resolve/reject within your class members, and return that promise. Otherwise, just return the promise normally to get your results.
Add an onFocus handler, and within it call the function to get your results, but also add .then and .catch callbacks passing the resolve and reject functions you stored previously.
Essentially, this makes react-select think you're working on getting the results with a long-running promise, but you don't actually even try to load the values until the field is selected.
I'm not 100% positive there aren't any negative side effects as I just wrote this, but it seems like a good place to start.
Hope this helps someone. I may submit a feature request for this.
In order to load options when user focus first time, set defaultOptions={true}
Thanks, Alexei Darmin for the solution, I was struggling with this... while testing it I converted the solution to a react functional component and added real API fetching.
Here is a working demo, I hope it helps someone

Is it possible to HIDE Javascript Object's prototype! What's the MYSTERY behind this?

I'm using openui5. There is a constructor Function for UI control Button,unable to see the prototype properties of the Button but the same thing when executed in browser console, shows up!
sap.m.Button.prototype.Move = function(){
console.log('Move');
}
var oButton = new sap.m.Button({text:"Hello"});
oButton.Move(); // throws undefined function!
The same code when executed browser in console, it works!
jsbin --> http://jsbin.com/tepum/1/edit
After running the code I find that creating the first instance of sap.m.Button causes script to change the prototype of sap.m.Button. It's valid in JavaScript but not very smart if you ask me.
A first creation causes a synchronous request (no no as well) to fetch library-parameters.json.
If you run the code the second time it will have prototype.move because creating an instance of Button will not change the Button.prototype.
The capital M in Move would suggest a constructor function so I would advice changing it to lower case.
Since fetching the parameters is synchronous you can create the first instance and then set the prototype:
console.log("First Button creation changes Button.prototype");
var oButton = new sap.m.Button({text:"Hello"});
sap.m.Button.prototype.move = function(){
console.log('Move');
}
oButton.placeAt('content');
oButton.move(); // logs Move
My guess is that this is done to lazy load controls, if a Button is never created then the json config files are never loaded for these unused controls. It has a couple of drawbacks though.
You have to create an instance first before you can set the prototype.
The config files are synchronously loaded so when creating first instance of many controls with a slow connection would cause the app to be unresponsive.
A better way would be for a factory function to return a promise so you create the control the same way every time and the config files can be fetched asynchronously.
[update]
Looking at the config it seems to be config for the whole gui library so I can't see any reason why this is loaded only after creating a first instance. A library that changes it's object definitions when creating instances is not very easy to extend because it's unpredictable. If it only changes prototype on first creation then it should be fine but it looks like the makers of the library didn't want people to extend it or they would not make the object definition unpredictable. If there is an api documentation available then maybe try to check that.
[update]
It seems the "correct" way to extend controls is to use extend.
#HMR is right the correct way to extend a control is by using the extend function provided by UI5 managed objects, see http://jsbin.com/linob/1/edit
in the example below when debugging as mentoned by others you will notice that the control is lazy loaded when required, any changes you make prior are lost when loaded
jQuery.sap.declare("my.Button");
jQuery.sap.require("sap.m.Button");
sap.m.Button.extend("my.Button", {
renderer: {}
});
my.Button.prototype.Move = function() {
console.log('Move');
};
var oButton = new my.Button({
text: "Hello"
});
oButton.placeAt('content');
oButton.Move();
It's not hiding the prototype per se. If a constructor function exits normally then you get that function's prototype. But, if a constructor function actually returns some other object then you get that other object's prototype, so it's not valid to assume that just because you added to the Button prototype that when you call new Button() that you will see your method on whatever you get back. I'm sure if you de-obfuscate that code you'll find that the constructor you are calling has a "return new SomeOtherInstanceOfButton()" or similar at the end of it.
Edit: Ok it's a bit difficult to see what's really going on in that sap code but, it looks like they have code that overwrites the prototypes of controls to add features to them, such as: sap.ui.core.EnabledPropagator, and those things aren't run until you actually instantiate a button. So if you change your code to instantiate the button on the page, then add to it's prototype, then construct and call the method, it works fine. Like so:
http://jsbin.com/benajuko/2/edit
So I guess my answer is, when you run it from console it's finished mucking around with that prototype, whereas in your test you were adding to the prototype, then constructing the button for the first time (which changes the prototype again) then trying to call your old one, which is no longer there.