PageSourceSearch

https://challenges.tekuoia.com/lib/redactor/plugins/table/table.js?v=8.8.81

js tekuoia.com collected 2026-09-29 09:38:44 UTC 14,149 bytes, 405 lines download raw bytes

1(function($R) {
2    $R.add('plugin', 'table', {
3        translations: {
4            en: {
5                "table": "Table",
6                "insert-table": "Insert table",
7                "insert-row-above": "Insert row above",
8                "insert-row-below": "Insert row below",
9                "insert-column-left": "Insert column left",
10                "insert-column-right": "Insert column right",
11                "add-head": "Add head",
12                "delete-head": "Delete head",
13                "delete-column": "Delete column",
14                "delete-row": "Delete row",
15                "delete-table": "Delete table"
16            }
17        },
18        init: function(app) {
19            this.app = app;
20            this.lang = app.lang;
21            this.opts = app.opts;
22            this.caret = app.caret;
23            this.editor = app.editor;
24            this.toolbar = app.toolbar;
25            this.component = app.component;
26            this.inspector = app.inspector;
27            this.insertion = app.insertion;
28            this.selection = app.selection;
29        },
30        // messages
31        ondropdown: {
32            table: {
33                observe: function(dropdown) {
34                    this._observeDropdown(dropdown);
35                }
36            }
37        },
38        onbottomclick: function() {
39            this.insertion.insertToEnd(this.editor.getLastNode(), 'table');
40        },
41
42        // public
43        start: function() {
44            var dropdown = {
45                observe: 'table',
46                'insert-table': {
47                    title: this.lang.get('insert-table'),
48                    api: 'plugin.table.insert'
49                },
50                'insert-row-above': {
51                    title: this.lang.get('insert-row-above'),
52                    classname: 'redactor-table-item-observable',
53                    api: 'plugin.table.addRowAbove'
54                },
55                'insert-row-below': {
56                    title: this.lang.get('insert-row-below'),
57                    classname: 'redactor-table-item-observable',
58                    api: 'plugin.table.addRowBelow'
59                },
60                'insert-column-left': {
61                    title: this.lang.get('insert-column-left'),
62                    classname: 'redactor-table-item-observable',
63                    api: 'plugin.table.addColumnLeft'
64                },
65                'insert-column-right': {
66                    title: this.lang.get('insert-column-right'),
67                    classname: 'redactor-table-item-observable',
68                    api: 'plugin.table.addColumnRight'
69                },
70                'add-head': {
71                    title: this.lang.get('add-head'),
72                    classname: 'redactor-table-item-observable',
73                    api: 'plugin.table.addHead'
74                },
75                'delete-head': {
76                    title: this.lang.get('delete-head'),
77                    classname: 'redactor-table-item-observable',
78                    api: 'plugin.table.deleteHead'
79                },
80                'delete-column': {
81                    title: this.lang.get('delete-column'),
82                    classname: 'redactor-table-item-observable',
83                    api: 'plugin.table.deleteColumn'
84                },
85                'delete-row': {
86                    title: this.lang.get('delete-row'),
87                    classname: 'redactor-table-item-observable',
88                    api: 'plugin.table.deleteRow'
89                },
90                'delete-table': {
91                    title: this.lang.get('delete-table'),
92                    classname: 'redactor-table-item-observable',
93                    api: 'plugin.table.deleteTable'
94                }
95            };
96            var obj = {
97                title: this.lang.get('table')
98            };
99
100            var $button = this.toolbar.addButtonBefore('link', 'table', obj);
101            $button.setIcon('<i aria-hidden="true" class="re-icon-table"></i>');
102            $button.setDropdown(dropdown);
103        },
104        insert: function() {
105            var rows = 2;
106            var columns = 3;
107            var $component = this.component.create('table');
108
109            for (var i = 0; i < rows; i++) {
110                $component.addRow(columns);
111            }
112
113            $component = this.insertion.insertHtml($component);
114            this.caret.setStart($component);
115        },
116        addRowAbove: function() {
117            var $component = this._getComponent();
118            if ($component) {
119                var current = this.selection.getCurrent();
120                var $row = $component.addRowTo(current, 'before');
121
122                this.caret.setStart($row);
123            }
124        },
125        addRowBelow: function() {
126            var $component = this._getComponent();
127            if ($component) {
128                var current = this.selection.getCurrent();
129                var $row = $component.addRowTo(current, 'after');
130
131                this.caret.setStart($row);
132            }
133        },
134        addColumnLeft: function() {
135            var $component = this._getComponent();
136            if ($component) {
137                var current = this.selection.getCurrent();
138
139                this.selection.save();
140                $component.addColumnTo(current, 'left');
141                this.selection.restore();
142            }
143        },
144        addColumnRight: function() {
145            var $component = this._getComponent();
146            if ($component) {
147                var current = this.selection.getCurrent();
148
149                this.selection.save();
150                $component.addColumnTo(current, 'right');
151                this.selection.restore();
152            }
153        },
154        addHead: function() {
155            var $component = this._getComponent();
156            if ($component) {
157                this.selection.save();
158                $component.addHead();
159                this.selection.restore();
160            }
161        },
162        deleteHead: function() {
163            var $component = this._getComponent();
164            if ($component) {
165                var current = this.selection.getCurrent();
166                var $head = $R.dom(current).closest('thead');
167                if ($head.length !== 0) {
168                    $component.removeHead();
169                    this.caret.setStart($component);
170                } else {
171                    this.selection.save();
172                    $component.removeHead();
173                    this.selection.restore();
174                }
175            }
176        },
177        deleteColumn: function() {
178            var $component = this._getComponent();
179            if ($component) {
180                var current = this.selection.getCurrent();
181
182                var $currentCell = $R.dom(current).closest('td, th');
183                var nextCell = $currentCell.nextElement().get();
184                var prevCell = $currentCell.prevElement().get();
185
186                $component.removeColumn(current);
187
188                if (nextCell) this.caret.setStart(nextCell);
189                else if (prevCell) this.caret.setEnd(prevCell);
190                else this.deleteTable();
191            }
192        },
193        deleteRow: function() {
194            var $component = this._getComponent();
195            if ($component) {
196                var current = this.selection.getCurrent();
197
198                var $currentRow = $R.dom(current).closest('tr');
199                var nextRow = $currentRow.nextElement().get();
200                var prevRow = $currentRow.prevElement().get();
201
202                $component.removeRow(current);
203
204                if (nextRow) this.caret.setStart(nextRow);
205                else if (prevRow) this.caret.setEnd(prevRow);
206                else this.deleteTable();
207            }
208        },
209        deleteTable: function() {
210            var table = this._getTable();
211            if (table) {
212                this.component.remove(table);
213            }
214        },
215
216        // private
217        _getTable: function() {
218            var current = this.selection.getCurrent();
219            var data = this.inspector.parse(current);
220            if (data.isTable()) {
221                return data.getTable();
222            }
223        },
224        _getComponent: function() {
225            var current = this.selection.getCurrent();
226            var data = this.inspector.parse(current);
227            if (data.isTable()) {
228                var table = data.getTable();
229
230                return this.component.create('table', table);
231            }
232        },
233        _observeDropdown: function(dropdown) {
234            var table = this._getTable();
235            var items = dropdown.getItemsByClass('redactor-table-item-observable');
236            var tableItem = dropdown.getItem('insert-table');
237            if (table) {
238                this._observeItems(items, 'enable');
239                tableItem.disable();
240            } else {
241                this._observeItems(items, 'disable');
242                tableItem.enable();
243            }
244        },
245        _observeItems: function(items, type) {
246            for (var i = 0; i < items.length; i++) {
247                items[i][type]();
248            }
249        }
250    });
251})(Redactor);
252(function($R) {
253    $R.add('class', 'table.component', {
254        mixins: ['dom', 'component'],
255        init: function(app, el) {
256            this.app = app;
257
258            // init
259            return (el && el.cmnt !== undefined) ? el : this._init(el);
260        },
261
262        // public
263        addHead: function() {
264            this.removeHead();
265
266            var columns = this.$element.find('tr').first().children('td, th').length;
267            var $head = $R.dom('<thead>');
268            var $row = this._buildRow(columns, '<th>');
269
270            $head.append($row);
271            this.$element.prepend($head);
272        },
273        addRow: function(columns) {
274            var $row = this._buildRow(columns);
275            this.$element.append($row);
276
277            return $row;
278        },
279        addRowTo: function(current, type) {
280            return this._addRowTo(current, type);
281        },
282        addColumnTo: function(current, type) {
283            var $current = $R.dom(current);
284            var $currentRow = $current.closest('tr');
285            var $currentCell = $current.closest('td, th');
286
287            var index = 0;
288            $currentRow.find('td, th').each(function(node, i) {
289                if (node === $currentCell.get()) index = i;
290            });
291
292            this.$element.find('tr').each(function(node) {
293                var $node = $R.dom(node);
294                var origCell = $node.find('td, th').get(index);
295                var $origCell = $R.dom(origCell);
296
297                var $td = $origCell.clone();
298                $td.html('<div data-redactor-tag="tbr"></div>');
299
300                if (type === 'right') $origCell.after($td);
301                else $origCell.before($td);
302            });
303        },
304        removeHead: function() {
305            var $head = this.$element.find('thead');
306            if ($head.length !== 0) $head.remove();
307        },
308        removeRow: function(current) {
309            var $current = $R.dom(current);
310            var $currentRow = $current.closest('tr');
311
312            $currentRow.remove();
313        },
314        removeColumn: function(current) {
315            var $current = $R.dom(current);
316            var $currentRow = $current.closest('tr');
317            var $currentCell = $current.closest('td, th');
318
319            var index = 0;
320            $currentRow.find('td, th').each(function(node, i) {
321                if (node === $currentCell.get()) index = i;
322            });
323
324            this.$element.find('tr').each(function(node) {
325                var $node = $R.dom(node);
326                var origCell = $node.find('td, th').get(index);
327                var $origCell = $R.dom(origCell);
328
329                $origCell.remove();
330            });
331        },
332
333        // private
334        _init: function(el) {
335            var wrapper, element;
336            if (typeof el !== 'undefined') {
337                var $node = $R.dom(el);
338                var node = $node.get();
339                var $figure = $node.closest('figure');
340                if ($figure.length !== 0) {
341                    wrapper = $figure;
342                    element = $figure.find('table').get();
343                } else if (node.tagName === 'TABLE') {
344                    element = node;
345                }
346            }
347
348            this._buildWrapper(wrapper);
349            this._buildElement(element);
350            this._initWrapper();
351        },
352        _addRowTo: function(current, position) {
353            var $current = $R.dom(current);
354            var $currentRow = $current.closest('tr');
355            if ($currentRow.length !== 0) {
356                var columns = $currentRow.children('td, th').length;
357                var $newRow = this._buildRow(columns);
358
359                $currentRow[position]($newRow);
360
361                return $newRow;
362            }
363        },
364        _buildRow: function(columns, tag) {
365            tag = tag || '<td>';
366
367            var $row = $R.dom('<tr>');
368            for (var i = 0; i < columns; i++) {
369                var $cell = $R.dom(tag);
370                $cell.attr('contenteditable', true);
371                $cell.html('<div data-redactor-tag="tbr"></div>');
372
373                $row.append($cell);
374            }
375
376            return $row;
377        },
378        _buildElement: function(node) {
379            if (node) {
380                this.$element = $R.dom(node);
381            } else {
382                this.$element = $R.dom('<table>');
383                this.append(this.$element);
384            }
385        },
386        _buildWrapper: function(node) {
387            node = node || '<figure>';
388
389            this.parse(node);
390        },
391        _initWrapper: function() {
392            this.addClass('redactor-component');
393            this.attr({
394                'data-redactor-type': 'table',
395                'tabindex': '-1',
396                'contenteditable': false
397            });
398
399            if (this.app.detector.isIe()) {
400                this.removeAttr('contenteditable');
401            }
402        }
403    });
404
405})(Redactor);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.