Chris
Chris

Reputation: 11

How to edit a textbox within a group in fabricjs

My fabric application requires a feature that allows the user edit textboxes within groups. I almost have it working. As it stands, this is how my application works:

  1. Click on a group
  2. Checks to see if you are clicking on a textbox. If yes...
  3. Ungroups the group
  4. Sets the focus on the textbox so that the user can make edits.
  5. On "editing:exited," re-groups the objects

Here is a fiddle with my code: https://jsfiddle.net/1dr8jn26/4/

Do the following to replicate my issue:

  1. Add 2 input boxes using the button at the top
  2. Group the input boxes using the button at the top
  3. Click once on one of the input boxes in the group you created
  4. Click on the canvas outside of the group
  5. Click back on the same input box
  6. Click on the canvas outside of the group again
  7. Repeat 5 & 6

You will notice that the group creates duplicates of itself off to the side of the page. What I have discovered on my own:

I am still relatively new to programming, so i'm sure this is something obvious to the experienced coders here. Any help would be appreciated!

canvas.on('mouse:down', function(options) {
if (options.target) {
    var thisTarget = options.target; 
    var mousePos = canvas.getPointer(options.e);
    if (thisTarget.isType('group')) {
       var groupPos = {
            x: thisTarget.left,
            y: thisTarget.top
        }
var currentGroup = [];
var groupItems = []
groupItems = thisTarget._objects;
thisTarget.forEachObject(function(object,i) {
currentGroup[i] = object;
currentGroup.push(object);
})
        thisTarget.forEachObject(function(object,i) {
         if(object.type == "textbox"){            
 console.log("Start for statement that finds the x and y for each 
object")            
var matrix = thisTarget.calcTransformMatrix()
var newPoint = fabric.util.transformPoint({y: object.top, x: 
object.left}, matrix)
            var objectPos = {
                xStart: newPoint.x,
                xEnd: newPoint.x + object.width,
                yStart: newPoint.y,
                yEnd: newPoint.y + object.height
            }
            if (mousePos.x >= objectPos.xStart && mousePos.x <= 
(objectPos.xEnd)) {
                if (mousePos.y >= objectPos.yStart && mousePos.y <= 
objectPos.yEnd) {
function ungroup (group) {
groupItems = group._objects;
group._restoreObjectsState();
canvas.remove(group);
for (var i = 0; i < groupItems.length; i++) {
    canvas.add(groupItems[i]);
}
canvas.renderAll();
};
ungroup(thisTarget)
canvas.setActiveObject(object);
object.enterEditing();
object.selectAll();
object.on('editing:exited', function (options) {
var items = [];
groupItems.forEach(function (obj) {
    items.push(obj);
    canvas.remove(obj);
});
console.log(JSON.stringify(groupItems))
var grp = new fabric.Group(items, {});
canvas.add(grp);   
                  });
                }
            }
        }
        });   
      }    
   }
}); 

-Chris

Upvotes: 1

Views: 2375

Answers (1)

Wilco
Wilco

Reputation: 11

Have been looking at the code and I think I found a solution. The group is added two times in the group groupItems. Once at the start and a second time when ungrouping the items.

Used the code below in your fiddle and that works...

canvas.on('mouse:down', function(options) {
var groupItems;
if (options.target) {
    var thisTarget = options.target; 
    var mousePos = canvas.getPointer(options.e);
    var editTextbox = false;
    var editObject;

    if (thisTarget.isType('group')) {
        var groupPos = {
            x: thisTarget.left,
            y: thisTarget.top
        }

        thisTarget.forEachObject(function(object,i) {
            if(object.type == "textbox"){           
                var matrix = thisTarget.calcTransformMatrix();
                var newPoint = fabric.util.transformPoint({y: object.top, x: object.left}, matrix);
                var objectPos = {
                    xStart: newPoint.x - (object.width * object.scaleX) / 2,//When OriginX and OriginY are centered, otherwise xStart: newpoint.x - object.width * object.scaleX etc...
                    xEnd: newPoint.x + (object.width * object.scaleX) / 2,
                    yStart: newPoint.y - (object.height * object.scaleY) / 2,
                    yEnd: newPoint.y + (object.height * object.scaleY) / 2
                }

                if ((mousePos.x >= objectPos.xStart && mousePos.x <= objectPos.xEnd) && (mousePos.y >= objectPos.yStart && mousePos.y <= objectPos.yEnd)) {
                    function ungroup (group) {
                        groupItems = group._objects;
                        group._restoreObjectsState();
                        canvas.remove(group);
                        for (var i = 0; i < groupItems.length; i++) {
                            if(groupItems[i] != "textbox"){
                                groupItems[i].selectable = false;
                            }                               
                            canvas.add(groupItems[i]);
                        }
                        canvas.renderAll();
                    };

                    ungroup(thisTarget);
                    canvas.setActiveObject(object);

                    object.enterEditing();
                    object.selectAll();

                    editObject = object;
                    var exitEditing = true;

                    editObject.on('editing:exited', function (options) {
                        if(exitEditing){
                            var items = [];
                            groupItems.forEach(function (obj) {
                                items.push(obj);
                                canvas.remove(obj);
                            });

                            var grp
                            grp = new fabric.Group(items, {});
                            canvas.add(grp);
                            exitEditing = false;
                        }
                    });
                }
            }
        });
    }    
}
});

Here is the fiddle: https://jsfiddle.net/u3Lfnja2/1/

Upvotes: 1

Related Questions