Deselection fabric.js object event - fabricjs

I am trying to execute some code every time a specific fabric object is "deselected". Is there any deselection event I can handle? I already have a function for when the object is selected, via the selected event, but have not found any documentation about the deselected one. At the canvas level I have the selection:cleared and selection:created events, but nothing for the deselection either.
Cheers,
Gonzalo

Use the before:selection:cleared event and get the active object or group. After that you can check if it corresponds to your specific fabric object.
canvas.on('before:selection:cleared', function() {
var clearedObject;
if(typeof(canvas.getActiveObject()) !== 'undefined') {
clearedObject = canvas.getActiveObject();
}
else {
clearedObject = canvas.getActiveGroup();
}
//do stuff with the deselected element if it is the specific one you want.
});

Just to let you all know that the newest versions of Fabric.js include a deselected event for the Object class. The only thing you need to do now is:
var aFabricObject = <create your fabric object>
aFabricObject.on('deselected', function (options) {
// your code here
});

Update for the upper answer:
The 'deselected' event fires a async method, so you can not get 'options.deselected' immediately.
var aFabricObject = <create your fabric object>
aFabricObject.on('deselected', function (options) {
console.log(options.deselected) // output undefined
setTimeout(() => {
console.log(options.deselected) // output the correct target
}, 0)
});

Related

Phaser 3 can't get the start method to work right

I'm trying to make a menu where the scene changes when the player clicks a button using the start method. At first, I had it all in the create function with this:
var levelOne = this.add.sprite(200, 400, 'LevelOne').setInteractive();
levelOne.on('pointerdown', function (pointer) {
this.scene.start('play');
});
But this led to an error in which it said that this.scene.start isn't a function.
I looked at a previous example where the method worked, the big difference was that the method was in the update function, so I rewrote my code to have this in the create function:
this.choice = 0;
var levelOne = this.add.sprite(200, 400, 'LevelOne').setInteractive();
levelOne.on('pointerdown', function (pointer) {
this.choice = 1;
//game.settings = {
//gameTimer: 60000
//}
});
And this in the update function:
if (this.choice == 1){
this.scene.start('play');
}
Sadly, this didn't work either and didn't even give an error message. I can't tell what went wrong. Please help.
You have to pass the scene as the context to the event function on(...) (link to the documentation), as the third parameter, so that you can access the scene properties and functions in the event callback.
levelOne.on('pointerdown', function (pointer) {
this.scene.start('play');
}, this); // <-- you have to add "this"

how to add an event listener in connectCallback

I want to wait until elements are rendered in the dom to dispatch an event. I have a lit element that is wrapped around a react element.
In the connectedCallback I have the following
connectedCallback() {
super.connectedCallback();
CommentsManager.register(this);
const event = new Event('ccx-comments-loaded');
window.dispatchEvent(event);
}
in the constructor, I have the following
this.isReadyPromise = new Promise(function(resolve, reject) {
window.addEventListener('ccx-comments-loaded', () => {
resolve(true);
});
});
How can I remove the listener that I created?
I want to wait until elements are rendered in the dom to dispatch an
event.
This looks like you could use an already existing updateComplete method from lit-element lifecycle. It is executed after render and it sounds like you may want to use it instead of having your own events.
You could read more about it here:
https://lit.dev/docs/v1/components/lifecycle/#updatecomplete
This would be a clean and more straightforward way to use lit-element. This way you don't reinvent something existing and your code would be more straightforward and clear for the other developers.
Store a reference to the Event Listener, then remove it in the disconnectedCallback
customElements.define("my-element", class extends HTMLElement {
constructor() {
super();
this.listener = window.addEventListener("click", () => {
this.remove();
});
}
connectedCallback() {
this.innerHTML = `Listening! Click to remove Web Component`;
}
disconnectedCallback() {
// element is no longer in the DOM; 'this' scope still available!!!
window.removeEventListener("click", this.listener);
document.body.append("Removed Web Component and Listener");
}
})
<my-element></my-element>

addTools is giving exception in rappidjs

In context of one of my assignment I was trying to use RappidJS. I was trying the below code for connecting an element by dropping it over another element.
https://resources.jointjs.com/tutorial/connecting-by-dropping
But I am getting exception as below
rappid.min.js:14 Uncaught TypeError: Cannot read property 'start' of null
at child.update (rappid.min.js:14)
at child.onRender (rappid.min.js:14)
at child.e.render (rappid.min.js:14)
at child.configure (rappid.min.js:14)
at child.addTools (rappid.min.js:14)
at child.element:pointerup (diagram.js:106)
at triggerEvents (backbone.js:338)
at triggerApi (backbone.js:322)
at eventsApi (backbone.js:110)
at child.Events.trigger (backbone.js:312)
I also took reference from below link
https://resources.jointjs.com/tutorial/link-tools .
Can any one suggest me what wrong I am doing here.
My code snippet is as below
function attachLinks(paper) {
paper.on({
'element:pointerdown': function (elementView, event) {
event.data = elementView.model.position();
},
'element:pointerup': function (elementView, event, x, y) {
var coordinates = new joint.g.Point(x, y);
var elementAbove = elementView.model;
var elementBelow = this.model.findModelsFromPoint(coordinates).find(function (el) {
return (el.id !== elementAbove.id);
});
// If the two elements are connected already, don't
// connect them again (this is application-specific though).
if (elementBelow && self.graph.getNeighbors(elementBelow).indexOf(elementAbove) === -1) {
// Move the element to the position before dragging.
elementAbove.position(event.data.x, event.data.y);
// Create a connection between elements.
var link = new joint.shapes.standard.Link();
link.source(elementAbove);
link.target(elementBelow);
link.addTo(this.model);
// Add remove button to the link.
var removeLinkTool = new joint.linkTools.Remove();
var tools = new joint.dia.ToolsView({
tools: [ removeLinkTool]
});
var linkView = link.findView(this);
linkView.addTools(tools); // getting exception at this place.
}
}
});
}
This issue is reproducible only in the paper async mode.
Make sure the view for the link is rendered when you add the link tools. For this please use joint.dia.Paper.prototype.requireView().
// It is fine to use the method in the `sync` mode as the view is rendered/updated
// synchronously as soon as the link is added to the graph.
var linkView = link.findView(paper);
// This method makes sure the view is ready to use in the `async` mode.
// It forces the view to render/update synchronously.
var linkView = paper.requireView(link);
Alternatively, you could pass async = false flag when adding the link to the graph to tell the paper to render the particular view synchronously.
link.addTo(graph, { 'async': false });

Define a global ready function for every page in WinJS

My WinJS app uses the single navigation model. There is some common code that I would like to apply to every page in the app. Instead of placing the code in each page's ready function, I would like to be able to able to define a "global" ready function that will be executed when a page's ready event is fired. Any ideas?
you can define a Mixin object with utility function used for all pages.
utils.js:
PageMixin = {
ready: function ready(element, options)
{
this.element = element;
this.options = options;
this.initialize();
this.onready();
},
initialize: function initialize()
{
// write common initialize code here
}
};
page.js:
var Page = WinJS.UI.Pages.define('/pages/mypage/page.html',
{
onready: function onready()
{
// page specific initialization code here
}
});
// this will make all PageMixin util methods available on Page.
WinJS.Class.mix(Page, PageMixin);
refer WinJS.Class.mixin for details.

Backbonejs, "Object #<Object> has no method apply" when setting model attribute inside a Collections.each

I made and initialized my model with the "change:status" event like this
Box = Backbone.Model.extend({
initialize: function() {
this.on('change:status', this.changed, this);
},
changed: function() {
$('.changed').text('I changed'); // Testing if the 'change:status' is fired
}
});
My Box collections is setup this way
BoxList = Backbone.Collection.extend({
model: Box,
initialize: function() {
this.on('add', this.addOne, this);
socket.on('box-status-change', this.boxStatusChanged, this);
},
boxStatusChanged: function(box) {
Boxes.each(function(model) {
if(model.get('changed') == box.changed) {
model.set({status: 'changed'});
}
});
},
addOne: function.... // Some code removed
});
Boxes = new BoxList();
Checking in Chromes web developer tools, the attribute status was set to changed properly but an error Uncaught TypeError: Object #<Object> has no method 'apply' occured. The change:title event of the model was not fired. Is there something I miss when adding the event to the model?
By the way, I'm using the backbone-iosync.js for the Backbone.sync method...
Backbone uses an internal attribute called changed on models:
http://backbonejs.org/#Model-changed
changed model.changed
The changed property is the internal hash containing all the
attributes that have changed since the last "change" event was
triggered. Please do not update changed directly. Its state is
maintained internally by set and change. A copy of changed can be
acquired from changedAttributes.
Rename your callback to something else and that works
Box = Backbone.Model.extend({
initialize: function() {
this.on('change:status', this.changedState, this);
},
changedState: function() {
console.log('changed');
}
});
A Fiddle to reproduce your problem http://jsfiddle.net/NrTPk/ and a modified version http://jsfiddle.net/NrTPk/1/

Resources