Превращение сложного селектора jquery css в контекст для кеширования - PullRequest
0 голосов
/ 10 июня 2009

После обратной связи завершите переписывание вопроса.

У меня есть следующая разметка:

<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)');

Я делаю это, чтобы получить все содержимое тела, кроме div, с идентификатором "do-not-modify-me".

Теперь, допустим, я хочу создать функцию, которая позволит другому программисту выбирать что-либо в теле, так же как выбор с помощью 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 () к дочерним элементам результата контекста, а не к самому результату.

E.G:

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 ]

1 голос
/ 11 июня 2009

Вы сказали, что код можно изменить любым способом, верно? Почему бы просто не думать об этом как о том, что вы делаете хотите искать вместо того, что вы не хотите искать. Поместите оставшуюся часть кода в <div> и просто используйте это как контекст. Это не собирается выиграть какие-либо награды за элегантность, но это просто и получает задание выполнено TM .

1 голос
/ 10 июня 2009

Я удалил все предыдущие правки, так как они больше не актуальны, их можно прочитать в истории правки.
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)');
  });
}

Вы должны попробовать сами, какой из них быстрее. Я не думаю, что есть какой-то другой способ убедиться, что вы не ищете в div # do-not-modify-me.

Еще одно, что вы можете сделать, чтобы сделать это еще проще (и думаю, быстрее), - обернуть редактируемую область в 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') );
}
0 голосов
/ 10 июня 2009

Прочитав расширенное объяснение, я попробую свой выстрел:

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 есть тонны полезной информации, также прочитайте this , вероятно, вы захотите создать свой собственный селектор.

EDIT:
После того, как я увидел ваше последнее обновление, я думаю, что вы ищете возможность перебирать элементы результатов контекста, так что это можно сделать, как я упоминал здесь несколько раз:

    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, например, чтобы реализовать таким образом, вы сможете использовать полную функциональность jquery с функцией pick, вероятно, вам следует рассмотреть возможность использования xpath DOM parser .

0 голосов
/ 10 июня 2009

Я почти уверен, что вы можете просто использовать 'context' напрямую, вот так:

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