0

反馈后,完成问题的重写。

我有以下标记:

<body>
  <h1>Title</h1>
  <p>bla</p>
  <div>
    ... <!-- a thousand tags -->
  </div>

  <div id="do-not-modify-me">
   <!-- a hundred tags -->
  </div>

</body>

我可以访问:

  <h1>Title</h1>
  <p>bla</p>
  <div>
    ... <!-- a thousand tags -->
  </div>

使用 :

$('body > *:not(div#do-not-modify-me)');

我这样做是为了获取正文的所有内容,除了 id 为“do-not-modify-me”的 div。

现在,假设我想构建一个函数,让另一个程序员选择正文中的任何内容,就像使用 jquery 进行选择一样。其他程序员不应该修改 div#do-not-modify-me,但他也不应该关心它。

$('body > *:not(div#do-not-modify-me)')会被调用很多时间,所以我们会缓存它。

这个想法是:

// TEST CODE

windows.new_body = $('body > *:not(div#do-not-modify-me)');

function select(selector) {
    return $(selector, windows.new_body);
}

所以其他程序员应该能够做到:

// TEST RESULT CODE
select("p").css("color", "red");

它会将身体的所有部分都涂成红色<p>,但不会将 div#do-not-modify-me 中包含的部分涂成红色。

测试代码不起作用,因为目前,它将 css() 应用于上下文结果的子级,而不是它自身的结果。

例如:

select("p").css("color", "red"); 

表现得像:

$('body > * p :not(div#do-not-modify-me)').css("color", "red");

虽然期望的结果是:

$('body > p :not(div#do-not-modify-me)').css("color", "red");

注意 :

$('body > * :not(div#do-not-modify-me)').parent().css("color", "red");

不起作用,因为<p>div#do-not-modify-me 变成红色。

您将如何获得 TEST RESULT CODE 中的结果?您可以修改代码的任何部分。

4

4 回答 4

1

我删除了所有以前的 EDIT,因为它们不再相关,您可以在 EDIT 历史记录中阅读它们。
EDIT3
基本上问题是你不能缓存选择器。那是因为 $()​​ 函数返回匹配的对象,而不是不匹配的对象。这意味着使用缓存选择器将意味着缓存可能与真实 DOM 不同步。即在这个简单的页面中:

<div>
 <p>foo</p><p>bar</p>
</div>
<div class='bar'></div>

.

var context = $('body').children(':not(.bar)'); //this holds: <div><p>foo</p><p>bar</p></div>
$('div', context).append('<p class="x">HAI</p>'); 
//context still is <div><p>foo</p><p>bar</p></div> even though it should be
//<div><p>foo</p><p>bar</p><p class="x">HAI</p></div>

所以你必须每次都重做选择,基本上你有两个选择:

//reselect the non-editable area everytime
function select(selector) {
  return $(selector, $('body').children(':not(div#do-not-modify-me)') );
}
//or, check the selection against being in the reselectable area.
function select(selector){
  return $(selector).filter(function(){
     return $(this).parents(':not(div#do-not-modify-me)');
  });
}

你应该自己试试哪个更快。我认为没有其他方法可以确保您不在#do-not-modify-me div 中进行搜索。

为了让这更容易(我认为更快),你可以做的其他事情是将可编辑区域包装在一个 div 中:

<body>
 <div id='modify-me'>
  <h1>Title</h1>
  <!-- thousands of tags -->
 </div>
 <div id='do-not-modify-me'>
  <!--hundreds of tags -->
 </div>
</body>

然后你可以做

function select(selector) {
  return $(selector, $('#modify-me') );
}
于 2009-06-10T17:59:48.330 回答
1

你说代码可以以任何方式修改,对吧?为什么不将其视为您想要搜索的内容,而不是您不想搜索的内容。将其余代码放在 a 中,然后将其用作上下文。它不会赢得任何优雅奖,但它很简单,而且 Get The Job Done TM<div>

于 2009-06-10T22:21:35.823 回答
0

我很确定您可以直接使用“上下文”,如下所示:

context = $('body > *:not(div#do-not-modify-me)');
context.doStuff();
于 2009-06-10T18:01:32.633 回答
0

阅读扩展解释后,我将尝试我的镜头:

context = $('body > *:not(div#do-not-modify-me)');
$("*:first",context);

你甚至可以这样做:

  context = $('body > *:not(div#do-not-modify-me)');
  context.find( "*:first");

要获取元素数量,您可以执行以下操作:

var len = context.length;

要访问集合中的元素编号 i,您可以使用:

context.get(i);

api.jquery.com上有大量有用的信息,也可以阅读这篇文章,您可能会想要创建自己的选择器。

编辑:
之后,我看到了您最近的更新,我认为您正在寻找的是对上下文结果元素进行迭代的能力,因此可以通过以下方式完成我在这里多次提到的:

    for ( var i = 0; i < context.length; ++i)
    {
         $( context[i]).method( );
         // do here you checks, adding, removing.
    }

这看起来不那么聪明,但应该可以工作,您可以通过扩展 $.fn 并为您的目的实现功能来封装它。 编辑#2:
让我们尝试另一种方式:

    (function($)
    {
         $.fn.tagName = function( ) 
         {
             return this.get(0).tagName;
         };
         $.fn.pick = function( tag)
         {
             return this.filter( function( )
             {
                return $(this).tagName == tag;
             });
         };
    }

})(jQuery);

在此之后您可以执行 contex.pick("p"),因此它将返回结果集中的所有段落,但是此代码不完整,因此您需要更多地查看 jquery 代码,例如在这样您就可以使用带有pick功能的完整jquery功能,可能您需要考虑使用xpath DOM parser

于 2009-06-10T18:37:00.130 回答