Event dispatching in Javascript [duplicate] - javascript

This question already has answers here:
How do I simulate a mouseover in pure JavaScript that activates the CSS ":hover"?
(6 answers)
Closed last year.
I'm trying to puzzle out the event dispatching in Javascript.
The example below uses Fabricjs library.
AS IS: if we mouseover the redBox, it becomes black.
TO BE: I'm trying to invoke the redBox mouseover event from greyBox mouseover event.
So if we mouseover the greyBox, it must work as if we mousever the redBox.
As a result the redBox must become black.
But I don't understand what to write instead of interrogation mark.
var greyBox = new fabric.Rect({
fill: 'grey',
width: 100,
height: 100
});
var redBox = new fabric.Rect({
left:300,
top:300,
fill: 'red',
width: 100,
height: 100
});
function createCanvas(id){
canvas = new fabric.Canvas(id);
canvas.add(greyBox);
canvas.add(redBox);
redBox.on("mouseover", function(e){
redBox.set({fill: 'black'});
})
greyBox.on("mouseover", function(e){
// ????
})
return canvas;
}

You could move the logic to a separate function and invoke it when necessary:
const makeRedBoxBlack = () => redBox.set({fill: 'black'});
redBox.on("mouseover", makeRedBoxBlack);
greyBox.on("mouseover", makeRedBoxBlack);

You only have to add that red box set statement, so it should something like :-
greyBox.on("mouseover", function(e){
redBox.set({fill: 'black'});
})

Related

How to delete a konva shape/image , when using node.destroy()

While using konva I am using a button to add a shape multiple times on to my Stage
using something similar to
document.getElementById('Rect').addEventListener( "click" , function () {
let layer = new Konva.Layer();
let item = new Konva.Rect({
x: 20,
y: 20,
width: 100,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
draggable: true,
});
This appends a rectangle shape, if clicked multiple times it also appends extra shapes
I want to provide user with an option of deleting a particular shape that he wishes to delete with a button.
I tried to use context Menu tutorial available at Konva Tutorials but when implementing the delete function available there
document.getElementById('delete-button').addEventListener('click', () => {
currentShape.destroy();
layer.draw();
});
It is unable to delete the transformer layer added to the shape
document.getElementById('delete-button').addEventListener('click', () => {
tr.detach();
currentShape.destroy();
layer.draw();
});
I tried to detach the transformer / hide it but it removes it from all available instances of the shape
How can I solve this problem, Thanks a lot !!
You are adding a new click event listener for the "delete" button INSIDE click event of "add" button. That means every time you click on "delete" ALL listeners will be triggered. That removes all transformers.
Instead, you need just add a click listener once and find active Transformer manually to delete it.
document.getElementById('delete-button').addEventListener('click', () => {
const tr = layer.find('Transformer').toArray().find(tr => tr.nodes()[0] === currentShape);
tr.destroy();
currentShape.destroy();
layer.draw();
});
https://codepen.io/lavrton/pen/VweKqrp?editors=0010

jointjs element mouse click event

I'm using jointjs to draw graphs.
I'm wondering how to listen to the mouse click event on an element?
I found on http://www.jointjs.com/api#joint.dia.Element, there is only change:position option but no onclick option lol.
There's only cell:pointerclick option on the whole paper instead of the single element.
How can I achieve only listen to mouse click element on the single element? (Say I want to resize the paper after the click)
Thanks!
You can use the pointerclick event to capture the click events on elements. The view is passed as a parameter to the function and you can obtain the model of the view through cellView.model
paper.on('cell:pointerclick', function (cellView) {
// your logic goes here
);
A way to do that it's using classes and javascript events, look:
First, you assign a class to the joint js element via markup , for example a class called 'myclass' in this case:
var rect1 = new joint.shapes.basic.Rect({
markup: '<g class="rotatable"><g class="scalable"><image id="myrect1" class="myclass"/></g><text/></g>',
size: { width: 30, height: 73.2 },
attrs: {
rect: { fill: bgcolor1,'stroke-width': 0 },
}
});
Then, you capture the click event on that class objects via javascript, not in the canvas but in the document :
$(document).on('click', '.myclass', function () {
//alert('yayy!');
});
Hope it helps !
you need to listen on view not on the model. Trace all caught events on the element:
var a = new joint.shapes.basic.Rect({
size: { width: 100, height: 100 },
position: { x: 300, y: 300 }
}).addTo(graph);
paper.findViewByModel(a).on('all', function() {
console.log(arguments);
});
https://jsfiddle.net/vtalas/0z6jyq70/

Simplest way to create pulsating (looping) background in Raphael JS?

I am looking for the simplest and more straightforward way for making a looping/repeating puslating background of some element.
E.g. if I have a circle:
var filler = {
'fill': 'white',
'stroke': 'white',
'stroke-width': '0'
}
var fillerHover = {
'fill': '#b6def1',
'stroke': '#b6def1',
'stroke-width': '0',
'cursor': 'pointer'
}
circle.hover(function() {
circle.animate(fillerHover, 500);
},
function() {
circle.animate(filler, 500);
}
);
This code above is working well, however it animates the transition only once and I would like to make a repeating loop as long as I am hovering over the circle.
And I want to loop the background when I have cursor on the circle from filler to fillerHover until I go out with the cursor.
How to create such loop in the simplest way?
You could add a callback to the animation that starts it again: http://raphaeljs.com/reference.html#Element.animate
Don't do it in a setInterval, that will f**k up the framerate!
Don't even use requestAnimationFrame. You don't know when it will trigger animation. The only 'safe' way to do this is let Raphael tell you when the animation finished (via the callback option) to start the next animation.
Something like:
fillerHover.callback = mouseOver;
function mouseOver() {
circle.animate(fillerHover, 500);
}
circle.hover(
mouseOver,
function() {
circle.animate(filler, 500);
}
);
Mix that with your current code =) You know what I mean.
EDIT: This looks like it: http://jsfiddle.net/rudiedirkx/j9XyX/6/show/

Stop animation and reset position of an element in Raphaël.js

I have this simple animation that moves from side to side, Im trying to create a reset button so that the animation stops and gets back to default, but I cant seem to get i right.
The library I am using is Raphael, but I'm almost sure that with a simple javascript I can reset the values inside the function.
Body onload init function
function init() {
paper = Raphael("loadSVG");
var bg = paper.rect( 0, 0, "240px", "90px", 0 );
bg.attr( {fill: "#f3f3ff"} );
rect1 = paper.rect(150, 20, 50, 50);
rect1.attr( {fill: "#ffaaaa", "stroke-width": 3} );
}
The animation function
function moveRect1() {
if( xEnd == 150 )
xEnd = 50;
else
xEnd = 150;
rect1.animate( {x: xEnd}, 1000, "Sine", function (){
moveRect1();
});
}
and the stop button that don't work :)
function stopsvgRect1() {
rect1.stop();
}
You need to bind the stop button to the function you've created.
For example like this:
document.querySelector('#stop').onclick = function() {
stopsvgRect1();
};
Open this fiddle to see it in action.
edit:
As the position should also be resetted, you can choose Raphael.transform() for this action.
Open my updated fiddle to see how it works.

How to update the source of an Image

I'm using the Raphaël Javascript lib (awesome stuff for SVG rendering, by the way) and am currently trying to update the source of an image as the mouse goes over it.
The thing is I can't find anything about it (it's probably not even possible, considering I've read a huge part of the Raphaël's source without finding anything related to that).
Does someone knows a way to do this ?
Maybe it can be done without directly using the Raphaël's API, but as the generated DOM elements doesn't have IDs I don't know how to manually change their properties.
I'm actually doing CoffeeScript, but it's really easy to understand. CoffeeScript is Javascript after all.
This is what I'm doing right know, and I would like the MouseOver and MouseOut methods to change the source of the "bg" attribute.
class Avatar
constructor: (father, pic, posx, posy) ->
#bg = father.container.image "pics/avatar-bg.png", posx, posy, 112, 112
#avatar = father.container.image pic, posx + 10, posy + 10, 92, 92
mouseOver = => #MouseOver()
mouseOut = => #MouseOut()
#bg.mouseover mouseOver
#bg.mouseout mouseOut
MouseOver: ->
#bg.src = "pics/avatar-bg-hovered.png"
alert "Hover"
MouseOut: ->
#bg.src = "pics/avatar-bg.png"
alert "Unhovered"
class Slider
constructor: ->
#container = Raphael "raphael", 320, 200
#sliderTab = new Array()
AddAvatar: (pic) ->
#sliderTab.push new Avatar this, pic, 10, 10
window.onload = ->
avatar = new Slider()
avatar.AddAvatar "pics/daAvatar.png"
This actually works, except for the "#bg.src" part : I wrote it knowing that it wouldn't work, but well...
var paper = Raphael("placeholder", 800, 600);
var c = paper.image("apple.png", 100, 100, 600, 400);
c.node.href.baseVal = "cherry.png"
I hope, you get the idea.
This works for me (and across all browsers):
targetImg.attr({src: "http://newlocation/image.png"})
I was using rmflow's answer until I started testing in IE8 and below which returned undefined for image.node.href.baseVal. IE8 and below did see image.node.src though so I wrote functions getImgSrc, setImgSrc so I can target all browsers.
function getImgSrc(targetImg) {
if (targetImg.node.src) {
return targetImg.node.src;
} else {
return targetImg.node.href.baseVal;
}
}
function setImgSrc(targetImg, newSrc) {
if (targetImg.node.src) {
targetImg.node.src = newSrc;
} else {
targetImg.node.href.baseVal = newSrc;
}
}

Categories