Created
September 6, 2011 17:30
-
-
Save iguigova/1198324 to your computer and use it in GitHub Desktop.
ExtJS HtmlEditor extension to work with tables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* Ext JS Library 3.2.1 | |
* Copyright(c) 2006-2010 Ext JS, Inc. | |
* licensing@extjs.com | |
* http://www.extjs.com/license | |
*/ | |
Ext.ns('Ext.ux.form'); | |
/** | |
* @class Ext.ux.form.HtmlTableEditor | |
* @extends Ext.form.HtmlTableEditor | |
* Creates an html editor with table management capability | |
* @xtype htmltableeditor | |
* @doc: http://dev.sencha.com/deploy/ext-3.3.1/docs/ | |
* @src: http://dev.sencha.com/deploy/ext-3.3.1/docs/source/HtmlEditor.html#cls-Ext.form.HtmlEditor | |
*/ | |
Ext.ux.form.HtmlTableEditor = Ext.extend(Ext.ux.form.HtmlLintEditor /*Ext.form.HtmlEditor */, { | |
initComponent : function(){ | |
Ext.ux.form.HtmlTableEditor.superclass.initComponent.call(this); | |
this.buttonTips.addtable = { | |
title: 'Add Table', | |
text: 'Add a new table.', | |
cls: 'x-html-editor-tip' | |
}; | |
this.buttonTips.addrow = { | |
title: 'Add Row', | |
text: 'Add a new row to the table.', | |
cls: 'x-html-editor-tip' | |
}; | |
this.buttonTips.deleterow = { | |
title: 'Delete Row', | |
text: 'Delete a row from the table.', | |
cls: 'x-html-editor-tip' | |
}; | |
this.buttonTips.addcol = { | |
title: 'Add Column', | |
text: 'Add a new column to the table.', | |
cls: 'x-html-editor-tip' | |
}; | |
this.buttonTips.deletecol = { | |
title: 'Delete Column', | |
text: 'Delete a column from the table.', | |
cls: 'x-html-editor-tip' | |
}; | |
this.on('initialize', function(editor){ | |
var cssLink = document.createElement("link") | |
cssLink.href = editor.cssHref || '/static/css/table.css'; | |
cssLink.rel = 'stylesheet'; | |
cssLink.type = 'text/css'; | |
editor.getEditorBody().appendChild(cssLink); | |
}); | |
}, | |
createToolbar : function(editor){ | |
Ext.ux.form.HtmlTableEditor.superclass.createToolbar.call(this, editor); | |
var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled(); | |
function btn(id, toggle, handler){ | |
return { | |
itemId : id, | |
cls : 'x-btn-icon', | |
iconCls: 'x-edit-'+id, | |
enableToggle: toggle !== false, | |
scope: editor, | |
handler:handler||editor.relayBtnCmd, | |
//clickEvent:'mousedown', | |
tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined, | |
overflowText: editor.buttonTips[id].title || undefined, | |
tabIndex:-1 | |
}; | |
} | |
editor.tb.add( | |
'->', | |
btn('addtable', false, editor.addTable), | |
btn('addrow', false, editor.addRow), | |
btn('deleterow', false, editor.deleteRow), | |
btn('addcol', false, editor.addCol), | |
btn('deletecol', false, editor.deleteCol) | |
); | |
editor.tb.doLayout(); | |
}, | |
select: function(selector){ | |
if (!editor.iframe) return; | |
return Ext.fly(editor.getEditorBody()).select(selector); | |
}, | |
getTableSelection: function(){ | |
var selection = this.getWin().getSelection(); | |
if (!selection){ | |
// TODO: select something | |
return; | |
} | |
var node = Ext.fly(selection.focusNode); | |
var cell = (node.is('td')) ? node : node.parent('td'); | |
if (cell) { | |
var row = cell.parent('tr'); | |
var table = row.parent('table'); | |
return {cell: cell.dom, row: row.dom, table: table.dom}; | |
} | |
}, | |
promptTableSelection: function(title, rowOrCell){ | |
if ((rowOrCell != 'row') && (rowOrCell != 'cell')) return; | |
var tableSelection = this.getTableSelection(); | |
if (tableSelection){ | |
var selectedIndex = tableSelection[rowOrCell][rowOrCell + 'Index']; | |
var newIndex = parseInt(prompt(title, selectedIndex)); | |
if (!isNaN(newIndex)){ | |
var maxIndex = (rowOrCell == 'row') ? tableSelection.table.rows.length : tableSelection.row.cells.length; | |
tableSelection.newIndex = Math.min(newIndex, maxIndex); | |
return tableSelection; | |
} | |
} | |
}, | |
resetCell: function(row, idx, insertOrDelete){ | |
if ((insertOrDelete != 'insert') && (insertOrDelete != 'delete')) return; | |
var cell = row[insertOrDelete + 'Cell'](idx); | |
if (cell){ | |
cell.innerHTML = ' '; | |
} | |
}, | |
resetCol: function(insertOrDelete){ | |
if ((insertOrDelete != 'insert') && (insertOrDelete != 'delete')) return; | |
var tableSelection = this.promptTableSelection('Choose column position: ', 'cell'); | |
if (tableSelection){ | |
var rows = tableSelection.table.rows; | |
var cellIndex = tableSelection.cell.cellIndex; | |
for (var i = 0, len = rows.length; i < len; i++){ | |
this.resetCell(rows[i], cellIndex, insertOrDelete); | |
} | |
} | |
}, | |
addCol: function(){ | |
this.resetCol('insert'); | |
}, | |
deleteCol: function(){ | |
this.resetCol('delete'); | |
}, | |
resetRow: function(insertOrDelete){ | |
if ((insertOrDelete != 'insert') && (insertOrDelete != 'delete')) return; | |
var tableSelection = this.promptTableSelection('Choose row position: ', 'row'); | |
if (tableSelection){ | |
var row = tableSelection.table[insertOrDelete + 'Row'](tableSelection.newIndex); | |
if (insertOrDelete == 'insert'){ | |
for (var i = 0, len = tableSelection.row.cells.length; i < len; i++){ | |
this.resetCell(row, -1, insertOrDelete); | |
} | |
} | |
} | |
}, | |
addRow: function(){ | |
this.resetRow('insert'); | |
}, | |
deleteRow: function(){ | |
this.resetRow('delete'); | |
}, | |
addTable : function() { | |
// src: http://www-archive.mozilla.org/editor/midasdemo/ | |
var doc = this.getDoc(); | |
rowstext = prompt("enter rows"); | |
colstext = prompt("enter cols"); | |
rows = parseInt(rowstext); | |
cols = parseInt(colstext); | |
if ((rows > 0) && (cols > 0)) { | |
var table = doc.createElement("table"); | |
table.className = 'template'; | |
table.setAttribute("border", "0"); | |
table.setAttribute("cellpadding", "0"); | |
table.setAttribute("cellspacing", "0"); | |
var tbody = doc.createElement("tbody"); | |
for (var i=0; i < rows; i++) { | |
var tr = doc.createElement("tr"); | |
for (var j=0; j < cols; j++) { | |
var td = doc.createElement("td"); | |
var br = doc.createElement("br"); | |
td.appendChild(br); | |
tr.appendChild(td); | |
} | |
tbody.appendChild(tr); | |
} | |
table.appendChild(tbody); | |
this.insertNodeAtSelection(this.getWin(), table); | |
} | |
}, | |
insertNodeAtSelection: function(win, insertNode) | |
{ | |
// get current selection | |
var sel = win.getSelection(); | |
// get the first range of the selection | |
// (there's almost always only one range) | |
var range = sel.getRangeAt(0); | |
// deselect everything | |
sel.removeAllRanges(); | |
// remove content of current selection from document | |
range.deleteContents(); | |
// get location of current selection | |
var container = range.startContainer; | |
var pos = range.startOffset; | |
// make a new range for the new selection | |
range = document.createRange(); | |
if (container.nodeType == 3 && insertNode.nodeType == 3) { | |
// if we insert text in a textnode, do optimized insertion | |
container.insertData(pos, insertNode.nodeValue); | |
// put cursor after inserted text | |
range.setEnd(container, pos+insertNode.length); | |
range.setStart(container, pos+insertNode.length); | |
} else { | |
var afterNode; | |
if (container.nodeType==3) { | |
// when inserting into a textnode | |
// we create 2 new textnodes | |
// and put the insertNode in between | |
var textNode = container; | |
container = textNode.parentNode; | |
var text = textNode.nodeValue; | |
// text before the split | |
var textBefore = text.substr(0,pos); | |
// text after the split | |
var textAfter = text.substr(pos); | |
var beforeNode = document.createTextNode(textBefore); | |
afterNode = document.createTextNode(textAfter); | |
// insert the 3 new nodes before the old one | |
container.insertBefore(afterNode, textNode); | |
container.insertBefore(insertNode, afterNode); | |
container.insertBefore(beforeNode, insertNode); | |
// remove the old node | |
container.removeChild(textNode); | |
} else { | |
// else simply insert the node | |
afterNode = container.childNodes[pos]; | |
container.insertBefore(insertNode, afterNode); | |
} | |
range.setEnd(afterNode, 0); | |
range.setStart(afterNode, 0); | |
} | |
sel.addRange(range); | |
} | |
}); | |
Ext.reg('htmltableeditor', Ext.ux.form.HtmlTableEditor); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment