假如你在写一个HTML所见即所得的编辑页面,一般考虑使用 Wang's Editor 或者 FCK Editor等第三方的编辑器,如果你实在不想用第三方的编辑器,又想扩展默认编辑器的表格编辑、IMG设置宽度高度等功能,请使用下面的代码:
在你的html head中,添加以下代码:
<script src="cm.js"></script>
把下面代码保存为一个 cm.js 文件,该脚本实现以下功能:
- 右击表格弹出菜单,可以在上方、下发插入行,或者在左边、右边插入列,设置表格列宽,删除行、删除列,设置表格自适应宽度等
- 双击img,可以弹出设置图片高度、宽度的对话框。用户输入像素,宽度百分比,或者输入(0~10)的浮点数可以自动按原图比例设置,例如 0.5 表示缩小一半,2表示原图两倍大小。
- 你可以扩展其他功能
document.addEventListener('contextmenu', function(event) {
if (!(event.target.tagName === 'TD' && event.target.closest('table'))) return;
event.preventDefault();
var contextMenu = document.createElement('div');
contextMenu.className = 'context-menu';
contextMenu.style.top = event.clientY + 'px';
contextMenu.style.left = event.clientX + 'px';
var menuItems = [
{ label: 'Insert Row Above', action: insertRowAbove},
{ label: 'Insert Row Below', action: insertRowBelow },
{ label: 'Insert Column Left', action: insertColumnLeft },
{ label: 'Insert Column Right', action: insertColumnRight },
{ label: 'Delete Current Row', action: deleteCurrentRow },
{ label: 'Delete Current Column', action: deleteCurrentColumn },
{ label: 'Set column width', action: setColumnWidth },
{ label: 'Set table auto size', action: setTableProperties }
];
menuItems.forEach(function(item) {
var menuItem = document.createElement('div');
menuItem.className = 'context-menu-item';
menuItem.innerText = item.label;
menuItem.addEventListener('click', function(e) {
item.action(e, menuItem, event.target.closest('table'), event.target.closest('td'));
});
contextMenu.appendChild(menuItem);
});
document.body.appendChild(contextMenu);
document.addEventListener('click', function() {
if (document.body.contains(contextMenu))
document.body.removeChild(contextMenu);
});
});
function insertRow(table, index) {
var len = table.rows[index >= table.rows.length ? 0 : index].cells.length;
var row = index >= table.rows.length ? table.insertRow() : table.insertRow(index);
for (var i=0; i< len; i++) {
row.insertCell().innerHTML = "<br/>";
}
}
function insertRowAbove(e, mi, table, cell) {
insertRow(table, cell.closest('tr').rowIndex);
}
function insertRowBelow(e, mi, table, cell) {
insertRow(table, cell.closest('tr').rowIndex + 1);
}
function insertColumn(table, index) {
for (var i=0; i<table.rows.length; i++) {
table.rows[i].insertCell(index).innerHTML = "<br/>";
}
}
function insertColumnLeft(e, mi, table, cell) {
insertColumn(table, cell.cellIndex);
}
function insertColumnRight(e, mi, table, cell) {
insertColumn(table, cell.cellIndex + 1);
}
function deleteCurrentRow(e, mi, table, cell) {
table.deleteRow(cell.closest('tr').rowIndex);
}
function setColumnWidth(e, mi, table, cell) {
var width = prompt("请输入列宽,例如 auto 或者 20% 或者 100px: ", cell.style.width)
for (var i = 0; i < table.rows.length; i++) {
table.rows[i].cells[cell.cellIndex].style.width = width;
}
}
function setTableProperties(e, mi, table, cell) {
table.style.width = table.style.width == "auto" ? "100%" : "auto"
}
function deleteCurrentColumn(e, mi, table, cell) {
var index = cell.cellIndex;
for (var i = 0; i < table.rows.length; i++) {
table.rows[i].deleteCell(index);
}
}
function isNumeric(str) {
var numberRegex = /^\d*\.?\d+$/;
return numberRegex.test(str);
}
document.addEventListener('dblclick', function(event) {
if (!(event.target.tagName === 'IMG')) return;
event.preventDefault();
var dialog = document.createElement('div');
dialog.className = 'image-dialog';
var widthInput = document.createElement('input');
widthInput.type = 'text';
widthInput.value = event.target.style.width;
widthInput.placeholder = '图像宽度,例如: 50px, 20%,0.5';
dialog.appendChild(widthInput);
var heightInput = document.createElement('input');
heightInput.type = 'text';
heightInput.value = event.target.style.height;
heightInput.placeholder = '图像宽度,例如: 50px, 20%,0.5';
dialog.appendChild(heightInput);
var okButton = document.createElement('button');
okButton.innerText = 'OK';
okButton.addEventListener('click', function() {
document.body.removeChild(dialog);
var sw = widthInput.value.trim();
event.target.style.width = isNumeric(sw) ? parseFloat(sw) * event.target.naturalWidth + 'px' : sw;
var sh = heightInput.value.trim();
event.target.style.height = isNumeric(sh) ? parseFloat(sh) * event.target.naturalHeight + 'px' : sh;
});
dialog.appendChild(okButton);
var cancelButton = document.createElement('button');
cancelButton.innerText = 'Cancel';
cancelButton.addEventListener('click', function() {
document.body.removeChild(dialog);
});
dialog.appendChild(cancelButton);
document.body.appendChild(dialog);
});
css 如下:
.context-menu {
position: absolute;
background: #fff;
border: 1px solid #ccc;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.context-menu-item {
padding: 8px;
cursor: pointer;
}
.context-menu-item:hover {
background: #f0f0f0;
}
.image-dialog {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
border: 1px solid #ccc;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.image-dialog input {
width: 100%;
padding: 10px;
margin-bottom: 10px;
box-sizing: border-box;
}
.image-dialog button {
display: block;
width: 100%;
margin-top: 5px;
padding: 10px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
.image-dialog button:hover {
background-color: #0056b3;
}