Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Кросс-браузерные функции (https://javascript.ru/forum/project/3754-kross-brauzernye-funkcii.html)

B~Vladi 20.05.2009 13:14

Кросс-браузерные функции
 
Вот такими функциями пользуюсь для себя. Может кому-то будут полезны. Пишите если в них что-то не так.

Функция получения CSS-свойства.

function xGetStyleValue(e,type1,type2){
	if(!type2)type2=type1;
	if(e.currentStyle&&e.currentStyle[type2]!='')return e.currentStyle[type2];
	else if(window.getComputedStyle(e,'').getPropertyValue(type1)!='')return window.getComputedStyle(e,'').getPropertyValue(type1);
}


Функция возвращает установленное, либо вычисленное значение указаного CSS-свойства. Под установленным подразумевается, значение описанное в CSS файле, либо присвоено по-умолчанию браузером. Если возвращается дефолтное значение, то естесственно оно может различаться в разных браузерах. Так же стоит заметить, что некоторые браузеры хранят значение CSS-свойств в разных форматах. Это не значит, что вы получите неправельные данные, просто они немного другого вида. Допустим вы определили в CSS файле сойство background-color в #fff для узла body. Тогда при попытке получить значение этого свойства, IE возвратит #fff, а Mozilla rgb(255, 255, 255). Оба ответа являются правельными и для того чтобы можно было пользоваться ими, необходима дополнительная функция-конвертер. Функция xGetStyleValue показывает, как всё-таки можно получить значения CSS свойств, если вы явно не указывали его в скрипте или через аттрибут style, т.к. при обращении, например, к ele.style.backgroundColor мы получим пустую строку.

Параметры:

e - узел DOM
type1 - своиство CSS (строка) как при использовании в файлах стилей, например 'margin-left'
type2 - свойство CSS (строка) как при динамическом обращении, например 'marginLeft'

Если свойства CSS одинаковые в обоих представлениях, например width, второй параметр можно не указывать.

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

function xAlpha(e,n){
	(document.body.style.opacity)?e.style.opacity=n/100:e.style.filter=(n>=100)?null:'progid:DXImageTransform.Microsoft.Alpha(opacity='+n+')';
}


Параметры:

e - узел DOM
n - число от 0 до 100. 100 - нет прозрачности.

Функции получения размеров клиентской области окна

function xClientWidth(){return document.compatMode=='CSS1Compat'&&!window.opera?document.documentElement.clientWidth:document.body.clientWidth;}
function xClientHeight(){return document.compatMode=='CSS1Compat'&&!window.opera?document.documentElement.clientHeight:document.body.clientHeight;}


Функции для работы с событиями

Добавление функции для обработчика

function xAddEventListener(e,eventType,eventListener){
	if(e.addEventListener) e.addEventListener(eventType,eventListener,false);
	else if(e.attachEvent) e.attachEvent('on'+eventType,eventListener);
}


Параметры:

e - узел DOM
eventType - тип события без префикса 'on', например 'mousedown'
eventListener - имя регистрируемой функции

Удаление функции из обработчика

function xRemoveEventListener(e,eventType,eventListener){
	if(e.removeEventListener) e.removeEventListener(eventType,eventListener,false);
	else if(e.detachEvent) e.detachEvent('on'+eventType,eventListener);
}


Параметры аналогичны функции xAddEventListener().

Получение объекта, вызвавшего данное событие

function xGetEventTarget(evt){
	var e=evt.target||event.srcElement;
	return (e.nodeType==1)?e:e.parentNode;
}


В качестве параметра передаём событие. Например мы зарегистрировали функцию onEvent() с помощью функции xAddEventListener(). Для того, чтобы передать событие в нашу ф-цию пишем так:

function onEvent(evt){
	var e=xGetEventTarget(evt);
}


В переменной е хранится узел DOM, сгенерировавший событие.

Снятие выделения с текста

function clearSelection(){
	(document.selection&&document.selection.empty)?document.selection.empty():window.getSelection().removeAllRanges();
}


Отмена просачивания события

function xClearEvent(evt){
	if(evt.stopPropagation)evt.stopPropagation();
	else event.cancelBubble=true;
}


Сюда передаём сгенерированное событие, как для xGetEventTarget().

Отмена события по-умолчанию

function xCancelDefEvent(evt){
	if(evt.preventDefault)evt.preventDefault();
	else event.returnValue=false;
}


Сюда передаём сгенерированное событие, как для xGetEventTarget().

Функции для работы с AJAX

Создание объекта AJAX

function xCreateRequest(){
	return (window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP");
}


Трансормация XML + XSL

function xTransform(xml,xsl){
	if(window.ActiveXObject)return xml.transformNode(xsl);
	var proc=new XSLTProcessor();
	var ser=new XMLSerializer();
	proc.importStylesheet(xsl);
	return ser.serializeToString(proc.transformToFragment(xml,document));
}


Передаём файлы XML и XSL, полученные в AJAX-ответе и получаем строку, которую затем можно вставить на страницу методом innerHTML.

Пока всё... Если кому непонятно как использовать ту или другую функцию - пишите.

ZoNT 20.05.2009 13:27

Цитата:

Сообщение от B~Vladi
if(e.currentStyle&&eval('e.currentStyle.'+type2)!= '')return eval('e.currentStyle.'+type2);

жесть!!! e.currentStyle[type2] не катит уже?
Цитата:

Сообщение от B~Vladi
function xGetEventTarget(evt){ var e=evt||window.event; return (e.target)?e.target:e.srcElement; }

function xGetEventTarget(e){
    e=e||event;
    return e.target||e.srcElement
}

ну и так далее...

B~Vladi 20.05.2009 13:31

СПС за замечание... оптимизация енто хорошо... исправлю...

Riim 20.05.2009 13:41

Цитата:

Сообщение от B~Vladi
if(document.getElementById)

Интересно где бы откопать браузер, который не поддерживает getElementById. Мне такой для коллекции нужен.

Цитата:

Сообщение от B~Vladi
if(e.currentStyle&&eval('e.currentStyle.'+type2)!= '')return eval('e.currentStyle.'+type2);

eval - зло. Здесь он совершенно не нужен.

Цитата:

Сообщение от B~Vladi
function xGetStyleValue(e,type1,type2){

Вы точно протестировали эту функцию? Для currentStyle нужен camelCase (или как там называется), а для getPropertyValue нужен .... , блин да не помню. В общем backgroundColor и background-color.

Цитата:

Сообщение от B~Vladi
if(document.documentElement.clientWidth)return document.documentElement.clientWidth;
return document.body.clientWidth;

Кто сказал, что если есть documentElement.clientWidth, то в нем обязательно правильное значение.

B~Vladi 20.05.2009 13:58

Цитата:

Сообщение от Riim (Сообщение 19486)
Интересно где бы откопать браузер, который не поддерживает getElementById. Мне такой для коллекции нужен.

eval - зло. Здесь он совершенно не нужен.


Вы точно протестировали эту функцию? Для currentStyle нужен camelCase (или как там называется), а для getPropertyValue нужен .... , блин да не помню. В общем backgroundColor и background-color.


Кто сказал, что если есть documentElement.clientWidth, то в нем обязательно правильное значение.

1. Вам мешает document.all?! стоит ли отрезать его, если можно добавить дополнительную возможность?!

2. Eval исправил... писал её давно.

3. Эта функция работает в указанных браузерах. Если чесно все своиства не перебирал, но если нужно - выложу отдельно ф-цию для чтения/смены бэкграунда.

4. В нём правильное значение. IE8 понимает только эту конструкцию. Без documentElement возвращается пустое значение.

Riim 20.05.2009 14:08

Цитата:

Сообщение от B~Vladi
Вам мешает document.all?! стоит ли отрезать его, если можно добавить дополнительную возможность?!

Смело режьте.

Цитата:

Сообщение от B~Vladi
Eval исправил... писал её давно.

Теперь одно и тоже два раза вызывается. Нужно сохранять в переменную.

Цитата:

Сообщение от B~Vladi
выложу отдельно ф-цию для чтения/смены бэкграунда.

background-color это для примера. Там еще много подобных свойств. Вы для каждого будете отдельную функцию писать?

Цитата:

Сообщение от B~Vladi
В нём правельное значение. IE8 понимает только эту конструкцию. Без documentElement возвращается пустое значение.

Тестируйте. На данный момент все совсем плохо.

B~Vladi 20.05.2009 14:18

Цитата:

Сообщение от Riim (Сообщение 19492)
Смело режьте.

Теперь одно и тоже два раза вызывается. Нужно сохранять в переменную.

background-color это для примера. Там еще много подобных свойств. Вы для каждого будете отдельную функцию пи сать?

Тестируйте. На данный момент все совсем плохо.

1. Ок... ф-ция удаляется из списка.

2. Так оформленно из соображений компактности кода. Не думаю, что это сильно напрягёт интерпретатор и Вам никто не мешает переписать всё так, как вам это видится.

3. По-видимому я вас не правильно понял. Вас смущает, что background-color!=backgroundСolor?! Прочитайте описание под ф-цией. Мы должны указывать и background-color и backgroundСolor. Если у нас совпадают названия сойств - 2-ой параметр опускаем.

4. ОК. Протестим

B~Vladi 20.05.2009 14:23

Функция "Функции получения размеров окна" работает в IE, FF и Opera. Что конкретно плохо?!

Riim 20.05.2009 14:29

Цитата:

Сообщение от B~Vladi
Ок... ф-ция удаляется из списка.

Зачем же совсем удалять. Я имел в виду сделать так:
var $ = function(elem/* id */) {
	return typeof elem == 'string' ? $d.getElementById(elem) : elem;
};


Цитата:

Сообщение от B~Vladi
Так оформленно из соображений компактности кода.

Так он наоборот больше становится.

Цитата:

Сообщение от B~Vladi
По-видимому я вас не правильно понял. Вас смущает, что background-color!=backgroundСolor?! Прочитайте описание под ф-цией. Мы должны указывать и background-color и backgroundСolor. Если у нас совпадают названия сойств - 2-ой параметр опускаем.

Так не проще сделать что бы 'margin-left' автоматически, когда это необходимо переводился в ''marginLeft'', и наоборот.

B~Vladi 20.05.2009 14:30

Исправлено описание для ф-ции "получения CSS-свойства". Ошибка была в неправильном описании порядка параметров. В часности свойство backgroudColor возвращается.

B~Vladi 20.05.2009 14:33

Цитата:

Сообщение от Riim (Сообщение 19499)
Так не проще сделать что бы 'margin-left' автоматически, когда это необходимо переводился в ''marginLeft'', и наоборот.

да... так тоже можно... опять же всё для компактности... любой может прикрутить себе такую фичу, если его не устраивают такие параметры... Суть ф-ции - работать... а удобство использования не так критично.

Kolyaj 20.05.2009 14:35

Цитата:

Сообщение от B~Vladi
Проверка типов переменных.

Зачем? typeof сам по себе нормален. А вот функция типа isArray не повредила бы.

B~Vladi 20.05.2009 14:37

Цитата:

Сообщение от Kolyaj (Сообщение 19502)
Зачем? typeof сам по себе нормален. А вот функция типа isArray не повредила бы.

Затем, что эти ф-ции используются почти во всех остальных. И я нахожу это удобным.

B~Vladi 20.05.2009 14:39

isArray да... но не для этого поста... тут не "полезные", а "кросс-браузерные" ф-ции...

Kolyaj 20.05.2009 14:39

Цитата:

Сообщение от B~Vladi
Затем, что эти ф-ции используются почти во всех остальных.

Аргумент из серии: я написал функцию
function f(x) { return x; }
и использую ее везде.

Riim 20.05.2009 14:40

Цитата:

Сообщение от B~Vladi
Функция "Функции получения размеров окна" работает в IE, FF и Opera. Что конкретно плохо?!

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

B~Vladi 20.05.2009 14:43

Цитата:

Сообщение от Riim (Сообщение 19508)
То, что она работает, еще не значит, что она выдает правильный результат во всех актуальных браузерах.

По крайней мере они совпадают, и все скрипты, которые я писал и используют эту функцию - работают пиксель-в-пиксель. Под понятием "размер окна" я подразумеваю размер узла body а не окно самого браузера. Не вижу никаких причин в сомнении... если у Вас есть что-то конкретное - говорите... зачем догадками?!

B~Vladi 20.05.2009 14:46

Цитата:

Сообщение от Kolyaj (Сообщение 19507)
Аргумент из серии: я написал функцию
function f(x) { return x; }
и использую ее везде.

:)

Когда в 100 местах мы будем писать typeof(n)=='хз_что' вместо xDef(n) - разница будет видна...

Riim 20.05.2009 14:46

Цитата:

Сообщение от B~Vladi
Под понятием "размер окна" я подразумеваю размер узла body а не окно самого браузера.

Размер клиентской области?

B~Vladi 20.05.2009 14:47

именно... Если кого ввёл в ступор - сори...

Riim 20.05.2009 14:54

Цитата:

Сообщение от B~Vladi
если у Вас есть что-то конкретное - говорите...

prototype.1.6.1_rc2.js
str 3093

document.viewport = {

  getDimensions: function() {
    return { width: this.getWidth(), height: this.getHeight() };
  },

  getScrollOffsets: function() {
    return Element._returnOffset(
      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
      window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);
  }
};

(function(viewport) {
  var B = Prototype.Browser, doc = document, element, property = {};

  function getRootElement() {
    if (B.WebKit && !doc.evaluate)
      return document;

    if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
      return document.body;

    return document.documentElement;
  }

  function define(D) {
    if (!element) element = getRootElement();

    property[D] = 'client' + D;

    viewport['get' + D] = function() { return element[property[D]] };
    return viewport['get' + D]();
  }

  viewport.getWidth  = define.curry('Width');

  viewport.getHeight = define.curry('Height');
})(document.viewport);


Единственный минус: не учитывается compatMode. Но это сейчас уже не столь актуально.

B~Vladi 20.05.2009 15:09

Очень хрупко...

window.parseFloat(window.opera.version()) < 9.5


Не стал бы таким пользоваться...

B~Vladi 20.05.2009 15:10

prototype.1.6.1_rc2.js
не до конца понятно для чего этот код.

Riim 20.05.2009 15:15

Цитата:

Сообщение от B~Vladi
Очень хрупко...

У вас предвзятое мнение. Хрупко как раз у вас.

B~Vladi 20.05.2009 15:20

Цитата:

Сообщение от Riim (Сообщение 19525)
У вас предвзятое мнение. Хрупко как раз у вас.

Везде и в любых авторитетных источниках говорится о неправильном подходе к написанию кросс-браузерных функций. А именно о том, что почти во всех библиотеках и фреймворках есть проверка версии или типа браузера и не её основе строят логику. Это не есть гуд. Покажите мне кусок моего кода, где используется неправельный код.

B~Vladi 20.05.2009 15:24

ИМХО

писать такие вещи нада так, что бы в конце всех условий была такая контрукция, которая описана в доках W3C.

Riim 20.05.2009 15:33

Цитата:

Сообщение от B~Vladi
А именно о том, что почти во всех библиотеках и фреймворках есть проверка версии или типа браузера и не её основе строят логику. Это не есть гуд.

Мнение в некотором смысле верное, но и меру нужно знать. В Opera9.5+ верное значение перенесли в documentElement.clientHeight. Как вы это хотите определить с помощью:
Цитата:

Сообщение от B~Vladi
Вместо этого идёт проверка соответствующих своиств или методов

?

Факт остается фактом: пока ваш вариант некроссбраузерен. Вариант из PrototypeJs, по-вашему, плох, но он работает верно. Когда напишете вашим способом кроссбраузерный вариант, тогда и поговорим.

Riim 20.05.2009 15:35

Цитата:

Сообщение от B~Vladi
писать такие вещи нада так, что бы в конце всех условий была такая контрукция, которая описана в доках W3C.

К этому нужно стремиться, но при всем желании это не всегда возможно.

B~Vladi 20.05.2009 15:42

Цитата:

Сообщение от Riim (Сообщение 19531)
documentElement.clientHeight.

А в чём, собственно, проблема?! Пусть переносят...

Цитата:

Сообщение от Riim (Сообщение 19531)
Факт остается фактом: пока ваш вариант некроссбраузерен. Вариант из PrototypeJs, по-вашему, плох, но он работает верно. Когда напишете вашим способом кроссбраузерный вариант, тогда и поговорим.

Мой вариант кроссбраузен для тех, которые я описал (IE, FF, Opera всех актуальных версий) и я сомневаюсь, что в Safari или Chrome что-то не сработает. Зачем так утверждать?! Лучше напишите ту ф-цию, которая не работает в заявленных браузерах.

Никто не говорил, что вариант из prototype плох.

Какой способ мне написать?! аналог их объекта?!

Riim 20.05.2009 15:57

Цитата:

Сообщение от B~Vladi
А в чём, собственно, проблема?! Пусть переносят...

Давно уже перенесли. И в вашем скрипте это не учитывается.

Цитата:

Сообщение от B~Vladi
Мой вариант кроссбраузен для тех, которые я описал (IE, FF, Opera всех актуальных версий)

Это вы так думаете. Простейший пример: уберите DOCTYPE из документа или поставьте любой старый. Ну как, правильно работает?

Цитата:

Сообщение от B~Vladi
и я сомневаюсь, что в Safari или Chrome что-то не сработает.

Как же вы можете утверждать, что функции кроссбраузерены, если вы их даже толком не тестируете.

----

Вы слышите только себя и ваше мнение всегда самое правильное? Обсуждение теряет смысл.

B~Vladi 20.05.2009 16:02

Давно уже перенесли. И в вашем скрипте это не учитывается.

Посмотрите на ф-цию... из какого, по вашему мнению, свойства возвратится значение в опере?!

Это вы так думаете. Простейший пример: уберите DOCTYPE из документа или поставьте любой старый. Ну как, правильно работает?

ОК... Сейчас проверим.

Как же вы можете утверждать, что функции кроссбраузерены, если вы их даже толком не тестируете.

Речь идёт о тех браузерах, которые я неоднократно уже перечислял.

Естесственно обсуждение не будет иметь смысла, когда тебе говорят - "Всё говно!" и при этом не приводят ни одного аргумента в поддержку этих слов.

B~Vladi 20.05.2009 16:12

Цитата:

Сообщение от Riim (Сообщение 19538)
Это вы так думаете. Простейший пример: уберите DOCTYPE из документа или поставьте любой старый. Ну как, правильно работает?

После смены HTML 4.01 Transitional с на XHTML 1.0 Strict и назад, значеня, возвращаемые IE, FF и Opera не изменились при тестировании ф-ций xGetStyleValue и xClientHeight/xClientWidth. Думаю, перебор всех DTD/ф-ций не изменит ситуацию. Если у Вас действительно есть пример с DTD/ф-цией/браузером, где что-то не работает - выкладывайте. В ближайшее время оттестирую на Chrome.

Riim 20.05.2009 16:13

Цитата:

Сообщение от B~Vladi
Посмотрите на ф-цию... из какого, по вашему мнению, свойства возвратится значение в опере?!

Для оперы <9.5 должно возвращаться из body. А у вас? Или эти версии оперы уже не актуальны?

Цитата:

Сообщение от B~Vladi
Речь идёт о тех браузера, которые я неоднократно уже перечислял.

Создается впечатление, что вы не код подстраиваете под среду исполнения, а просто составили список браузеров, где ваш код все же заработал и все эти браузеры объявили актуальными.

Цитата:

Сообщение от B~Vladi
"Всё говно!" и при этом не приводят ни одного аргумента в поддержку этих слов.

Вы же обсуждали эти аргументы. Или может, обсуждали и не заметили?

Riim 20.05.2009 16:16

Цитата:

Сообщение от B~Vladi
После смены HTML 4.01 Transitional с на XHTML 1.0 Strict

Хорошо, раз кроме последних (почти) версий HTML и XHTML для вас ничего не существует (не актуально) попробуйте вообще убрать DOCTYPE.

B~Vladi 20.05.2009 16:20

Цитата:

Сообщение от Riim (Сообщение 19542)
Для оперы <9.5 должно возвращаться из body. А у вас? Или эти версии оперы уже не актуальны?

В опере можно использовать как одно значение, так и другое при любом DTD, т.е. они ОДИНАКОВЫЕ. Где Вы видели разницу?!

Цитата:

Сообщение от Riim (Сообщение 19542)
Создается впечатление, что вы не код подстраиваете под среду исполнения, а просто составили список браузеров, где ваш код все же заработал и все эти браузеры объявили актуальными.

Мой код не просто "всё же заработал". Эти функции писались ещё до появления Оперы 9.6 и IE8. И они продолжали работать без корректировки. И тестились не в 1 день, а больше года и в при разных условиях (типа DTD).

Цитата:

Сообщение от Riim (Сообщение 19542)
Вы же обсуждали эти аргументы. Или может, обсуждали и не заметили?

Я всё время пытаюсь добиться от Вас этих аргументов... То что всё же мне удаётся понять из ваших постов - то я и аргументирую.

B~Vladi 20.05.2009 16:21

Цитата:

Сообщение от Riim (Сообщение 19543)
Хорошо, раз кроме последних (почти) версий HTML и XHTML для вас ничего не существует (не актуально) попробуйте вообще убрать DOCTYPE.

ОК... минуту...

B~Vladi 20.05.2009 16:22

Цитата:

Сообщение от B~Vladi (Сообщение 19545)
ОК... минуту...

Работает...

Riim 20.05.2009 16:31

Цитата:

Сообщение от B~Vladi
В опере можно использовать как одно значение, так и другое

Что, правда? Зачем же тогда в PrototypeJs написано:
window.parseFloat(window.opera.version()) < 9.5 ? document.body : document.documentElement

Да и в любом известном фреймворке есть что-то подобное? Они все глупые там наверно. А вы умный.

Цитата:

Сообщение от B~Vladi
Эти функции писались ещё до появления Оперы 9.6 и IE8

Ой как давно.

Цитата:

Сообщение от B~Vladi
То что всё же мне удаётся понять из ваших постов

Я что так не понятно пишу?

Riim 20.05.2009 16:34

Цитата:

Сообщение от B~Vladi
Работает...

Правда? Ух, ты!
Знаете, много косяков полезет, когда вы начнете применять эти функции к реальным сайтам.

B~Vladi 20.05.2009 16:37

Цитата:

Сообщение от Riim (Сообщение 19549)
Что, правда? Зачем же тогда в PrototypeJs написано:
window.parseFloat(window.opera.version()) < 9.5 ? document.body : document.documentElement

Да и в любом известном фреймворке есть что-то подобное? Они все глупые там наверно. А вы умный.

Я пишу свои наблюдения, а не утверждение, того, что без разницы что использовать. Когда эти значения изменятся - тогда и поговорим. Никто никогда не сможет предугадать заранее какое свойство предпочтительней, в том числе и парни из prototype. А пока это всё работает - это кроссбраузерно.

Цитата:

Сообщение от Riim (Сообщение 19549)
Ой как давно.

Это было приведено для понимания, что после появления новых версий - ничего не упало. Для меня это только + к этим ф-циям.

Цитата:

Сообщение от Riim (Сообщение 19549)
Я что так не понятно пишу?

Нет, понятно. Просто немножко не дописываете:)


Часовой пояс GMT +3, время: 14:18.