如何使用jQuery截断文本但保留HTML? 试过以下代码,但遗憾的是没有返回HTML格式。
var truncate = function() {
$('p.truncated').text(function(index, oldText) {
if (oldText.length > 20) {
return '...' + oldText.substr(-25);
}
return oldText;
});
}
如果您运行该代码段,您将看到我正在寻找的内容。
var truncate = function() {
$('p.truncated').text(function(index, oldText) {
if (oldText.length > 20) {
return '...' + oldText.substr(-25);
}
return oldText;
});
}
truncate();
var truncate2 = function() {
$("p.truncated2").each(function() {
//var theContent = $(this).text();
var theContent = $(this).html();
var n = theContent.substr(-25);
$(this).html( '...' +n );
});
}
truncate2();

p {
margin: 0 0 30px 0;
display: block;
padding: 5px;
}
streak {
color: green;
}
double {
color: orange;
}
p span {
color: grey;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
How to make something like this...
<p class="sheet">
<streak>start</streak>
<streak>1</streak>
<streak>2</streak>
<double>3</double>
<double>4</double>
<span>5</span>
<span>6</span>
<streak>7</streak>
<streak>8</streak>
<double>9</double>
<double>10</double>
<streak>end</streak>
</p>
...becomes something like this with jquery?
<p>
...
<span>6</span>
<streak>7</streak>
<streak>8</streak>
<double>9</double>
<double>10</double>
<streak>end</streak>
</p>
<hr />Here is a try with jquery but it return text without html elements.
<p class="truncated">
<streak>start</streak>
<streak>1</streak>
<streak>2</streak>
<double>3</double>
<double>4</double>
<span>5</span>
<span>6</span>
<streak>7</streak>
<streak>8</streak>
<double>9</double>
<double>10</double>
<streak>end</streak>
</p>
The second try
<p class="truncated2">
<streak>start</streak>
<streak>1</streak>
<streak>2</streak>
<double>3</double>
<double>4</double>
<span>5</span>
<span>6</span>
<streak>7</streak>
<streak>8</streak>
<double>9</double>
<double>10</double>
<streak>end</streak>
</p>
How can I keep html elements?
&#13;
答案 0 :(得分:2)
如果要继续计算字符数,也可以使用range
对象。您可以设置要删除的范围,也可以删除节点。所以你操纵文字但保留html
标签。
var truncate = function() {
var range_all = document.createRange();
range_all.selectNodeContents(document.getElementsByClassName('truncated')[0]);
if (range_all.endOffset > 20) {
range_all.setEnd(document.getElementsByClassName('truncated')[0], range_all.endOffset - 12);
range_all.deleteContents();
$('p.truncated').html('... ' + $('p.truncated').html());
}
}
truncate();
var truncate2 = function() {
$("p.truncated2").each(function() {
//var theContent = $(this).text();
var theContent = $(this).html();
var n = theContent.substr(-25);
$(this).html('...' + n);
});
}
truncate2();
&#13;
p {
margin: 0 0 30px 0;
display: block;
padding: 5px;
}
streak {
color: green;
}
double {
color: orange;
}
p span {
color: grey;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
How to make something like this...
<p class="sheet">
<streak>start</streak>
<streak>1</streak>
<streak>2</streak>
<double>3</double>
<double>4</double>
<span>5</span>
<span>6</span>
<streak>7</streak>
<streak>8</streak>
<double>9</double>
<double>10</double>
<streak>end</streak>
</p>
...becomes something like this with jquery?
<p>
...
<span>6</span>
<streak>7</streak>
<streak>8</streak>
<double>9</double>
<double>10</double>
<streak>end</streak>
</p>
<hr />If text is longer than 25 character, select until 12th and delete selection. Then add '...' at the beginning.
<p class="truncated">
<streak>start</streak>
<streak>1</streak>
<streak>2</streak>
<double>3</double>
<double>4</double>
<span>5</span>
<span>6</span>
<streak>7</streak>
<streak>8</streak>
<double>9</double>
<double>10</double>
<streak>end</streak>
</p>
The second try
<p class="truncated2">
<streak>start</streak>
<streak>1</streak>
<streak>2</streak>
<double>3</double>
<double>4</double>
<span>5</span>
<span>6</span>
<streak>7</streak>
<streak>8</streak>
<double>9</double>
<double>10</double>
<streak>end</streak>
</p>
How can I keep html elements?
&#13;
答案 1 :(得分:2)
这是任何CMS或博客的经典困境,其中预告片应该是文章的开头:通常解决方案是从其标签中剥离文本并按精确计数切割或保留标签,但由于标签大致切割也计算在内......
这是我建议的方法来满足两种紧急情况(保持标签和精确计数):
function cutKeepingTags(elem, count) {
var matches = $(elem).html().match(/([^<])*(<.*>)?(.*)/),
// To be more clear, let's "rename" what we get:
textBefore = matches[1] || '',
children = matches[2] || '',
textAfter = matches[3] || '';
if (textBefore.length <= count) {
// cool, already that's end!
return textBefore.substr(count);
}
if ($(elem).text().length == textBefore.length + textAfter.length) {
/* (remember that .text() returns the concatenation of all text nodes found
deeply in the element)
If equal there is no child (or there are children but no text in them),
so we can simply keep children and text enough after children:
*/
return textBefore + chidren + textAfter.substr(count - textBefore.length);
}
// Otherwise we must loop through children to get more text:
var grabText = textBefore;
$(elem).children().each(function() {
// Get text from current child:
grabText += cutKeepingTags(this, count - grabText.length);
if (grabText.length == count) {
// We already got text enough:
return grabText;
}
});
// No more child and count not reached, return what we got.
return grabText;
}
未经测试!
修改强>
最后得到了一个功能性解决方案:你找到它here on Code Review。
答案 2 :(得分:1)
您首先要拆分子元素。
var truncate = function() {
var $elem = $('p.truncated');
var html = $elem.html().split(/>\s*</);
if(html.length > 5)
html = "... <" + html.slice(-6).join('> <');
$elem.html(html);
}
truncate();
p {
margin: 0 0 30px 0;
display: block;
padding: 5px;
}
streak {
color: green;
}
double {
color: orange;
}
p span {
color: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="truncated">
<streak>start</streak>
<streak>1</streak>
<streak>2</streak>
<double>3</double>
<double>4</double>
<span>5</span>
<span>6</span>
<streak>7</streak>
<streak>8</streak>
<double>9</double>
<double>10</double>
<streak>end</streak>
</p>
答案 3 :(得分:0)
交配,替换你的
var theContent = $(this).html();
与
var theContent = $(this).outerHTML();
答案 4 :(得分:0)
我已经根据上面发布的代码完成了自己的纯JS(实际上是TypeScript)实现。它使用了不同的方法来提取父级的html,并具有附加功能,可在提供的html的开头处修剪空格,并在文本被截断时始终在结尾处修剪空白
/**
* recursively looks through all the text nodes until the text size exceeds the limit
* in that case will trim the html preserving all the existing tags
* @param element html element to be processed
* @param maxLength max amount of text symbols to be present
* @param shouldTrimStart set to false to preserve whitespace at the beginning of the projected content.
*/
function truncateHTML<T extends ChildNode>(element?: T, maxLength = 0, shouldTrimStart = true) {
let truncatedHTML = '';
let innerTextLength = 0;
const nodes = Array.from(element?.childNodes ?? []);
for (let index = 0; index < nodes.length; index++) {
const node = nodes[index];
switch (node.nodeType) {
case Node.TEXT_NODE: {
let content = (node.nodeValue ?? '').substr(0, maxLength - innerTextLength);
if (shouldTrimStart) {
content = content.trimLeft();
if (content) {
shouldTrimStart = false;
}
}
truncatedHTML += content;
innerTextLength += content.length;
break;
}
case Node.ELEMENT_NODE: {
const childPart = truncateHTML(node, maxLength - innerTextLength, shouldTrimStart);
const clone = node.cloneNode(true) as Element;
if (innerTextLength + childPart.innerTextLength === maxLength && index === nodes.length - 1) {
// removing trailing spaces in the end of the last word
childPart.truncatedHTML = childPart.truncatedHTML.trimRight();
}
clone.innerHTML = childPart.truncatedHTML;
truncatedHTML += clone.outerHTML;
innerTextLength += childPart.innerTextLength;
shouldTrimStart = childPart.shouldTrimStart;
break;
}
default:
console.error(new Error(`Unexpected node type: ${node.nodeType}`));
}
if (innerTextLength === maxLength) {
break;
}
}
return { truncatedHTML, innerTextLength, shouldTrimStart };
}