From 06aa8bff259ccf5620b0f8564f376af22b71895e Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 19 Jan 2016 15:27:52 +0000 Subject: [PATCH] enhanced the table editing in the extended wiki editor (medium-editor-tables) disabled firefox object resizing and inline table editing --- codepot/src/codepot/views/wiki_editx.php | 15 +- codepot/src/codepot/views/wiki_show.php | 4 +- codepot/src/css/common.css | 6 +- codepot/src/js/Makefile.am | 2 +- codepot/src/js/Makefile.in | 2 +- codepot/src/js/medium-editor-tables.js | 732 +++++++++++++++++++++ codepot/src/js/medium-editor-tables.min.js | 1 - 7 files changed, 753 insertions(+), 9 deletions(-) create mode 100644 codepot/src/js/medium-editor-tables.js delete mode 100644 codepot/src/js/medium-editor-tables.min.js diff --git a/codepot/src/codepot/views/wiki_editx.php b/codepot/src/codepot/views/wiki_editx.php index 1ea40d46..77f93815 100644 --- a/codepot/src/codepot/views/wiki_editx.php +++ b/codepot/src/codepot/views/wiki_editx.php @@ -28,8 +28,8 @@ - - + + converter->AsciiToHex ($wiki->name); @@ -365,7 +365,8 @@ $(function () { toolbar: { allowMultiParagraphSelection: true, - buttons: ['bold', 'italic', 'underline', 'strikethrough', + buttons: ['fontname', 'fontsize', + 'bold', 'italic', 'underline', 'strikethrough', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'subscript', 'superscript', 'removeFormat', 'pre', 'anchor', 'image', @@ -526,6 +527,14 @@ $(function () { // quirkiness of medium editor's toolbar resize_editor (); resize_editor (); + + // to diable firefox's object resizing. + try + { + document.execCommand("enableInlineTableEditing", false, false); + document.execCommand("enableObjectResizing", false, false); + } + catch (err) { } }); diff --git a/codepot/src/codepot/views/wiki_show.php b/codepot/src/codepot/views/wiki_show.php index 3e8662ce..bd7c2bac 100644 --- a/codepot/src/codepot/views/wiki_show.php +++ b/codepot/src/codepot/views/wiki_show.php @@ -1,4 +1,6 @@ - + + + diff --git a/codepot/src/css/common.css b/codepot/src/css/common.css index dcd705e3..0505ea09 100644 --- a/codepot/src/css/common.css +++ b/codepot/src/css/common.css @@ -952,11 +952,13 @@ pre.codepot-line-numbered span.codepot-line-number-clear { -webkit-box-sizing: border-box; box-sizing: border-box; - margin: 0.1em 0 0.1em 0; - padding: 0; + padding: 0.3em 1em 0.3em 1em; + margin: 0; max-width: 100%; border: 1px solid #DFDFDF; + + table-layout: auto !important; } .codepot-styled-text-view table tr, diff --git a/codepot/src/js/Makefile.am b/codepot/src/js/Makefile.am index 96408cb5..e2f7088e 100644 --- a/codepot/src/js/Makefile.am +++ b/codepot/src/js/Makefile.am @@ -25,7 +25,7 @@ www_DATA = \ jquery.flot.tickrotor.js \ jqueryui-editable.min.js \ medium-editor.min.js \ - medium-editor-tables.min.js \ + medium-editor-tables.js \ showdown.js \ d3.min.js \ CodeFlower.js diff --git a/codepot/src/js/Makefile.in b/codepot/src/js/Makefile.in index f8845813..cd24eccc 100644 --- a/codepot/src/js/Makefile.in +++ b/codepot/src/js/Makefile.in @@ -178,7 +178,7 @@ www_DATA = \ jquery.flot.tickrotor.js \ jqueryui-editable.min.js \ medium-editor.min.js \ - medium-editor-tables.min.js \ + medium-editor-tables.js \ showdown.js \ d3.min.js \ CodeFlower.js diff --git a/codepot/src/js/medium-editor-tables.js b/codepot/src/js/medium-editor-tables.js new file mode 100644 index 00000000..a86df826 --- /dev/null +++ b/codepot/src/js/medium-editor-tables.js @@ -0,0 +1,732 @@ +(function (root, factory) { + 'use strict'; + if (typeof module === 'object') { + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define(factory); + } else { + root.MediumEditorTable = factory; + } +}(this, function () { + + 'use strict'; + +function extend(dest, source) { + var prop; + dest = dest || {}; + for (prop in source) { + if (source.hasOwnProperty(prop) && !dest.hasOwnProperty(prop)) { + dest[prop] = source[prop]; + } + } + return dest; +} + +function getSelectionText(doc) { + if (doc.getSelection) { + return doc.getSelection().toString(); + } + if (doc.selection && doc.selection.type !== 'Control') { + return doc.selection.createRange().text; + } + return ''; +} + +function getSelectionStart(doc) { + var node = doc.getSelection().anchorNode, + startNode = (node && node.nodeType === 3 ? node.parentNode : node); + + return startNode; +} + +function placeCaretAtNode(doc, node, before) { + if (doc.getSelection !== undefined && node) { + var range = doc.createRange(), + selection = doc.getSelection(); + + if (before) { + range.setStartBefore(node); + } else { + range.setStartAfter(node); + } + + range.collapse(true); + + selection.removeAllRanges(); + selection.addRange(range); + } +} + +function isInsideElementOfTag(node, tag) { + if (!node) { + return false; + } + + var parentNode = node.parentNode, + tagName = parentNode.tagName.toLowerCase(); + + while (tagName !== 'body') { + if (tagName === tag) { + return true; + } + parentNode = parentNode.parentNode; + + if (parentNode && parentNode.tagName) { + tagName = parentNode.tagName.toLowerCase(); + } else { + return false; + } + } + + return false; +} + +function getParentOf(el, tagTarget) { + var tagName = el && el.tagName ? el.tagName.toLowerCase() : false; + + if (!tagName) { + return false; + } + while (tagName && tagName !== 'body') { + if (tagName === tagTarget) { + return el; + } + el = el.parentNode; + tagName = el && el.tagName ? el.tagName.toLowerCase() : false; + } +} + +function Grid(el, callback, rows, columns) { + return this.init(el, callback, rows, columns); +} + +Grid.prototype = { + init: function (el, callback, rows, columns) { + this._root = el; + this._callback = callback; + this.rows = rows; + this.columns = columns; + return this._render(); + }, + + setCurrentCell: function (cell) { + this._currentCell = cell; + }, + + markCells: function () { + [].forEach.call(this._cellsElements, function (el) { + var cell = { + column: parseInt(el.dataset.column, 10), + row: parseInt(el.dataset.row, 10) + }, + active = this._currentCell && + cell.row <= this._currentCell.row && + cell.column <= this._currentCell.column; + + if (active === true) { + el.classList.add('active'); + } else { + el.classList.remove('active'); + } + }.bind(this)); + }, + + _generateCells: function () { + this._cells = []; + + for (var i = 0; i < this.rows * this.columns; i++) { + var column = i % this.columns, + row = Math.floor(i / this.rows); + + this._cells.push({ + column: column, + row: row, + active: false + }); + } + }, + + _html: function () { + var html = '
'; + html += this._cellsHTML(); + html += '
'; + return html; + }, + + _cellsHTML: function () { + var html = ''; + this._generateCells(); + this._cells.map(function (cell) { + html += ''; + html += ''; + }); + return html; + }, + + _render: function () { + this._root.innerHTML = this._html(); + this._cellsElements = this._root.querySelectorAll('a'); + this._bindEvents(); + }, + + _bindEvents: function () { + [].forEach.call(this._cellsElements, function (el) { + this._onMouseEnter(el); + this._onClick(el); + }.bind(this)); + }, + + _onMouseEnter: function (el) { + var self = this, + timer; + + el.addEventListener('mouseenter', function () { + clearTimeout(timer); + + var dataset = this.dataset; + + timer = setTimeout(function () { + self._currentCell = { + column: parseInt(dataset.column, 10), + row: parseInt(dataset.row, 10) + }; + self.markCells(); + }, 50); + }); + }, + + _onClick: function (el) { + var self = this; + el.addEventListener('click', function (e) { + e.preventDefault(); + self._callback(this.dataset.row, this.dataset.column); + }); + } +}; + +function Builder(options) { + return this.init(options); +} + +Builder.prototype = { + init: function (options) { + this.options = options; + this._doc = options.ownerDocument || document; + this._root = this._doc.createElement('div'); + this._root.className = 'medium-editor-table-builder'; + this.grid = new Grid( + this._root, + this.options.onClick, + this.options.rows, + this.options.columns + ); + + this._range = null; + this._toolbar = this._doc.createElement('div'); + this._toolbar.className = 'medium-editor-table-builder-toolbar'; + + var spanRow = this._doc.createElement('span'); + spanRow.innerHTML = 'Row:'; + this._toolbar.appendChild(spanRow); + var addRowBefore = this._doc.createElement('button'); + addRowBefore.title = 'Add row before'; + addRowBefore.innerHTML = ''; + addRowBefore.onclick = this.addRow.bind(this, true); + this._toolbar.appendChild(addRowBefore); + + var addRowAfter = this._doc.createElement('button'); + addRowAfter.title = 'Add row after'; + addRowAfter.innerHTML = ''; + addRowAfter.onclick = this.addRow.bind(this, false); + this._toolbar.appendChild(addRowAfter); + + var remRow = this._doc.createElement('button'); + remRow.title = 'Remove row'; + remRow.innerHTML = ''; + remRow.onclick = this.removeRow.bind(this); + this._toolbar.appendChild(remRow); + + var spanCol = this._doc.createElement('span'); + spanCol.innerHTML = 'Column:'; + this._toolbar.appendChild(spanCol); + var addColumnBefore = this._doc.createElement('button'); + addColumnBefore.title = 'Add column before'; + addColumnBefore.innerHTML = ''; + addColumnBefore.onclick = this.addColumn.bind(this, true); + this._toolbar.appendChild(addColumnBefore); + + var addColumnAfter = this._doc.createElement('button'); + addColumnAfter.title = 'Add column after'; + addColumnAfter.innerHTML = ''; + addColumnAfter.onclick = this.addColumn.bind(this, false); + this._toolbar.appendChild(addColumnAfter); + + var remColumn = this._doc.createElement('button'); + remColumn.title = 'Remove column'; + remColumn.innerHTML = ''; + remColumn.onclick = this.removeColumn.bind(this); + this._toolbar.appendChild(remColumn); + + var remTable = this._doc.createElement('button'); + remTable.title = 'Remove table'; + remTable.innerHTML = ''; + remTable.onclick = this.removeTable.bind(this); + this._toolbar.appendChild(remTable); + + var grid = this._root.childNodes[0]; + this._root.insertBefore(this._toolbar, grid); + //console.log(this._root); + }, + + getElement: function () { + return this._root; + }, + + hide: function () { + this._root.style.display = ''; + this.grid.setCurrentCell({ column: -1, row: -1 }); + this.grid.markCells(); + }, + + show: function (left) { + this._root.style.display = 'block'; + this._root.style.left = left + 'px'; + }, + + setEditor: function (range) { + this._range = range; + this._doc.getElementsByClassName('medium-editor-table-builder-toolbar')[0].style.display = 'block'; + }, + + setBuilder: function () { + this._range = null; + this._doc.getElementsByClassName('medium-editor-table-builder-toolbar')[0].style.display = 'none'; + var elements = this._doc.getElementsByClassName('medium-editor-table-builder-grid'); + for (var i = 0; i < elements.length; i++) { + // TODO: what is 16 and what is 2? + elements[i].style.height = (16 * this.rows + 2) + 'px'; + elements[i].style.width = (16 * this.columns + 2) + 'px'; + } + }, + + addRow: function (before, e) { + e.preventDefault(); + e.stopPropagation(); + + // codepot + //var tbody = this._range.parentNode.parentNode, + // tr = this._doc.createElement('tr'), + // td; + var num_cols; + var tbody, tr, td; + + tr = this._doc.createElement('tr'); + + var in_thead = this._range.parentNode.parentNode.tagName.toLowerCase() == 'thead'; + if (in_thead) + { + // the current cell is the header. + var thead = this._range.parentNode.parentNode; + var table = thead.parentNode; + tbody = table.childNodes[1]; + + } + else + { + tbody = this._range.parentNode.parentNode; + } + + if (tbody.childNodes[0] && tbody.childNodes[0].childNodes[0] && tbody.childNodes[0].childNodes[0].tagName.toLowerCase() == 'th') + { + td = this._doc.createElement('th'); + tr.appendChild(td); + num_cols = this._range.parentNode.childNodes.length - 1; + } + else + { + num_cols = this._range.parentNode.childNodes.length; + } + // end codepot + + for (var i = 0; i < num_cols /*this._range.parentNode.childNodes.length*/; i++) { + td = this._doc.createElement('td'); + td.appendChild(this._doc.createElement('br')); + tr.appendChild(td); + } + + // codepot + if (in_thead) tbody.appendChild(tr); + // end codepot + else if (before !== true && this._range.parentNode.nextSibling) { + tbody.insertBefore(tr, this._range.parentNode.nextSibling); + } else if (before === true) { + tbody.insertBefore(tr, this._range.parentNode); + } else { + tbody.appendChild(tr); + } + // codepot + //this.options.onClick(0, 0); + this.options.onClick(-1, -1); + // end codepot + }, + + removeRow: function (e) { + e.preventDefault(); + e.stopPropagation(); + + // codepot + if (this._range.parentNode.parentNode.tagName.toLowerCase() == 'thead') // remove the whole thead + this._range.parentNode.parentNode.parentNode.removeChild(this._range.parentNode.parentNode); + else + // end codepot + this._range.parentNode.parentNode.removeChild(this._range.parentNode); + + // codepot + //this.options.onClick(0, 0); + this.options.onClick(-1, -1); + // end codepot + }, + + addColumn: function (before, e) { + e.preventDefault(); + e.stopPropagation(); + var cell = Array.prototype.indexOf.call(this._range.parentNode.childNodes, this._range); + var td; + + // codepot + //var tbody = this._range.parentNode.parentNode; + var tbody; + + var table = this._range.parentNode.parentNode.parentNode; + if (table.childNodes[0].tagName.toLowerCase() == 'thead') + { + var thead = table.childNodes[0]; + if (thead.childNodes[0]) + { + // tr is expected inside thead. if no exists, don't add a column + td = this._doc.createElement('th'); + if (before) + thead.childNodes[0].insertBefore(td, thead.childNodes[0].childNodes[cell]); + else if (thead.childNodes[0].childNodes[cell].nextSibling) + thead.childNodes[0].insertBefore(td, thead.childNodes[0].childNodes[cell].nextSibling); + else + thead.childNodes[0].appendChild(td); + } + } + + var in_thead = this._range.parentNode.parentNode.tagName.toLowerCase() == 'thead'; + if (in_thead) + { + // the current cell is the header. + var thead = this._range.parentNode.parentNode; + var table = thead.parentNode; + tbody = table.childNodes[1]; + } + else + { + tbody = this._range.parentNode.parentNode; + } + // end codepot + + for (var i = 0; i < tbody.childNodes.length; i++) { + td = this._doc.createElement('td'); + td.appendChild(this._doc.createElement('br')); + if (before === true) { + tbody.childNodes[i].insertBefore(td, tbody.childNodes[i].childNodes[cell]); + // codepot + //} else if (this._range.parentNode.parentNode.childNodes[i].childNodes[cell].nextSibling) { + } else if (tbody.childNodes[i].childNodes[cell].nextSibling) { + // end codepot + tbody.childNodes[i].insertBefore(td, tbody.childNodes[i].childNodes[cell].nextSibling); + } else { + tbody.childNodes[i].appendChild(td); + } + } + + // codepot + //this.options.onClick(0, 0); + this.options.onClick(-1, -1); + // end codepot + }, + + removeColumn: function (e) { + e.preventDefault(); + e.stopPropagation(); + + // codepot + //var cell = Array.prototype.indexOf.call(this._range.parentNode.childNodes, this._range), + // tbody = this._range.parentNode.parentNode, + // rows = tbody.childNodes.length; + + var table, thead, tbody, rows; + var cell = Array.prototype.indexOf.call(this._range.parentNode.childNodes, this._range); + + if (this._range.parentNode.parentNode.tagName.toLowerCase() == 'thead') + { + // the current cell is the header. + thead = this._range.parentNode.parentNode; + table = thead.parentNode; + tbody = table.childNodes[1]; + } + else + { + tbody = this._range.parentNode.parentNode; + table = tbody.parentNode; + } + rows = tbody.childNodes.length; + + if (table.childNodes[0].tagName.toLowerCase() == 'thead') + { + var thead = table.childNodes[0]; + if (thead.childNodes[0]) + { + // if no is inside , don't delete any. + thead.childNodes[0].removeChild (thead.childNodes[0].childNodes[cell]); + } + } + // end codepot + + for (var i = 0; i < rows; i++) { + tbody.childNodes[i].removeChild(tbody.childNodes[i].childNodes[cell]); + } + + // codepot + //this.options.onClick(0, 0); + this.options.onClick(-1, -1); + // end codepot + }, + + removeTable: function (e) { + e.preventDefault(); + e.stopPropagation(); + var cell = Array.prototype.indexOf.call(this._range.parentNode.childNodes, this._range), + table = this._range.parentNode.parentNode.parentNode; + + table.parentNode.removeChild(table); + this.options.onClick(0, 0); + } +}; + +function Table(editor) { + return this.init(editor); +} + +var TAB_KEY_CODE = 9; + +Table.prototype = { + init: function (editor) { + this._editor = editor; + this._doc = this._editor.options.ownerDocument; + this._bindTabBehavior(); + }, + + insert: function (rows, cols) { + + var html = this._html(rows, cols); + // codepot + var header = this._header(rows, cols); + // end codepot + + this._editor.pasteHTML( + '' + + // codepot + '' + + header + + '' + + // end codepot + '' + + html + + '' + + '
', { + cleanAttrs: [], + cleanTags: [] + } + ); + + var table = this._doc.getElementById('medium-editor-table'); + table.removeAttribute('id'); + placeCaretAtNode(this._doc, table.querySelector('td'), true); + + this._editor.checkSelection(); + }, + + // codepot + _header: function (rows, cols) { + var html = '', x, y; + + for (x = 0; x < 1; x++) { + html += ''; + for (y = 0; y <= cols; y++) { + html += '' + y + ''; + } + html += ''; + } + return html; + }, + // end codepot + + _html: function (rows, cols) { + var html = '', + x, y, + text = getSelectionText(this._doc); + + for (x = 0; x <= rows; x++) { + // codepot + html += '' + x + ''; + // end codepot + for (y = 0; y <= cols; y++) { + html += '' + (x === 0 && y === 0 ? text : '
') + ''; + } + html += ''; + } + return html; + }, + + _bindTabBehavior: function () { + var self = this; + [].forEach.call(this._editor.elements, function (el) { + el.addEventListener('keydown', function (e) { + self._onKeyDown(e); + }); + }); + }, + + _onKeyDown: function (e) { + var el = getSelectionStart(this._doc), + table; + + if (e.which === TAB_KEY_CODE && isInsideElementOfTag(el, 'table')) { + e.preventDefault(); + e.stopPropagation(); + table = this._getTableElements(el); + if (e.shiftKey) { + this._tabBackwards(el.previousSibling, table.row); + } else { + // codepot - note table.row or table.cell tends to become null in firefox + // when moving between cells with a tab key. the el passed + // seems to get wrong in firefox. + if (this._isLastCell(el, table.row, table.root)) { + // codepot + if (table.row.cells[0].tagName.toLowerCase() == 'th') + this._insertRow(getParentOf(el, 'tbody'), table.row.cells.length - 1, 1); + else + // end codepot + this._insertRow(getParentOf(el, 'tbody'), table.row.cells.length, 0); + } + placeCaretAtNode(this._doc, el); + } + } + }, + + _getTableElements: function (el) { + return { + // codepot + //cell: getParentOf(el, 'td'), + cell: getParentOf(el, el.tagName.toLowerCase()), + // end codepot + row: getParentOf(el, 'tr'), + root: getParentOf(el, 'table') + }; + }, + + _tabBackwards: function (el, row) { + el = el || this._getPreviousRowLastCell(row); + placeCaretAtNode(this._doc, el, true); + }, + + _insertRow: function (tbody, cols, prepend_th) { + var tr = document.createElement('tr'), + html = '', + i; + + if (prepend_th) html += '
'; + for (i = 0; i < cols; i += 1) { + html += '
'; + } + tr.innerHTML = html; + tbody.appendChild(tr); + }, + + _isLastCell: function (el, row, table) { + return ( + (row.cells.length - 1) === el.cellIndex && + (table.rows.length - 1) === row.rowIndex + ); + }, + + _getPreviousRowLastCell: function (row) { + row = row.previousSibling; + if (row) { + return row.cells[row.cells.length - 1]; + } + } +}; + +var MediumEditorTable = MediumEditor.extensions.form.extend({ + name: 'table', + + aria: 'create table', + action: 'table', + contentDefault: 'TBL', + contentFA: '', + + handleClick: function (event) { + event.preventDefault(); + event.stopPropagation(); + + this[this.isActive() === true ? 'hide' : 'show'](); + }, + + hide: function () { + this.setInactive(); + this.builder.hide(); + }, + + show: function () { + this.setActive(); + + var range = MediumEditor.selection.getSelectionRange(this.document); + if (range.startContainer.nodeName.toLowerCase() === 'td' || + range.endContainer.nodeName.toLowerCase() === 'td' || + MediumEditor.util.getClosestTag(MediumEditor.selection.getSelectedParentElement(range), 'td')) { + this.builder.setEditor(MediumEditor.selection.getSelectedParentElement(range)); + // codepot + } else if (range.startContainer.nodeName.toLowerCase() === 'th' || + range.endContainer.nodeName.toLowerCase() === 'th' || + MediumEditor.util.getClosestTag(MediumEditor.selection.getSelectedParentElement(range), 'th')) { + this.builder.setEditor(MediumEditor.selection.getSelectedParentElement(range)); + // end codepot + } else { + this.builder.setBuilder(); + } + this.builder.show(this.button.offsetLeft); + }, + + getForm: function () { + this.builder = new Builder({ + onClick: function (rows, columns) { + // codepot + //if (rows > 0 && columns > 0) { + if (rows >= 0 && columns >= 0) { + // end codepot + this.table.insert(rows, columns); + } + this.hide(); + }.bind(this), + ownerDocument: this.document, + rows: this.rows || 10, + columns: this.columns || 10 + }); + + this.table = new Table(this.base); + + return this.builder.getElement(); + } +}); + + return MediumEditorTable; +}())); diff --git a/codepot/src/js/medium-editor-tables.min.js b/codepot/src/js/medium-editor-tables.min.js deleted file mode 100644 index fa6af802..00000000 --- a/codepot/src/js/medium-editor-tables.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(a,b){"use strict";"object"==typeof module?module.exports=b:"function"==typeof define&&define.amd?define(b):a.MediumEditorTable=b}(this,function(){"use strict";function a(a){return a.getSelection?a.getSelection().toString():a.selection&&"Control"!==a.selection.type?a.selection.createRange().text:""}function b(a){var b=a.getSelection().anchorNode,c=b&&3===b.nodeType?b.parentNode:b;return c}function c(a,b,c){if(void 0!==a.getSelection&&b){var d=a.createRange(),e=a.getSelection();c?d.setStartBefore(b):d.setStartAfter(b),d.collapse(!0),e.removeAllRanges(),e.addRange(d)}}function d(a,b){if(!a)return!1;for(var c=a.parentNode,d=c.tagName.toLowerCase();"body"!==d;){if(d===b)return!0;if(c=c.parentNode,!c||!c.tagName)return!1;d=c.tagName.toLowerCase()}return!1}function e(a,b){var c=a&&a.tagName?a.tagName.toLowerCase():!1;if(!c)return!1;for(;c&&"body"!==c;){if(c===b)return a;a=a.parentNode,c=a&&a.tagName?a.tagName.toLowerCase():!1}}function f(a,b,c,d){return this.init(a,b,c,d)}function g(a){return this.init(a)}function h(a){return this.init(a)}f.prototype={init:function(a,b,c,d){return this._root=a,this._callback=b,this.rows=c,this.columns=d,this._render()},setCurrentCell:function(a){this._currentCell=a},markCells:function(){[].forEach.call(this._cellsElements,function(a){var b={column:parseInt(a.dataset.column,10),row:parseInt(a.dataset.row,10)},c=this._currentCell&&b.row<=this._currentCell.row&&b.column<=this._currentCell.column;c===!0?a.classList.add("active"):a.classList.remove("active")}.bind(this))},_generateCells:function(){this._cells=[];for(var a=0;a"},_cellsHTML:function(){var a="";return this._generateCells(),this._cells.map(function(b){a+='',a+=""}),a},_render:function(){this._root.innerHTML=this._html(),this._cellsElements=this._root.querySelectorAll("a"),this._bindEvents()},_bindEvents:function(){[].forEach.call(this._cellsElements,function(a){this._onMouseEnter(a),this._onClick(a)}.bind(this))},_onMouseEnter:function(a){var b,c=this;a.addEventListener("mouseenter",function(){clearTimeout(b);var a=this.dataset;b=setTimeout(function(){c._currentCell={column:parseInt(a.column,10),row:parseInt(a.row,10)},c.markCells()},50)})},_onClick:function(a){var b=this;a.addEventListener("click",function(a){a.preventDefault(),b._callback(this.dataset.row,this.dataset.column)})}},g.prototype={init:function(a){this.options=a,this._doc=a.ownerDocument||document,this._root=this._doc.createElement("div"),this._root.className="medium-editor-table-builder",this.grid=new f(this._root,this.options.onClick,this.options.rows,this.options.columns),this._range=null,this._toolbar=this._doc.createElement("div"),this._toolbar.className="medium-editor-table-builder-toolbar";var b=this._doc.createElement("span");b.innerHTML="Row:",this._toolbar.appendChild(b);var c=this._doc.createElement("button");c.title="Add row before",c.innerHTML='',c.onclick=this.addRow.bind(this,!0),this._toolbar.appendChild(c);var d=this._doc.createElement("button");d.title="Add row after",d.innerHTML='',d.onclick=this.addRow.bind(this,!1),this._toolbar.appendChild(d);var e=this._doc.createElement("button");e.title="Remove row",e.innerHTML='',e.onclick=this.removeRow.bind(this),this._toolbar.appendChild(e);var g=this._doc.createElement("span");g.innerHTML="Column:",this._toolbar.appendChild(g);var h=this._doc.createElement("button");h.title="Add column before",h.innerHTML='',h.onclick=this.addColumn.bind(this,!0),this._toolbar.appendChild(h);var i=this._doc.createElement("button");i.title="Add column after",i.innerHTML='',i.onclick=this.addColumn.bind(this,!1),this._toolbar.appendChild(i);var j=this._doc.createElement("button");j.title="Remove column",j.innerHTML='',j.onclick=this.removeColumn.bind(this),this._toolbar.appendChild(j);var k=this._doc.createElement("button");k.title="Remove table",k.innerHTML='',k.onclick=this.removeTable.bind(this),this._toolbar.appendChild(k);var l=this._root.childNodes[0];this._root.insertBefore(this._toolbar,l),console.log(this._root)},getElement:function(){return this._root},hide:function(){this._root.style.display="",this.grid.setCurrentCell({column:-1,row:-1}),this.grid.markCells()},show:function(a){this._root.style.display="block",this._root.style.left=a+"px"},setEditor:function(a){this._range=a,this._doc.getElementsByClassName("medium-editor-table-builder-toolbar")[0].style.display="block"},setBuilder:function(){this._range=null,this._doc.getElementsByClassName("medium-editor-table-builder-toolbar")[0].style.display="none";for(var a=this._doc.getElementsByClassName("medium-editor-table-builder-grid"),b=0;be;e++)c.childNodes[e].removeChild(c.childNodes[e].childNodes[b]);this.options.onClick(0,0)},removeTable:function(a){a.preventDefault(),a.stopPropagation();var b=(Array.prototype.indexOf.call(this._range.parentNode.childNodes,this._range),this._range.parentNode.parentNode.parentNode);b.parentNode.removeChild(b),this.options.onClick(0,0)}};var i=9;h.prototype={init:function(a){this._editor=a,this._doc=this._editor.options.ownerDocument,this._bindTabBehavior()},insert:function(a,b){var d=this._html(a,b);this._editor.pasteHTML(''+d+"
",{cleanAttrs:[],cleanTags:[]});var e=this._doc.getElementById("medium-editor-table");e.removeAttribute("id"),c(this._doc,e.querySelector("td"),!0),this._editor.checkSelection()},_html:function(b,c){var d,e,f="",g=a(this._doc);for(d=0;b>=d;d++){for(f+="",e=0;c>=e;e++)f+=""+(0===d&&0===e?g:"
")+"";f+=""}return f},_bindTabBehavior:function(){var a=this;[].forEach.call(this._editor.elements,function(b){b.addEventListener("keydown",function(b){a._onKeyDown(b)})})},_onKeyDown:function(a){var f,g=b(this._doc);a.which===i&&d(g,"table")&&(a.preventDefault(),a.stopPropagation(),f=this._getTableElements(g),a.shiftKey?this._tabBackwards(g.previousSibling,f.row):(this._isLastCell(g,f.row,f.root)&&this._insertRow(e(g,"tbody"),f.row.cells.length),c(this._doc,g)))},_getTableElements:function(a){return{cell:e(a,"td"),row:e(a,"tr"),root:e(a,"table")}},_tabBackwards:function(a,b){a=a||this._getPreviousRowLastCell(b),c(this._doc,a,!0)},_insertRow:function(a,b){var c,d=document.createElement("tr"),e="";for(c=0;b>c;c+=1)e+="
";d.innerHTML=e,a.appendChild(d)},_isLastCell:function(a,b,c){return b.cells.length-1===a.cellIndex&&c.rows.length-1===b.rowIndex},_getPreviousRowLastCell:function(a){return a=a.previousSibling,a?a.cells[a.cells.length-1]:void 0}};var j=MediumEditor.extensions.form.extend({name:"table",aria:"create table",action:"table",contentDefault:"TBL",contentFA:'',handleClick:function(a){a.preventDefault(),a.stopPropagation(),this[this.isActive()===!0?"hide":"show"]()},hide:function(){this.setInactive(),this.builder.hide()},show:function(){this.setActive();var a=MediumEditor.selection.getSelectionRange(this.document);"td"===a.startContainer.nodeName.toLowerCase()||"td"===a.endContainer.nodeName.toLowerCase()||MediumEditor.util.getClosestTag(MediumEditor.selection.getSelectedParentElement(a),"td")?this.builder.setEditor(MediumEditor.selection.getSelectedParentElement(a)):this.builder.setBuilder(),this.builder.show(this.button.offsetLeft)},getForm:function(){return this.builder=new g({onClick:function(a,b){a>0&&b>0&&this.table.insert(a,b),this.hide()}.bind(this),ownerDocument:this.document,rows:this.rows||10,columns:this.columns||10}),this.table=new h(this.base),this.builder.getElement()}});return j}()); \ No newline at end of file