我有contentEditable InputStream input = assetManager.open(assetName);
,每个字母都有自己的元素,如:
div
我正在尝试使用<div contenteditable="true">
<p id="p1">
<span id="s1">S</span>
<span id="s2">o</span>
<span id="s3">m</span>
<span id="s4">e</span>
<span id="s5"> </span>
<span id="s6">t</span>
<span id="s7">e</span>
<span id="s8">x</span>
<span id="s9">t</span>
</p>
</div>
来证明一些较长的文本,但这不起作用。这很奇怪,因为text-align: justify
和text-align: center
有效。
之后我尝试使用一个脚本向每个空格添加text-align: right
,但是当我将新文本写入段落时,它会崩溃。
如何使用JavaScript和/或JQuery执行此操作(并在每个元素中保存margin-right
和其他属性)?
答案 0 :(得分:4)
以下是一个JS + jQuery方法的示例,用于模拟contenteditable
元素内部包含的字符的对齐方式。它只是一个快速的概念证明,仅在Chrome中测试过,而不是彻底的。删除/撤消/复制/粘贴等功能未添加到此示例中。
var selectors = {
'wrapper': '#editable',
'paragraphs': '#editable > p',
'spans': '#editable > p > span'
}
function get_cursor_position(element) {
var caretOffset = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
}
} else if ((sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
}
function set_cursor_position(pos) {
if (document.selection) {
sel = document.selection.createRange();
sel.moveStart('character', pos);
sel.select();
} else {
sel = window.getSelection();
sel.collapse($(selectors['spans'])[pos].firstChild, 0);
}
}
function set_cursor_position_to_element(el) {
if (document.selection) {
sel = document.selection.createRange();
sel.moveStart('character', pos);
sel.select();
} else {
sel = window.getSelection();
sel.collapse(el, 0);
}
}
function justify(wrapper_selector, children_selector) {
var line_width = 0,
first_line_char = 0,
wrapper = $(wrapper_selector),
wrapper_width = wrapper.width(),
children = $(children_selector),
position_of_last_space_found,
filled_line_width_at_last_space_found;
// refresh
children.removeAttr("padding-right").removeClass("spaced first-line-char last-line-space");
for (var space_positions = [], l = children.length, child_i = 0; child_i < l; child_i++) {
child_e = children.eq(child_i);
line_width += $(child_e).width();
first_line_char += 1;
if (/\s/g.test($(child_e).text())) {
space_positions.push(child_i);
position_of_last_space_found = child_i;
filled_line_width_at_last_space_found = line_width - child_e.width();
}
if (line_width >= wrapper_width) {
remaining_space = wrapper_width - filled_line_width_at_last_space_found;
line_chars_extra_margin = remaining_space / (space_positions.length - 1);
for (margin_i = 0; margin_i < space_positions.length; margin_i++) {
children.eq(space_positions[margin_i]).addClass("spaced").css("padding-right", Math.floor(line_chars_extra_margin * 10) / 10);
}
children.eq(position_of_last_space_found + 1).addClass("first-line-char");
children.eq(position_of_last_space_found).addClass("last-line-space");
line_width = 0;
child_i = position_of_last_space_found;
first_line_char = 0;
space_positions = [];
}
}
}
function insert_char(html) {
var sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(),
node, lastNode;
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node);
}
var firstNode = frag.firstChild;
pos = $(range.commonAncestorContainer).parent('span').index() + range.startOffset;
$(selectors['spans']).eq(pos).before(frag);
set_cursor_position(pos + 1, $(selectors['paragraphs']));
}
}
}
function get_span_at(x, y) {
var $elements = $(selectors['spans']).map(function() {
var $this = $(this);
var offset = $this.offset();
var l = offset.left;
var t = offset.top;
var h = $this.outerHeight(true);
var w = $this.outerWidth(true);
var maxx = l + w;
var maxy = t + h;
return (y <= maxy && y >= t) && (x <= maxx && x >= l) ? $this : null;
});
return $elements;
}
function init_demo() {
var next_pos;
// Copy the text from div.reference inside div.editable
// (only for the purpose of this example)
var characters = $('div.reference p').text().trim().replace(/ /g, '\u00a0');
for (var x = 0; x < characters.length; x++) {
var c = characters.charAt(x);
// wrap each character in a span
$(selectors['paragraphs']).append("<span>" + c + "</span");
}
// initial justification
justify(selectors['wrapper'], selectors['spans']);
// re-justify on window resize
$(window).resize(function() {
clearTimeout(window.resizedFinished);
window.resizedFinished = setTimeout(function() {
justify(selectors['wrapper'], selectors['spans']);
}, 20);
});
// Improve navigation with arrow keys
$(selectors['wrapper']).on('keydown', function(e) {
switch (e.which) {
case 37: // left
next_pos = get_cursor_position($(selectors['spans'])[0]) - 1;
set_cursor_position(next_pos, $(selectors['paragraphs']));
break;
case 38: // up
curr_pos = get_cursor_position($(selectors['spans'])[0]);
curr_span = $(selectors['spans']).eq(curr_pos);
curr_span_y = curr_span.position().top;
curr_span_x = curr_span.position().left;
next_span_y = curr_span_y - 1;
next_span_x = curr_span_x + 1;
next_span = get_span_at(curr_span_x, next_span_y);
if (next_span[0]) {
set_cursor_position_to_element(next_span[0][0]);
}
break;
case 39: // right
next_pos = get_cursor_position($(selectors['spans'])[0]);
set_cursor_position(next_pos, $(selectors['paragraphs']));
break;
case 40: // down
curr_pos = get_cursor_position($(selectors['spans'])[0]);
curr_span = $(selectors['spans']).eq(curr_pos);
curr_span_y = curr_span.position().top;
curr_span_x = curr_span.position().left;
curr_span_h = curr_span.outerHeight(true);
next_span_y = curr_span_y + curr_span_h + 1;
next_span_x = curr_span_x + 1;
next_span = get_span_at(curr_span_x, next_span_y);
if (next_span[0]) {
set_cursor_position_to_element(next_span[0][0]);
}
break;
}
});
// re-justify on character insertion
$(selectors['wrapper']).on('keypress', function(e) {
new_char = String.fromCharCode(e.which).replace(/ /g, '\u00a0');
// Wrap new characters in spans
new_el = '<span>' + new_char + '</span>';
insert_char(new_el);
justify(selectors['wrapper'], selectors['spans']);
e.preventDefault();
});
}
init_demo();
div.col {
width: 50%;
overflow: hidden;
font-size: 1.2em;
float: left;
box-sizing: border-box;
padding: 20px;
}
p {
overflow: hidden;
}
div.reference p {
text-align: justify;
}
div span {
display: block;
float: left;
}
.first-line-char {
content: ' ';
display: block;
clear: left;
}
.last-line-space {
display: none;
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<div class="col col1">
<h2>reference</h2>
<h4>This is just a reference. Edit the right column.</h4>
<div class="reference">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Excepturi provident, nemo incidunt voluptate officia, ipsa nulla itaque laudantium aperiam cupiditate vero, nesciunt consequuntur, facilis aliquam enim quis ad. Fugiat, magni.
</p>
</div>
</div>
<div class="col col2">
<h2>editable</h2>
<h4>Click the paragraph text below to start to edit.</h4>
<div contenteditable="true" class="editable" id="editable">
<p>
<!-- Text will be copied from the reference div -->
</p>
</div>
</div>
答案 1 :(得分:0)
您可以在最后添加一个假单词并制作其width:100%
和display: inline-block
。像这样:(根据你的要求改变父母的宽度)
.justified {
width: 300px;
text-align: justify;
}
.justified .fake-word {
width: 100%;
display: inline-block;
height: 0.1em;
}
&#13;
<div contenteditable="true">
<p id="p1" class="justified">
<span id="s1">S</span>
<span id="s2">o</span>
<span id="s3">m</span>
<span id="s4">e</span>
<span id="s5"> </span>
<span id="s6">t</span>
<span id="s7">e</span>
<span id="s8">x</span>
<span id="s9">t</span>
<span class="fake-word"></span>
</p>
</div>
&#13;
编辑1:
如果您不想在字符之间留出空格,则可以删除所有范围标记:
<div contenteditable="true">
<p id="p1" class="justified">
Some Text
<span class="fake-word"></span>
</p>
</div>
编辑2: 此外,您不必添加.fake-word,还有另一种方法可以使用伪类:
.justified:after {
content: "";
display: inline-block;
width: 100%;
}
答案 2 :(得分:0)
对于这个问题,我认为最好采用flexbox方法。将id
添加到<div>
或为其指定样式,使其占据您想要的宽度,例如:
<div contenteditable="true" id="container">
<p id="p1">
<span id="s1">S</span>
<span id="s2">o</span>
<span id="s3">m</span>
<span id="s4">e</span>
<span id="s5"> </span>
<span id="s6">t</span>
<span id="s7">e</span>
<span id="s8">x</span>
<span id="s9">t</span>
</p>
</div>
然后在你的css中添加以下内容:
#container {
width: 400px;
}
#p1 {
width: 100%;
display: flex;
justify-content: space-between;
}
答案 3 :(得分:0)
苛刻的答案是,如果你想要正常的辩护行为但保持所有的跨度,要达到你想要的东西并不容易。
但是如果你想尝试这样的事情,你需要制作自己的对齐脚本。要做到这一点,你需要循环遍历所有跨度,当你输入一个新行(检查从顶部开始的跨度的偏移)时,你需要回到最后一个空格,然后尝试证明以前迭代过的所有字符。这可以通过将它们封装在新的span或div中并在其内部进行调整来完成(封装div需要100%宽度)。要么只使用css,要么改变空间跨度,只扩展跨度。
回答如何检查范围偏移的问题:How to select nth line of text (CSS/JS)
很抱歉,如果没有添加更多的跨度/ div或删除跨度,就无法正确地证明这些内容的正确性。
答案 4 :(得分:0)
你有什么工作,但由于几个原因它只是没有显示你的文字。
第一个原因是该文字太短。你需要足够的文本包装来显示理由。
第二个原因是将span标记放在新行中是在每行之间添加一个空格。 尝试将所有内容放在同一行
喜欢这个
[SQL0104] Token MERGE was not valid. Valid tokens: ( CL END GET SET CALL DROP FREE HOLD LOCK OPEN WITH ALTER. [SQL State=42601, DB Errorcode=-104]
这是[{3}}示例工作
答案 5 :(得分:0)
您可以通过将span
标记中的字词包装在display: inline-block;
中来实现此目的。
例如:https://codepen.io/MaxViewUp/pen/XeMJmX?editors=1100
<div id="d1" contenteditable="true">
<p id="p1">
<span class="word">
<span id="s1">S</span>
<span id="s2">o</span>
<span id="s3">m</span>
<span id="s4">e</span>
</span>
<span id="s5"> </span>
<span class="word">
<span id="s1">S</span>
<span id="s2">o</span>
<span id="s3">m</span>
<span id="s4">e</span>
</span>
</p>
</div>
答案 6 :(得分:-3)
使用text-align:justify和display:flex(有时是强制性的)这应该有用。