Chris M
Chris M

Reputation: 242

fabricjs single click on textbox, begin editing with caret location where clicked

I'm looking for some guidance on textbox editing. I have a working canvas with a textbox on it. When I click the textbox I select it, when I double click I begin editing, this seems like normal behaviour - is it possible to begin editing with the single click and (important) have the text caret (cursor) where I clicked.

EG: If my textbox already has the words "Click me", if I click (single) before the 'me' can I begin editing using canvas.getActiveObject().enterEditing() or similar with the position of the textbox caret (cursor) in the location I clicked?

Double click works fine, but I'm trying to do this with one click.

Here is a JSFiddle, to play with or clone. https://jsfiddle.net/Milner99/2vgb5cLz/7/

Fiddle code

let canvas = new fabric.Canvas('fabricjs1');
let jsonDesign = ` {"version":"4.4.0","objects[{"type":"textbox","version":"4.4.0","originX":"left","originY":"top","left":54.99,"top":155.62,"width":381,"height":161.09,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeDashOffset":0,"strokeLineJoin":"miter","strokeUniform":false,"strokeMiterLimit":4,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","skewX":0,"skewY":0,"text":"YOUR LINE TEXT twice","fontSize":"66","fontWeight":"normal","fontFamily":"CandyCardCasual","fontStyle":"normal","lineHeight":1.16,"underline":false,"overline":false,"linethrough":false,"textAlign":"center","textBackgroundColor":"","charSpacing":0,"path":null,"minWidth":20,"splitByGrapheme":false,"styles":{}}]} `;
canvas.loadFromJSON(
        jsonDesign,
        canvas.renderAll.bind(canvas)
    );

canvas.on('selection:created', function(obj) {
    console.log(obj);
    canvas.getActiveObject().enterEditing();
});

Thank you

Upvotes: 2

Views: 1134

Answers (1)

obscure
obscure

Reputation: 12891

With a little trickery you can achieve this functionality. The IText class provides a method called setCursorByClick({x , y}) which positions the cursor according the x and y values given to the method. So you basically need to attach a mousedown and a mouseup listener to your object, get the mouse position from the event and use it with the setCursorByClick method on your actual text object.

I recommend using a mousedown listener first as you probably still want your object to be draggable. So on mouseup, we're comparing the mouse position with the mousedown event and if it's equal position the cursor - if not we do not.

Here's an example:

let canvas = new fabric.Canvas('fabricjs1');
let jsonDesign = ` {"version":"4.4.0","objects":[{"type":"textbox","version":"4.4.0","originX":"left","originY":"top","left":54.99,"top":155.62,"width":381,"height":161.09,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeDashOffset":0,"strokeLineJoin":"miter","strokeUniform":false,"strokeMiterLimit":4,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","skewX":0,"skewY":0,"text":"YOUR LINE TEXT twice","fontSize":"66","fontWeight":"normal","fontFamily":"CandyCardCasual","fontStyle":"normal","lineHeight":1.16,"underline":false,"overline":false,"linethrough":false,"textAlign":"center","textBackgroundColor":"","charSpacing":0,"path":null,"minWidth":20,"splitByGrapheme":false,"styles":{}}]} `;
canvas.loadFromJSON(
  jsonDesign,
  canvas.renderAll.bind(canvas)
);
let coords = {};
canvas.getObjects()[0].on('mousedown', function(obj) {
  coords = this.canvas.getPointer(obj.e);
});

canvas.getObjects()[0].on('mouseup', function(obj) {
  let e = this.canvas.getPointer(obj.e);
  if (e.x == coords.x && e.y == coords.y) {
    obj.target.enterEditing();
    obj.target.setCursorByClick(e);
  }
});
<canvas id="fabricjs1" width="500" height="500"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.min.js"></script>

Upvotes: 5

Related Questions