We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Question: RE: Disabled Node Constraints: Resize and Rotate adorner visibility

So, I have a node (ellipse) for which I do not want the user to be able to resize or rotate. 

That's easy enough through a constraints definition on the bound node like:

self.constraints = ej.datavisualization.Diagram.NodeConstraints.Default & ~(ej.datavisualization.Diagram.NodeConstraints.Resize | ej.datavisualization.Diagram.NodeConstraints.Rotate);

The resultant configuration has those features displayed, but disabled. However, with a small node, these features showing as disabled removes the ability to easily interact with the node.

Example

Instead, I believe the behavior in these situations should be to hide the adorner layer rendering of these elements - that seems like it would be more logical (why display something they can't use.)

Styling it out would be alright except in the case where you have a mixed set of nodes where some have the feature enabled and others do not.

Any advice/suggestions for modifying the behavior to reflect the configuration for improved usability?

Thank you.

11 Replies

SG Shyam G Syncfusion Team February 20, 2017 08:46 AM UTC

Hi Robert, 
 
Please use selectorConstraints to achieve your requirement. please refer to the code example, sample and help documentation below. 
 
Code example: 
// Initializes the Diagram control 
        $("#diagram").ejDiagram({ 
            //remove the rotate handle and resize handle through selector constraints. 
            selectedItems: { 
                constraints: ej.datavisualization.Diagram.SelectorConstraints.All & ~(ej.datavisualization.Diagram.SelectorConstraints.Rotator | ej.datavisualization.Diagram.SelectorConstraints.Resizer), 
            }, 
        }); 
 
 
 
Regards, 
Shyam G 



RM Robert Mims February 20, 2017 11:35 AM UTC

I totally missed that, thank you for the quick reply and great feedback - I'll implement your solution promptly.


RM Robert Mims February 20, 2017 01:39 PM UTC

In follow-up, your answer helped me focus more on modifying the selection constraints - which is exactly what I need to accomplish, however, I am seeing behavior that I cannot quite reconcile with the documentation or my use case.

For example, see: http://jsplayground.syncfusion.com/zmpckytq

And for documentation references: https://help.syncfusion.com/api/js/ejdiagram#members:selecteditems-constraints and https://help.syncfusion.com/api/js/ejdiagram#members:selecteditems-getconstraints

My observations:

1. The getConstraints method is only called for a multiple selection. I understand it is a part of the selected items and that is plural, however, if you are implementing overriding behavior it also makes sense to have it called for any selection, even if only a single item. Otherwise you'll have user experience code/implementation to manage in two places, rather than one within this method.

2. The documentation comments for getConstraints indicate that the constraints can be overriden with the result of the method, however you'll see in the playground this doesn't appear to be exactly predictable. In my example I have disabled rotation for multiple selection and within getConstraints, essentially indicated I want it enabled again and resize to be disabled (this is just to demonstrate the concept, my broader use case has mixed node constraints based on node type and selection.) The resulting behavior does reflect that resize is disabled (though the wrong visual cues, perhaps), but rotate behavior is not restored.

My follow-up question:

What is the expected behavior of getConstraints relative to overriding constraint configuration for selected items?


SG Shyam G Syncfusion Team February 21, 2017 12:30 PM UTC

Hi Robert, 

·         By default, if any one of the element contained in the selection list has node constraints disabled, then we couldn’t perform interaction for the multiple elements. So you can use getConstraints method to enable interaction for the multiple elements. 
·         The getConstraints method dynamically enables/disables the interaction with multiple selection. In your sample, you have disabled resize constraints. So resizing could not occur for multiple selection. 

Regards, 
Shyam G 



RM Robert Mims February 21, 2017 01:12 PM UTC

Shyam, 

Thank you for the explanation. Let me try and explain the nuance of my example using your feedback.

You are correct, resize is being disabled - that was one of the two conditions I demonstrate. The sample flips both Resize and Rotate. By default, Rotate is removed from the selection, with Resize enabled.

However with getConstraints I restore (with Default) and remove Resize. Therefore, the expected behavior in this sample would be that you can rotate the selection as the getConstraints configuration takes precedence over the selectedItems constraints, per your first bullet point statement.

In my opinion, the following changes are necessary:

1. The getConstraints constraint overrides need to take precedence.

In the sample (from All, remove Rotate to Default, remove Resize) we should see the final configuration, instead we see a merge of the selected Items (remove Rotate) and getConstraints (remove Resize) it would appear.

2. Apply these behaviors to the selection, not just when the selection has more than one. 

That reduces the code that developers like myself have to implement to retain user experience. As it is, I'll solve the multiple selection constraint management using the selection constraints and getConstraints override - and then have to develop another solution to accommodate a single selection.

Thank you.


SG Shyam G Syncfusion Team February 22, 2017 12:24 PM UTC

Hi Robert, 

Please use selectionChange event in which you can set the selectorConstraints as rotator, so that the rotation handle appears when you multiselect the elements. By the same way, you can control the visibility of selection handles in that event. Please refer to the code example and JSPlayground link below. 

Code example: 

window.viewModel.selectionchange= function(args){ 
            var diagram=$("#diagram").ejDiagram("instance"); 
            if(args && args.changeType==="insert"){ 
                if(args.newItems.length>1){         
                    //set rotator handle visible 
                    diagram.model.selectedItems.constraints=diagram.model.selectedItems.constraints |ej.datavisualization.Diagram.SelectorConstraints.Rotator; 
                } 
                else{ 
                    //remove rotator handle 
                    diagram.model.selectedItems.constraints=diagram.model.selectedItems.constraints &~ ej.datavisualization.Diagram.SelectorConstraints.Rotator; 
                } 
            } 
        } 


Regards, 
Shyam G 



RM Robert Mims February 22, 2017 12:26 PM UTC

Great, I'll pursue that avenue.

Thank you, Shyam.


RM Robert Mims February 22, 2017 02:23 PM UTC

For future readers of this thread, when you handle the event, be sure to be mindful of the args.state/args.cause values as the event will fire twice per selection change, as alluded to in the documentation.

In example:

1. Select nodes
- First fire of changeType "insert" with cause "rubberBand" and state of "changing"
- Second fire of changeType "insert" with cause "unknown" and state of "changed"

2. Deselect nodes
- First fire of changeType "remove" with cause "mouse" and state of "changing"
- Second fire of changeType "remove" with cause "unknown" and state of "changed"

Finally, when removing resize, you lose the visual selection grouping cue (resize rectangle), so, you'll need to consider an alternative for notifying your users of the state change (though it would be nice if Syncfusion separated the adorned resize rectangle from the resize behavior.)


RM Robert Mims February 22, 2017 03:15 PM UTC

One final follow-up with regard to the visual cue for selection and the resizeBorder rectangle.

My solution was to add a view model property whose state was managed by the selectionChange event (insert + changed) to detect my condition. I then activate a CSS class (diagram-override-noresize) on the diagram dive to hide the resize items within the diagram, leaving the rectangle for the visual cue.

Example CSS:

.diagram-override-noresize circle.resizeCorners, circle.nw-resize, circle.n-resize, circle.ne-resize, circle.w-resize, circle.e-resize, circle.sw-resize, circle.se-resize {
    display: none;
}

Example Property with Knockout view model:

my.DiagramViewModel = function() {

            var self = this;

            // Properties
            self.canResizeSelection = ko.observable(true);
           ...
}

Example Event handler:

            self.resolveSelectionChange = function(args) {
                /// <summary>Manages the selection node features</summary>
                /// <param name="args" type="Object">The event arguments for the selectionChange event, see: https://goo.gl/LE4M1U </param>

                // As the implementation within https://goo.gl/vTmAfq did not function as desired, this method leverages a more explicit 
                // approach for managing the selected item constraints as suggested by Shyam https://goo.gl/zc5jFu
                if (args && args.state === "changed") {
                    var selectedCustomTypes = args.selectedItems.filter(function (node) {
                        return node.hasOwnProperty("myType") && node.myType === window.my.constants.nodeTypes.myCustomShape;
                    });
                    self.canResizeSelection(selectedCustomTypes.length === 0);
                }
            }

Example HTML Mark-up with Knockout binding:

<div id="my-diagram"
             class="col-md-12"
             data-bind="ejDiagram: {
                    height: '84vh',
                    nodes: diagram().nodes,
                    enableContextMenu: true,
                    pageSettings: {
                        pageOrientation: ej.datavisualization.Diagram.PageOrientations.Landscape,
                        scrollLimit: ej.datavisualization.Diagram.ScrollLimit.Diagram
                    },
                    selectionChange: diagram().resolveSelectionChange
                },
                css: { 
                    'diagram-override-noresize': !diagram().canResizeSelection()
                }">
        </div>


SG Shyam G Syncfusion Team February 24, 2017 01:44 AM UTC

Hi Robert, 

Query 
Response 
One final follow-up with regard to the visual cue for selection and the resizeBorder rectangle. 
 
My solution was to add a view model property whose state was managed by the selectionChange event (insert + changed) to detect my condition. I then activate a CSS class (diagram-override-noresize) on the diagram dive to hide the resize items within the diagram, leaving the rectangle for the visual cue. 
Please use the below code example to hide the selector in the selectionChange event. 

Code example: 
 self.resolveSelectionChange = function(args) { 
    if (args && args.state === "changed") { 
          $(".resizeCorners").hide() 
    } 
 } 
For future readers of this thread, when you handle the event, be sure to be mindful of the args.state/args.cause values as the event will fire twice per selection change, as alluded to in the documentation. 
 
In example: 
 
1. Select nodes 
- First fire of changeType "insert" with cause "rubberBand" and state of "changing" 
- Second fire of changeType "insert" with cause "unknown" and state of "changed" 
 
2. Deselect nodes 
- First fire of changeType "remove" with cause "mouse" and state of "changing" 
- Second fire of changeType "remove" with cause "unknown" and state of "changed" 

Yes, we will change the args.cause value in the selectionChange event and provide you the patch on 24th February,2017. 


Regards, 
Shyam G 



RM Robert Mims February 24, 2017 12:38 PM UTC

Thank you, Shyam.

Loader.
Up arrow icon