简体   繁体   English

用jQuery检测换行符?

[英]detecting line-breaks with jQuery?

有没有可能让jQuery / javascript检测字符串被破坏的位置(为了适应CSS宽度约束),以便在新行的开头之前插入DOM元素?

I came up with an approach, but it might be overkill for your purposes, so take this into account. 我提出了一种方法,但是对于你的目的来说可能有些过分,所以考虑到这一点。

You need to create a clone of the element, empty the original, then move each word back into the original element. 您需要创建元素的克隆,清空原始元素,然后将每个单词移回原始元素。 If the height changes at any point, there's a line-break before that word. 如果高度在任何点发生变化,那么在该单词之前会有一个换行符。 This would be fairly simple to do using $(el).text() , but it gets more complicated if there can be other tags inside, not just text. 使用$(el).text()可以相当简单,但如果内部可以有其他标记,则会变得更复杂,而不仅仅是文本。 I tried explaining how to break it down by node in this answer box, but found it easier just to create a jQuery plugin in a jsFiddle. 我试着解释如何在这个答案框中按节点分解它,但发现在jsFiddle中创建一个jQuery插件更容易。 Link here: http://jsfiddle.net/nathan/qkmse/ ( Gist ). 链接到这里: http//jsfiddle.net/nathan/qkmse/Gist )。

It won't handle floated elements all that well, and there are a few other situations where it'll fall over. 它不会很好地处理浮动元素,还有一些其他情况会崩溃。 Let me know if you'd like more options, or if it doesn't quite work for your purposes, or if you're not sure how to apply it and I'll try to help. 如果您想要更多选项,或者如果它不适合您的目的,或者如果您不确定如何应用它,我会尽力提供帮助,请告诉我。

Here is one approach. 这是一种方法。 Note: I do not see a ideal solution without using monospace fonts. 注意:如果不使用等宽字体,我看不到理想的解决方案。 The equal with characters make this task much easier. 与字符相等使这项任务更容易。

  1. Equal width characters 等宽字符
  2. Calculate the size of one character 计算一个字符的大小
  3. Calculate the size of the container 计算容器的大小
  4. Find characters per row 每行查找字符
  5. Find where the row will break (ie whitespace, dashes, etc) 查找行将中断的位置(即空格,破折号等)
  6. Get all breaking indexes. 获取所有破坏索引。

Have a look at the jsfiddle for associated html. 看一下相关html的jsfiddle。 I have not completed this function. 我还没有完成这个功能。 More checks need to be put in when calculating the breaking index. 在计算破坏指数时需要进行更多检查。 Right now it is using lastIndexOf(' '), but this ignores that the next index could be a space, or the current. 现在它正在使用lastIndexOf(''),但这忽略了下一个索引可能是空格或当前。 Also I am not accounting for other line-breaking characters. 另外,我不考虑其他破线字符。 However this should be a great starting point. 然而,这应该是一个很好的起点。

var text = $('#text').text(),                   // "lorem ipsum ... "
    len = text.length,                          // total chars
    width = $('#text').width(),                 // container width
    span = $('<span />').append('a').appendTo('#sandbox'),
    charWidth = span.width(),                  // add single character to span and test width
    charsPerRow = Math.floor(width/charWidth); // total characters that can fit in one row

var breakingIndexes = [], // will contain indexes of all soft-breaks
    gRowStart = 0,        // global row start index
    gRowEnd = charsPerRow;// global row end index

while(gRowEnd < len){
    var rowEnd = text.substring(gRowStart, gRowEnd).lastIndexOf(' '); // add more checks for break conditions here
    breakingIndexes.push(gRowStart + rowEnd); // add breaking index to array
    gRowStart = gRowStart + rowEnd + 1; // next start is the next char
    gRowEnd = gRowStart + charsPerRow;  // global end inxex is start + charsperrow
}

var text2 = $('#text2').text();           // "lorem ipsum ... " now not width bound
var start = 0, newText = '';
for(var i=0; i < breakingIndexes.length; i++){
    newText += text2.substring(start, breakingIndexes[i]) + '<br />'; // add hard breaks
    start = breakingIndexes[i]; // update start
}

$('#text2').html(newText); // output with breaks

http://jsfiddle.net/Y5Ftn/1/ http://jsfiddle.net/Y5Ftn/1/

this is my script, that takes text, and then makes each line a span 这是我的脚本,它接受文本,然后使每一行成为一个跨度

CSS: CSS:

    margin: 0;
        padding: 0;
    }

    .title{
        width: 300px;
        background-color: rgba(233,233,233,0.5);
        line-height: 20px;
    }

    span{
        color: white;
        background-color: red;
        display: inline-block;
        font-size: 30px;
    }

    a{
        text-decoration: none;
        color: black;
    }

html HTML

<div class="title">
        <a href="">SOME TEXT LONG TEXT ANDTHISISLONG AND THIS OTHER TEXT</a>
    </div>

JS JS

$(function(){

        $(".title").find("a").each(function(){

            var $this = $(this);
            var originalText = $this.text();
            $this.empty();

            var sections = [];

            $.each( originalText.split(" "), function(){
                var $span = $("<span>" + this + "</span>");
                $this.append($span);

                var index = $span.position().top;

                if( sections[index] === undefined ){
                    sections[index] = "";
                }

                sections[index] += $span.text() + " ";
            });

            $this.empty();

            for(var i = 0; i< sections.length; i++){
                if( sections[i] !== undefined ){
                    var spanText = $.trim(sections[i]);                     
                    $this.append("<span>" + spanText + "</span>");
                }
            }

        });

    });

You have to got jQuery included. 你必须包含jQuery。

I think it would be easier to detect using a regex -- much less code while retaining efficiency. 我认为使用正则表达式检测更容易 - 在保持效率的同时更少的代码。

Here's something that worked for me: 这对我有用:

if ((/(\r\n|\n|\r)/.test($(this).val()))) {
    alert('there are line breaks here')
}

I'm not sure if this will work with your broken strings, but it works for detecting line-breks with jQuery. 我不确定这是否适用于你的断字符串,但它适用于使用jQuery检测行错误。

Alternatively you could compare width of the text block with its parent's width. 或者,您可以比较文本块的宽度与其父级的宽度。 If the block is at least 98% of the width of its parent, pretty sure it breaks 如果该块至少是其父级宽度的98%,那么确定它会中断

I don't know of any built in jQuery of javascript function to do this. 我不知道有任何内置的jQuery javascript函数来做到这一点。 You could, however, do it yourself, but it would be potentially slow if you have a lot of text. 但是,你可以自己做,但如果你有很多文字,它可能会很慢。

In theory, you could make sure the height is set to auto, remove the text, and then word by word reinsert it. 从理论上讲,您可以确保将高度设置为自动,删除文本,然后逐字逐句重新插入。 On a change in the height, you remove the last word, and insert your dom element. 在更改高度时,删除最后一个单词,然后插入dom元素。 Again, this will be slow if there is a lot of text, and the better way to do this would be to not change the original element, but do it in another element which could be hidden, and then replace the original element on completion. 同样,如果有大量文本,这将是缓慢的,更好的方法是不更改原始元素,而是在另一个可隐藏的元素中执行,然后在完成时替换原始元素。 That way, your user wouldn't see the content disappear and then come back word by word. 这样,您的用户就不会看到内容消失,然后一字一句地回来。

Another way would be to use a similar principle, and start with an empty element of the same size with height auto, and insert a new character and a space until you get a new line. 另一种方法是使用类似的原则,并从具有高度auto的相同大小的空元素开始,并插入一个新字符和一个空格,直到你得到一个新行。 From there, you can use this as an approximation with the above techinique, or you can blindly add up the length of each string until you find a new line, taking into account the width of your dom element. 从那里,你可以使用它作为上述技术的近似,或者你可以盲目地加上每个字符串的长度,直到找到一个新的行,同时考虑到你的dom元素的宽度。 This technique works better with monospaced fonts though, which is where using it only as an approximation comes in. 尽管使用等宽字体,这种技术效果更好,这只是作为近似值使用它的地方。

That said, there is a way to measure text using canvas, but that may be extreme. 也就是说,有一种方法可以使用画布来测量文本,但这可能是极端的。 In theory it would be, create a canvas element, get the context, set all the font properties, and then use the context.measureText() method. 从理论上讲,它将创建一个canvas元素,获取上下文,设置所有字体属性,然后使用context.measureText()方法。 An example of it use can be found here . 可以在此处找到它的使用示例。

不确定您的用例究竟是什么,但http://code.google.com/p/hyphenator/可能是您的问题的解决方案,或者如果您深入了解hyphenator.js源代码,您可能能够找到代码你在找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM