Пользователь
0,0
рейтинг
21 мая 2012 в 21:14

Разработка → JavaScript для «маленьких». DOM (часть 3)

Ну что же плывем дальше, а на очереди следующие 4 функций, связанные с путешествием по Антоновке. Для начала определимся с понятием «чего надобно». Итак, я хочу:
  • выбирать элементы по атрибуту ID;
  • выбирать элементы по атрибуту NAME;
  • выбирать элементы определенного тэга;
  • выбирать элементы определенного класса.


Начнем с функции получения элемента по его ID:
Хм…Назовем ее…GetElementById=>GetById=>GetId=>gi
function gi(id){
	return document.getElementById(id);
}

Здесь все просто; передаем что нужно – получаем то, что полезно.

Подобным способом напишем следующую функцию.
function gn(name){
	return document.getElementsByName(name);
}


Теперь напишем функцию получения элементов определенного тэга:
function gt(tag, el){
	return (el || document).getElementsByTagName(tag);
}

Нюанс этой функции заключается в том, что второй необязательный параметр указывает, где именно стоит искать нужные тэги. В случае его отсутствия поиск будет вестись по всей «яблоне».

Функция для получения элементов нужного класса выглядит чуточку сложнее, потому что не все браузеры предоставляют эту «родную возможность». Для этого реализуем еще одну полезную функцию, которая возьмет на себя всю работу, связанную с манипуляцией атрибутами «яблока Антоновки».
function attr(el, at, value){
	at = {'for': 'htmlFor', 'class': 'className'}[at] || at;
	if(!value){
		return el[at] || el.getAttribute(at) || '';
	}else{
		el[at] = value;
       if (el.setAttribute)	el.setAttribute(at, value);
	} 
}

Давайте построчно разберем код этой функции:

Функция имеет необязательный параметр value, при наличие которого элемент получит новый атрибут с именем at и значением value.
at = {'for': 'htmlFor', 'class': 'className'}[at] || at;

Так как в JavaScript слова «for» и «class» являются частью языка, чтобы не возникало «непредвиденных ситуаций», при обращении к одноименным атрибутам элемента, рекомендуется использовать: className, а не class, htmlFor, а не for. Поэтому, если переменная at будет равна одному из «нежелательных значений», то ее значение будет заменено на более дружелюбное.
Если мы не передавали новое значение атрибута, то возвращаем текущее, где el[at] – это быстрый способ обращения к атрибуту элемента.
Соответственно иначе устанавливаем новое значение атрибуту.

Ну и основная функция…GetElementsByClass=>GetByClass=>GetClass=>gc
function gc(name, type) {
	var r = [];
	var re = new RegExp("(^|\\s)" + name + "(\\s|$)");
	var e = (type) ? gt(type) : ((navigator.userAgent.indexOf("MSIE") >= 0) ? document.all : gt("*"));
	for ( var j = 0; j < e.length; j++ ){
		if (re.test(attr(e[j], "class"))){
			r.push( e[j] )
		}
	}
	return r;
}

Спокойно, на самом деле функция довольно проста. Разбираем:
  • Первый параметр функции – название класса, второй же – это тип элементов, среди которых нужно искать. Например: gc(“hello”, “div”) – будут найдены все div’ы страницы, с классом “hello”.
  • Далее разбираем регулярное выражение:
    "(^|\\s)" + name + "(\\s|$)"
    Так как класс у элемента может быть составным, например:
    <div class=”hello world i am tratotui ”>hello</div>
    Этот div попадет в список элементов, имеющих класс “hello”, благодаря нашему регулярному выражению.
  • Если переменная type не указана, то переменная e получит все «яблоки нашей Антоновки». Причем для получения «всех яблок» в IE используется выражение document.all, а в других браузерах достаточно выполнить функцию № 3: gt(“*”). * — любой тэг документа.
  • Иначе, если type существует, то выполняем функции № 3.
  • Ну а дальше семечки.
    Перебираем в цикле все элементы, если класс элемента удовлетворяем регулярному выражению, то добавляем его в список r.

P.S.


Предыдущие посты:

Список литературы:
JavaScript.Профессиональные приёмы программирования(Джон Рейсиг)
Олег Володин @tratotui
карма
7,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (41)

  • 0
    Может я что-то не понял, но зачем писать велосипед с регэкспами, когда есть getElementsByClassName?
    • 0
      Не везде
    • +1
      ie?
      • –1
        теперь понял
      • 0
        querySelector и querySelectorAll есть в восьмом ослике.
  • +5
    Называть функции и переменные gi, gn, el, at, gc, e, r — не самый хороший пример.
    • –3
      Если вы хотите разобраться с кодом — да, но если вы пишете библиотеку — короткие, в контексте понятные имена переменных — хорошо.
      • 0
        Для этого есть минимизаторы, а для того чтобы они работали надо создавать правильные обертки.
        • 0
          Посмотрите на код библиотеки jQuery, раз уж автор статьи ссылается на Резига, там используются короткие имена. И я не зря говорил про контекст. Хотя в статье имена чересчур короткие, согласен.
          • +1
            Покажите мне в jQuery имена типа gm gv… на публичные методы. Называть методы надо так, чтобы было понятно что они делают. Эта тема не раз подымалась на хабре. Мне например неприятно видеть статьи для новичков где заведомо говнокодят, так как в свое время наступал на подобные грабли.
            • 0
              Разумеется, публичные методы не должны так называться. Вы, наверное, не внимательно прочитали комментарий, я говорил именно про переменные.
              • 0
                А вы посмотрите внимательней исходники jquery перед тем как что-то утверждать, у них лишь временные переменные укороченые, все ключевые имеют полноценные и понятные названия + все методы и функции имеют вполне адекватные и понятные названия.
                • 0
                  Вы возможно путаете переменные с свойствами объектов, да, свойства имеют понятные название и без контекста. Но переменные в функциях все же короткие, средняя длина 4-5 символов.
                  • 0
                    Кусочек кода оттуда, огрызки — временные, а все нужные переменные имеют нормальные и понятные имена.
                    // Recurse if we're merging plain objects or arrays
                    if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                    	if ( copyIsArray ) {
                    		copyIsArray = false;
                    		clone = src && jQuery.isArray(src) ? src : [];
                    
                    	} else {
                    		clone = src && jQuery.isPlainObject(src) ? src : {};
                    	}
                    
                    	// Never move original objects, clone them
                    	target[ name ] = jQuery.extend( deep, clone, copy );
                    
                    	// Don't bring in undefined values
                    } else if ( copy !== undefined ) {
                    	target[ name ] = copy;
                    }
                    
                  • 0
                    Ещё раз, покажите такие глупые названия переменные в jQuery?
                    • 0
                      Да легко:
                      var al, bl,
                      	ap = [],
                      	bp = [],
                      	aup = a.parentNode,
                      	bup = b.parentNode,
                      	cur = aup;
                      
                      // If the nodes are siblings (or identical) we can do a quick check
                      if ( aup === bup ) {
                      	return siblingCheck( a, b );
                      
                      // If no parents were found then the nodes are disconnected
                      }
                      
                      ...
                      
                      while ( cur ) {
                      	bp.unshift( cur );
                      	cur = cur.parentNode;
                      }
                      
                      al = ap.length;
                      bl = bp.length;
                      
                      // Start walking down the tree looking for a discrepancy
                      for ( var i = 0; i < al && i < bl; i++ ) {
                      	if ( ap[i] !== bp[i] ) {
                      		return siblingCheck( ap[i], bp[i] );
                      	}
                      }
                      
                      • 0
                        Хорошо, признаю, есть такое в jQuery.
                        Но это плохой стиль и не надо ставить его в пример.
                        Учитесь хорошему и именно этот кусок кода — отвратительный.
                        • 0
                          Просто я очень долго работаю с jQuery и не просто так говорю про переменные. Использовать короткие имена можно, но очень аккуратно, чтобы в контексте было понятно о чем идёт речь. И конечно же, в приведённом мною примере стиль кода ужасный.
                          • –1
                            Ну так зачем его приводить в пример? Можно, но стиль кода будет ужасный? Так зачем использовать?
                            • 0
                              Просили пример кода jQuery с короткими переменными — вот и привел. Я не сказал что этот код хороший, но иногда короткие переменные использовать можно, например «е» в событиях, чтобы указать на event.
      • +1
        Как можно такое писать, да ещё и в статье для «маленьких»?

        «Дети» не слушаете его.
        • 0
          Я же написал, что для маленьких — это плохо. А если вы хотите писать библиотеку (значит скорее всего доросли) — то хорошо.
          • +2
            Да никогда это не хорошо.

            А если вы пишете библиотеку, это особенно плохо. Очевидно библиотекой будет пользоваться кто-то кроме вас. И наступит момент, когда этот кто-то залезет в код, чтобы получше разобраться с чем-то, или баг исправить, и проклянёт вас.
            • 0
              Тогда почему в библиотеке jQuery (не минимизированной) так много переменных с именами в 1, 2, 3 символа? Да и не только в этой библиотеке.
              • 0
                Внутри методов и функций можете делать что хотите, особенно если метод на три строчки. Но его название оставьте в покое. В jQuery они вполне осмысленны.
                • 0
                  Да не трогаю я имена функций, я говорю про переменные. Или каждый слышит то, что хочет?
          • +1
            Нет, я не могу молчать, мне-ж потом эта «библиотека» где-нибудь попасться может.

            Скажите, можете вы по названию определить, что делает функции gc(), pn(), ty()?
            Я вот уже даже не помню, какие из них встречались в этом тексте.
            Даже если вы пишите исключительно для себя — не делайте так,
            сами себе скажете потом спасибо.
            • 0
              Еще раз повторяю, в верхнем комментарии я написал про имена переменных. В именах функций, конечно же, нужно использовать понятные имена (глаголы).
              • 0
                Ок. Теперь нужно дополнить это уточнением — что в общем случае имеются в виду переменные, локальные в пределах одного метода. Да, я видел потроха jQuery, но его создатели сознательно выбирали усложнение поддержки в пользу небольшой экономии ресурсов.
                • 0
                  Да, вы правы. И это не плохой подход, это оптимизация. Хотя, конечно, порой читать исходники jQuery довольно непростое занятие.
    • 0
      я бы сказал, что это антипаттерн =)
  • 0
    Пишите все недочеты, пожелания, нюансы. Буду все разбирать.
    • +2
      ((navigator.userAgent.indexOf("MSIE") >= 0) ? document.all : gt("*"))

      ;)

      Вот моя реализация getElementsByClassName:

      
      var getElementsByClassName = function(name) {
      	if(document.querySelectorAll)
      		return document.querySelectorAll('.' + name);
      
      	else if(document.getElementsByClassName)
      		return document.getElementsByClassName(name);
      
      	else {
      		var list = document.getElementsByTagName('*'), i = list.length,
      		array = name.split(/\s+/), result = [];
      
      		while(i--) {
      			if(list[i].className.search('\\b' + array + '\\b') != -1)
      				result.push(list[i]);
      		}
      		return result;
      	}
      };
      
      • 0
        Хорошо, мне нравится =)
  • +3
    Я вообще не понимаю зачем эта статья и для кого? Вот ответьте — для кого? Помоему писать учебник в статьях на хабре — занятие очень плохое, во вторых сумбурность, непродуманность только помешает людям изучить язык.
    Помоему уже давно есть много книз где все это написано и не требует копипаста, есть прекрасный ресурс learn.javascript.ru/ написанный Ильеё Кантором. который реально тратит свое время на разработку, продумывание и обработку материла, который не копипастт отовсюду невесть, что и не ленится пару раз переписать главу чтобы он была реально понятна и точна в формулировках.
    javascript.ru/tutorial/dom — вот конкретно пара статей по DOM
    • 0
      Полностью поддерживаю. На хабре явно сидят не «маленькие». Адыкватные взрослые, которые хотят научится js, именно научится, а не просто смочь сказать «я видел пару строк на js и могу кодить на нём», такие статьи читать не будут.

      Ну и уже указанный ресурс — просто идеально подходит для начало обучения, там же есть и форум, на котором многие интересные темы уже обсуждались и есть что почитать.
  • 0
    Понимаю, пересмотрю свою точку зрения.
  • 0
    первая часть не открывается — habrahabr.ru/sandbox/44038/
    • 0
      Да и незачем. Написание подобных постов – занятие бессмысленное, т.к. приведенная информация имеется в любой книге по JavaScript. Хотя нет, написание смысл имеет, а вот публикация за пределами личного бложика – не думаю.
      • 0
        Иногда проще такой-вот бложик почитать, нежели книгу. Я очень не люблю книжно-учебное изложение, к примеру.
  • 0
    Автор, оживи ссылку на первую часть, пожалуйста. Хотел начать с начала читать, а оно ниале(

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.