Javascript.RU

Пара полезных, кроссбраузерных функций

Решил собрать функции с которыми разработчики встречаются часто.

1. Обработка события DOMContentLoaded (полная загрузка html кода) что бы func не вызывался два раза, нужно поставить проверку на выполнение этой функции

function DOMOnload(func) {
    var doc = document;
    if(doc.addEventListener) {
	        doc.addEventListener('DOMContentLoaded', func, false);	
	}
	else if(doc.attachEvent) {
	    if(doc.documentElement.doScroll && window == window.top) {
		    (function() {
		        try {
			        doc.documentElement.doScroll('left');
				    func();
			    }
			    catch(e) {
			        setTimeout(arguments.callee, 10);
			    }
			})()
		}
	}
        
	if(window.attachEvent) {
	    window.attachEvent('onload', func);	
	}
	else if(window.addEventListener) {
	    window.addEventListener('load', func, false);
	}
} // в функции func добавьте проверку, что бы она вызвалась только 1 раз

2. Получение прозрачности getOpacity

function getOpacity(obj) {
    var result = window.getComputedStyle ? window.getComputedStyle(obj, null).opacity : null; 
	if(!+"\v1")   //самое короткое определение ie		
		result = obj.filters.alpha ? (obj.filters.alpha.opacity / 100) : 1; 		
	
	return result;
}

3. Установка прозрачности setOpacity

function setOpacity(obj, val) {
    if(!+"\v1") {
	    typeof obj.filters.alpha != 'undefined'
	        ? obj.filters.alpha.opacity = val * 100
		    : obj.style.filter = 'alpha(opacity=' + val * 100 + ');';
	}
		
	obj.style.opacity = val;
}

4. Добавление события addEvent

function addEvent(obj, type, func) {
    if(obj.addEventListener) {
        obj.addEventListener(type, func, false);	
    }
    else if(obj.attachEvent) {
        var f = function(e) {
            func.call(obj, e); 
        }
        obj.attachEvent('on' + type, f); // obj.attachEvent('on' + type, func); не правильно передаст объект this
    }	
}

5. Получение координат мыши getMousePos

function getMousePos(e) {
    var mouseX = mouseY = 0;
    var e = e || window.event;
    var html = document.documentElement;
    var bady = document.body;
		
    if(document.attachEvent) {
        mouseX = e.clientX + (html.scrollLeft ? html.scrollLeft : bady.scrollLeft);
	    mouseY = e.clientY + (html.scrollTop  ? html.scrollTop  : bady.scrollTop);			
    }
    else if(document.addEventListener) {
	    mouseX = e.clientX + window.scrollX;
	    mouseY = e.clientY + window.scrollY;
    }
	return {x : mouseX, y : mouseY}
}

6. Получение места расположения объекта getObjPos

function getObjPos(elem) {  
    var box = elem.getBoundingClientRect()  
    
    var body = document.body  
    var docElem = document.documentElement  
    
    var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop  
    var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft  
    
    var clientTop = docElem.clientTop || body.clientTop || 0  
    var clientLeft = docElem.clientLeft || body.clientLeft || 0  
    
    var top  = Math.round(box.top +  scrollTop - clientTop);
    var left = Math.round(box.left + scrollLeft - clientLeft);  
	
	return {x : left, y : top}
}
+5

Автор: ixth, дата: 4 октября, 2010 - 19:16
#permalink

> function getOpacity(obj)

Ой, порочный способ по-моему. Прежде всего result, возвращаемый фильтром, затирается, затем страшная конструкция с currentStyle (проприетарное из Explorer'а, да?).

Я бы сократил так, но не уверен в целесообразности currentStyle:

function getOpacity(obj) {
	if (obj.filters) {
		return obj.filters.alpha.opacity || 1;
	} else {
		return (obj.currentStyle || obj.style).opacity || 1;
	}
}

Автор: HelpeR, дата: 4 октября, 2010 - 20:04
#permalink

Так нельзя сокращать, т.к. если значение прозрачности будет равно нулю, то такая строка

return (obj.currentStyle || obj.style).opacity || 1;

всегда будет возвращать 1. Поэтому важной проверкой в этой функции является эта строка

(obj.currentStyle || obj.style).opacity !== ''

Если возвращаемый результат будет равен 0 и сравнение будет != , то опять таки возвращаемый результат всегда будет 1. А obj.currentStyle нужен для того, что бы получить значение стиля если он установлен через CSS


Автор: ixth, дата: 4 октября, 2010 - 23:21
#permalink

Да, действительно. Но с currentStyle я все равно не понял. Он ведь проприетарный и работает только в ie, который изначально отфильтровывается. В семерке разве не поддерживается element.style?


Автор: HelpeR, дата: 5 октября, 2010 - 13:46
#permalink

Удобства currentStyle в этом случае таково, что оно работает точно так же (кроме установки значения) как и style, но может получать первоначальное значение стиля прописанного с помощью CSS


Автор: I-zone, дата: 4 октября, 2010 - 21:57
#permalink

Ерунда и велосипед.

result = obj.filters?obj.filters.alpha.opacity:1;

После этого вы сразу переписываете значение.
Хотя бы так:

getOpacity=function(elem){
   if(typeof elem.style.opacity=="number") return elem.style.opacity;
   if(elem.style.filter) return Number(elem.style.filter.match(/opacity=(\d+)/i)||[1,1])[1]);
   return 1;
}

> DOMContentLoaded (полная загрузка html кода)
CB DOMContentLoaded


Автор: HelpeR, дата: 5 октября, 2010 - 13:44
#permalink

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

if(typeof elem.style.opacity=="number") return elem.style.opacity;

точно попадает, т.к. таким образом не получишь значение прописанное через CSS
Переписал функцию

function getOpacity(obj) {
    var result;
	result = window.getComputedStyle ? window.getComputedStyle(obj, null).opacity : null; // Firefox, Opera, Chrome

	if(result === null) { // для IE так же удобно получать значение opacity, что бы прописывать в setOpacity
	    result = typeof (obj.currentStyle || obj.style).opacity != 'undefined' && (obj.currentStyle || obj.style).opacity !== ''
	        ? (obj.currentStyle || obj.style).opacity
	        : 1;
	}
	return result;
}

Автор: I-zone, дата: 5 октября, 2010 - 22:50
#permalink

В список ерунды попадает твоя фунция в принципе, ибо она не достанет свойство в 70% браузеров. В IE<8, свойства opacity нет.

return (obj.currentStyle || obj.style).opacity || 1;

>всегда будет возвращать 1. Поэтому важной проверкой в этой функции является >эта строка

Бред. style.opacity возвращает не число, а строку...

!!0 - будет false, !!"0" - будет true;


Автор: HelpeR, дата: 6 октября, 2010 - 14:31
#permalink

>В список ерунды попадает твоя фунция в принципе, ибо она не достанет свойство в 70% браузеров. В IE<8, свойства opacity нет.

Опять вы ленитесь! IE6 и 7 поддерживают это свойство.

>Бред. style.opacity возвращает не число, а строку...

Если значение будет установлено след. образом

style.opacity = 0;

то

return (obj.currentStyle || obj.style).opacity || 1;

эта строка вернет 1 хотя должна была вернуть 0


Автор: I-zone, дата: 11 октября, 2010 - 00:03
#permalink

> эта строка вернет 1 хотя должна была вернуть 0
Если ты установишь 0 туда, где не поддерживается свойство opacity, поэтому рекомендую устанавливать "0", на такой случай. Так и правильней, ведь в CSS свойства строковые. Попробуй проверить typeof в разных браузерах

И с каких пор IE поддерживает свойство opacity?
Ты мне говоришь "Опять вы ленитесь!", если самому лень элементарно проверить или прочитать где нибудь в интернете про это свойство...
Если его можно установить - это не значит, что оно меняет прозрачность.

Это свойство поддерживается лишь в W3C совместимых браузерах и является частью рекомендаций CSS3, IE таковым никогда не был и использует DirectX фильтры...

Зачем тогда в своем первом примере считываешь прозрачность через фильтр, а в фунции setOpacity записываешь фильтр?

Не заметил, сам себе противоречишь!


Автор: I-zone, дата: 5 октября, 2010 - 23:02
#permalink

Проще рассказать минусы.

1) Нет обработки filter для ie
2) В первую очередь ты вытаскиваешь изначальное значение, которое никогда не поменяется. т.е. в первую очередь нужно смотреть в .style, а потом уже вычислять computed.
Твоя функция будет возвращать всегда только одно значение, если изначально стиль имел значение opacity.
4) var result; result =
Не проще var result=, сэкономил 9 байт

Можно еще перечислить, но лень...
Вот еще вариант, который можно улучшить, опять же лень))

var getOpacity=function(style){
   if(!style) return;
   if(style.nodeName){
      var computed=window.getComputedStyle?getComputedStyle(style,null):style.currentStyle;
      return getOpacity(style.style)||getOpacity(computed)||1;
   }
   var opacity=style.opacity, filter=style.filter;
   if(opacity){
      return Number(opacity);
   }else if(filter){
      var alpha=filter.match(/opacity=(\d+)/i);
      if(alpha&&alpha[1]) return Number(alpha[1])/100;
   }
}

Функция setOpacity:

function setOpacity(obj, val) {
    obj.style.filter && obj.filters
	    ? obj.filters.alpha.opacity = val * 100
		: obj.style.filter = 'alpha(opacity=' + val * 100 + ');';
		
	obj.style.opacity = val;	
}

Если будет указан фильтр, но не будет указана alpha, то свойство obj.filters.alpha - будет undefined, дальнейший вызов obj.filters.alpha.opacity выкинет ошибку-исключение...
Зачем вообще извращение с obj.filters.alpha.opacity, если можно просто установить obj.style.filter? Разве что только для сохранения другого фильтра.

Наверное лучше:

var setOpacity=function(el,alpha){
   el.style.filter="alpha(opacity="+(el.style.opacity=alpha)*100+")";
}

Автор: HelpeR, дата: 6 октября, 2010 - 14:32
#permalink

>1) Нет обработки filter для ie
2) В первую очередь ты вытаскиваешь изначальное значение, которое никогда не поменяется. т.е. в первую очередь нужно смотреть в .style, а потом уже вычислять computed.
Твоя функция будет возвращать всегда только одно значение, если изначально стиль имел значение opacity.

1) Взамен этого и достается значение opacity
2) Разница getComputedStyle и style для не IE в том, что с помощью первого можно только читать, а с помощью второго можно и читать и устанавливать. Не ленитесь не в чем!

.d {
   opacity:0.2;   
}
<div id="d" class="d">Text</div>
var d = document.getElementById('d');
d.style.opacity = 0.33;
function getOpacity(obj) {
	var result = window.getComputedStyle ? window.getComputedStyle(obj, null).opacity : null; // Firefox, Opera, Chrome

	if(result === null) { //IE
	    result = typeof (obj.currentStyle || obj.style).opacity != 'undefined' && (obj.currentStyle || obj.style).opacity !== ''
	        ? (obj.currentStyle || obj.style).opacity
	        : 1;
	}
	return result;
}
alert(getOpacity(d));

>Наверное лучше:
Опять таки не ленитесь и если сомневаетесь, то проверьте!


Автор: I-zone, дата: 10 октября, 2010 - 23:25
#permalink

> Взамен этого и достается значение opacity

Оно всего лишь достается, раз ты сам его вписал! А прозрачности не будет в IE, если фильтр не установлен.

А со вторым, просмотрел я проверку if(result === null) { //IE


Автор: I-zone, дата: 5 октября, 2010 - 22:55
#permalink
function addEvent(obj, evnt, func) {
    if(obj.attachEvent) {
	    obj.attachEvent('on' + evnt, func);	
	}
	else if(obj.addEventListener) {
	    obj.addEventListener(evnt, func, false);
	}
}

Зачем так Oper'у обидел? Будет вернее:

function addEvent(obj, evnt, func) {
   if(obj.addEventListener) {
      obj.addEventListener(evnt, func, false);
   }else if(obj.attachEvent) {
      obj.attachEvent('on' + evnt, func);	
   }
}

То же самое и тут:

function getMousePos(e) {
	mouseX = mouseY = 0;
    var e = e || window.event;
	var html = document.documentElement;
	var bady = document.body;
		
	if(document.attachEvent) {
        mouseX = e.clientX + (html.scrollLeft ? html.scrollLeft : bady.scrollLeft);
	    mouseY = e.clientY + (html.scrollTop  ? html.scrollTop  : bady.scrollTop);			
    }
    else if(document.addEventListener) {
	    mouseX = e.clientX + window.scrollX;
	    mouseY = e.clientY + window.scrollY;
    }
	return {x : mouseX, y : mouseY}
}

Плюс засоряешь глобал переменными mouseX = mouseY = 0;
Сам писал, что при нуле условие не сработает, так?
html.scrollLeft ? html.scrollLeft : bady.scrollLeft

А вообще можно перечислить еще громадное количество ошибок, можешь поверить на слово.
Зачем надо было это писать и путать новичков в js, подобным абсурдным арсеналом?


Автор: HelpeR, дата: 6 октября, 2010 - 14:51
#permalink

>Плюс засоряешь глобал переменными mouseX = mouseY = 0;

Согласен!

>Сам писал, что при нуле условие не сработает, так?
В этом случае это не играет роли, если прокрутка равна нулю, но так и надо!

>Зачем надо было это писать и путать новичков в js, подобным абсурдным арсеналом?
Не соглашаюсь, вашим мнением, т.к. они основаны всего лишь на ваших рассуждениях!


Автор: I-zone, дата: 11 октября, 2010 - 10:02
#permalink

> Не соглашаюсь, вашим мнением, т.к. они основаны всего лишь на ваших рассуждениях!

Ну да, в прошлой статье ты тоже был уверен, что открыл мега способ, ну да ладно...
Понимаю, что мне не доверяешь, а себе доверяешь?
Тогда предлагаю протестировать (!) СВОИ (!) функции:
1) Функции addEvent, getMousePos под браузерами Opera, особенно 9.XX, посмотреть, как ставятся ивенты.
2) setOpacity в IE, если установлен фильтр и не указана alpha.
3) Свою последнюю getOpacity в IE, если .div {filter: alpha(opacity=90)}
4) DOMOnload попробовать навесить два обработчика, это позволяют делать все библиотеки.
5) getObjPos попробовать запустить в Safari, Chrome, Konqueror, FF2 (В самых новых версиях WebKit уже поддерживается getBoundingClientRect)

> Пара полезных, кроссбраузерных функций

Да уж, кроссбраузерность!

Даже я твои функции потестил, а ты никак не соберёшься, а еще мне пишешь, чтобы не ленился...


Автор: Craigy (не зарегистрирован), дата: 7 октября, 2010 - 09:18
#permalink

Похоже на повторное изобретение велосипеда, только отточенный аппарат был сделан заново некрасиво и с ошибками...
Всё это есть в jquery и иже с ними, причём в гораздо более продуманном виде.

Вашим хозяйством как-то совсем уж неудобно пользоваться...


Автор: I-zone, дата: 11 октября, 2010 - 00:28
#permalink

В DOMOnload хорошо бы сделать проверку document.readyState и/или document.onreadystatechange, как в цивиллизованых библиотеках.

В DOMOnload навешивая мнежества обработчиков, с коллбеком func, ты обрекаешь пользователь на её многокрытный запуск, потому что в 90% случаев сработает несколько событий.

(obj.currentStyle || obj.style).opacity != 'undefined'

Вот это проверка!!!
Когда это opacity бывало со значением "undefined"?
Может быть так, не?

(obj.currentStyle || obj.style).opacity!=undefined

Или

typeof (obj.currentStyle || obj.style).opacity!='undefined'

И ещё

(obj.currentStyle || obj.style).opacity!==''

Большинство браузеров возвращают null, если свойство поддерживается, но не установлено, а ""!==null

(obj.currentStyle || obj.style).opacity !== ''

Вызовет ошибку у элемента с пустым style и если браузер не поддерживает getComputedStyle (кроме IE). У undefined не возможно прочитать свойство opacity

Пишу снова, что есть еще куча ошибок


Автор: HelpeR, дата: 11 октября, 2010 - 16:31
#permalink

Исправил функцию getOpacity!
Протестил IE6,7,8 Firefox 3.6 Opera 10.53 Chrome 6.0.472.63


Автор: I-zone, дата: 11 октября, 2010 - 19:45
#permalink
function getOpacity(obj) {
    var result = window.getComputedStyle ? window.getComputedStyle(obj, null).opacity : null; 
	if(result === null)   		
		result = obj.filters.alpha ? (obj.filters.alpha.opacity / 100) : 1; 		
	
	return result;
}

>Протестил IE6,7,8 Firefox 3.6 Opera 10.53 Chrome 6.0.472.63

1) Браузеры не поддерживающие getComputedStyle и страницы в которых не установлена .opacity (! КРОМЕ IE) попадают в жестокую битву с result = obj.filters.alpha ? (obj.filters.alpha.opacity / 100) : 1; и сразу же выкидывают исключение, потому что у них нет свойства obj.filters.
Большинство браузеров W3C в которых свойство не установлено никаким из способов, будет вызывать ошибку исключение.

2) obj.style.filter="progid:DXImageTransform.Microsoft.Alpha(opacity=80)";
Этот вариант является предпочтительным в IE (синтаксис IE5), и именно таким способом устанавливают прозрачность множество (если не большинство) webdev.
obj.filters.alpha - не считает это свойство, а считывается оно так:
obj.filters['DXImageTransform.Microsoft.alpha']
Потому и удобнее использовать регулярку /opacity=([0-9])/i

3) А если opacity не задано? Будешь undefined на сто делить и возврашать пользователю NaN, чтобы у него весь дальнейший код порушить? (obj.filters.alpha.opacity / 100)

4) window.getComputedStyle ? window.getComputedStyle(obj, null).opacity
В этом случае, ты возвращаешь string.
obj.filters.alpha ? (obj.filters.alpha.opacity / 100)
А в этом - number.
Если пользователь захочет прибавить 0.1 к opacity равмому 0.1 полученному через твою функцию, в IE он получит число 0.2, в других браузерах строку "0.10.1"
Стоит хотя бы так сделать: return Number(result);

5) И опять же можно продолжить

Воспользуюсь твоей фразой: "Не ленитесь не в чем!" и "Опять таки не ленитесь и если сомневаетесь, то проверьте!"


Автор: HelpeR, дата: 11 октября, 2010 - 22:07
#permalink

>1) Браузеры не поддерживающие getComputedStyle
Хотел бы поинтересоваться, что это за браузеры кроме IE

>и страницы в которых не установлена .opacity
если у элемента не установлен opacity не в каком виде, getComputedStyle вернет 1, а это выражение

result = obj.filters.alpha ? (obj.filters.alpha.opacity / 100) : 1;

тоже вернет 1.
Функция работает так:
1) Если это не IE и opacity не установлен, то

window.getComputedStyle ? window.getComputedStyle(obj, null).opacity : null;

вернет 1! А если opacity установлен либо через css либо через javascript, то

window.getComputedStyle(obj, null).opacity

вернет это значение.
2) Если IE и

filter:alpha(opacity=50)

установлен через css или

obj.style.filter = 'alpha(opacity=53)';
//а в дальнейшем 
obj.filters.alpha.opacity = 88;

, то

obj.filters.alpha

будет иметь значение [object] и свойство opacity всегда доступно. А если alpha никаким образом и ни где не указано, то возвращаемый результат будет 1!
Долго тестил перед тем как выкладывать! согласен на счет того, что выдаваемый результат нужно возвращать в числовом виде!


Автор: I-zone, дата: 12 октября, 2010 - 17:04
#permalink

И действительно getComputedStyle возвращает 1, хотя и есть ноды, в которых свойство не прочитать.
И alpha тоже возвращает, с любыми стилями, позициями и конечной прозрачностью в фильтре.
Проглядел.

ОК, 1 и 3 пункт снимаются из за невнимательности

Ну а такое:
.filter="progid:DXImageTransform.Microsoft.Alpha(opacity=80)";
или, как сейчас валидней в ie8:
.MsFilter="progid:DXImageTransform.Microsoft.Alpha(opacity=80)";
функция не достанет, что очень печально, так как использует этот синтаксис очень много девелоперов

Ну раз снял 2 пункта, надо бы их возместить

function setOpacity(obj, val) {
    if(document.all) {
	    typeof obj.filters.alpha != 'undefined'
	        ? obj.filters.alpha.opacity = val * 100
		    : obj.style.filter = 'alpha(opacity=' + val * 100 + ');';
	}
		
	obj.style.opacity = val;
}

1) Коллекция document.all есть уже почти во всех современных браузерах и obj.filters.alpha вызовет исключение в браузерах (не ie).
2) Этим:
obj.style.filter = 'alpha(opacity=' + val * 100 + ');
затираешь другие фильтры, применённые к элементу. Например так часто используемый DXImageTransform.Microsoft.AlphaImageLoader.

Удачи


Автор: Tester (не зарегистрирован), дата: 11 декабря, 2010 - 21:23
#permalink

у вас тут ошибочка!!!

Форум Книги Блоги Стандарт языка * Мастер-классы по javascript * Справочник
Статьи Тест знаний Аналоги функций PHP PHPClub.ru Примерочная Курсы javascript

Поиск по форуму

Отображать темы Отображать сообщения
Расширенный поиск

К странице...

Главная » Javascript-Блоги » HelpeR » Пара полезных, кроссбраузерных функций

« Проблема insertBefore с таблицейДоступ к объекту filters »
HelpeR (блог) , 4 окт 2010 - 13:34 функции просмотров:2232

Пара полезных, кроссбраузерных функций
Решил собрать функции с которыми разработчики встречаются часто.

1. Обработка события DOMContentLoaded (полная загрузка html кода) что бы func не вызывался два раза, нужно поставить проверку на выполнение этой функции

показать чистый исходник в новом окнеСкрыть/показать номера строкпечать кода с сохранением подсветки01 function DOMOnload(func) {

02 var doc = document;

03 if(doc.addEventListener) {

04 doc.addEventListener('DOMContentLoaded', func, false);

05 }

06 else if(doc.attachEvent) {

07 if(doc.documentElement.doScroll && window == window.top) {

08 (function() {

09 try {

10 doc.documentElement.doScroll('left');

11 func();

12 }

13 catch(e) {

14 setTimeout(arguments.callee, 10);

15 }

16 })()

17 }

18 }

19

20 if(window.attachEvent) {

21 window.attachEvent('onload', func);

22 }

23 else if(window.addEventListener) {

24 window.addEventListener('load', func, false);

25 }

26 } // в функции func добавьте проверку, что бы она вызвалась только 1 раз

2. Получение прозрачности getOpacity

показать чистый исходник в новом окнеСкрыть/показать номера строкпечать кода с сохранением подсветки1 function getOpacity(obj) {

2 var result = window.getComputedStyle ? window.getComputedStyle(obj, null).opacity : null;

3 if(!+"\v1") //самое короткое определение ie

4 result = obj.filters.alpha ? (obj.filters.alpha.opacity / 100) : 1;

5

6 return result;

7 }

3. Установка прозрачности setOpacity

показать чистый исходник в новом окнеСкрыть/показать номера строкпечать кода с сохранением подсветки1 function setOpacity(obj, val) {

2 if(!+"\v1") {

3 typeof obj.filters.alpha != 'undefined'

4 ? obj.filters.alpha.opacity = val * 100

5 : obj.style.filter = 'alpha(opacity=' + val * 100 + ');';

6 }

7

8 obj.style.opacity = val;

9 }

4. Добавление события addEvent

показать чистый исходник в новом окнеСкрыть/показать номера строкпечать кода с сохранением подсветки01 function addEvent(obj, type, func) {

02 if(obj.addEventListener) {

03 obj.addEventListener(type, func, false);

04 }

05 else if(obj.attachEvent) {

06 var f = function(e) {

07 func.call(obj, e);

08 }

09 obj.attachEvent('on' + type, f); // obj.attachEvent('on' + type, func); не правильно передаст объект this

10 }

11 }

5. Получение координат мыши getMousePos

показать чистый исходник в новом окнеСкрыть/показать номера строкпечать кода с сохранением подсветки01 function getMousePos(e) {

02 var mouseX = mouseY = 0;

03 var e = e || window.event;

04 var html = document.documentElement;

05 var bady = document.body; здесь var body!!!!<<<<<<<<<


Автор: HelpeR, дата: 14 декабря, 2010 - 09:48
#permalink

с чего вы взяли, что должно быть body?


Автор: I-zone, дата: 16 декабря, 2010 - 14:06
#permalink

Синтаксически-правильнее, более читабельно.
Можно было-бы и var html назвать var hpml


 
Поиск по сайту
Другие записи этого автора
HelpeR
Содержание

Учебник javascript

Основные элементы языка

Сундучок с инструментами

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Популярные таги
Последние темы на форуме
Forum