Создайте сетку таблицы с изменяемыми размерами, изменяя размеры с помощью мыши, внутри содержимого, редактируемого с помощью vanilla javascript - PullRequest
0 голосов
/ 08 января 2020

Я хочу создать обычную таблицу с изменяемыми размерами внутри редактируемого содержимого. Таблица должна быть изменяемого размера с помощью мыши, предпочтительно изменяемого размера как по оси X, так и по оси Y, но этот вопрос больше направлен на изменение размера по оси X. У меня есть следующий код

index. html

<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<link rel="stylesheet" type="text/css" href="styles.css">
<script src="javascript.js"></script>
<!--- <script src="jquery-3.4.1.js"></script> -->

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

<title>Resizable table hobby testing</title>
</head>
<body>
    <div contenteditable="true" style="width: 500px; height: 500px;"></div>
<button onclick="insert_table(5, 5);>insert table</button>
</body>
</html>

styles. css

table {
    border-collapse: collapse;
    table-layout: fixed;
}

table, tr, td {
  border: 1px solid #AAAAAA;
}

tr, td {
    width: 60px;
    height: 16px;
    overflow: hidden;
    padding: 3px;
}

javascript. js

var th_element;
var startOffset;

function insert_table(rows, cols) { // inserts a table into the div
    // gets the selected text inside the content editable div and deletes it
    var selection = window.getSelection();
    var range = selection.getRangeAt(0);
    range.deleteContents();
    // Create a table element
    var ins_table = document.createElement("table");
    // set unique id, useful for getting the element later
    ins_table.setAttribute("id", "table"); // maybe change to ins_table.id = "table";? (note to self)
    // Create the format of rows and columns for the table
    for(var r = 0; r < rows; r++) {
        ins_table.innerHTML += "<tr></tr>";
        ins_table.childNodes[r].innerHTML = "<tr>" + '<td style="min-width: 30px;"> </td>'.repeat(cols) + "</tr>";
    }

    // general css styling
    ins_table.style.width = "200px";
    ins_table.style.float = "left";

    // insert table into cursor position
    range.insertNode(ins_table);

    // get the table by finding its id
    var the_table = document.getElementById('table');

    // get the first row, in order to add a div there that acts as a resize bar grab thingy
    var row = table.getElementsByTagName('tr')[0];
    var cols = row.childNodes; // the cols is all the child nodes of the first row

    for(var i = 0; i < cols.length; i++) { // iterate through all cols and insert the resize grab thingt
        var div = create_div(the_table.offsetHeight); // create a div for the selected cell with the height of the table
        cols[i].appendChild(div); // append that div to the cell
        cols[i].style.position = "relative"; // change position
        cols[i].style.overflow = "visible"; // needs to be set as visible to actually be used on the other rows. Without this it only works with the first row
        add_listener(div, cols[i]); // add a listener
    }
}

function create_div(height){ // create the div the user grabs onto
    var div = document.createElement('div'); // create the resize div to grab onto later
    // general styling
    div.style.top = 0;
    div.style.right = 0;
    div.style.width = '5px';
    div.style.position = 'absolute';
    div.style.cursor = 'col-resize';
    div.style.userSelect = 'none';
    div.style.height = height + 'px';
    div.className = 'columnSelector';
    div.style.border = "none";
    return div; // return the created div, to be inserted into the cell above
}

function add_listener(div, col) {
    div.addEventListener('mousedown', function(event) {
        th_element = col;
        startOffset = col.offsetWidth - event.pageX;
    });

    document.addEventListener('mousemove', function(event) {
        if(th_element) {
            th_element.style.width = startOffset + event.pageX + 'px';
        }
    });

    document.addEventListener('mouseup', function() {
        th_element = undefined;
    });
}

Я пробовал код из brainbell , но он не распространяется на несколько ячеек и не работает для меня без настройки вызовов переменных (например, brainbell использует parentElement вместо parentNode, который прерывается для меня). Перетаскивание div (вещь, которую вы берете, чтобы изменить размер таблицы) слишком далеко вправо или влево вызывает странное поведение, когда другие ячейки изменяются в размерах, но при этом их не изменяют. Среди прочего.

Код, из которого я черпал вдохновение: Изменение размеров таблиц в ванили JavaScript без влияния на позиционирование , но, как вы можете видеть, он ломается несколькими способами (1), например, когда Я перетаскиваю второй элемент изменения размера элемента div вперед и назад, первый элемент div встряхивает. (2) изменение размера с использованием третьего или четвертого div вызывает странные изменения размера. (3) Я нахожусь внутри редактируемого содержимого, делая текст внутри таблицы выделенным, я думаю, это потому, что изменение размеров таблиц происходит не достаточно быстро, поэтому мышь «перетаскивает» текст в следующем, предыдущем, et c cell, несмотря на то, что это не должно происходить (отключение выделения в contenteditable при изменении размера невозможно, я попытался сделать это через CSS). Среди прочего.

Я занимаюсь минимальным хобби в области кодирования в стиле «classi c», ванильным javascript, поэтому я не собираюсь использовать jQuery. Кто-нибудь знает, как (1) немного исправить мой код или (2) как создать сетку таблицы с изменяемым размером (используя vanilla JS и мышь для изменения размера) с редактируемым содержимым внутри ячеек, пожалуйста, оставьте комментарий или ответ ! Спасибо!

Здесь - это также кодовая ручка, чтобы SOMEWHAT иллюстрировал мою проблему, потому что по какой-то причине кодовая ручка менее сломана, чем моя, которую я использую на сервере httpd, не знаю, почему моя более сломанный (или медленный?)

...