我有一个包含大量文本的字符串, 文本,在我的JavaScript文件中。我也有一个元素, DIV#集装箱 使用可能非标准的样式(使用单独的CSS) line-height
, font-size
, font-face
,也许还有其他人。它有一个固定的高度和宽度。
我想获得适合的最大文本量 DIV#集装箱 没有任何字符串溢出。这样做的最佳方法是什么?
这需要能够处理使用标签格式化的文本,例如:
<strong>Hello person that is this is long and may take more than a</strong>
line and so on.
目前,我有一个适用于纯文本的JQuery插件,代码如下:
// returns the part of the string that cannot fit into the object
$.fn.func = function(str) {
var height = this.height();
this.height("auto");
while(true) {
if(str == "") {
this.height(height);
return str; // the string is empty, we're done
}
var r = sfw(str); // r = [word, rest of String] (sfw is a split first word function defined elsewhere
var w = r[0], s = r[1];
var old_html = this.html();
this.html(old_html + " " + w);
if(this.height() > height)
{
this.html(old_html);
this.height(height);
return str; // overflow, return to last working version
}
str = s;
}
}
更新:
数据如下所示:
<ol>
<li>
<h2>Title</h2>
<ol>
<li>Character</li>
<ol>
<li>Line one that might go on a long time, SHOULD NOT BE BROKEN</li>
<li>Line two can be separated from line one, but not from itself</li>
</ol>
</ol>
<ol>
<li>This can be split from other</li>
<ol>
<li>Line one that might go on a long time, SHOULD NOT BE BROKEN</li>
<li>Line two can be separated from line one, but not from itself</li>
</ol>
</ol>
</li> <li>
<h2>Title</h2>
<ol>
<li>Character</li>
<ol>
<li>Line one that might go on a long time, SHOULD NOT BE BROKEN</li>
<li>Line two can be separated from line one, but not from itself</li>
</ol>
</ol>
<ol>
<li>This can be split from other</li>
<ol>
<li>Line one that might go on a long time, SHOULD NOT BE BROKEN</li>
<li>Line two can be separated from line one, but not from itself</li>
</ol>
</ol>
</li>
</ol>
好吧,让我试着解决它;)实际上考虑解决方案我注意到我对你的要求知之甚少,所以我决定开发简单的JavaScript代码并向你展示结果;尝试之后你可以告诉我什么是错的,所以我可以修理/改变它,交易?
我使用纯JavaScript,没有jQuery(如果需要可以重写)。原理类似于你的jQuery插件:
- 我们逐个取字符(而不是单词)
sfw
功能呢;它可以改变)
- 如果它是开始标记的一部分,浏览器不会显示它,所以我没有特别处理它,只是从标记名称和容器的检查高度逐个添加...不知道是不是那么糟糕。我的意思是当我写作
container.innerHTML = "My String has a link <a href='#'";
在浏览器中,我看到“My String has a link
“,所以”未完成“标签不会影响容器的大小(至少在我测试过的所有浏览器中)
- 检查容器的大小,如果它大于我们预期的大小,那么之前的字符串(实际上当前字符串没有最后一个字符)就是我们要找的东西
- 现在我们必须关闭所有因切割而未关闭的开口标签
用于测试它的HTML页面:
<html>
<head>
<style>
div {
font-family: Arial;
font-size: 20px;
width: 200px;
height: 25px;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"> <strong><i>Strong text with <a href="#">link</a> </i> and </strong> simple text </div>
<script>
/**
* this function crops text inside div element, leaving DOMstructure valid (as much as possible ;).
* also it makes visible part as "big" as possible, meaning that last visible word will be split
* to show its first letters if possible
*
* @param container {HTMLDivElement} - container which can also have html elements inside
* @return {String} - visible part of html inside div element given
*/
function cropInnerText( container ) {
var fullText = container.innerHTML; // initial html text inside container
var realHeight = container.clientHeight; // remember initial height of the container
container.style.height = "auto"; // change height to "auto", now div "fits" its content
var i = 0;
var croppedText = "";
while(true) {
// if initial container content is the same that cropped one then there is nothing left to do
if(croppedText == fullText) {
container.style.height = realHeight + "px";
return croppedText;
}
// actually append fullText characters one by one...
var nextChar = fullText.charAt( i );
container.innerHTML = croppedText + nextChar;
// ... and check current height, if we still fit size needed
// if we don't, then we found that visible part of string
if ( container.clientHeight > realHeight ) {
// take all opening tags in cropped text
var openingTags = croppedText.match( /<[^<>\/]+>/g );
if ( openingTags != null ) {
// take all closing tags in cropped text
var closingTags = croppedText.match( /<\/[^<>]+>/g ) || [];
// for each opening tags, which are not closed, in right order...
for ( var j = openingTags.length - closingTags.length - 1; j > -1; j-- ) {
var openingTag;
if ( openingTags[j].indexOf(' ') > -1 ) {
// if there are attributes, then we take only tag name
openingTag = openingTags[j].substr(1, openingTags[j].indexOf(' ')-1 ) + '>';
}
else {
openingTag = openingTags[j].substr(1);
}
// ... close opening tag to have valid html
croppedText += '</' + openingTag;
}
}
// return height of container back ...
container.style.height = realHeight + "px";
// ... as well as its visible content
container.innerHTML = croppedText;
return croppedText;
}
i++;
croppedText += nextChar;
}
}
var container = document.getElementById("container");
var str = cropInnerText( container );
console.info( str ); // in this case it prints '<strong><i>Strong text with <a href="#">link</a></i></strong>'
</script>
</body>
可能的改进/变化:
- 我不创建任何新的DOM元素,所以我只是重用当前的容器(以确保我考虑到所有的CSS样式);这样我就会一直改变它的内容,但是在获取可见文本后你就可以写了
fullText
如果需要可以回到容器中(我也不会改变)
- 逐字处理原始文本将让我们对DOM进行较少的更改(我们将逐字逐句地逐字逐句地写),因此这种方式应该更快。你已经拥有了
sfw
功能,所以你可以轻松改变它。
-
热门问题
不使用eval / new函数的JavaScript模板库
当涉及内部类时,Java继承如何工作
.NET Windows服务的奇怪问题
在.ipa或.app下查找App ID
快速入门XSLT参考[关闭]
如何找出Android应用程序中未使用的资源
Ruby中并发的同步方法[重复]
将std :: chrono :: system_clock :: time_point转换为struct timeval并返回
Google Drive API V3(javascript)更新文件内容
Bootstrap 3.0 - 将元素推到底部
受密码保护的.NET ClickOnce部署?
如何用postgresql安装wordpress
coq Set或Type如何成为命题
硒滚动元素进入(中心)视图
在Spring Transaction JUnit测试中自动装配Hibernate会话的正确方法
Git的Dockerfile策略
如何在FOS_PICKFOLDER中使用IFileDialog,同时仍在对话框中显示文件名
在Firefox扩展中复制Google Chrome浏览器操作弹出效果
CakePHP找到MAX
芹菜 - 完成任务的召唤功能
从使用fmemopen创建的流中读取宽字符
.NET是否为每个程序集创建一个字符串实习池?
DefaultModelBinder不绑定嵌套模型
Navigator.MediaDevices.getUserMedia()使用了哪些相机通信标准?
选择命名空间名称时应该知道什么?
cout
Swagger Codegen CLI Java客户端 - 如何正确使用它
一个很好的哈希函数用于采访整数,字符串?
Maven 3 ciManagement配置的目的是什么?
如何通过语言文化获取代码页?