Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 01.09.2011, 03:12
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 09.07.2008
Сообщений: 3,873

Отличить DOM-элемент от объекта
Есть функция is, которая проверяет, удовлетворяет ли указанным параметрам DOM-элемент.
Ну например в jQuery:
$("body").is(document.body) //→ true


Пишу подобную функцию, но с возможностью указать объект с набором свойств для сравнения:
//сравниваем свойства
$("html").is({lang: "ru-RU"})

//сравниваем атрибуты
$("html").is('[lang="ru-RU"]')


И тут возникает проблема:
$("html").is({nodeType: 1, nodeName: "html"})

как отличить DOM-объект от обычного объекта?

Из-за IE простой проверкой node instanceof Node не обойтись, пришлось городить кучу условий:
//для IE<8
	function isNode(arg) {
		return Boolean(typeof arg == "object" && !(arg instanceof Object) && arg.nodeType);
	}


Есть ли способ сделать лучше?

Последний раз редактировалось Octane, 11.09.2011 в 11:42.
Ответить с цитированием
  #2 (permalink)  
Старый 01.09.2011, 06:51
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

function isNode( obj ) {
	var documentElement = ( obj ? obj.ownerDocument || obj : 0 ).documentElement;
	return documentElement ? documentElement.nodeName === "HTML" : false;
}
Ответить с цитированием
  #3 (permalink)  
Старый 01.09.2011, 11:56
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 09.07.2008
Сообщений: 3,873

На свойстве ownerDocument сломается:
function isNode( obj ) {
	var documentElement = ( obj ? obj.ownerDocument || obj : 0 ).documentElement;
	return documentElement ? documentElement.nodeName === "HTML" : false;
}

alert(isNode({ownerDocument: document})) // true


Я в надежде, что всплывёт какой-нибудь трюк, типа:
Array.isArray = function (obj) {
	return Object.prototype.toString.call(obj) == "[object Array]";
};
Ответить с цитированием
  #4 (permalink)  
Старый 01.09.2011, 13:51
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Можно воспользоваться тем, что IE не даёт выполнить стандартные js-методы в контексте не JScript-объектов.
alert([].slice.call(document.body))

Если вылетела ошибка, значит не обычный объект, для верности можно ещё проверить какой-нибудь tagName.
Ответить с цитированием
  #5 (permalink)  
Старый 01.09.2011, 14:13
Профессор
Отправить личное сообщение для nikita.mmf Посмотреть профиль Найти все сообщения от nikita.mmf
 
Регистрация: 01.02.2010
Сообщений: 364

Первое что пришло в голову поиграться с nodeType.
function isNode ( node ) {
	var nodeType = node && node.nodeType, isNode = true;
	if ( nodeType !== 1 || nodeType !== 9 ) { return !isNode; }
	try {
		delete node.nodeType;
		isNode = node.nodeType === nodeType;
		node.nodeType = nodeType;
	} catch ( e ) {}
	return isNode;
}

Еще интересным является, то что в IE, у dom элемента отсутствует конструктор
function isNode ( node ) {
	if ( !node ) return false;
	var type = Object.prototype.toString.call( node ).toLowerCase().slice(8,-1);
	return (type == "object" && node.constructor == null && typeof node.nodeType == "number") || (/^html/.test( type ) && !/collection$/.test( type ) || type == "global");
}

Последний раз редактировалось nikita.mmf, 01.09.2011 в 14:32.
Ответить с цитированием
  #6 (permalink)  
Старый 01.09.2011, 14:34
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 09.07.2008
Сообщений: 3,873

delete только в IE7 для свойств DOM-элементов приведет к ошибке, а [].slice.call(node) — в IE7,8, тогда вариант без try-catch:
typeof obj == "object" && !(obj instanceof Object)
для этих браузеров привлекательнее мне кажется, под такое условие только null еще попадает.

Последний раз редактировалось Octane, 01.09.2011 в 14:53.
Ответить с цитированием
  #7 (permalink)  
Старый 01.09.2011, 15:59
Аватар для Snipe
Профессор
Отправить личное сообщение для Snipe Посмотреть профиль Найти все сообщения от Snipe
 
Регистрация: 06.05.2008
Сообщений: 765

А проверить наличие какой-нибудь функции, типа getElementById или cloneNode?
Или речь не только про теги?

Последний раз редактировалось Snipe, 01.09.2011 в 16:05.
Ответить с цитированием
  #8 (permalink)  
Старый 01.09.2011, 16:14
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 09.07.2008
Сообщений: 3,873

Да это понятно, что можно напроверять наличие кучи свойств и методов, но опять же, допустим напишем:

function isNode(obj) {
    return "hasChildNodes" in obj;
}


а кто-нибудь додумается сделать:
$(…).is({hasChildNodes: false})


дополнительными проверками конечно сведем вероятность неправильного результата к минимуму, но тему создавал в надежде, что найдем какое-нибудь интересное решение, как в случае с isArray
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как узнать находится ли DOM элемент в области видимости? phgrey Общие вопросы Javascript 4 22.03.2011 18:05
Как удалить элемент из дерева DOM dummer jQuery 13 16.01.2011 15:19
Как добавить элемент в XML через DOM используя PHP? bayah Серверные языки и технологии 6 11.08.2010 12:33
Как отличить массив от объекта Ilyan Общие вопросы Javascript 3 20.04.2010 22:08
Как узнать содержит ли DOM определенный элемент Ruslan Events/DOM/Window 8 12.03.2010 21:02