使用jQuery定位纯文本

时间:2009-11-13 17:03:02

标签: javascript jquery

我正在尝试隔离(然后操纵)以常见新闻阅读器和电子邮件客户端方式格式化的报价块。

HTML:

<p>
  Hello there!
  <br />
  I'm great, how are you?
  <br />
  <br />
  Someone wrote:
  <br />
  > Greetings,
  <br />
  > How are you?
</p>

我需要定位所有以&gt;开头的行,并将它们隐藏为可折叠块。在上面的例子中,“Someone写道:”之后的所有内容都将被隐藏,保存为变量,JS生成的最终结果将是:

<p>
  Hello there!
  <br />
  I'm great, how are you?
  <br />
  <br />
  Someone wrote:
  <br />
  <a href="#">Click to expand</a>
</p>

Gmail做同样的事情,但是服务器端将报价块包装在<div>中,由于我的项目的特定性质,完整的过程必须由JS单独完成。 我正在使用jQuery框架。

提前致谢!

2 个答案:

答案 0 :(得分:2)

我不相信jquery会像这样分析文本。您必须自己解析以'&gt;'开头的行并根据需要编辑字符串。然后,您可以使用jquery对您添加的元素进行操作。

答案 1 :(得分:1)

我在this pastebin为你准备了一个例子。这是添加了注释的代码。

HTML

<p>
  Hello there!
  <br />
  I'm great, how are you?
  <br />
  <br />
  Someone wrote:
  <br />
  > Greetings,
  <br />
  > How are you?
  <br />
  <br />
  Someone else wrote:
  <br />
  > I like turtles
  <br />
  <br />
  > Someone odd person wrote:
  <br />
  > > You smell like cheese
  <br />
  > > and now I'm hungry
  <br />
  <br />
  and that's the end,
  <br />
  of all of this.
</p>

脚本

$(document).ready(function(){
 // link text to inform users to click to expand
 var lnk = '[+]';
 // variable to look for stating it's a new reply
 var newrply = 'wrote:';
 // reply indicator (HTML escape code for ' > ' to exclude any HTML that might be found
 var isrply = '&gt; ';
 // collect html and split it into an array
 var txt = $('p').html().split('<br>');
 // flag showing that the text is within a reply block
 var rply = false;
 // cycle through each portion of text
 $.each(txt, function(i){
  // look for a new reply
  if (this.match(newrply)){
   // if within a reply and it finds a new reply, close previous
   var tmp = (rply) ? '</div>' : '';
   // add link
   txt[i] = tmp + txt[i] + ' <a href="#" class="replylink">' + lnk + '</a>';
   // go to next variable in array and add wrapper, this makes sure the <br> is outside the reply (formatting purposes)
   txt[i+1] = '<div class="reply">' + txt[i+1];
   // look for reply indicator or text that is <5 characters in length
   // (in the HTML above, the array value will have carriage return plus two spaces for each <br>)
  } else if (this.match(isrply) || txt[i].length < 5) {
   rply = true;
  } else {
   rply = false;
   // close the reply, add the close to the previous array element (most likely a <br>)
   txt[i-1] = txt[i-1] + '</div>';
  }
  // close the reply at the end of the array
  if(i == txt.length) {
   txt[i-1] = txt[i-1] + '</div>';
  }
 })
 // join the array and add it back
 $('p').html( txt.join('<br>') );
 // hide the replies
 $('.reply').hide();
 // add toggle view
 $('.replylink').click(function(){
  $(this).next().next('.reply').toggle();
  return false;
 })
})

我将链接更改为'[+]'以切换视图,但在回复打开时我没有费心将其更改为'[ - ]'。我认为代码变得足够长,就像这个例子一样。


使用您发布的新代码,我不得不做一些更改。

  • 现在可以使用多个帖子(它处理每个“div.post”)
  • 如果“&gt;”现在只会找到新回复是在一个新行的开头
  • 它使用rel标记来索引每个回复,因为jQuery的.next()函数会找到“
    ”并且这些变量的数量是可变的
  • 我遇到的一个问题是点击功能,我最终切换到.live,因为点击事件被触发了两次(我无法找出原因,但是使用实时工作)。
  • 最后,我将<a name="" style="color: gray;"/>留在了代码中,但格式不正确的HTML ...您无法以这种方式关闭<a>代码。

新更新:

  • 修正了使用IE的脚本,显然IE使用<BR>而不是<br>,因此拆分无效。尽管it isn't recommended,我最终还是使用了$.browser.msie。此外,原始脚本未打开</div>,这也是它在IE中崩溃的原因。
  • 我之前使用的rply变量没有在每个函数的迭代之间进行更新,因此我将其值移动到隐藏的输入标记中。我试图让它成为全球性的,但它只是不合作。这可能不是理想的做法,所以根据需要进行修复/调整。

必填HTML

<input id="replyflag" type="hidden" value="false"/>

更新了IE&amp; amp;的代码新pastbin posting

$(document).ready(function(){
 $('div.post').each(function(){
  // link text to inform users to click to expand
  var lnk = '[+]';
  // variable to look for stating it's a new reply
  var newrply = 'wrote:';
  // reply indicator (HTML escape code for ' > ' to exclude any HTML that might be found
  var isrply = '&gt;';
  // IE capitalizes the <BR>, collect html and split it into an array
  var splt = ($.browser.msie) ? '<BR>' : '<br>';
  var txt = $(this).find('p:eq(0)').html().split(splt);
  // index of each reply in a post
  var indx = 0;
  // start <div> tag around contents, as the script automatically closes the tag, even without replies
  txt[0] = '<div>' + txt[0];
  // cycle through each portion of text
  $.each(txt, function(i){
   // look for a new reply
   if (this.match(newrply)){
    // if within a reply and it finds a new reply, close previous
    var tmp = ($('#replyflag').val()) ? '</div>' : '';
    // set the "within a reply flag" to true
    $('#replyflag').val(true);
    // increment index
    indx++;
    // add link, the rel attrib contains the index of the reply
    txt[i] = tmp + txt[i] + ' <a href="#" class="replylink" rel="' + indx + '">' + lnk + '</a>';
    // go to next variable in array and add wrapper, this makes sure the <br> is outside the reply (formatting purposes)
    txt[i+1] = '<div class="reply" rel="' + indx + '">' + txt[i+1];
   // look for reply indicator at the beginning of a line or text that is > 3 characters in length, if not there, turn off reply flag.
   } else if (this.substring(0,4)!=isrply | this.length > 3) {
    $('#replyflag').val(false);
   }
   // close the reply at the end of the array
   if (i >= txt.length-1) {
    txt[i] = txt[i] + '</div>';
   }
  })
  // join the array and add it back
  $(this).find('p:eq(0)').html( txt.join('<br>') );
  // hide the replies
  $('.reply').hide();
  // add toggle view (using live because sometimes the click event is called twice and the toggle appears to not work)
  $('.replylink').live('click',function(){
   $(this).parent().find('.reply[rel=' + $(this).attr('rel') + ']').toggle();
   return false;
  })
 })
})