ata1704
ata1704

Reputation: 23

Jointjs trigger action when hovering a markup selector of cell

I know that it's pretty easy to trigger an action in JointJS if you click a markup selector. We can simply add a custom event attr of that markup element, but as far as I know only pointer events are allowed. Is there any way to archive the same for hovering?

For example I have a custom cell with 4 buttons, that are just a bunch of svg tag added via the markup. I want to change the opacity of all other elements on the canvas, depending on the button that was hovered. I have an idea on how to filter everything and change the opacity, but I have no idea on how to trigger that event and know what selector I'm hovering.

Upvotes: 0

Views: 402

Answers (1)

James
James

Reputation: 336

You could take advantage of the 'element:mouseenter' event on the paper, then event.target can give you access to sub-elements on the shape.

In the following example, when you hover a color on the button shape, the standard.Rectangle type shapes all change to that color.

This solution takes advantage of adding classes via markup, and checking if the target has the particular class.

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.6.5/joint.css" />
    <style>
        .joint-paper {
            display: inline-block;
            border: 1px solid gray;
        }
    </style>
</head>
<body>
    <!-- content -->
    <div id="myholder"></div>

    <!-- dependencies -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.4.1/backbone.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.6.5/joint.js"></script>

    <!-- code -->
    <script type="text/javascript">

        var namespace = joint.shapes;

        var graph = new joint.dia.Graph({}, { cellNamespace: namespace });

        var paper = new joint.dia.Paper({
            el: document.getElementById('myholder'),
            model: graph,
            width: 600,
            height: 300,
            gridSize: 1,
            cellViewNamespace: namespace
        });

        class ButtonShape extends joint.dia.Element {

            defaults() {
                return {
                    ...super.defaults,
                    type: 'MyShape',
                    size: {
                        width: 120,
                        height: 155
                    },
                    attrs: {
                        body: {
                            width: 'calc(w)',
                            height: 'calc(h)',
                            fill: '#ffffff',
                            stroke: '#333333',
                            strokeWidth: 2,
                            rx: 5,
                            ry: 5,
                            pointerEvents: 'none'
                        },
                        rectUpper: {
                            width: 'calc(0.8*w)',
                            height: 'calc(h/2.5)',
                            fill: 'cornflowerblue',
                            stroke: '#333333',
                            strokeWidth: 2,
                            x: 'calc(0.1*w)',
                            y: 10
                        },
                        rectLower: {
                            width: 'calc(0.8*w)',
                            height: 'calc(h/2.5)',
                            fill: 'tomato',
                            stroke: '#333333',
                            strokeWidth: 2,
                            x: 'calc(0.1*w)',
                            y: 'calc(h - calc(h/2.5 + 10))'
                        },
                    }
                };
            }

            preinitialize() {
                this.markup = [{
                    tagName: 'rect',
                    selector: 'body'
                }, {
                    tagName: 'rect',
                    selector: 'rectUpper',
                    className: 'upper'
                }, {
                    tagName: 'rect',
                    selector: 'rectLower',
                    className: 'lower'
                }];
            }
        }

        const buttonShape = new ButtonShape();
        buttonShape.position(10, 10);
        buttonShape.addTo(graph);

        for(let i = 0; i < 5; i++) {
            const rect = new joint.shapes.standard.Rectangle();
            rect.position(i * 60 + 10, 200);
            rect.resize(50, 50);
            rect.addTo(graph);
        }
        
        paper.on('element:mouseenter', function (cellView, evt) {
            const rectangles = graph.getElements().filter((el) => el.get('type') === 'standard.Rectangle');

            if (evt.target.classList.contains('upper')) {
                rectangles.forEach((rect) => {
                    rect.attr('body/fill', 'cornflowerblue')
                });
            } 
            
            if (evt.target.classList.contains('lower')) {
                rectangles.forEach((rect) => {
                    rect.attr('body/fill', 'tomato')
                });
            } 

        });
    </script>
</body>
</html>

Upvotes: 0

Related Questions