V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
enj0y
V2EX  ›  程序员

JS求助

  •  
  •   enj0y · 2012-10-16 18:46:42 +08:00 · 3345 次点击
    这是一个创建于 4422 天前的主题,其中的信息可能已经有所发展或是发生改变。
    代码:
    http://bluehua.org/tag/substr#post-927
    复制代码
    这个可以在不破坏HTML规范的前提下对elements进行截断。
    已经实现了截断method。

    求实现:
    获取未被截断的部分。

    比如

    str="<div>我</div><div>爱</div><div>v2ex</div><div></div>";
    console.log(sub_html_str(str,2));
    可以截取出“<div>我</div><div>爱</div>”

    我想要截取出上面未被截取到的部分,
    也就是console.log(sub_html_str_rest(str,2));
    要可以截取出“<div>v2ex</div>”

    谢谢了,思密达
    8 条回复    1970-01-01 08:00:00 +08:00
    CoX
        1
    CoX  
       2012-10-16 19:35:50 +08:00
    把一个字符串分两部分,前部分有了,后部分不也就有了么?
    CoX
        2
    CoX  
       2012-10-16 19:37:14 +08:00
    sub_html_str_rest=str.replace(sub_html_str(str,2),'')
    enj0y
        3
    enj0y  
    OP
       2012-10-17 00:08:12 +08:00
    enj0y
        4
    enj0y  
    OP
       2012-10-17 00:09:34 +08:00
    假设<div>我爱你</div>
    sub_html_str(str,2)被截取出来的是<div>我爱</div>
    而此时,我想要截取出剩余部分的是<div>你</div>
    chone
        5
    chone  
       2012-10-17 02:47:25 +08:00   ❤️ 1
    字符串就剩余部分就.substr(num)就行了,主要是标签的去除和重新加入逻辑要改一下,从后往前索引和添加,这样就可以避免删除字符后回填标签的时候位置不对。

    另外还可以借用dom来处理,直接处理textnode就行了,这样就避免了处理标签的问题。而且就算用正则表达式也可以用类似的遍历方法,这样逻辑上要简单和清晰一些。

    http://jsfiddle.net/SCyAF/1/
    enj0y
        6
    enj0y  
    OP
       2012-10-17 05:09:28 +08:00
    @chone 十分感谢!如此深夜还乐于助人,小弟自愧疚不如
    chone
        7
    chone  
       2012-10-17 05:40:39 +08:00
    @enj0y 算不上只是看到就想想如何解决而已,其实可以按照dom tree的概念写一个基于string而不是dom的walk那样可能效果更好一些。如果是要解决页面中的问题,那直接用dom来得直接一些。
    colonel
        8
    colonel  
       2012-10-17 12:18:27 +08:00   ❤️ 1
    按你的思路简单改了下:

    function sub_html_restr(str, num)
    {
    var reg = new RegExp( '<[^>]+>' , 'g' );
    var rt, rts = [], indexs = [], tstr, endstr, rstr, sstr, endtag, rtstr, restr;

    //提取所有的html标签和标签在字符串中的位置
    while ( ( rt = reg.exec(str) ) != null )
    {
    rts.push(rt[0]);
    indexs.push(rt['index']);
    }

    //删除字符串中所有的html标签
    tstr = str.replace(reg, '');
    //对剩余的纯字符串进行substr

    sstr = tstr.substr(num, tstr.length);
    tstr = tstr.substr(0, num);



    //判断有没有把实体腰斩,如果有腰斩的就再接上
    endstr = (/&[^&]*$/.exec(tstr) || '');
    if ( endstr !== '' ) endstr += '' + (/^[^;]*;/.exec(sstr) || '');
    if (/^(&\w{1,10};|&#\d+;)$/.test(endstr))
    {
    rtstr = tstr.replace(/&[^&]*$/, endstr);
    }
    else
    {
    rtstr = tstr;
    }

    //把html标签放回到截断完毕的字符串中,当然有的html标签这时候已经无家可归了

    var index = 0;

    for (var i = 0; i < rts.length; i ++)
    {
    index = indexs[i];
    if (rtstr.length >= index)
    {
    rtstr = rtstr.substr(0, index) + rts[i] + rtstr.substr(index, rtstr.length);
    }
    else
    {
    break;
    }
    }

    restr = str.substr(rtstr.length,str.length)

    //把闭合的标签全部删除
    tstr = restr;
    rstr = '';
    while ( rstr != tstr )
    {
    rstr = tstr;
    tstr = tstr.replace(/<[^\/][^>]*>[^<]*<\/[^>]+>/g, '').replace(/<[^>]+ \/>/g, '');
    }

    var lastindex = i ;
    var endreg = new RegExp('<\/([^>]+)>', 'g');
    var tagreg = new RegExp('<?([^ >]+)[ ]?[^ ]*>?');
    //如果存在没有闭合的标签,从切断的标签里找上半身
    while( (endrt = endreg.exec(tstr))!=null){
    for(var i = lastindex-1;i>-1;i--){
    if(tagreg.exec(rts[i])[1]==tagreg.exec(endrt[1])[1]){
    restr = rts[i] + restr;
    lastindex = i;
    break;
    }
    }
    }
    return restr;
    }

    </script>
    <script>
    document.writeln('<textarea cols="100" rows="10">');
    document.writeln(sub_html_restr('<xx><oo>嵌套标签截断测试</oo><fk><test>lala</test></fk></xx>', 5));
    document.writeln(sub_html_restr('正常字符串测试', 5));
    document.writeln(sub_html_restr('<xx>带标签的字符串截断</xx>', 5));
    document.writeln(sub_html_restr('<xx><oo>嵌套标签截断测试</oo><fk>lala</fk></xx>', 5));
    document.writeln(sub_html_restr('<xx><oo>嵌套标签<img src="http://www.google.com/logo.gif" />截断测试</oo></xx>', 5));
    document.writeln(sub_html_restr('<xx><oo>实体截断&nbsp;测试测试</oo></xx>', 5));
    document.writeln(sub_html_restr('<xx><oo>实体截断&nbsp;测试测试</oo></xx>', 5));
    document.writeln('</textarea>');
    </script>

    但是,这里有个bug,你没有存储标签的配对,所以遇到document.writeln(sub_html_restr('<xx><oo><oo a=1></oo>截断测试测试</oo></xx>', 5));这种就没办法了.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1104 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:31 · PVG 07:31 · LAX 15:31 · JFK 18:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.