我有一个contenteditable div和一个combobx,可以在其上应用各种字体大小。
我已经完成了javascript实现,用于更改所选文本的字体大小,但不知道如何为下一个用户输入设置字体大小。
例如,
1) 在内容可编辑的div中,用户首先选择字体大小,然后开始键入,然后应将选定的fontsize应用于用户输入文本。
2)用户输入了文字"你好"现在他将字体大小更改为24px并键入" world"然后说'世界"字体大小应为24像素。
下面是带有javascript代码的HTML页面,用于在所选文本上应用字体大小。
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function GetNextLeaf (node) {
while (!node.nextSibling) {
node = node.parentNode;
if (!node) {
return node;
}
}
var leaf = node.nextSibling;
while (leaf.firstChild) {
leaf = leaf.firstChild;
}
return leaf;
}
function GetPreviousLeaf (node) {
while (!node.previousSibling) {
node = node.parentNode;
if (!node) {
return node;
}
}
var leaf = node.previousSibling;
while (leaf.lastChild) {
leaf = leaf.lastChild;
}
return leaf;
}
// If the text content of an element contains white-spaces only, then does not need to colorize
function IsTextVisible (text) {
for (var i = 0; i < text.length; i++) {
if (text[i] != ' ' && text[i] != '\t' && text[i] != '\r' && text[i] != '\n')
return true;
}
return false;
}
function ColorizeLeaf (node, size) {
if (!IsTextVisible (node.textContent))
return;
var parentNode = node.parentNode;
// if the node does not have siblings and the parent is a span element, then modify its color
if (!node.previousSibling && !node.nextSibling) {
if (parentNode.tagName.toLowerCase () == "span") {
//parentNode.style.color = color;
parentNode.style.fontSize = size+"px";
return;
}
}
// Create a span element around the node
var span = document.createElement("span");
//span.style.color = color;
span.style.fontSize = size + "px";
var nextSibling = node.nextSibling;
parentNode.removeChild (node);
span.appendChild (node);
parentNode.insertBefore (span, nextSibling);
}
function ColorizeLeafFromTo (node, size, from, to) {
var text = node.textContent;
if (!IsTextVisible (text))
return;
if (from < 0)
from = 0;
if (to < 0)
to = text.length;
if (from == 0 && to >= text.length) {
// to avoid unnecessary span elements
ColorizeLeaf(node, size);
return;
}
var part1 = text.substring (0, from);
var part2 = text.substring (from, to);
var part3 = text.substring (to, text.length);
var parentNode = node.parentNode;
var nextSibling = node.nextSibling;
parentNode.removeChild (node);
if (part1.length > 0) {
var textNode = document.createTextNode (part1);
parentNode.insertBefore (textNode, nextSibling);
}
if (part2.length > 0) {
var span = document.createElement ("span");
//span.style.color = color;
span.style.fontSize = size+"px";
var textNode = document.createTextNode (part2);
span.appendChild (textNode);
parentNode.insertBefore (span, nextSibling);
}
if (part3.length > 0) {
var textNode = document.createTextNode (part3);
parentNode.insertBefore (textNode, nextSibling);
}
}
function ColorizeNode (node, size) {
var childNode = node.firstChild;
if (!childNode) {
ColorizeLeaf(node, size);
return;
}
while (childNode) {
// store the next sibling of the childNode, because colorizing modifies the DOM structure
var nextSibling = childNode.nextSibling;
ColorizeNode(childNode, size);
childNode = nextSibling;
}
}
function ColorizeNodeFromTo(node, size, from, to) {
var childNode = node.firstChild;
if (!childNode) {
ColorizeLeafFromTo(node, size, from, to);
return;
}
for (var i = from; i < to; i++) {
ColorizeNode(node.childNodes[i], size);
}
}
function ColorizeSelection(size) {
if (window.getSelection) { // all browsers, except IE before version 9
var selectionRange = window.getSelection ();
if (selectionRange.isCollapsed) {
// no idea on how to apply font size here. at cursor point.
}
else {
var range = selectionRange.getRangeAt (0);
// store the start and end points of the current selection, because the selection will be removed
var startContainer = range.startContainer;
var startOffset = range.startOffset;
var endContainer = range.endContainer;
var endOffset = range.endOffset;
// because of Opera, we need to remove the selection before modifying the DOM hierarchy
selectionRange.removeAllRanges ();
if (startContainer == endContainer) {
ColorizeNodeFromTo(startContainer, size, startOffset, endOffset);
}
else {
if (startContainer.firstChild) {
var startLeaf = startContainer.childNodes[startOffset];
}
else {
var startLeaf = GetNextLeaf (startContainer);
ColorizeLeafFromTo(startContainer, size, startOffset, -1);
}
if (endContainer.firstChild) {
if (endOffset > 0) {
var endLeaf = endContainer.childNodes[endOffset - 1];
}
else {
var endLeaf = GetPreviousLeaf (endContainer);
}
}
else {
var endLeaf = GetPreviousLeaf (endContainer);
ColorizeLeafFromTo(endContainer, size, 0, endOffset);
}
while (startLeaf) {
var nextLeaf = GetNextLeaf (startLeaf);
ColorizeLeaf(startLeaf, size);
if (startLeaf == endLeaf) {
break;
}
startLeaf = nextLeaf;
}
}
}
}
else {
// Internet Explorer before version 9
alert ("Your browser does not support this example!");
}
}
</script>
</head>
<body contenteditable="true">
Select some content on this page and use the buttons below to colorize the selected text.<br /><br />
<button onclick="ColorizeSelection (12);">Font 12</button>
<button onclick="ColorizeSelection (14);">Font 14</button>
<button onclick="ColorizeSelection (18);">Font 18</button>
<button onclick="ColorizeSelection (28);">Font 28</button>
<br />
<div>Some text for selection</div>
<div contentEditable="true" id="editor"><b>Some bold text for selection.</b></div>
<ul>
<li>One </li>
<li>Two </li>
<li>Three </li>
<li>Four </li>
</ul>
</body>
</html>
&#13;
答案 0 :(得分:1)
最后,我已经找到了解决方法来满足我的需求,如下所述。
完整的更新代码如下所述。
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function GetNextLeaf(node) {
while (!node.nextSibling) {
node = node.parentNode;
if (!node) {
return node;
}
}
var leaf = node.nextSibling;
while (leaf.firstChild) {
leaf = leaf.firstChild;
}
return leaf;
}
function GetPreviousLeaf(node) {
while (!node.previousSibling) {
node = node.parentNode;
if (!node) {
return node;
}
}
var leaf = node.previousSibling;
while (leaf.lastChild) {
leaf = leaf.lastChild;
}
return leaf;
}
// If the text content of an element contains white-spaces only, then does not need to colorize
function IsTextVisible(text) {
for (var i = 0; i < text.length; i++) {
if (text[i] != ' ' && text[i] != '\t' && text[i] != '\r' && text[i] != '\n')
return true;
}
return false;
}
function ColorizeLeaf(node, size) {
if (!IsTextVisible(node.textContent))
return;
var parentNode = node.parentNode;
// if the node does not have siblings and the parent is a span element, then modify its color
if (!node.previousSibling && !node.nextSibling) {
if (parentNode.tagName.toLowerCase() == "span") {
//parentNode.style.color = color;
parentNode.style.fontSize = size + "px";
return;
}
}
// Create a span element around the node
var span = document.createElement("span");
//span.style.color = color;
span.style.fontSize = size + "px";
var nextSibling = node.nextSibling;
parentNode.removeChild(node);
span.appendChild(node);
parentNode.insertBefore(span, nextSibling);
}
function ColorizeLeafFromTo(node, size, from, to) {
var text = node.textContent;
if (!IsTextVisible(text))
return;
if (from < 0)
from = 0;
if (to < 0)
to = text.length;
if (from == 0 && to >= text.length) {
// to avoid unnecessary span elements
ColorizeLeaf(node, size);
return;
}
var part1 = text.substring(0, from);
var part2 = text.substring(from, to);
var part3 = text.substring(to, text.length);
var parentNode = node.parentNode;
var nextSibling = node.nextSibling;
parentNode.removeChild(node);
if (part1.length > 0) {
var textNode = document.createTextNode(part1);
parentNode.insertBefore(textNode, nextSibling);
}
if (part2.length > 0) {
var span = document.createElement("span");
//span.style.color = color;
span.style.fontSize = size + "px";
var textNode = document.createTextNode(part2);
span.appendChild(textNode);
parentNode.insertBefore(span, nextSibling);
}
if (part3.length > 0) {
var textNode = document.createTextNode(part3);
parentNode.insertBefore(textNode, nextSibling);
}
}
function ColorizeNode(node, size) {
var childNode = node.firstChild;
if (!childNode) {
ColorizeLeaf(node, size);
return;
}
while (childNode) {
// store the next sibling of the childNode, because colorizing modifies the DOM structure
var nextSibling = childNode.nextSibling;
ColorizeNode(childNode, size);
childNode = nextSibling;
}
}
function ColorizeNodeFromTo(node, size, from, to) {
var childNode = node.firstChild;
if (!childNode) {
ColorizeLeafFromTo(node, size, from, to);
return;
}
for (var i = from; i < to; i++) {
ColorizeNode(node.childNodes[i], size);
}
}
var font_size = 14;
var selection_range;
function ColorizeSelection(size) {
if (window.getSelection) { // all browsers, except IE before version 9
var selectionRange = window.getSelection();
if (selectionRange.isCollapsed) {
font_size = size;
document.getElementById("editor").addEventListener("keypress", clickHandler);
selection_range = selectionRange;
}
else {
var range = selectionRange.getRangeAt(0);
// store the start and end points of the current selection, because the selection will be removed
var startContainer = range.startContainer;
var startOffset = range.startOffset;
var endContainer = range.endContainer;
var endOffset = range.endOffset;
// because of Opera, we need to remove the selection before modifying the DOM hierarchy
selectionRange.removeAllRanges();
if (startContainer == endContainer) {
ColorizeNodeFromTo(startContainer, size, startOffset, endOffset);
}
else {
if (startContainer.firstChild) {
var startLeaf = startContainer.childNodes[startOffset];
}
else {
var startLeaf = GetNextLeaf(startContainer);
ColorizeLeafFromTo(startContainer, size, startOffset, -1);
}
if (endContainer.firstChild) {
if (endOffset > 0) {
var endLeaf = endContainer.childNodes[endOffset - 1];
}
else {
var endLeaf = GetPreviousLeaf(endContainer);
}
}
else {
var endLeaf = GetPreviousLeaf(endContainer);
ColorizeLeafFromTo(endContainer, size, 0, endOffset);
}
while (startLeaf) {
var nextLeaf = GetNextLeaf(startLeaf);
ColorizeLeaf(startLeaf, size);
if (startLeaf == endLeaf) {
break;
}
startLeaf = nextLeaf;
}
}
}
}
else {
// Internet Explorer before version 9
alert("Your browser does not support this example!");
}
}
function pasteHtmlAtCaret(html) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(), node, lastNode;
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(lastNode);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}
var clickHandler = function (event) {
document.getElementById("editor").removeEventListener("keypress", clickHandler);
updateFontSizeForNewText(event);
};
function updateFontSizeForNewText(e) {
var timestamp = new Date().getUTCMilliseconds();
var key="";
if (isValidKeyPress(e)) {
event.preventDefault();
key = e.key;
var span = document.createElement("span");
span.id = timestamp;
var txt = document.createTextNode(key);
span.style.fontSize = font_size + "px";
span.appendChild(txt);
var wrap = document.createElement('div');
wrap.appendChild(span.cloneNode(true));
pasteHtmlAtCaret(wrap.innerHTML);
}
}
function isValidKeyPress(e) {
var keycode = e.keyCode;
var valid =
(keycode > 47 && keycode < 58) || // number keys
(keycode > 64 && keycode < 91) || // letter keys
(keycode > 95 && keycode < 112) || // numpad keys
(keycode > 185 && keycode < 193) || // ;=,-./` (in order)
(keycode > 218 && keycode < 223); // [\]' (in order)
return valid;
}
</script>
</head>
<body>
Select some content on this page and use the buttons below to colorize the selected text.<br /><br />
<button onclick="ColorizeSelection (12);">Font 12</button>
<button onclick="ColorizeSelection (14);">Font 14</button>
<button onclick="ColorizeSelection (18);">Font 18</button>
<button onclick="ColorizeSelection (28)">Font 28</button>
<!--<button onclick="ColorizeSelection ('#FF0000');">Set color to red!</button>
<button onclick="ColorizeSelection ('#0000FF');">Set color to blue!</button>-->
<br />
<div>Some text for selection</div>
<div contentEditable="true" id="editor"><b>Some bold text for selection.</b></div>
<ul>
<li>One </li>
<li>Two </li>
<li>Three </li>
<li>Four </li>
</ul>
</body>
</html>
答案 1 :(得分:0)
您正在使用click
事件处理程序触发所有内容。此时,您将计算所选内容并从那里开始。问题是,当您点击某些内容时,未选中。由于click
事件触发了焦点更改,您将丢失任何当前选择!
我已将onclick
处理程序更改为onmousedown
处理程序。这会使代码工作,但可能不是您想要的。只要按下任何鼠标按钮,mousedown
事件就会重复触发。您可以检测mouseup事件并确保只运行一次代码直到下一次mouseup,或者有一种方法可以使其适应onclick。为此,您还可以实现一个onselect处理程序。
使用onselect,每次进行选择时,处理程序都会运行。您可以在此时获取当前选择并将其保存在变量中。然后,当点击处理程序触发时,您可以检查已保存的变量,该变量将包含最后一个已知选择。
function GetNextLeaf (node) {
while (!node.nextSibling) {
node = node.parentNode;
if (!node) {
return node;
}
}
var leaf = node.nextSibling;
while (leaf.firstChild) {
leaf = leaf.firstChild;
}
return leaf;
}
function GetPreviousLeaf (node) {
while (!node.previousSibling) {
node = node.parentNode;
if (!node) {
return node;
}
}
var leaf = node.previousSibling;
while (leaf.lastChild) {
leaf = leaf.lastChild;
}
return leaf;
}
// If the text content of an element contains white-spaces only, then does not need to colorize
function IsTextVisible (text) {
for (var i = 0; i < text.length; i++) {
if (text[i] != ' ' && text[i] != '\t' && text[i] != '\r' && text[i] != '\n')
return true;
}
return false;
}
function ColorizeLeaf (node, size) {
if (!IsTextVisible (node.textContent))
return;
var parentNode = node.parentNode;
// if the node does not have siblings and the parent is a span element, then modify its color
if (!node.previousSibling && !node.nextSibling) {
if (parentNode.tagName.toLowerCase () == "span") {
//parentNode.style.color = color;
parentNode.style.fontSize = size+"px";
return;
}
}
// Create a span element around the node
var span = document.createElement("span");
//span.style.color = color;
span.style.fontSize = size + "px";
var nextSibling = node.nextSibling;
parentNode.removeChild (node);
span.appendChild (node);
parentNode.insertBefore (span, nextSibling);
}
function ColorizeLeafFromTo (node, size, from, to) {
var text = node.textContent;
if (!IsTextVisible (text))
return;
if (from < 0)
from = 0;
if (to < 0)
to = text.length;
if (from == 0 && to >= text.length) {
// to avoid unnecessary span elements
ColorizeLeaf(node, size);
return;
}
var part1 = text.substring (0, from);
var part2 = text.substring (from, to);
var part3 = text.substring (to, text.length);
var parentNode = node.parentNode;
var nextSibling = node.nextSibling;
parentNode.removeChild (node);
if (part1.length > 0) {
var textNode = document.createTextNode (part1);
parentNode.insertBefore (textNode, nextSibling);
}
if (part2.length > 0) {
var span = document.createElement ("span");
//span.style.color = color;
span.style.fontSize = size+"px";
var textNode = document.createTextNode (part2);
span.appendChild (textNode);
parentNode.insertBefore (span, nextSibling);
}
if (part3.length > 0) {
var textNode = document.createTextNode (part3);
parentNode.insertBefore (textNode, nextSibling);
}
}
function ColorizeNode (node, size) {
var childNode = node.firstChild;
if (!childNode) {
ColorizeLeaf(node, size);
return;
}
while (childNode) {
// store the next sibling of the childNode, because colorizing modifies the DOM structure
var nextSibling = childNode.nextSibling;
ColorizeNode(childNode, size);
childNode = nextSibling;
}
}
function ColorizeNodeFromTo(node, size, from, to) {
var childNode = node.firstChild;
if (!childNode) {
ColorizeLeafFromTo(node, size, from, to);
return;
}
for (var i = from; i < to; i++) {
ColorizeNode(node.childNodes[i], size);
}
}
function UpdateCurrentSelection(event) {
var selection = window.getSelection();
}
function ColorizeSelection(size) {
if (window.getSelection) { // all browsers, except IE before version 9
var selectionRange = window.getSelection ();
if (selectionRange.isCollapsed) {
// no idea on how to apply font size here. at cursor point.
}
else {
var range = selectionRange.getRangeAt (0);
// store the start and end points of the current selection, because the selection will be removed
var startContainer = range.startContainer;
var startOffset = range.startOffset;
var endContainer = range.endContainer;
var endOffset = range.endOffset;
// because of Opera, we need to remove the selection before modifying the DOM hierarchy
selectionRange.removeAllRanges ();
if (startContainer == endContainer) {
ColorizeNodeFromTo(startContainer, size, startOffset, endOffset);
}
else {
if (startContainer.firstChild) {
var startLeaf = startContainer.childNodes[startOffset];
}
else {
var startLeaf = GetNextLeaf (startContainer);
ColorizeLeafFromTo(startContainer, size, startOffset, -1);
}
if (endContainer.firstChild) {
if (endOffset > 0) {
var endLeaf = endContainer.childNodes[endOffset - 1];
}
else {
var endLeaf = GetPreviousLeaf (endContainer);
}
}
else {
var endLeaf = GetPreviousLeaf (endContainer);
ColorizeLeafFromTo(endContainer, size, 0, endOffset);
}
while (startLeaf) {
var nextLeaf = GetNextLeaf (startLeaf);
ColorizeLeaf(startLeaf, size);
if (startLeaf == endLeaf) {
break;
}
startLeaf = nextLeaf;
}
}
}
}
else {
// Internet Explorer before version 9
alert ("Your browser does not support this example!");
}
}
&#13;
<!DOCTYPE html>
<html>
<body contenteditable="true">
Select some content on this page and use the buttons below to colorize the selected text.<br /><br />
<button onmousedown="ColorizeSelection (12);">Font 12</button>
<button onmousedown="ColorizeSelection (14);">Font 14</button>
<button onmousedown="ColorizeSelection (18);">Font 18</button>
<button onmousedown="ColorizeSelection (28);">Font 28</button>
<br />
<div>Some text for selection</div>
<div contentEditable="true" id="editor"><b>Some bold text for selection.</b></div>
<ul>
<li>One </li>
<li>Two </li>
<li>Three </li>
<li>Four </li>
</ul>
</body>
</html>
&#13;