0

I'm trying to edit a cell with an input and a dropdown. The goal being to edit, in this case, a disk size.

I would therefore need to combine , editor:"input", editor:true, validator:["min:0", "max:999", "numeric"]} with , editor:"select", editorParams:{"MB":"MB", "TB":"TB", "GB":"GB"}

The final result being something like 146GB.

1st try: Since this looks like a custom editor, I wrote this:

var CapacityEditor = function(cell, onRendered, success, cancel, editorParams){
    var capacity = document.createElement("div");
    capacity.style.width = "100%";

    var size = document.createElement("input");
    size.setAttribute("type", "text");
    size.style.width = "50px";
    size.style.textAlign = "right";
    onRendered(function(){
        size.focus();
        //size.style.css = "100%";
    });
    capacity.append(size);

    var multiplier = document.createElement("select");
    multiplier.style.width = "45px";
    multiplier.append(new Option("MB","MB",true,true));
    multiplier.append(new Option("GB","GB"));
    multiplier.append(new Option("TB","TB"));
    capacity.append(multiplier);
    var multi = "MB";

    function successFunc(){
        success(size.value+multi);
    }

    function setmultiFunc() {
        multi = multiplier.options[multiplier.selectedIndex].text;
        successFunc();
    }

    size.addEventListener("change", successFunc);
    size.addEventListener("blur", successFunc);
    multiplier.addEventListener("change", successFunc);
    multiplier.addEventListener("blur", successFunc);

    return capacity;
}

with:

{title:"Capacity", field:"Size", align:"center", width:95, editor:CapacityEditor, sorter:SizeSorter, sortable: true},

So, on that one, there are 'a few' issues. - I have no idea what the success() is supposed to do - I'm returning a div hoping that the content would populate the cell - Whenever I put in a value and make a selection, it does not get saved at all; probably because I'm returning a div in the first place

2nd try: Since the edit does not work, maybe I could use the cell click event instead...

The cell.getElement() does give me the DIV content for the cell as expected but there is no such thing as a cell.setElement(), right? I can create my own div, like in the first try and then use the cell.setValue() to well, set the value but if I can't display my div in the first place, that doesn't work too good. Tried cell.getElement().innerHTML = "<div>...</div>" but nothing (waaaay too easy)

3rd try: Well, let's thing outside the box then (literally)

In other words, lets create a very simple modal, display it on top of the existing cell and then use, again, cell.setValue() to update the value. Problem is: how do I get the position of the cell? Using the built-in editor, the editor:"select" replaces the cell's div with an input in readonly and created a div in the document body with multiple div and then positions it right below the cell making it look like a dropdown:

<input type="text" readonly="" style="padding: 4px; width: 100%; box-sizing: border-box; height: 100%;">
<div class="tabulator-edit-select-list" style="min-width: 80px; top: 348px; left: 671px;"><div class="tabulator-edit-select-list-item" tabindex="0">10K</div><div class="tabulator-edit-select-list-item" tabindex="0">15K</div><div class="tabulator-edit-select-list-item" tabindex="0">7.2K</div><div class="tabulator-edit-select-list-item active" tabindex="0">na</div></div>

Note the top and left style attributes.

Oli is able to do it so there has to be a way, right?

Any help, advise, fix would be much appreciated.

Nick
  • 79
  • 1
  • 11

1 Answers1

0

Ok, so, if anyone is interested, I was able to get the cell's position using a function found on this forum by meouw (https://stackoverflow.com/a/442474/2868497):

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

With the cell's top and left position, I was able to place my div to edit my field:

var globalCellClick = function(e, cell){
    var capacity = document.createElement("div");
    capacity.style.position = "absolute";
    capacity.style.left = getOffset(cell.getElement()).left + "px";
    capacity.style.top = getOffset(cell.getElement()).top + "px";
    capacity.setAttribute("name", "capacity-edit");

    var size = document.createElement("input");
    size.setAttribute("type", "", "text");
    size.style.width = "47px";
    size.style.height = "31px";
    size.style.textAlign = "right";
    capacity.append(size);

    var multiplier = document.createElement("select");
    multiplier.style.width = "47px";
    multiplier.style.height = "31px";
    multiplier.append(new Option("MB","MB",true,true));
    multiplier.append(new Option("GB","GB"));
    multiplier.append(new Option("TB","TB"));
    capacity.append(multiplier);

    document.body.appendChild(capacity); 

    function updateCell(){
        var multi = multiplier.options[multiplier.selectedIndex].text;
        cell.setValue(size.value+multi);
    }

    size.focus();
    size.addEventListener("change", updateCell);
    size.addEventListener("blur", updateCell);
    multiplier.addEventListener("change", updateCell);
    multiplier.addEventListener("blur", updateCell);
};

with:

{title:"Capacity", field:"Size", align:"center", width:95, cellClick:globalCellClick, sorter:SizeSorter, sortable: true},

I can edit the rest of the fields as needed and I'm then using a save button to save the modifications and destroy all the div I created to edit:

$("#tabulator-controls  button[name=save-data]").on("click", function(){
    $("div[name=capacity-edit]").remove();
    // update the database
});

There may be an easier/cleaner way to get it done but it works so happy with it.

Nick
  • 79
  • 1
  • 11