Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Наши скрипты > Перестановка блоков.


Автор: AKS 9.11.2006, 09:33
Функция для перестановки блоков была написана вчера на форуме http://xpoint.ru/forums/programming/javascript/misc/thread/38776.xhtml в результате попыток "оказать помощь" в решении следующей задачи. 
Автору темы нужно было переставлять блоки при клике по заголовку блока. Каждый блок при этом должен меняться местом с "верхним соседом". Нечто похожее обычно делают для сортировки таблиц. Одно из условий было таким - в заголоке могут быть ссылки, и при клике по ним должен осуществляться обычный переход по ссылке без перестановки блока.
Предлагая вам эту самую функцию, которая выполняет описанные выше действия, отмечу парочку условий: 
  • перемещаемые блоки должны быть родительскими элементами для заголовков (в функции это заголовки h3)
  • перемещаемые блоки должны находиться в одном блоке-контейнере, который будет заниматься "перетасовкой" этих блоков (см. пример (x)html-кода)
Спасибо Zeroglif, т.к. этот код ни что иное, как попытка реализовать все то, что он показывал и объяснял.
Надеюсь, что эта функция сможет пригодиться для практического применения или же просто для обсуждения каких-либо аспектов использования JavaScript (последнее лично меня интересует больше всего).

JavaScript (может располагаться в любом месте страницы):
Код

var F = (function(o, e) {
  o = (e) ? o : (e = 'click', 
    document.getElementById('content').getElementsByTagName('h3'));
  var l, b, m = (this.addEventListener) ? 'addEventListener' : 
    (b = (e = 'on' + e), 'attachEvent');
  if(l = o.length) for(var i = 0; i < l; i++) o[i][m](e, F, !1);
  else if(o[m]) { 
    l = (b) ? ')' : ', !1)'; 
    eval('o[m](e, arguments.callee' + l); 
    return (function(e) {
      var el = e.srcElement || e.target, s, b;
      while((s = el.tagName.toLowerCase()) != 'div') { 
        el = el.parentNode; 
        if(s == 'a') return;
      }
      while((s = (b) ? s : (b = el.previousSibling)) && s.nodeType != 1) 
        s = s.previousSibling;
      el.parentNode.insertBefore(el, s);
    });
  }
})((window.opera) ? document : window, 'load');

(x)html (примерный образец того, какой должна быть разметка):
Код

<div id='content'>
  <div>
    <h3><a href='#' title=''><span style='color:green'>t</span>ext1</a></h3>
    <p>sdfdsf</p>
  </div>
  <div>
    <h3><i>text2</i></h3>
    <p>dsdfd</p>
  </div>
  <div>
    <h3>text3</h3>
    <ul>
      <li>ddsf</li>
      <li>ddsf</li>
    </ul>
  </div>
  <div>
    <h3>texts</h3>
    <p>dfdsf</p>
  </div>
</div>

Автор: SelenIT 9.11.2006, 13:13
AKS, прошу прощения за частичный оффтоп, но... в Опере с onload для window есть проблемы? Какие?

Автор: AKS 9.11.2006, 17:43
SelenIT, 
Цитата

Опере с onload для window есть проблемы?
 
Проблем-то нет, просто когда нужно было выбирать между addEventListner и attachEvent (чуть ниже поясню зачем нужен выбор) мне надо было передать параметром в функцию document, т.к. в моей Opera 7.23 нет window.addEventListener, а есть только document.addEventListener. 
Это осталось из темы http://forum.vingrad.ru/topic-117729.html. Там нужно было выбрать именно метод addEventListener, т.к. в случае выбора attachEvent моя Opera 7.23 не хотела принимать третий аргумент (т.е. window.attachEvent(event, method, capture) работает, но только не в Opera 7.23). Тогда я сумел найти только два варианта:
  • передать document, используя конструкцию (window.opera) ? document : window
  • или использовать eval, как здесь ( eval('o[m](e, arguments.callee' + l); )
В тот раз я выбрал первое.
В данном сценарии конструкция (window.opera) ? document : window не нужна, но и не мешает  ;)  - поэтому осталась "валяться". 
Зато когда я возился с этой функцией (а возился я долго ;) ), я обнаружил для себя интересный факт, касающийся Opera и ключевого слова this. 
Как видно из сценария, я здесь использовал такую вот конструкцию для определения поддерживаемого метода:
m = (this.addEventListener) ? ....
При первом вызове this указывает на window и Opera 7.23 выбирает в этом случае attachEvent (нет у нее window.addEventListener) и поэтому, именно для нее, потом пришлось применять eval. Но оказалось, что eval понадобится только при первом вызове! В Opera во время второго вызова ключевое (или, опять же, "глючевое" ;) ) слово this указывает на object HTMLDocument!!! Мне-то, конечно, хорошо - не пришлось использовать eval в цикле for, но... Касательно Opera 8+ - у них есть window.addEventListener, но в зарегестрированном методе this указывает на документ, а у "лисиц" this указывает на window. 
Вот такая вот у них (Opera) осталась странность с поддержкой window.addEventListener...

Автор: AKS 9.11.2006, 18:18
SelenIT, можно в условии проверки на поддержку методов 
m = (this.addEventListener) ? ....
заменить this на document. Тогда не нужен будет eval, однако для Opera 7 обязательным будет 
(window.opera) ? document : window
...

Автор: SelenIT 9.11.2006, 18:27
AKS, огромное спасибо за подробное объяснение! Осталось мне утрясти его в голове (столько нового за раз;)...

Цитата(AKS @  9.11.2006,  17:43 Найти цитируемый пост)
...ключевое (или, опять же, "глючевое" ;)...

5+ smile!

Вообще, загадочная она - Опера... хотя если покопать, так все браузеры загадочные)

AKS, еще к слову об Опере: в новых версиях нет такого, что поведение скриптов меняется в зависимости от того, под кого она мимикрирует? В 6-х, кажется, было... или это уже мои персональные глюки?

Автор: AKS 9.11.2006, 18:37
SelenIT, 
Цитата

в новых версиях нет такого, что поведение скриптов меняется в зависимости от того, под кого она мимикрирует?

Я не знаю. Вообще, такое сделать ей вряд ли под силу. Т.е. одно дело идентифицироваться по-разному, а другое дело работать по-разному - получается, что для этого ей надо иметь набор разных движков. Хотя чего только не бывает...   ;) 

Автор: Kasper1985 11.6.2007, 21:29
Подскажите пожалуйста как сделать чтобы свободно позиционируемы элементы на странице не смещались в сторону при изменении разрешения экрана, ни при нажатии f11 и т.д. Заранее спасибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)