wysihtml-rails 0.5.5 → 0.6.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -6
- data/lib/wysihtml/rails/version.rb +1 -1
- data/vendor/assets/javascripts/wysihtml.js +5944 -8553
- data/vendor/assets/javascripts/wysihtml/all_commands.js +23 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/alignCenterStyle.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/alignJustifyStyle.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/alignLeftStyle.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/alignRightStyle.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/bgColorStyle.js +48 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/bold.js +16 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/command_formatCode.js +52 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/command_insertImage.js +108 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/fontSize.js +13 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/fontSizeStyle.js +35 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/foreColor.js +13 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/foreColorStyle.js +52 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/insertBlockQuote.js +16 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/insertOrderedList.js +11 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/insertUnorderedList.js +11 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/italic.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/justifyCenter.js +18 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/justifyFull.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/justifyLeft.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/justifyRight.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/subscript.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/superscript.js +17 -0
- data/vendor/assets/javascripts/wysihtml/extra_commands/underline.js +17 -0
- data/vendor/assets/javascripts/{parser_rules → wysihtml/parser_rules}/advanced.js +4 -4
- data/vendor/assets/javascripts/{parser_rules → wysihtml/parser_rules}/advanced_and_extended.js +25 -25
- data/vendor/assets/javascripts/{parser_rules → wysihtml/parser_rules}/advanced_unwrap.js +5 -5
- data/vendor/assets/javascripts/{parser_rules → wysihtml/parser_rules}/simple.js +2 -2
- data/vendor/assets/javascripts/wysihtml/table_editing.js +1163 -0
- data/vendor/assets/javascripts/wysihtml/toolbar.js +850 -0
- metadata +35 -9
- data/vendor/assets/javascripts/wysihtml-toolbar.js +0 -19308
@@ -0,0 +1,1163 @@
|
|
1
|
+
wysihtml.commands.addTableCells = {
|
2
|
+
exec: function(composer, command, value) {
|
3
|
+
if (composer.tableSelection && composer.tableSelection.start && composer.tableSelection.end) {
|
4
|
+
|
5
|
+
// switches start and end if start is bigger than end (reverse selection)
|
6
|
+
var tableSelect = wysihtml.dom.table.orderSelectionEnds(composer.tableSelection.start, composer.tableSelection.end);
|
7
|
+
if (value == 'before' || value == 'above') {
|
8
|
+
wysihtml.dom.table.addCells(tableSelect.start, value);
|
9
|
+
} else if (value == 'after' || value == 'below') {
|
10
|
+
wysihtml.dom.table.addCells(tableSelect.end, value);
|
11
|
+
}
|
12
|
+
setTimeout(function() {
|
13
|
+
composer.tableSelection.select(tableSelect.start, tableSelect.end);
|
14
|
+
},0);
|
15
|
+
}
|
16
|
+
},
|
17
|
+
|
18
|
+
state: function(composer, command) {
|
19
|
+
return false;
|
20
|
+
}
|
21
|
+
};
|
22
|
+
|
23
|
+
wysihtml.commands.createTable = {
|
24
|
+
exec: function(composer, command, value) {
|
25
|
+
var col, row, html;
|
26
|
+
if (value && value.cols && value.rows && parseInt(value.cols, 10) > 0 && parseInt(value.rows, 10) > 0) {
|
27
|
+
if (value.tableStyle) {
|
28
|
+
html = '<table style="' + value.tableStyle + '">';
|
29
|
+
} else {
|
30
|
+
html = '<table>';
|
31
|
+
}
|
32
|
+
html += '<tbody>';
|
33
|
+
for (row = 0; row < value.rows; row ++) {
|
34
|
+
html += '<tr>';
|
35
|
+
for (col = 0; col < value.cols; col ++) {
|
36
|
+
html += '<td><br></td>';
|
37
|
+
}
|
38
|
+
html += '</tr>';
|
39
|
+
}
|
40
|
+
html += '</tbody></table>';
|
41
|
+
composer.commands.exec('insertHTML', html);
|
42
|
+
}
|
43
|
+
},
|
44
|
+
|
45
|
+
state: function(composer, command) {
|
46
|
+
return false;
|
47
|
+
}
|
48
|
+
};
|
49
|
+
|
50
|
+
wysihtml.commands.deleteTableCells = {
|
51
|
+
exec: function(composer, command, value) {
|
52
|
+
if (composer.tableSelection && composer.tableSelection.start && composer.tableSelection.end) {
|
53
|
+
var tableSelect = wysihtml.dom.table.orderSelectionEnds(composer.tableSelection.start, composer.tableSelection.end),
|
54
|
+
idx = wysihtml.dom.table.indexOf(tableSelect.start),
|
55
|
+
selCell,
|
56
|
+
table = composer.tableSelection.table;
|
57
|
+
|
58
|
+
wysihtml.dom.table.removeCells(tableSelect.start, value);
|
59
|
+
setTimeout(function() {
|
60
|
+
// move selection to next or previous if not present
|
61
|
+
selCell = wysihtml.dom.table.findCell(table, idx);
|
62
|
+
|
63
|
+
if (!selCell) {
|
64
|
+
if (value == 'row') {
|
65
|
+
selCell = wysihtml.dom.table.findCell(table, {
|
66
|
+
'row': idx.row - 1,
|
67
|
+
'col': idx.col
|
68
|
+
});
|
69
|
+
}
|
70
|
+
|
71
|
+
if (value == 'column') {
|
72
|
+
selCell = wysihtml.dom.table.findCell(table, {
|
73
|
+
'row': idx.row,
|
74
|
+
'col': idx.col - 1
|
75
|
+
});
|
76
|
+
}
|
77
|
+
}
|
78
|
+
if (selCell) {
|
79
|
+
composer.tableSelection.select(selCell, selCell);
|
80
|
+
}
|
81
|
+
}, 0);
|
82
|
+
}
|
83
|
+
},
|
84
|
+
|
85
|
+
state: function(composer, command) {
|
86
|
+
return false;
|
87
|
+
}
|
88
|
+
};
|
89
|
+
|
90
|
+
wysihtml.commands.mergeTableCells = {
|
91
|
+
exec: function(composer, command) {
|
92
|
+
if (composer.tableSelection && composer.tableSelection.start && composer.tableSelection.end) {
|
93
|
+
if (this.state(composer, command)) {
|
94
|
+
wysihtml.dom.table.unmergeCell(composer.tableSelection.start);
|
95
|
+
} else {
|
96
|
+
wysihtml.dom.table.mergeCellsBetween(composer.tableSelection.start, composer.tableSelection.end);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
},
|
100
|
+
|
101
|
+
state: function(composer, command) {
|
102
|
+
if (composer.tableSelection) {
|
103
|
+
var start = composer.tableSelection.start,
|
104
|
+
end = composer.tableSelection.end;
|
105
|
+
if (start && end && start == end &&
|
106
|
+
((
|
107
|
+
wysihtml.dom.getAttribute(start, 'colspan') &&
|
108
|
+
parseInt(wysihtml.dom.getAttribute(start, 'colspan'), 10) > 1
|
109
|
+
) || (
|
110
|
+
wysihtml.dom.getAttribute(start, 'rowspan') &&
|
111
|
+
parseInt(wysihtml.dom.getAttribute(start, 'rowspan'), 10) > 1
|
112
|
+
))
|
113
|
+
) {
|
114
|
+
return [start];
|
115
|
+
}
|
116
|
+
}
|
117
|
+
return false;
|
118
|
+
}
|
119
|
+
};
|
120
|
+
|
121
|
+
(function() {
|
122
|
+
|
123
|
+
var api = wysihtml.dom;
|
124
|
+
|
125
|
+
var MapCell = function(cell) {
|
126
|
+
this.el = cell;
|
127
|
+
this.isColspan= false;
|
128
|
+
this.isRowspan= false;
|
129
|
+
this.firstCol= true;
|
130
|
+
this.lastCol= true;
|
131
|
+
this.firstRow= true;
|
132
|
+
this.lastRow= true;
|
133
|
+
this.isReal= true;
|
134
|
+
this.spanCollection= [];
|
135
|
+
this.modified = false;
|
136
|
+
};
|
137
|
+
|
138
|
+
var TableModifyerByCell = function (cell, table) {
|
139
|
+
if (cell) {
|
140
|
+
this.cell = cell;
|
141
|
+
this.table = api.getParentElement(cell, { query: "table" });
|
142
|
+
} else if (table) {
|
143
|
+
this.table = table;
|
144
|
+
this.cell = this.table.querySelectorAll('th, td')[0];
|
145
|
+
}
|
146
|
+
};
|
147
|
+
|
148
|
+
function queryInList(list, query) {
|
149
|
+
var ret = [],
|
150
|
+
q;
|
151
|
+
for (var e = 0, len = list.length; e < len; e++) {
|
152
|
+
q = list[e].querySelectorAll(query);
|
153
|
+
if (q) {
|
154
|
+
for(var i = q.length; i--; ret.unshift(q[i]));
|
155
|
+
}
|
156
|
+
}
|
157
|
+
return ret;
|
158
|
+
}
|
159
|
+
|
160
|
+
function removeElement(el) {
|
161
|
+
el.parentNode.removeChild(el);
|
162
|
+
}
|
163
|
+
|
164
|
+
function insertAfter(referenceNode, newNode) {
|
165
|
+
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
|
166
|
+
}
|
167
|
+
|
168
|
+
function nextNode(node, tag) {
|
169
|
+
var element = node.nextSibling;
|
170
|
+
while (element.nodeType !=1) {
|
171
|
+
element = element.nextSibling;
|
172
|
+
if (!tag || tag == element.tagName.toLowerCase()) {
|
173
|
+
return element;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
return null;
|
177
|
+
}
|
178
|
+
|
179
|
+
TableModifyerByCell.prototype = {
|
180
|
+
|
181
|
+
addSpannedCellToMap: function(cell, map, r, c, cspan, rspan) {
|
182
|
+
var spanCollect = [],
|
183
|
+
rmax = r + ((rspan) ? parseInt(rspan, 10) - 1 : 0),
|
184
|
+
cmax = c + ((cspan) ? parseInt(cspan, 10) - 1 : 0);
|
185
|
+
|
186
|
+
for (var rr = r; rr <= rmax; rr++) {
|
187
|
+
if (typeof map[rr] == "undefined") { map[rr] = []; }
|
188
|
+
for (var cc = c; cc <= cmax; cc++) {
|
189
|
+
map[rr][cc] = new MapCell(cell);
|
190
|
+
map[rr][cc].isColspan = (cspan && parseInt(cspan, 10) > 1);
|
191
|
+
map[rr][cc].isRowspan = (rspan && parseInt(rspan, 10) > 1);
|
192
|
+
map[rr][cc].firstCol = cc == c;
|
193
|
+
map[rr][cc].lastCol = cc == cmax;
|
194
|
+
map[rr][cc].firstRow = rr == r;
|
195
|
+
map[rr][cc].lastRow = rr == rmax;
|
196
|
+
map[rr][cc].isReal = cc == c && rr == r;
|
197
|
+
map[rr][cc].spanCollection = spanCollect;
|
198
|
+
|
199
|
+
spanCollect.push(map[rr][cc]);
|
200
|
+
}
|
201
|
+
}
|
202
|
+
},
|
203
|
+
|
204
|
+
setCellAsModified: function(cell) {
|
205
|
+
cell.modified = true;
|
206
|
+
if (cell.spanCollection.length > 0) {
|
207
|
+
for (var s = 0, smax = cell.spanCollection.length; s < smax; s++) {
|
208
|
+
cell.spanCollection[s].modified = true;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
},
|
212
|
+
|
213
|
+
setTableMap: function() {
|
214
|
+
var map = [];
|
215
|
+
var tableRows = this.getTableRows(),
|
216
|
+
ridx, row, cells, cidx, cell,
|
217
|
+
c,
|
218
|
+
cspan, rspan;
|
219
|
+
|
220
|
+
for (ridx = 0; ridx < tableRows.length; ridx++) {
|
221
|
+
row = tableRows[ridx];
|
222
|
+
cells = this.getRowCells(row);
|
223
|
+
c = 0;
|
224
|
+
if (typeof map[ridx] == "undefined") { map[ridx] = []; }
|
225
|
+
for (cidx = 0; cidx < cells.length; cidx++) {
|
226
|
+
cell = cells[cidx];
|
227
|
+
|
228
|
+
// If cell allready set means it is set by col or rowspan,
|
229
|
+
// so increase cols index until free col is found
|
230
|
+
while (typeof map[ridx][c] != "undefined") { c++; }
|
231
|
+
|
232
|
+
cspan = api.getAttribute(cell, 'colspan');
|
233
|
+
rspan = api.getAttribute(cell, 'rowspan');
|
234
|
+
|
235
|
+
if (cspan || rspan) {
|
236
|
+
this.addSpannedCellToMap(cell, map, ridx, c, cspan, rspan);
|
237
|
+
c = c + ((cspan) ? parseInt(cspan, 10) : 1);
|
238
|
+
} else {
|
239
|
+
map[ridx][c] = new MapCell(cell);
|
240
|
+
c++;
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
this.map = map;
|
245
|
+
return map;
|
246
|
+
},
|
247
|
+
|
248
|
+
getRowCells: function(row) {
|
249
|
+
var inlineTables = this.table.querySelectorAll('table'),
|
250
|
+
inlineCells = (inlineTables) ? queryInList(inlineTables, 'th, td') : [],
|
251
|
+
allCells = row.querySelectorAll('th, td'),
|
252
|
+
tableCells = (inlineCells.length > 0) ? wysihtml.lang.array(allCells).without(inlineCells) : allCells;
|
253
|
+
|
254
|
+
return tableCells;
|
255
|
+
},
|
256
|
+
|
257
|
+
getTableRows: function() {
|
258
|
+
var inlineTables = this.table.querySelectorAll('table'),
|
259
|
+
inlineRows = (inlineTables) ? queryInList(inlineTables, 'tr') : [],
|
260
|
+
allRows = this.table.querySelectorAll('tr'),
|
261
|
+
tableRows = (inlineRows.length > 0) ? wysihtml.lang.array(allRows).without(inlineRows) : allRows;
|
262
|
+
|
263
|
+
return tableRows;
|
264
|
+
},
|
265
|
+
|
266
|
+
getMapIndex: function(cell) {
|
267
|
+
var r_length = this.map.length,
|
268
|
+
c_length = (this.map && this.map[0]) ? this.map[0].length : 0;
|
269
|
+
|
270
|
+
for (var r_idx = 0;r_idx < r_length; r_idx++) {
|
271
|
+
for (var c_idx = 0;c_idx < c_length; c_idx++) {
|
272
|
+
if (this.map[r_idx][c_idx].el === cell) {
|
273
|
+
return {'row': r_idx, 'col': c_idx};
|
274
|
+
}
|
275
|
+
}
|
276
|
+
}
|
277
|
+
return false;
|
278
|
+
},
|
279
|
+
|
280
|
+
getElementAtIndex: function(idx) {
|
281
|
+
this.setTableMap();
|
282
|
+
if (this.map[idx.row] && this.map[idx.row][idx.col] && this.map[idx.row][idx.col].el) {
|
283
|
+
return this.map[idx.row][idx.col].el;
|
284
|
+
}
|
285
|
+
return null;
|
286
|
+
},
|
287
|
+
|
288
|
+
getMapElsTo: function(to_cell) {
|
289
|
+
var els = [];
|
290
|
+
this.setTableMap();
|
291
|
+
this.idx_start = this.getMapIndex(this.cell);
|
292
|
+
this.idx_end = this.getMapIndex(to_cell);
|
293
|
+
|
294
|
+
// switch indexes if start is bigger than end
|
295
|
+
if (this.idx_start.row > this.idx_end.row || (this.idx_start.row == this.idx_end.row && this.idx_start.col > this.idx_end.col)) {
|
296
|
+
var temp_idx = this.idx_start;
|
297
|
+
this.idx_start = this.idx_end;
|
298
|
+
this.idx_end = temp_idx;
|
299
|
+
}
|
300
|
+
if (this.idx_start.col > this.idx_end.col) {
|
301
|
+
var temp_cidx = this.idx_start.col;
|
302
|
+
this.idx_start.col = this.idx_end.col;
|
303
|
+
this.idx_end.col = temp_cidx;
|
304
|
+
}
|
305
|
+
|
306
|
+
if (this.idx_start != null && this.idx_end != null) {
|
307
|
+
for (var row = this.idx_start.row, maxr = this.idx_end.row; row <= maxr; row++) {
|
308
|
+
for (var col = this.idx_start.col, maxc = this.idx_end.col; col <= maxc; col++) {
|
309
|
+
els.push(this.map[row][col].el);
|
310
|
+
}
|
311
|
+
}
|
312
|
+
}
|
313
|
+
return els;
|
314
|
+
},
|
315
|
+
|
316
|
+
orderSelectionEnds: function(secondcell) {
|
317
|
+
this.setTableMap();
|
318
|
+
this.idx_start = this.getMapIndex(this.cell);
|
319
|
+
this.idx_end = this.getMapIndex(secondcell);
|
320
|
+
|
321
|
+
// switch indexes if start is bigger than end
|
322
|
+
if (this.idx_start.row > this.idx_end.row || (this.idx_start.row == this.idx_end.row && this.idx_start.col > this.idx_end.col)) {
|
323
|
+
var temp_idx = this.idx_start;
|
324
|
+
this.idx_start = this.idx_end;
|
325
|
+
this.idx_end = temp_idx;
|
326
|
+
}
|
327
|
+
if (this.idx_start.col > this.idx_end.col) {
|
328
|
+
var temp_cidx = this.idx_start.col;
|
329
|
+
this.idx_start.col = this.idx_end.col;
|
330
|
+
this.idx_end.col = temp_cidx;
|
331
|
+
}
|
332
|
+
|
333
|
+
return {
|
334
|
+
"start": this.map[this.idx_start.row][this.idx_start.col].el,
|
335
|
+
"end": this.map[this.idx_end.row][this.idx_end.col].el
|
336
|
+
};
|
337
|
+
},
|
338
|
+
|
339
|
+
createCells: function(tag, nr, attrs) {
|
340
|
+
var doc = this.table.ownerDocument,
|
341
|
+
frag = doc.createDocumentFragment(),
|
342
|
+
cell;
|
343
|
+
for (var i = 0; i < nr; i++) {
|
344
|
+
cell = doc.createElement(tag);
|
345
|
+
|
346
|
+
if (attrs) {
|
347
|
+
for (var attr in attrs) {
|
348
|
+
if (attrs.hasOwnProperty(attr)) {
|
349
|
+
cell.setAttribute(attr, attrs[attr]);
|
350
|
+
}
|
351
|
+
}
|
352
|
+
}
|
353
|
+
|
354
|
+
// add non breaking space
|
355
|
+
cell.appendChild(document.createTextNode("\u00a0"));
|
356
|
+
frag.appendChild(cell);
|
357
|
+
}
|
358
|
+
return frag;
|
359
|
+
},
|
360
|
+
|
361
|
+
// Returns next real cell (not part of spanned cell unless first) on row if selected index is not real. I no real cells -1 will be returned
|
362
|
+
correctColIndexForUnreals: function(col, row) {
|
363
|
+
var r = this.map[row],
|
364
|
+
corrIdx = -1;
|
365
|
+
for (var i = 0, max = col; i < col; i++) {
|
366
|
+
if (r[i].isReal){
|
367
|
+
corrIdx++;
|
368
|
+
}
|
369
|
+
}
|
370
|
+
return corrIdx;
|
371
|
+
},
|
372
|
+
|
373
|
+
getLastNewCellOnRow: function(row, rowLimit) {
|
374
|
+
var cells = this.getRowCells(row),
|
375
|
+
cell, idx;
|
376
|
+
|
377
|
+
for (var cidx = 0, cmax = cells.length; cidx < cmax; cidx++) {
|
378
|
+
cell = cells[cidx];
|
379
|
+
idx = this.getMapIndex(cell);
|
380
|
+
if (idx === false || (typeof rowLimit != "undefined" && idx.row != rowLimit)) {
|
381
|
+
return cell;
|
382
|
+
}
|
383
|
+
}
|
384
|
+
return null;
|
385
|
+
},
|
386
|
+
|
387
|
+
removeEmptyTable: function() {
|
388
|
+
var cells = this.table.querySelectorAll('td, th');
|
389
|
+
if (!cells || cells.length == 0) {
|
390
|
+
removeElement(this.table);
|
391
|
+
return true;
|
392
|
+
} else {
|
393
|
+
return false;
|
394
|
+
}
|
395
|
+
},
|
396
|
+
|
397
|
+
// Splits merged cell on row to unique cells
|
398
|
+
splitRowToCells: function(cell) {
|
399
|
+
if (cell.isColspan) {
|
400
|
+
var colspan = parseInt(api.getAttribute(cell.el, 'colspan') || 1, 10),
|
401
|
+
cType = cell.el.tagName.toLowerCase();
|
402
|
+
if (colspan > 1) {
|
403
|
+
var newCells = this.createCells(cType, colspan -1);
|
404
|
+
insertAfter(cell.el, newCells);
|
405
|
+
}
|
406
|
+
cell.el.removeAttribute('colspan');
|
407
|
+
}
|
408
|
+
},
|
409
|
+
|
410
|
+
getRealRowEl: function(force, idx) {
|
411
|
+
var r = null,
|
412
|
+
c = null;
|
413
|
+
|
414
|
+
idx = idx || this.idx;
|
415
|
+
|
416
|
+
for (var cidx = 0, cmax = this.map[idx.row].length; cidx < cmax; cidx++) {
|
417
|
+
c = this.map[idx.row][cidx];
|
418
|
+
if (c.isReal) {
|
419
|
+
r = api.getParentElement(c.el, { query: "tr" });
|
420
|
+
if (r) {
|
421
|
+
return r;
|
422
|
+
}
|
423
|
+
}
|
424
|
+
}
|
425
|
+
|
426
|
+
if (r === null && force) {
|
427
|
+
r = api.getParentElement(this.map[idx.row][idx.col].el, { query: "tr" }) || null;
|
428
|
+
}
|
429
|
+
|
430
|
+
return r;
|
431
|
+
},
|
432
|
+
|
433
|
+
injectRowAt: function(row, col, colspan, cType, c) {
|
434
|
+
var r = this.getRealRowEl(false, {'row': row, 'col': col}),
|
435
|
+
new_cells = this.createCells(cType, colspan);
|
436
|
+
|
437
|
+
if (r) {
|
438
|
+
var n_cidx = this.correctColIndexForUnreals(col, row);
|
439
|
+
if (n_cidx >= 0) {
|
440
|
+
insertAfter(this.getRowCells(r)[n_cidx], new_cells);
|
441
|
+
} else {
|
442
|
+
r.insertBefore(new_cells, r.firstChild);
|
443
|
+
}
|
444
|
+
} else {
|
445
|
+
var rr = this.table.ownerDocument.createElement('tr');
|
446
|
+
rr.appendChild(new_cells);
|
447
|
+
insertAfter(api.getParentElement(c.el, { query: "tr" }), rr);
|
448
|
+
}
|
449
|
+
},
|
450
|
+
|
451
|
+
canMerge: function(to) {
|
452
|
+
this.to = to;
|
453
|
+
this.setTableMap();
|
454
|
+
this.idx_start = this.getMapIndex(this.cell);
|
455
|
+
this.idx_end = this.getMapIndex(this.to);
|
456
|
+
|
457
|
+
// switch indexes if start is bigger than end
|
458
|
+
if (this.idx_start.row > this.idx_end.row || (this.idx_start.row == this.idx_end.row && this.idx_start.col > this.idx_end.col)) {
|
459
|
+
var temp_idx = this.idx_start;
|
460
|
+
this.idx_start = this.idx_end;
|
461
|
+
this.idx_end = temp_idx;
|
462
|
+
}
|
463
|
+
if (this.idx_start.col > this.idx_end.col) {
|
464
|
+
var temp_cidx = this.idx_start.col;
|
465
|
+
this.idx_start.col = this.idx_end.col;
|
466
|
+
this.idx_end.col = temp_cidx;
|
467
|
+
}
|
468
|
+
|
469
|
+
for (var row = this.idx_start.row, maxr = this.idx_end.row; row <= maxr; row++) {
|
470
|
+
for (var col = this.idx_start.col, maxc = this.idx_end.col; col <= maxc; col++) {
|
471
|
+
if (this.map[row][col].isColspan || this.map[row][col].isRowspan) {
|
472
|
+
return false;
|
473
|
+
}
|
474
|
+
}
|
475
|
+
}
|
476
|
+
return true;
|
477
|
+
},
|
478
|
+
|
479
|
+
decreaseCellSpan: function(cell, span) {
|
480
|
+
var nr = parseInt(api.getAttribute(cell.el, span), 10) - 1;
|
481
|
+
if (nr >= 1) {
|
482
|
+
cell.el.setAttribute(span, nr);
|
483
|
+
} else {
|
484
|
+
cell.el.removeAttribute(span);
|
485
|
+
if (span == 'colspan') {
|
486
|
+
cell.isColspan = false;
|
487
|
+
}
|
488
|
+
if (span == 'rowspan') {
|
489
|
+
cell.isRowspan = false;
|
490
|
+
}
|
491
|
+
cell.firstCol = true;
|
492
|
+
cell.lastCol = true;
|
493
|
+
cell.firstRow = true;
|
494
|
+
cell.lastRow = true;
|
495
|
+
cell.isReal = true;
|
496
|
+
}
|
497
|
+
},
|
498
|
+
|
499
|
+
removeSurplusLines: function() {
|
500
|
+
var row, cell, ridx, rmax, cidx, cmax, allRowspan;
|
501
|
+
|
502
|
+
this.setTableMap();
|
503
|
+
if (this.map) {
|
504
|
+
ridx = 0;
|
505
|
+
rmax = this.map.length;
|
506
|
+
for (;ridx < rmax; ridx++) {
|
507
|
+
row = this.map[ridx];
|
508
|
+
allRowspan = true;
|
509
|
+
cidx = 0;
|
510
|
+
cmax = row.length;
|
511
|
+
for (; cidx < cmax; cidx++) {
|
512
|
+
cell = row[cidx];
|
513
|
+
if (!(api.getAttribute(cell.el, "rowspan") && parseInt(api.getAttribute(cell.el, "rowspan"), 10) > 1 && cell.firstRow !== true)) {
|
514
|
+
allRowspan = false;
|
515
|
+
break;
|
516
|
+
}
|
517
|
+
}
|
518
|
+
if (allRowspan) {
|
519
|
+
cidx = 0;
|
520
|
+
for (; cidx < cmax; cidx++) {
|
521
|
+
this.decreaseCellSpan(row[cidx], 'rowspan');
|
522
|
+
}
|
523
|
+
}
|
524
|
+
}
|
525
|
+
|
526
|
+
// remove rows without cells
|
527
|
+
var tableRows = this.getTableRows();
|
528
|
+
ridx = 0;
|
529
|
+
rmax = tableRows.length;
|
530
|
+
for (;ridx < rmax; ridx++) {
|
531
|
+
row = tableRows[ridx];
|
532
|
+
if (row.childNodes.length == 0 && (/^\s*$/.test(row.textContent || row.innerText))) {
|
533
|
+
removeElement(row);
|
534
|
+
}
|
535
|
+
}
|
536
|
+
}
|
537
|
+
},
|
538
|
+
|
539
|
+
fillMissingCells: function() {
|
540
|
+
var r_max = 0,
|
541
|
+
c_max = 0,
|
542
|
+
prevcell = null;
|
543
|
+
|
544
|
+
this.setTableMap();
|
545
|
+
if (this.map) {
|
546
|
+
|
547
|
+
// find maximal dimensions of broken table
|
548
|
+
r_max = this.map.length;
|
549
|
+
for (var ridx = 0; ridx < r_max; ridx++) {
|
550
|
+
if (this.map[ridx].length > c_max) { c_max = this.map[ridx].length; }
|
551
|
+
}
|
552
|
+
|
553
|
+
for (var row = 0; row < r_max; row++) {
|
554
|
+
for (var col = 0; col < c_max; col++) {
|
555
|
+
if (this.map[row] && !this.map[row][col]) {
|
556
|
+
if (col > 0) {
|
557
|
+
this.map[row][col] = new MapCell(this.createCells('td', 1));
|
558
|
+
prevcell = this.map[row][col-1];
|
559
|
+
if (prevcell && prevcell.el && prevcell.el.parent) { // if parent does not exist element is removed from dom
|
560
|
+
insertAfter(this.map[row][col-1].el, this.map[row][col].el);
|
561
|
+
}
|
562
|
+
}
|
563
|
+
}
|
564
|
+
}
|
565
|
+
}
|
566
|
+
}
|
567
|
+
},
|
568
|
+
|
569
|
+
rectify: function() {
|
570
|
+
if (!this.removeEmptyTable()) {
|
571
|
+
this.removeSurplusLines();
|
572
|
+
this.fillMissingCells();
|
573
|
+
return true;
|
574
|
+
} else {
|
575
|
+
return false;
|
576
|
+
}
|
577
|
+
},
|
578
|
+
|
579
|
+
unmerge: function() {
|
580
|
+
if (this.rectify()) {
|
581
|
+
this.setTableMap();
|
582
|
+
this.idx = this.getMapIndex(this.cell);
|
583
|
+
|
584
|
+
if (this.idx) {
|
585
|
+
var thisCell = this.map[this.idx.row][this.idx.col],
|
586
|
+
colspan = (api.getAttribute(thisCell.el, "colspan")) ? parseInt(api.getAttribute(thisCell.el, "colspan"), 10) : 1,
|
587
|
+
cType = thisCell.el.tagName.toLowerCase();
|
588
|
+
|
589
|
+
if (thisCell.isRowspan) {
|
590
|
+
var rowspan = parseInt(api.getAttribute(thisCell.el, "rowspan"), 10);
|
591
|
+
if (rowspan > 1) {
|
592
|
+
for (var nr = 1, maxr = rowspan - 1; nr <= maxr; nr++){
|
593
|
+
this.injectRowAt(this.idx.row + nr, this.idx.col, colspan, cType, thisCell);
|
594
|
+
}
|
595
|
+
}
|
596
|
+
thisCell.el.removeAttribute('rowspan');
|
597
|
+
}
|
598
|
+
this.splitRowToCells(thisCell);
|
599
|
+
}
|
600
|
+
}
|
601
|
+
},
|
602
|
+
|
603
|
+
// merges cells from start cell (defined in creating obj) to "to" cell
|
604
|
+
merge: function(to) {
|
605
|
+
if (this.rectify()) {
|
606
|
+
if (this.canMerge(to)) {
|
607
|
+
var rowspan = this.idx_end.row - this.idx_start.row + 1,
|
608
|
+
colspan = this.idx_end.col - this.idx_start.col + 1;
|
609
|
+
|
610
|
+
for (var row = this.idx_start.row, maxr = this.idx_end.row; row <= maxr; row++) {
|
611
|
+
for (var col = this.idx_start.col, maxc = this.idx_end.col; col <= maxc; col++) {
|
612
|
+
|
613
|
+
if (row == this.idx_start.row && col == this.idx_start.col) {
|
614
|
+
if (rowspan > 1) {
|
615
|
+
this.map[row][col].el.setAttribute('rowspan', rowspan);
|
616
|
+
}
|
617
|
+
if (colspan > 1) {
|
618
|
+
this.map[row][col].el.setAttribute('colspan', colspan);
|
619
|
+
}
|
620
|
+
} else {
|
621
|
+
// transfer content
|
622
|
+
if (!(/^\s*<br\/?>\s*$/.test(this.map[row][col].el.innerHTML.toLowerCase()))) {
|
623
|
+
this.map[this.idx_start.row][this.idx_start.col].el.innerHTML += ' ' + this.map[row][col].el.innerHTML;
|
624
|
+
}
|
625
|
+
removeElement(this.map[row][col].el);
|
626
|
+
}
|
627
|
+
|
628
|
+
}
|
629
|
+
}
|
630
|
+
this.rectify();
|
631
|
+
} else {
|
632
|
+
if (window.console) {
|
633
|
+
console.log('Do not know how to merge allready merged cells.');
|
634
|
+
}
|
635
|
+
}
|
636
|
+
}
|
637
|
+
},
|
638
|
+
|
639
|
+
// Decreases rowspan of a cell if it is done on first cell of rowspan row (real cell)
|
640
|
+
// Cell is moved to next row (if it is real)
|
641
|
+
collapseCellToNextRow: function(cell) {
|
642
|
+
var cellIdx = this.getMapIndex(cell.el),
|
643
|
+
newRowIdx = cellIdx.row + 1,
|
644
|
+
newIdx = {'row': newRowIdx, 'col': cellIdx.col};
|
645
|
+
|
646
|
+
if (newRowIdx < this.map.length) {
|
647
|
+
|
648
|
+
var row = this.getRealRowEl(false, newIdx);
|
649
|
+
if (row !== null) {
|
650
|
+
var n_cidx = this.correctColIndexForUnreals(newIdx.col, newIdx.row);
|
651
|
+
if (n_cidx >= 0) {
|
652
|
+
insertAfter(this.getRowCells(row)[n_cidx], cell.el);
|
653
|
+
} else {
|
654
|
+
var lastCell = this.getLastNewCellOnRow(row, newRowIdx);
|
655
|
+
if (lastCell !== null) {
|
656
|
+
insertAfter(lastCell, cell.el);
|
657
|
+
} else {
|
658
|
+
row.insertBefore(cell.el, row.firstChild);
|
659
|
+
}
|
660
|
+
}
|
661
|
+
if (parseInt(api.getAttribute(cell.el, 'rowspan'), 10) > 2) {
|
662
|
+
cell.el.setAttribute('rowspan', parseInt(api.getAttribute(cell.el, 'rowspan'), 10) - 1);
|
663
|
+
} else {
|
664
|
+
cell.el.removeAttribute('rowspan');
|
665
|
+
}
|
666
|
+
}
|
667
|
+
}
|
668
|
+
},
|
669
|
+
|
670
|
+
// Removes a cell when removing a row
|
671
|
+
// If is rowspan cell then decreases the rowspan
|
672
|
+
// and moves cell to next row if needed (is first cell of rowspan)
|
673
|
+
removeRowCell: function(cell) {
|
674
|
+
if (cell.isReal) {
|
675
|
+
if (cell.isRowspan) {
|
676
|
+
this.collapseCellToNextRow(cell);
|
677
|
+
} else {
|
678
|
+
removeElement(cell.el);
|
679
|
+
}
|
680
|
+
} else {
|
681
|
+
if (parseInt(api.getAttribute(cell.el, 'rowspan'), 10) > 2) {
|
682
|
+
cell.el.setAttribute('rowspan', parseInt(api.getAttribute(cell.el, 'rowspan'), 10) - 1);
|
683
|
+
} else {
|
684
|
+
cell.el.removeAttribute('rowspan');
|
685
|
+
}
|
686
|
+
}
|
687
|
+
},
|
688
|
+
|
689
|
+
getRowElementsByCell: function() {
|
690
|
+
var cells = [];
|
691
|
+
this.setTableMap();
|
692
|
+
this.idx = this.getMapIndex(this.cell);
|
693
|
+
if (this.idx !== false) {
|
694
|
+
var modRow = this.map[this.idx.row];
|
695
|
+
for (var cidx = 0, cmax = modRow.length; cidx < cmax; cidx++) {
|
696
|
+
if (modRow[cidx].isReal) {
|
697
|
+
cells.push(modRow[cidx].el);
|
698
|
+
}
|
699
|
+
}
|
700
|
+
}
|
701
|
+
return cells;
|
702
|
+
},
|
703
|
+
|
704
|
+
getColumnElementsByCell: function() {
|
705
|
+
var cells = [];
|
706
|
+
this.setTableMap();
|
707
|
+
this.idx = this.getMapIndex(this.cell);
|
708
|
+
if (this.idx !== false) {
|
709
|
+
for (var ridx = 0, rmax = this.map.length; ridx < rmax; ridx++) {
|
710
|
+
if (this.map[ridx][this.idx.col] && this.map[ridx][this.idx.col].isReal) {
|
711
|
+
cells.push(this.map[ridx][this.idx.col].el);
|
712
|
+
}
|
713
|
+
}
|
714
|
+
}
|
715
|
+
return cells;
|
716
|
+
},
|
717
|
+
|
718
|
+
// Removes the row of selected cell
|
719
|
+
removeRow: function() {
|
720
|
+
var oldRow = api.getParentElement(this.cell, { query: "tr" });
|
721
|
+
if (oldRow) {
|
722
|
+
this.setTableMap();
|
723
|
+
this.idx = this.getMapIndex(this.cell);
|
724
|
+
if (this.idx !== false) {
|
725
|
+
var modRow = this.map[this.idx.row];
|
726
|
+
for (var cidx = 0, cmax = modRow.length; cidx < cmax; cidx++) {
|
727
|
+
if (!modRow[cidx].modified) {
|
728
|
+
this.setCellAsModified(modRow[cidx]);
|
729
|
+
this.removeRowCell(modRow[cidx]);
|
730
|
+
}
|
731
|
+
}
|
732
|
+
}
|
733
|
+
removeElement(oldRow);
|
734
|
+
}
|
735
|
+
},
|
736
|
+
|
737
|
+
removeColCell: function(cell) {
|
738
|
+
if (cell.isColspan) {
|
739
|
+
if (parseInt(api.getAttribute(cell.el, 'colspan'), 10) > 2) {
|
740
|
+
cell.el.setAttribute('colspan', parseInt(api.getAttribute(cell.el, 'colspan'), 10) - 1);
|
741
|
+
} else {
|
742
|
+
cell.el.removeAttribute('colspan');
|
743
|
+
}
|
744
|
+
} else if (cell.isReal) {
|
745
|
+
removeElement(cell.el);
|
746
|
+
}
|
747
|
+
},
|
748
|
+
|
749
|
+
removeColumn: function() {
|
750
|
+
this.setTableMap();
|
751
|
+
this.idx = this.getMapIndex(this.cell);
|
752
|
+
if (this.idx !== false) {
|
753
|
+
for (var ridx = 0, rmax = this.map.length; ridx < rmax; ridx++) {
|
754
|
+
if (!this.map[ridx][this.idx.col].modified) {
|
755
|
+
this.setCellAsModified(this.map[ridx][this.idx.col]);
|
756
|
+
this.removeColCell(this.map[ridx][this.idx.col]);
|
757
|
+
}
|
758
|
+
}
|
759
|
+
}
|
760
|
+
},
|
761
|
+
|
762
|
+
// removes row or column by selected cell element
|
763
|
+
remove: function(what) {
|
764
|
+
if (this.rectify()) {
|
765
|
+
switch (what) {
|
766
|
+
case 'row':
|
767
|
+
this.removeRow();
|
768
|
+
break;
|
769
|
+
case 'column':
|
770
|
+
this.removeColumn();
|
771
|
+
break;
|
772
|
+
}
|
773
|
+
this.rectify();
|
774
|
+
}
|
775
|
+
},
|
776
|
+
|
777
|
+
addRow: function(where) {
|
778
|
+
var doc = this.table.ownerDocument;
|
779
|
+
|
780
|
+
this.setTableMap();
|
781
|
+
this.idx = this.getMapIndex(this.cell);
|
782
|
+
if (where == "below" && api.getAttribute(this.cell, 'rowspan')) {
|
783
|
+
this.idx.row = this.idx.row + parseInt(api.getAttribute(this.cell, 'rowspan'), 10) - 1;
|
784
|
+
}
|
785
|
+
|
786
|
+
if (this.idx !== false) {
|
787
|
+
var modRow = this.map[this.idx.row],
|
788
|
+
newRow = doc.createElement('tr');
|
789
|
+
|
790
|
+
for (var ridx = 0, rmax = modRow.length; ridx < rmax; ridx++) {
|
791
|
+
if (!modRow[ridx].modified) {
|
792
|
+
this.setCellAsModified(modRow[ridx]);
|
793
|
+
this.addRowCell(modRow[ridx], newRow, where);
|
794
|
+
}
|
795
|
+
}
|
796
|
+
|
797
|
+
switch (where) {
|
798
|
+
case 'below':
|
799
|
+
insertAfter(this.getRealRowEl(true), newRow);
|
800
|
+
break;
|
801
|
+
case 'above':
|
802
|
+
var cr = api.getParentElement(this.map[this.idx.row][this.idx.col].el, { query: "tr" });
|
803
|
+
if (cr) {
|
804
|
+
cr.parentNode.insertBefore(newRow, cr);
|
805
|
+
}
|
806
|
+
break;
|
807
|
+
}
|
808
|
+
}
|
809
|
+
},
|
810
|
+
|
811
|
+
addRowCell: function(cell, row, where) {
|
812
|
+
var colSpanAttr = (cell.isColspan) ? {"colspan" : api.getAttribute(cell.el, 'colspan')} : null;
|
813
|
+
if (cell.isReal) {
|
814
|
+
if (where != 'above' && cell.isRowspan) {
|
815
|
+
cell.el.setAttribute('rowspan', parseInt(api.getAttribute(cell.el,'rowspan'), 10) + 1);
|
816
|
+
} else {
|
817
|
+
row.appendChild(this.createCells('td', 1, colSpanAttr));
|
818
|
+
}
|
819
|
+
} else {
|
820
|
+
if (where != 'above' && cell.isRowspan && cell.lastRow) {
|
821
|
+
row.appendChild(this.createCells('td', 1, colSpanAttr));
|
822
|
+
} else if (c.isRowspan) {
|
823
|
+
cell.el.attr('rowspan', parseInt(api.getAttribute(cell.el, 'rowspan'), 10) + 1);
|
824
|
+
}
|
825
|
+
}
|
826
|
+
},
|
827
|
+
|
828
|
+
add: function(where) {
|
829
|
+
if (this.rectify()) {
|
830
|
+
if (where == 'below' || where == 'above') {
|
831
|
+
this.addRow(where);
|
832
|
+
}
|
833
|
+
if (where == 'before' || where == 'after') {
|
834
|
+
this.addColumn(where);
|
835
|
+
}
|
836
|
+
}
|
837
|
+
},
|
838
|
+
|
839
|
+
addColCell: function (cell, ridx, where) {
|
840
|
+
var doAdd,
|
841
|
+
cType = cell.el.tagName.toLowerCase();
|
842
|
+
|
843
|
+
// defines add cell vs expand cell conditions
|
844
|
+
// true means add
|
845
|
+
switch (where) {
|
846
|
+
case "before":
|
847
|
+
doAdd = (!cell.isColspan || cell.firstCol);
|
848
|
+
break;
|
849
|
+
case "after":
|
850
|
+
doAdd = (!cell.isColspan || cell.lastCol || (cell.isColspan && cell.el == this.cell));
|
851
|
+
break;
|
852
|
+
}
|
853
|
+
|
854
|
+
if (doAdd){
|
855
|
+
// adds a cell before or after current cell element
|
856
|
+
switch (where) {
|
857
|
+
case "before":
|
858
|
+
cell.el.parentNode.insertBefore(this.createCells(cType, 1), cell.el);
|
859
|
+
break;
|
860
|
+
case "after":
|
861
|
+
insertAfter(cell.el, this.createCells(cType, 1));
|
862
|
+
break;
|
863
|
+
}
|
864
|
+
|
865
|
+
// handles if cell has rowspan
|
866
|
+
if (cell.isRowspan) {
|
867
|
+
this.handleCellAddWithRowspan(cell, ridx+1, where);
|
868
|
+
}
|
869
|
+
|
870
|
+
} else {
|
871
|
+
// expands cell
|
872
|
+
cell.el.setAttribute('colspan', parseInt(api.getAttribute(cell.el, 'colspan'), 10) + 1);
|
873
|
+
}
|
874
|
+
},
|
875
|
+
|
876
|
+
addColumn: function(where) {
|
877
|
+
var row, modCell;
|
878
|
+
|
879
|
+
this.setTableMap();
|
880
|
+
this.idx = this.getMapIndex(this.cell);
|
881
|
+
if (where == "after" && api.getAttribute(this.cell, 'colspan')) {
|
882
|
+
this.idx.col = this.idx.col + parseInt(api.getAttribute(this.cell, 'colspan'), 10) - 1;
|
883
|
+
}
|
884
|
+
|
885
|
+
if (this.idx !== false) {
|
886
|
+
for (var ridx = 0, rmax = this.map.length; ridx < rmax; ridx++ ) {
|
887
|
+
row = this.map[ridx];
|
888
|
+
if (row[this.idx.col]) {
|
889
|
+
modCell = row[this.idx.col];
|
890
|
+
if (!modCell.modified) {
|
891
|
+
this.setCellAsModified(modCell);
|
892
|
+
this.addColCell(modCell, ridx , where);
|
893
|
+
}
|
894
|
+
}
|
895
|
+
}
|
896
|
+
}
|
897
|
+
},
|
898
|
+
|
899
|
+
handleCellAddWithRowspan: function (cell, ridx, where) {
|
900
|
+
var addRowsNr = parseInt(api.getAttribute(this.cell, 'rowspan'), 10) - 1,
|
901
|
+
crow = api.getParentElement(cell.el, { query: "tr" }),
|
902
|
+
cType = cell.el.tagName.toLowerCase(),
|
903
|
+
cidx, temp_r_cells,
|
904
|
+
doc = this.table.ownerDocument,
|
905
|
+
nrow;
|
906
|
+
|
907
|
+
for (var i = 0; i < addRowsNr; i++) {
|
908
|
+
cidx = this.correctColIndexForUnreals(this.idx.col, (ridx + i));
|
909
|
+
crow = nextNode(crow, 'tr');
|
910
|
+
if (crow) {
|
911
|
+
if (cidx > 0) {
|
912
|
+
switch (where) {
|
913
|
+
case "before":
|
914
|
+
temp_r_cells = this.getRowCells(crow);
|
915
|
+
if (cidx > 0 && this.map[ridx + i][this.idx.col].el != temp_r_cells[cidx] && cidx == temp_r_cells.length - 1) {
|
916
|
+
insertAfter(temp_r_cells[cidx], this.createCells(cType, 1));
|
917
|
+
} else {
|
918
|
+
temp_r_cells[cidx].parentNode.insertBefore(this.createCells(cType, 1), temp_r_cells[cidx]);
|
919
|
+
}
|
920
|
+
|
921
|
+
break;
|
922
|
+
case "after":
|
923
|
+
insertAfter(this.getRowCells(crow)[cidx], this.createCells(cType, 1));
|
924
|
+
break;
|
925
|
+
}
|
926
|
+
} else {
|
927
|
+
crow.insertBefore(this.createCells(cType, 1), crow.firstChild);
|
928
|
+
}
|
929
|
+
} else {
|
930
|
+
nrow = doc.createElement('tr');
|
931
|
+
nrow.appendChild(this.createCells(cType, 1));
|
932
|
+
this.table.appendChild(nrow);
|
933
|
+
}
|
934
|
+
}
|
935
|
+
}
|
936
|
+
};
|
937
|
+
|
938
|
+
api.table = {
|
939
|
+
getCellsBetween: function(cell1, cell2) {
|
940
|
+
var c1 = new TableModifyerByCell(cell1);
|
941
|
+
return c1.getMapElsTo(cell2);
|
942
|
+
},
|
943
|
+
|
944
|
+
addCells: function(cell, where) {
|
945
|
+
var c = new TableModifyerByCell(cell);
|
946
|
+
c.add(where);
|
947
|
+
},
|
948
|
+
|
949
|
+
removeCells: function(cell, what) {
|
950
|
+
var c = new TableModifyerByCell(cell);
|
951
|
+
c.remove(what);
|
952
|
+
},
|
953
|
+
|
954
|
+
mergeCellsBetween: function(cell1, cell2) {
|
955
|
+
var c1 = new TableModifyerByCell(cell1);
|
956
|
+
c1.merge(cell2);
|
957
|
+
},
|
958
|
+
|
959
|
+
unmergeCell: function(cell) {
|
960
|
+
var c = new TableModifyerByCell(cell);
|
961
|
+
c.unmerge();
|
962
|
+
},
|
963
|
+
|
964
|
+
orderSelectionEnds: function(cell, cell2) {
|
965
|
+
var c = new TableModifyerByCell(cell);
|
966
|
+
return c.orderSelectionEnds(cell2);
|
967
|
+
},
|
968
|
+
|
969
|
+
indexOf: function(cell) {
|
970
|
+
var c = new TableModifyerByCell(cell);
|
971
|
+
c.setTableMap();
|
972
|
+
return c.getMapIndex(cell);
|
973
|
+
},
|
974
|
+
|
975
|
+
findCell: function(table, idx) {
|
976
|
+
var c = new TableModifyerByCell(null, table);
|
977
|
+
return c.getElementAtIndex(idx);
|
978
|
+
},
|
979
|
+
|
980
|
+
findRowByCell: function(cell) {
|
981
|
+
var c = new TableModifyerByCell(cell);
|
982
|
+
return c.getRowElementsByCell();
|
983
|
+
},
|
984
|
+
|
985
|
+
findColumnByCell: function(cell) {
|
986
|
+
var c = new TableModifyerByCell(cell);
|
987
|
+
return c.getColumnElementsByCell();
|
988
|
+
},
|
989
|
+
|
990
|
+
canMerge: function(cell1, cell2) {
|
991
|
+
var c = new TableModifyerByCell(cell1);
|
992
|
+
return c.canMerge(cell2);
|
993
|
+
}
|
994
|
+
};
|
995
|
+
|
996
|
+
})();
|
997
|
+
|
998
|
+
(function() {
|
999
|
+
|
1000
|
+
// Keep the old composer.observe function.
|
1001
|
+
var oldObserverFunction = wysihtml.views.Composer.prototype.observe;
|
1002
|
+
|
1003
|
+
var extendedObserverFunction = function() {
|
1004
|
+
oldObserverFunction.call(this);
|
1005
|
+
// Bind the table user interaction tracking
|
1006
|
+
if (this.config.handleTables) {
|
1007
|
+
// If handleTables option is true, table handling functions are bound
|
1008
|
+
initTableHandling.call(this);
|
1009
|
+
}
|
1010
|
+
};
|
1011
|
+
|
1012
|
+
// Table management.
|
1013
|
+
// If present enableObjectResizing and enableInlineTableEditing command
|
1014
|
+
// should be called with false to prevent native table handlers.
|
1015
|
+
var initTableHandling = function() {
|
1016
|
+
var hideHandlers = function() {
|
1017
|
+
this.win.removeEventListener('load', hideHandlers);
|
1018
|
+
this.doc.execCommand('enableObjectResizing', false, 'false');
|
1019
|
+
this.doc.execCommand('enableInlineTableEditing', false, 'false');
|
1020
|
+
}.bind(this),
|
1021
|
+
iframeInitiator = (function() {
|
1022
|
+
hideHandlers.call(this);
|
1023
|
+
actions.removeListeners(this.sandbox.getIframe(), ['focus', 'mouseup', 'mouseover'], iframeInitiator);
|
1024
|
+
}).bind(this);
|
1025
|
+
|
1026
|
+
if (
|
1027
|
+
this.doc.execCommand &&
|
1028
|
+
wysihtml.browser.supportsCommand(this.doc, 'enableObjectResizing') &&
|
1029
|
+
wysihtml.browser.supportsCommand(this.doc, 'enableInlineTableEditing')
|
1030
|
+
) {
|
1031
|
+
if (this.sandbox.getIframe) {
|
1032
|
+
actions.addListeners(this.sandbox.getIframe(), ['focus', 'mouseup', 'mouseover'], iframeInitiator);
|
1033
|
+
} else {
|
1034
|
+
this.win.addEventListener('load', hideHandlers);
|
1035
|
+
}
|
1036
|
+
}
|
1037
|
+
this.tableSelection = wysihtml.quirks.tableCellsSelection(this.element, this.parent);
|
1038
|
+
};
|
1039
|
+
|
1040
|
+
// Cell selections handling
|
1041
|
+
var tableCellsSelection = function(editable, editor) {
|
1042
|
+
|
1043
|
+
var init = function() {
|
1044
|
+
editable.addEventListener('mousedown', handleMouseDown);
|
1045
|
+
return select;
|
1046
|
+
};
|
1047
|
+
|
1048
|
+
var handleMouseDown = function(event) {
|
1049
|
+
var target = wysihtml.dom.getParentElement(event.target, {query: 'td, th'}, false, editable);
|
1050
|
+
if (target) {
|
1051
|
+
handleSelectionMousedown(target);
|
1052
|
+
}
|
1053
|
+
};
|
1054
|
+
|
1055
|
+
var handleSelectionMousedown = function(target) {
|
1056
|
+
select.start = target;
|
1057
|
+
select.end = target;
|
1058
|
+
select.cells = [target];
|
1059
|
+
select.table = dom.getParentElement(select.start, {query: 'table'}, false, editable);
|
1060
|
+
|
1061
|
+
if (select.table) {
|
1062
|
+
removeCellSelections();
|
1063
|
+
dom.addClass(target, selectionClass);
|
1064
|
+
editable.addEventListener('mousemove', handleMouseMove);
|
1065
|
+
editable.addEventListener('mouseup', handleMouseUp);
|
1066
|
+
editor.fire('tableselectstart').fire('tableselectstart:composer');
|
1067
|
+
}
|
1068
|
+
};
|
1069
|
+
|
1070
|
+
// remove all selection classes
|
1071
|
+
var removeCellSelections = function() {
|
1072
|
+
if (editable) {
|
1073
|
+
var selectedCells = editable.querySelectorAll('.' + selectionClass);
|
1074
|
+
if (selectedCells.length > 0) {
|
1075
|
+
for (var i = 0; i < selectedCells.length; i++) {
|
1076
|
+
dom.removeClass(selectedCells[i], selectionClass);
|
1077
|
+
}
|
1078
|
+
}
|
1079
|
+
}
|
1080
|
+
};
|
1081
|
+
|
1082
|
+
var addSelections = function(cells) {
|
1083
|
+
for (var i = 0; i < cells.length; i++) {
|
1084
|
+
dom.addClass(cells[i], selectionClass);
|
1085
|
+
}
|
1086
|
+
};
|
1087
|
+
|
1088
|
+
var handleMouseMove = function(event) {
|
1089
|
+
var curTable = null,
|
1090
|
+
cell = dom.getParentElement(event.target, {query: 'td, th'}, false, editable),
|
1091
|
+
oldEnd;
|
1092
|
+
|
1093
|
+
if (cell && select.table && select.start) {
|
1094
|
+
curTable = dom.getParentElement(cell, {query: 'table'}, false, editable);
|
1095
|
+
if (curTable && curTable === select.table) {
|
1096
|
+
removeCellSelections();
|
1097
|
+
oldEnd = select.end;
|
1098
|
+
select.end = cell;
|
1099
|
+
select.cells = dom.table.getCellsBetween(select.start, cell);
|
1100
|
+
if (select.cells.length > 1) {
|
1101
|
+
editor.composer.selection.deselect();
|
1102
|
+
}
|
1103
|
+
addSelections(select.cells);
|
1104
|
+
if (select.end !== oldEnd) {
|
1105
|
+
editor.fire('tableselectchange').fire('tableselectchange:composer');
|
1106
|
+
}
|
1107
|
+
}
|
1108
|
+
}
|
1109
|
+
};
|
1110
|
+
|
1111
|
+
var handleMouseUp = function(event) {
|
1112
|
+
editable.removeEventListener('mousemove', handleMouseMove);
|
1113
|
+
editable.removeEventListener('mouseup', handleMouseUp);
|
1114
|
+
editor.fire('tableselect').fire('tableselect:composer');
|
1115
|
+
setTimeout(function() {
|
1116
|
+
bindSideclick();
|
1117
|
+
}, 0);
|
1118
|
+
};
|
1119
|
+
|
1120
|
+
var sideClickHandler = function(event) {
|
1121
|
+
editable.ownerDocument.removeEventListener('click', sideClickHandler);
|
1122
|
+
if (dom.getParentElement(event.target, {query: 'table'}, false, editable) != select.table) {
|
1123
|
+
removeCellSelections();
|
1124
|
+
select.table = null;
|
1125
|
+
select.start = null;
|
1126
|
+
select.end = null;
|
1127
|
+
editor.fire('tableunselect').fire('tableunselect:composer');
|
1128
|
+
}
|
1129
|
+
};
|
1130
|
+
|
1131
|
+
var bindSideclick = function() {
|
1132
|
+
editable.ownerDocument.addEventListener('click', sideClickHandler);
|
1133
|
+
};
|
1134
|
+
|
1135
|
+
var selectCells = function(start, end) {
|
1136
|
+
select.start = start;
|
1137
|
+
select.end = end;
|
1138
|
+
select.table = dom.getParentElement(select.start, {query: 'table'}, false, editable);
|
1139
|
+
selectedCells = dom.table.getCellsBetween(select.start, select.end);
|
1140
|
+
addSelections(selectedCells);
|
1141
|
+
bindSideclick();
|
1142
|
+
editor.fire('tableselect').fire('tableselect:composer');
|
1143
|
+
};
|
1144
|
+
|
1145
|
+
var dom = wysihtml.dom,
|
1146
|
+
select = {
|
1147
|
+
table: null,
|
1148
|
+
start: null,
|
1149
|
+
end: null,
|
1150
|
+
cells: null,
|
1151
|
+
select: selectCells
|
1152
|
+
},
|
1153
|
+
selectionClass = 'wysiwyg-tmp-selected-cell';
|
1154
|
+
|
1155
|
+
return init();
|
1156
|
+
};
|
1157
|
+
|
1158
|
+
// Bind to wysihtml
|
1159
|
+
wysihtml.Editor.prototype.defaults.handleTables = true;
|
1160
|
+
wysihtml.quirks.tableCellsSelection = tableCellsSelection;
|
1161
|
+
wysihtml.views.Composer.prototype.observe = extendedObserverFunction;
|
1162
|
+
|
1163
|
+
})();
|