1

I may be misunderstanding the purpose of .focus().

When I insert a table into a content editable element, I want to set the focus to the first cell of the table. By focus i mean the cursor will be in the first cell and the user can start typing directly into the cell without selecting it.

However I just can't seem to achieve this.

Also when I click off the table, on content inside the editable div only, I want to remove the ClassTwo from the table and can't get that right either

var iDoc;

iDoc = document.getElementById("MyEditor");
iDoc.focus();

  function postedTableCap() {
  alert("called");
 $('.ClassTwo td:first').focus();
      };

   function insertTable(position, height, width, rows, columns, bkcolor, bcolor, bsiz, bstyle) {
        var mybody = document.getElementById("MyEditor");

        mytable = document.createElement("table");
        mytablebody = document.createElement("tbody");

        for (var r = 0; r < rows; r++) {
            mycurrent_row = document.createElement("tr");

            for (var c = 0; c < columns; c++) {
                mycurrent_cell = document.createElement("td");
                mycurrent_row.appendChild(mycurrent_cell);
            }
            mytablebody.appendChild(mycurrent_row);
        }

        mytable.appendChild(mytablebody);
        mybody.appendChild(mytable);
        mytable.className = "ClassOne";
        mytable.classList.add("ClassTwo");
        mytable.style.height = height + 'px';
        mytable.style.width = width + 'px';
        if (!(bsiz === undefined || bsiz === null)) {
            mytable.style.borderColor = "#" + bcolor;
            mytable.style.borderWidth = bsiz + 'px';
            mytable.style.borderStyle = bstyle;
        };
        mytable.style.backgroundColor = '#' + bkcolor;

        if (position == 1) {
            //mytable.style.width = "auto"
            mytable.style.marginLeft = "0px";
            mytable.style.marginRight = "auto";
        }
        else if (position == 2) {
            //mytable.style.width = "auto"
            mytable.style.marginLeft = "auto";
            mytable.style.marginRight = "auto";
        }
        else if (position == 3) {
            //mytable.style.width = "auto"
            mytable.style.marginLeft = "auto";
            mytable.style.marginRight = "0px";
        };
    };
    
    
$("#MyBtn").click(function () {
       var d1 = $.Deferred();

        $.when(d1).then(function () {
            $(".GSM-i-tbl-active").focus().blur();
            $('.TableOptions').hide();
            postedTableCap();                
        })

        d1.resolve(insertTable(2, 200, 200, 3, 3, "#ff0000", "#0000FF", 1, "solid"));
        
    });

    
    
    
table.ClassOne tr td{
  border: 1px solid lightgrey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" id="MyBtn">
InsertTable
</button>
<div id="MyEditor" contenteditable="true" style="height:300px; width:300px; background-color:white;"></div>
JQuery
  • 889
  • 3
  • 13
  • 35

1 Answers1

2

There are two errors with your code. The first one is that you are calling focus too early (I see you knew about it and tried to resolve it with a deferred...). You can notice that when the alert dialog is displayed, the javascript engine is frozen and it's a good time to see that the table you are trying to focus on does not even exist yet. You'd have to wait the end of the current call loop for the drawing to occur. I've used window.setTimeout to make sure it is called after everything has been done.

Next error: You can only focus on "focusable" elements. This includes inputs, contentEditables, buttons, links and so on. But not table cells, even when they are inside a contentEditable. Your best bet is to work with the document selection, grab the selection of the document and collapse it on the node of your choice.

var iDoc;

iDoc = document.getElementById("MyEditor");
iDoc.focus();

function postedTableCap() {
  var sel = document.getSelection();
  sel.collapse($('.ClassTwo td:first')[0]);
};

function insertTable(position, height, width, rows, columns, bkcolor, bcolor, bsiz, bstyle) {
  var mybody = document.getElementById("MyEditor");

  mytable = document.createElement("table");
  mytablebody = document.createElement("tbody");

  for (var r = 0; r < rows; r++) {
    mycurrent_row = document.createElement("tr");

    for (var c = 0; c < columns; c++) {
      mycurrent_cell = document.createElement("td");
      mycurrent_row.appendChild(mycurrent_cell);
    }
    mytablebody.appendChild(mycurrent_row);
  }

  mytable.appendChild(mytablebody);
  mybody.appendChild(mytable);
  mytable.className = "ClassOne";
  mytable.classList.add("ClassTwo");
  mytable.style.height = height + 'px';
  mytable.style.width = width + 'px';
  if (!(bsiz === undefined || bsiz === null)) {
    mytable.style.borderColor = "#" + bcolor;
    mytable.style.borderWidth = bsiz + 'px';
    mytable.style.borderStyle = bstyle;
  };
  mytable.style.backgroundColor = '#' + bkcolor;

  if (position == 1) {
    //mytable.style.width = "auto"
    mytable.style.marginLeft = "0px";
    mytable.style.marginRight = "auto";
  } else if (position == 2) {
    //mytable.style.width = "auto"
    mytable.style.marginLeft = "auto";
    mytable.style.marginRight = "auto";
  } else if (position == 3) {
    //mytable.style.width = "auto"
    mytable.style.marginLeft = "auto";
    mytable.style.marginRight = "0px";
  };
};


$("#MyBtn").click(function() {
  var d1 = $.Deferred();

  $.when(d1).then(function() {
    $(".GSM-i-tbl-active").focus().blur();
    $('.TableOptions').hide();
    window.setTimeout(postedTableCap, 0);
  })

  d1.resolve(insertTable(2, 200, 200, 3, 3, "#ff0000", "#0000FF", 1, "solid"));

});
table.ClassOne tr td {
  border: 1px solid lightgrey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" id="MyBtn">
InsertTable
</button>
<div id="MyEditor" contenteditable="true" style="height:300px; width:300px; background-color:white;"></div>

As for your second question, how to react to select/deselect inside a contentEditable, you should read questions like this one. The trick is again to use the selection, and listen on click events to know when it changes and see if you should add or remove the class.

Salketer
  • 14,263
  • 2
  • 30
  • 58
  • Thanks, really appreciate it! – JQuery Oct 06 '17 at 09:16
  • I was hoping to use the .on('focus',... to trigger an event when the cell was selected. Is it possible to fire that and store the $(this) of a the selected cell in a var to change it's properties? – JQuery Oct 06 '17 at 09:33
  • You could reproduce the focus and blur behaviors if you wanted... Use the proper events to detect a selection change, detect the the element where the selection is now, and trigger 'focus' on it. You can save it in a variable so you can trigger blur in due time. – Salketer Oct 06 '17 at 10:02